Annotation of quakeworld/progs/triggers.qc, revision 1.1

1.1     ! root        1: 
        !             2: entity stemp, otemp, s, old;
        !             3: 
        !             4: 
        !             5: void() trigger_reactivate =
        !             6: {
        !             7:        self.solid = SOLID_TRIGGER;
        !             8: };
        !             9: 
        !            10: //=============================================================================
        !            11: 
        !            12: float  SPAWNFLAG_NOMESSAGE = 1;
        !            13: float  SPAWNFLAG_NOTOUCH = 1;
        !            14: 
        !            15: // the wait time has passed, so set back up for another activation
        !            16: void() multi_wait =
        !            17: {
        !            18:        if (self.max_health)
        !            19:        {
        !            20:                self.health = self.max_health;
        !            21:                self.takedamage = DAMAGE_YES;
        !            22:                self.solid = SOLID_BBOX;
        !            23:        }
        !            24: };
        !            25: 
        !            26: 
        !            27: // the trigger was just touched/killed/used
        !            28: // self.enemy should be set to the activator so it can be held through a delay
        !            29: // so wait for the delay time before firing
        !            30: void() multi_trigger =
        !            31: {
        !            32:        if (self.nextthink > time)
        !            33:        {
        !            34:                return;         // allready been triggered
        !            35:        }
        !            36: 
        !            37:        if (self.classname == "trigger_secret")
        !            38:        {
        !            39:                if (self.enemy.classname != "player")
        !            40:                        return;
        !            41:                found_secrets = found_secrets + 1;
        !            42:                WriteByte (MSG_ALL, SVC_FOUNDSECRET);
        !            43:        }
        !            44: 
        !            45:        if (self.noise)
        !            46:                sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
        !            47: 
        !            48: // don't trigger again until reset
        !            49:        self.takedamage = DAMAGE_NO;
        !            50: 
        !            51:        activator = self.enemy;
        !            52:        
        !            53:        SUB_UseTargets();
        !            54: 
        !            55:        if (self.wait > 0)      
        !            56:        {
        !            57:                self.think = multi_wait;
        !            58:                self.nextthink = time + self.wait;
        !            59:        }
        !            60:        else
        !            61:        {       // we can't just remove (self) here, because this is a touch function
        !            62:                // called wheil C code is looping through area links...
        !            63:                self.touch = SUB_Null;
        !            64:                self.nextthink = time + 0.1;
        !            65:                self.think = SUB_Remove;
        !            66:        }
        !            67: };
        !            68: 
        !            69: void() multi_killed =
        !            70: {
        !            71:        self.enemy = damage_attacker;
        !            72:        multi_trigger();
        !            73: };
        !            74: 
        !            75: void() multi_use =
        !            76: {
        !            77:        self.enemy = activator;
        !            78:        multi_trigger();
        !            79: };
        !            80: 
        !            81: void() multi_touch =
        !            82: {
        !            83:        if (other.classname != "player")
        !            84:                return;
        !            85:        
        !            86: // if the trigger has an angles field, check player's facing direction
        !            87:        if (self.movedir != '0 0 0')
        !            88:        {
        !            89:                makevectors (other.angles);
        !            90:                if (v_forward * self.movedir < 0)
        !            91:                        return;         // not facing the right way
        !            92:        }
        !            93:        
        !            94:        self.enemy = other;
        !            95:        multi_trigger ();
        !            96: };
        !            97: 
        !            98: /*QUAKED trigger_multiple (.5 .5 .5) ? notouch
        !            99: Variable sized repeatable trigger.  Must be targeted at one or more entities.  If "health" is set, the trigger must be killed to activate each time.
        !           100: If "delay" is set, the trigger waits some time after activating before firing.
        !           101: "wait" : Seconds between triggerings. (.2 default)
        !           102: If notouch is set, the trigger is only fired by other entities, not by touching.
        !           103: NOTOUCH has been obsoleted by trigger_relay!
        !           104: sounds
        !           105: 1)     secret
        !           106: 2)     beep beep
        !           107: 3)     large switch
        !           108: 4)
        !           109: set "message" to text string
        !           110: */
        !           111: void() trigger_multiple =
        !           112: {
        !           113:        if (self.sounds == 1)
        !           114:        {
        !           115:                precache_sound ("misc/secret.wav");
        !           116:                self.noise = "misc/secret.wav";
        !           117:        }
        !           118:        else if (self.sounds == 2)
        !           119:        {
        !           120:                precache_sound ("misc/talk.wav");
        !           121:                self.noise = "misc/talk.wav";
        !           122:        }
        !           123:        else if (self.sounds == 3)
        !           124:        {
        !           125:                precache_sound ("misc/trigger1.wav");
        !           126:                self.noise = "misc/trigger1.wav";
        !           127:        }
        !           128:        
        !           129:        if (!self.wait)
        !           130:                self.wait = 0.2;
        !           131:        self.use = multi_use;
        !           132: 
        !           133:        InitTrigger ();
        !           134: 
        !           135:        if (self.health)
        !           136:        {
        !           137:                if (self.spawnflags & SPAWNFLAG_NOTOUCH)
        !           138:                        objerror ("health and notouch don't make sense\n");
        !           139:                self.max_health = self.health;
        !           140:                self.th_die = multi_killed;
        !           141:                self.takedamage = DAMAGE_YES;
        !           142:                self.solid = SOLID_BBOX;
        !           143:                setorigin (self, self.origin);  // make sure it links into the world
        !           144:        }
        !           145:        else
        !           146:        {
        !           147:                if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
        !           148:                {
        !           149:                        self.touch = multi_touch;
        !           150:                }
        !           151:        }
        !           152: };
        !           153: 
        !           154: 
        !           155: /*QUAKED trigger_once (.5 .5 .5) ? notouch
        !           156: Variable sized trigger. Triggers once, then removes itself.  You must set the key "target" to the name of another object in the level that has a matching
        !           157: "targetname".  If "health" is set, the trigger must be killed to activate.
        !           158: If notouch is set, the trigger is only fired by other entities, not by touching.
        !           159: if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
        !           160: if "angle" is set, the trigger will only fire when someone is facing the direction of the angle.  Use "360" for an angle of 0.
        !           161: sounds
        !           162: 1)     secret
        !           163: 2)     beep beep
        !           164: 3)     large switch
        !           165: 4)
        !           166: set "message" to text string
        !           167: */
        !           168: void() trigger_once =
        !           169: {
        !           170:        self.wait = -1;
        !           171:        trigger_multiple();
        !           172: };
        !           173: 
        !           174: //=============================================================================
        !           175: 
        !           176: /*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
        !           177: This fixed size trigger cannot be touched, it can only be fired by other events.  It can contain killtargets, targets, delays, and messages.
        !           178: */
        !           179: void() trigger_relay =
        !           180: {
        !           181:        self.use = SUB_UseTargets;
        !           182: };
        !           183: 
        !           184: 
        !           185: //=============================================================================
        !           186: 
        !           187: /*QUAKED trigger_secret (.5 .5 .5) ?
        !           188: secret counter trigger
        !           189: sounds
        !           190: 1)     secret
        !           191: 2)     beep beep
        !           192: 3)
        !           193: 4)
        !           194: set "message" to text string
        !           195: */
        !           196: void() trigger_secret =
        !           197: {
        !           198:        total_secrets = total_secrets + 1;
        !           199:        self.wait = -1;
        !           200:        if (!self.message)
        !           201:                self.message = "You found a secret area!";
        !           202:        if (!self.sounds)
        !           203:                self.sounds = 1;
        !           204:        
        !           205:        if (self.sounds == 1)
        !           206:        {
        !           207:                precache_sound ("misc/secret.wav");
        !           208:                self.noise = "misc/secret.wav";
        !           209:        }
        !           210:        else if (self.sounds == 2)
        !           211:        {
        !           212:                precache_sound ("misc/talk.wav");
        !           213:                self.noise = "misc/talk.wav";
        !           214:        }
        !           215: 
        !           216:        trigger_multiple ();
        !           217: };
        !           218: 
        !           219: //=============================================================================
        !           220: 
        !           221: 
        !           222: void() counter_use =
        !           223: {
        !           224:        local string junk;
        !           225: 
        !           226:        self.count = self.count - 1;
        !           227:        if (self.count < 0)
        !           228:                return;
        !           229:        
        !           230:        if (self.count != 0)
        !           231:        {
        !           232:                if (activator.classname == "player"
        !           233:                && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
        !           234:                {
        !           235:                        if (self.count >= 4)
        !           236:                                centerprint (activator, "There are more to go...");
        !           237:                        else if (self.count == 3)
        !           238:                                centerprint (activator, "Only 3 more to go...");
        !           239:                        else if (self.count == 2)
        !           240:                                centerprint (activator, "Only 2 more to go...");
        !           241:                        else
        !           242:                                centerprint (activator, "Only 1 more to go...");
        !           243:                }
        !           244:                return;
        !           245:        }
        !           246:        
        !           247:        if (activator.classname == "player"
        !           248:        && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
        !           249:                centerprint(activator, "Sequence completed!");
        !           250:        self.enemy = activator;
        !           251:        multi_trigger ();
        !           252: };
        !           253: 
        !           254: /*QUAKED trigger_counter (.5 .5 .5) ? nomessage
        !           255: Acts as an intermediary for an action that takes multiple inputs.
        !           256: 
        !           257: If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
        !           258: 
        !           259: After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
        !           260: */
        !           261: void() trigger_counter =
        !           262: {
        !           263:        self.wait = -1;
        !           264:        if (!self.count)
        !           265:                self.count = 2;
        !           266: 
        !           267:        self.use = counter_use;
        !           268: };
        !           269: 
        !           270: 
        !           271: /*
        !           272: ==============================================================================
        !           273: 
        !           274: TELEPORT TRIGGERS
        !           275: 
        !           276: ==============================================================================
        !           277: */
        !           278: 
        !           279: float  PLAYER_ONLY     = 1;
        !           280: float  SILENT = 2;
        !           281: 
        !           282: void() play_teleport =
        !           283: {
        !           284:        local   float v;
        !           285:        local   string tmpstr;
        !           286: 
        !           287:        v = random() * 5;
        !           288:        if (v < 1)
        !           289:                tmpstr = "misc/r_tele1.wav";
        !           290:        else if (v < 2)
        !           291:                tmpstr = "misc/r_tele2.wav";
        !           292:        else if (v < 3)
        !           293:                tmpstr = "misc/r_tele3.wav";
        !           294:        else if (v < 4)
        !           295:                tmpstr = "misc/r_tele4.wav";
        !           296:        else
        !           297:                tmpstr = "misc/r_tele5.wav";
        !           298: 
        !           299:        sound (self, CHAN_VOICE, tmpstr, 1, ATTN_NORM);
        !           300:        remove (self);
        !           301: };
        !           302: 
        !           303: void(vector org) spawn_tfog =
        !           304: {
        !           305:        s = spawn ();
        !           306:        s.origin = org;
        !           307:        s.nextthink = time + 0.2;
        !           308:        s.think = play_teleport;
        !           309: 
        !           310:        WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
        !           311:        WriteByte (MSG_MULTICAST, TE_TELEPORT);
        !           312:        WriteCoord (MSG_MULTICAST, org_x);
        !           313:        WriteCoord (MSG_MULTICAST, org_y);
        !           314:        WriteCoord (MSG_MULTICAST, org_z);
        !           315:        multicast (org, MULTICAST_PHS);
        !           316: };
        !           317: 
        !           318: 
        !           319: void() tdeath_touch =
        !           320: {
        !           321:        local entity other2;
        !           322: 
        !           323:        if (other == self.owner)
        !           324:                return;
        !           325: 
        !           326: // frag anyone who teleports in on top of an invincible player
        !           327:        if (other.classname == "player")
        !           328:        {
        !           329:                if (other.invincible_finished > time &&
        !           330:                        self.owner.invincible_finished > time) {
        !           331:                        self.classname = "teledeath3";
        !           332:                        other.invincible_finished = 0;
        !           333:                        self.owner.invincible_finished = 0;
        !           334:                        T_Damage (other, self, self, 50000);
        !           335:                        other2 = self.owner;
        !           336:                        self.owner = other;
        !           337:                        T_Damage (other2, self, self, 50000);
        !           338:                }
        !           339:                        
        !           340:                if (other.invincible_finished > time)
        !           341:                {
        !           342:                        self.classname = "teledeath2";
        !           343:                        T_Damage (self.owner, self, self, 50000);
        !           344:                        return;
        !           345:                }
        !           346:                
        !           347:        }
        !           348: 
        !           349:        if (other.health)
        !           350:        {
        !           351:                T_Damage (other, self, self, 50000);
        !           352:        }
        !           353: };
        !           354: 
        !           355: 
        !           356: void(vector org, entity death_owner) spawn_tdeath =
        !           357: {
        !           358: local entity   death;
        !           359: 
        !           360:        death = spawn();
        !           361:        death.classname = "teledeath";
        !           362:        death.movetype = MOVETYPE_NONE;
        !           363:        death.solid = SOLID_TRIGGER;
        !           364:        death.angles = '0 0 0';
        !           365:        setsize (death, death_owner.mins - '1 1 1', death_owner.maxs + '1 1 1');
        !           366:        setorigin (death, org);
        !           367:        death.touch = tdeath_touch;
        !           368:        death.nextthink = time + 0.2;
        !           369:        death.think = SUB_Remove;
        !           370:        death.owner = death_owner;
        !           371:        
        !           372:        force_retouch = 2;              // make sure even still objects get hit
        !           373: };
        !           374: 
        !           375: void() teleport_touch =
        !           376: {
        !           377: local entity   t;
        !           378: local vector   org;
        !           379: 
        !           380:        if (self.targetname)
        !           381:        {
        !           382:                if (self.nextthink < time)
        !           383:                {
        !           384:                        return;         // not fired yet
        !           385:                }
        !           386:        }
        !           387: 
        !           388:        if (self.spawnflags & PLAYER_ONLY)
        !           389:        {
        !           390:                if (other.classname != "player")
        !           391:                        return;
        !           392:        }
        !           393: 
        !           394: // only teleport living creatures
        !           395:        if (other.health <= 0 || other.solid != SOLID_SLIDEBOX)
        !           396:                return;
        !           397: 
        !           398:        SUB_UseTargets ();
        !           399: 
        !           400: // put a tfog where the player was
        !           401:        spawn_tfog (other.origin);
        !           402: 
        !           403:        t = find (world, targetname, self.target);
        !           404:        if (!t)
        !           405:                objerror ("couldn't find target");
        !           406:                
        !           407: // spawn a tfog flash in front of the destination
        !           408:        makevectors (t.mangle);
        !           409:        org = t.origin + 32 * v_forward;
        !           410: 
        !           411:        spawn_tfog (org);
        !           412:        spawn_tdeath(t.origin, other);
        !           413: 
        !           414: // move the player and lock him down for a little while
        !           415:        if (!other.health)
        !           416:        {
        !           417:                other.origin = t.origin;
        !           418:                other.velocity = (v_forward * other.velocity_x) + (v_forward * other.velocity_y);
        !           419:                return;
        !           420:        }
        !           421: 
        !           422:        setorigin (other, t.origin);
        !           423:        other.angles = t.mangle;
        !           424:        if (other.classname == "player")
        !           425:        {
        !           426:                other.fixangle = 1;             // turn this way immediately
        !           427:                other.teleport_time = time + 0.7;
        !           428:                if (other.flags & FL_ONGROUND)
        !           429:                        other.flags = other.flags - FL_ONGROUND;
        !           430:                other.velocity = v_forward * 300;
        !           431:        }
        !           432:        other.flags = other.flags - other.flags & FL_ONGROUND;
        !           433: };
        !           434: 
        !           435: /*QUAKED info_teleport_destination (.5 .5 .5) (-8 -8 -8) (8 8 32)
        !           436: This is the destination marker for a teleporter.  It should have a "targetname" field with the same value as a teleporter's "target" field.
        !           437: */
        !           438: void() info_teleport_destination =
        !           439: {
        !           440: // this does nothing, just serves as a target spot
        !           441:        self.mangle = self.angles;
        !           442:        self.angles = '0 0 0';
        !           443:        self.model = "";
        !           444:        self.origin = self.origin + '0 0 27';
        !           445:        if (!self.targetname)
        !           446:                objerror ("no targetname");
        !           447: };
        !           448: 
        !           449: void() teleport_use =
        !           450: {
        !           451:        self.nextthink = time + 0.2;
        !           452:        force_retouch = 2;              // make sure even still objects get hit
        !           453:        self.think = SUB_Null;
        !           454: };
        !           455: 
        !           456: /*QUAKED trigger_teleport (.5 .5 .5) ? PLAYER_ONLY SILENT
        !           457: Any object touching this will be transported to the corresponding info_teleport_destination entity. You must set the "target" field, and create an object with a "targetname" field that matches.
        !           458: 
        !           459: If the trigger_teleport has a targetname, it will only teleport entities when it has been fired.
        !           460: */
        !           461: void() trigger_teleport =
        !           462: {
        !           463:        local vector o;
        !           464: 
        !           465:        InitTrigger ();
        !           466:        self.touch = teleport_touch;
        !           467:        // find the destination 
        !           468:        if (!self.target)
        !           469:                objerror ("no target");
        !           470:        self.use = teleport_use;
        !           471: 
        !           472:        if (!(self.spawnflags & SILENT))
        !           473:        {
        !           474:                precache_sound ("ambience/hum1.wav");
        !           475:                o = (self.mins + self.maxs)*0.5;
        !           476:                ambientsound (o, "ambience/hum1.wav",0.5 , ATTN_STATIC);
        !           477:        }
        !           478: };
        !           479: 
        !           480: /*
        !           481: ==============================================================================
        !           482: 
        !           483: trigger_setskill
        !           484: 
        !           485: ==============================================================================
        !           486: */
        !           487: 
        !           488: /*QUAKED trigger_setskill (.5 .5 .5) ?
        !           489: sets skill level to the value of "message".
        !           490: Only used on start map.
        !           491: */
        !           492: void() trigger_setskill =
        !           493: {
        !           494:        remove (self);
        !           495: };
        !           496: 
        !           497: 
        !           498: /*
        !           499: ==============================================================================
        !           500: 
        !           501: ONLY REGISTERED TRIGGERS
        !           502: 
        !           503: ==============================================================================
        !           504: */
        !           505: 
        !           506: void() trigger_onlyregistered_touch =
        !           507: {
        !           508:        if (other.classname != "player")
        !           509:                return;
        !           510:        if (self.attack_finished > time)
        !           511:                return;
        !           512: 
        !           513:        self.attack_finished = time + 2;
        !           514:        if (cvar("registered"))
        !           515:        {
        !           516:                self.message = "";
        !           517:                SUB_UseTargets ();
        !           518:                remove (self);
        !           519:        }
        !           520:        else
        !           521:        {
        !           522:                if (self.message != "")
        !           523:                {
        !           524:                        centerprint (other, self.message);
        !           525:                        sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
        !           526:                }
        !           527:        }
        !           528: };
        !           529: 
        !           530: /*QUAKED trigger_onlyregistered (.5 .5 .5) ?
        !           531: Only fires if playing the registered version, otherwise prints the message
        !           532: */
        !           533: void() trigger_onlyregistered =
        !           534: {
        !           535:        precache_sound ("misc/talk.wav");
        !           536:        InitTrigger ();
        !           537:        self.touch = trigger_onlyregistered_touch;
        !           538: };
        !           539: 
        !           540: //============================================================================
        !           541: 
        !           542: void() hurt_on =
        !           543: {
        !           544:        self.solid = SOLID_TRIGGER;
        !           545:        self.nextthink = -1;
        !           546: };
        !           547: 
        !           548: void() hurt_touch =
        !           549: {
        !           550:        if (other.takedamage)
        !           551:        {
        !           552:                self.solid = SOLID_NOT;
        !           553:                T_Damage (other, self, self, self.dmg);
        !           554:                self.think = hurt_on;
        !           555:                self.nextthink = time + 1;
        !           556:        }
        !           557: 
        !           558:        return;
        !           559: };
        !           560: 
        !           561: /*QUAKED trigger_hurt (.5 .5 .5) ?
        !           562: Any object touching this will be hurt
        !           563: set dmg to damage amount
        !           564: defalt dmg = 5
        !           565: */
        !           566: void() trigger_hurt =
        !           567: {
        !           568:        InitTrigger ();
        !           569:        self.touch = hurt_touch;
        !           570:        if (!self.dmg)
        !           571:                self.dmg = 5;
        !           572: };
        !           573: 
        !           574: //============================================================================
        !           575: 
        !           576: float PUSH_ONCE = 1;
        !           577: 
        !           578: void() trigger_push_touch =
        !           579: {
        !           580:        if (other.classname == "grenade")
        !           581:                other.velocity = self.speed * self.movedir * 10;
        !           582:        else if (other.health > 0)
        !           583:        {
        !           584:                other.velocity = self.speed * self.movedir * 10;
        !           585:                if (other.classname == "player")
        !           586:                {
        !           587:                        if (other.fly_sound < time)
        !           588:                        {
        !           589:                                other.fly_sound = time + 1.5;
        !           590:                                sound (other, CHAN_AUTO, "ambience/windfly.wav", 1, ATTN_NORM);
        !           591:                        }
        !           592:                }
        !           593:        }
        !           594:        if (self.spawnflags & PUSH_ONCE)
        !           595:                remove(self);
        !           596: };
        !           597: 
        !           598: 
        !           599: /*QUAKED trigger_push (.5 .5 .5) ? PUSH_ONCE
        !           600: Pushes the player
        !           601: */
        !           602: void() trigger_push =
        !           603: {
        !           604:        InitTrigger ();
        !           605:        precache_sound ("ambience/windfly.wav");
        !           606:        self.touch = trigger_push_touch;
        !           607:        if (!self.speed)
        !           608:                self.speed = 1000;
        !           609: };
        !           610: 
        !           611: //============================================================================
        !           612: 
        !           613: void() trigger_monsterjump_touch =
        !           614: {
        !           615:        if ( other.flags & (FL_MONSTER | FL_FLY | FL_SWIM) != FL_MONSTER )
        !           616:                return;
        !           617: 
        !           618: // set XY even if not on ground, so the jump will clear lips
        !           619:        other.velocity_x = self.movedir_x * self.speed;
        !           620:        other.velocity_y = self.movedir_y * self.speed;
        !           621:        
        !           622:        if ( !(other.flags & FL_ONGROUND) )
        !           623:                return;
        !           624:        
        !           625:        other.flags = other.flags - FL_ONGROUND;
        !           626: 
        !           627:        other.velocity_z = self.height;
        !           628: };
        !           629: 
        !           630: /*QUAKED trigger_monsterjump (.5 .5 .5) ?
        !           631: Walking monsters that touch this will jump in the direction of the trigger's angle
        !           632: "speed" default to 200, the speed thrown forward
        !           633: "height" default to 200, the speed thrown upwards
        !           634: */
        !           635: void() trigger_monsterjump =
        !           636: {
        !           637:        if (!self.speed)
        !           638:                self.speed = 200;
        !           639:        if (!self.height)
        !           640:                self.height = 200;
        !           641:        if (self.angles == '0 0 0')
        !           642:                self.angles = '0 360 0';
        !           643:        InitTrigger ();
        !           644:        self.touch = trigger_monsterjump_touch;
        !           645: };
        !           646: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.