Annotation of quakeworld/progs/triggers.qc, revision 1.1.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.