Annotation of quake2/xatrix/g_trigger.c, revision 1.1.1.1

1.1       root        1: #include "g_local.h"
                      2: 
                      3: 
                      4: void InitTrigger (edict_t *self)
                      5: {
                      6:        if (!VectorCompare (self->s.angles, vec3_origin))
                      7:                G_SetMovedir (self->s.angles, self->movedir);
                      8: 
                      9:        self->solid = SOLID_TRIGGER;
                     10:        self->movetype = MOVETYPE_NONE;
                     11:        gi.setmodel (self, self->model);
                     12:        self->svflags = SVF_NOCLIENT;
                     13: }
                     14: 
                     15: 
                     16: // the wait time has passed, so set back up for another activation
                     17: void multi_wait (edict_t *ent)
                     18: {
                     19:        ent->nextthink = 0;
                     20: }
                     21: 
                     22: 
                     23: // the trigger was just activated
                     24: // ent->activator should be set to the activator so it can be held through a delay
                     25: // so wait for the delay time before firing
                     26: void multi_trigger (edict_t *ent)
                     27: {
                     28:        if (ent->nextthink)
                     29:                return;         // already been triggered
                     30: 
                     31:        G_UseTargets (ent, ent->activator);
                     32: 
                     33:        if (ent->wait > 0)      
                     34:        {
                     35:                ent->think = multi_wait;
                     36:                ent->nextthink = level.time + ent->wait;
                     37:        }
                     38:        else
                     39:        {       // we can't just remove (self) here, because this is a touch function
                     40:                // called while looping through area links...
                     41:                ent->touch = NULL;
                     42:                ent->nextthink = level.time + FRAMETIME;
                     43:                ent->think = G_FreeEdict;
                     44:        }
                     45: }
                     46: 
                     47: void Use_Multi (edict_t *ent, edict_t *other, edict_t *activator)
                     48: {
                     49:        ent->activator = activator;
                     50:        multi_trigger (ent);
                     51: }
                     52: 
                     53: void Touch_Multi (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
                     54: {
                     55:        if(other->client)
                     56:        {
                     57:                if (self->spawnflags & 2)
                     58:                        return;
                     59:        }
                     60:        else if (other->svflags & SVF_MONSTER)
                     61:        {
                     62:                if (!(self->spawnflags & 1))
                     63:                        return;
                     64:        }
                     65:        else
                     66:                return;
                     67: 
                     68:        if (!VectorCompare(self->movedir, vec3_origin))
                     69:        {
                     70:                vec3_t  forward;
                     71: 
                     72:                AngleVectors(other->s.angles, forward, NULL, NULL);
                     73:                if (_DotProduct(forward, self->movedir) < 0)
                     74:                        return;
                     75:        }
                     76: 
                     77:        self->activator = other;
                     78:        multi_trigger (self);
                     79: }
                     80: 
                     81: /*QUAKED trigger_multiple (.5 .5 .5) ? MONSTER NOT_PLAYER TRIGGERED
                     82: Variable sized repeatable trigger.  Must be targeted at one or more entities.
                     83: If "delay" is set, the trigger waits some time after activating before firing.
                     84: "wait" : Seconds between triggerings. (.2 default)
                     85: sounds
                     86: 1)     secret
                     87: 2)     beep beep
                     88: 3)     large switch
                     89: 4)
                     90: set "message" to text string
                     91: */
                     92: void trigger_enable (edict_t *self, edict_t *other, edict_t *activator)
                     93: {
                     94:        self->solid = SOLID_TRIGGER;
                     95:        self->use = Use_Multi;
                     96:        gi.linkentity (self);
                     97: }
                     98: 
                     99: void SP_trigger_multiple (edict_t *ent)
                    100: {
                    101:        if (ent->sounds == 1)
                    102:                ent->noise_index = gi.soundindex ("misc/secret.wav");
                    103:        else if (ent->sounds == 2)
                    104:                ent->noise_index = gi.soundindex ("misc/talk.wav");
                    105:        else if (ent->sounds == 3)
                    106:                ent->noise_index = gi.soundindex ("misc/trigger1.wav");
                    107:        
                    108:        if (!ent->wait)
                    109:                ent->wait = 0.2;
                    110:        ent->touch = Touch_Multi;
                    111:        ent->movetype = MOVETYPE_NONE;
                    112:        ent->svflags |= SVF_NOCLIENT;
                    113: 
                    114: 
                    115:        if (ent->spawnflags & 4)
                    116:        {
                    117:                ent->solid = SOLID_NOT;
                    118:                ent->use = trigger_enable;
                    119:        }
                    120:        else
                    121:        {
                    122:                ent->solid = SOLID_TRIGGER;
                    123:                ent->use = Use_Multi;
                    124:        }
                    125: 
                    126:        if (!VectorCompare(ent->s.angles, vec3_origin))
                    127:                G_SetMovedir (ent->s.angles, ent->movedir);
                    128: 
                    129:        gi.setmodel (ent, ent->model);
                    130:        gi.linkentity (ent);
                    131: }
                    132: 
                    133: 
                    134: /*QUAKED trigger_once (.5 .5 .5) ? x x TRIGGERED
                    135: Triggers once, then removes itself.
                    136: You must set the key "target" to the name of another object in the level that has a matching "targetname".
                    137: 
                    138: If TRIGGERED, this trigger must be triggered before it is live.
                    139: 
                    140: sounds
                    141:  1)    secret
                    142:  2)    beep beep
                    143:  3)    large switch
                    144:  4)
                    145: 
                    146: "message"      string to be displayed when triggered
                    147: */
                    148: 
                    149: void SP_trigger_once(edict_t *ent)
                    150: {
                    151:        // make old maps work because I messed up on flag assignments here
                    152:        // triggered was on bit 1 when it should have been on bit 4
                    153:        if (ent->spawnflags & 1)
                    154:        {
                    155:                vec3_t  v;
                    156: 
                    157:                VectorMA (ent->mins, 0.5, ent->size, v);
                    158:                ent->spawnflags &= ~1;
                    159:                ent->spawnflags |= 4;
                    160:                gi.dprintf("fixed TRIGGERED flag on %s at %s\n", ent->classname, vtos(v));
                    161:        }
                    162: 
                    163:        ent->wait = -1;
                    164:        SP_trigger_multiple (ent);
                    165: }
                    166: 
                    167: /*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
                    168: This fixed size trigger cannot be touched, it can only be fired by other events.
                    169: */
                    170: void trigger_relay_use (edict_t *self, edict_t *other, edict_t *activator)
                    171: {
                    172:        G_UseTargets (self, activator);
                    173: }
                    174: 
                    175: void SP_trigger_relay (edict_t *self)
                    176: {
                    177:        self->use = trigger_relay_use;
                    178: }
                    179: 
                    180: 
                    181: /*
                    182: ==============================================================================
                    183: 
                    184: trigger_key
                    185: 
                    186: ==============================================================================
                    187: */
                    188: 
                    189: /*QUAKED trigger_key (.5 .5 .5) (-8 -8 -8) (8 8 8)
                    190: A relay trigger that only fires it's targets if player has the proper key.
                    191: Use "item" to specify the required key, for example "key_data_cd"
                    192: */
                    193: void trigger_key_use (edict_t *self, edict_t *other, edict_t *activator)
                    194: {
                    195:        int                     index;
                    196: 
                    197:        if (!self->item)
                    198:                return;
                    199:        if (!activator->client)
                    200:                return;
                    201: 
                    202:        index = ITEM_INDEX(self->item);
                    203:        if (!activator->client->pers.inventory[index])
                    204:        {
                    205:                if (level.time < self->touch_debounce_time)
                    206:                        return;
                    207:                self->touch_debounce_time = level.time + 5.0;
                    208:                gi.centerprintf (activator, "You need the %s", self->item->pickup_name);
                    209:                gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/keytry.wav"), 1, ATTN_NORM, 0);
                    210:                return;
                    211:        }
                    212: 
                    213:        gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/keyuse.wav"), 1, ATTN_NORM, 0);
                    214:        if (coop->value)
                    215:        {
                    216:                int             player;
                    217:                edict_t *ent;
                    218: 
                    219:                if (strcmp(self->item->classname, "key_power_cube") == 0)
                    220:                {
                    221:                        int     cube;
                    222: 
                    223:                        for (cube = 0; cube < 8; cube++)
                    224:                                if (activator->client->pers.power_cubes & (1 << cube))
                    225:                                        break;
                    226:                        for (player = 1; player <= game.maxclients; player++)
                    227:                        {
                    228:                                ent = &g_edicts[player];
                    229:                                if (!ent->inuse)
                    230:                                        continue;
                    231:                                if (!ent->client)
                    232:                                        continue;
                    233:                                if (ent->client->pers.power_cubes & (1 << cube))
                    234:                                {
                    235:                                        ent->client->pers.inventory[index]--;
                    236:                                        ent->client->pers.power_cubes &= ~(1 << cube);
                    237:                                }
                    238:                        }
                    239:                }
                    240:                else
                    241:                {
                    242:                        for (player = 1; player <= game.maxclients; player++)
                    243:                        {
                    244:                                ent = &g_edicts[player];
                    245:                                if (!ent->inuse)
                    246:                                        continue;
                    247:                                if (!ent->client)
                    248:                                        continue;
                    249:                                ent->client->pers.inventory[index] = 0;
                    250:                        }
                    251:                }
                    252:        }
                    253:        else
                    254:        {
                    255:                activator->client->pers.inventory[index]--;
                    256:        }
                    257: 
                    258:        G_UseTargets (self, activator);
                    259: 
                    260:        self->use = NULL;
                    261: }
                    262: 
                    263: void SP_trigger_key (edict_t *self)
                    264: {
                    265:        if (!st.item)
                    266:        {
                    267:                gi.dprintf("no key item for trigger_key at %s\n", vtos(self->s.origin));
                    268:                return;
                    269:        }
                    270:        self->item = FindItemByClassname (st.item);
                    271: 
                    272:        if (!self->item)
                    273:        {
                    274:                gi.dprintf("item %s not found for trigger_key at %s\n", st.item, vtos(self->s.origin));
                    275:                return;
                    276:        }
                    277: 
                    278:        if (!self->target)
                    279:        {
                    280:                gi.dprintf("%s at %s has no target\n", self->classname, vtos(self->s.origin));
                    281:                return;
                    282:        }
                    283: 
                    284:        gi.soundindex ("misc/keytry.wav");
                    285:        gi.soundindex ("misc/keyuse.wav");
                    286: 
                    287:        self->use = trigger_key_use;
                    288: }
                    289: 
                    290: 
                    291: /*
                    292: ==============================================================================
                    293: 
                    294: trigger_counter
                    295: 
                    296: ==============================================================================
                    297: */
                    298: 
                    299: /*QUAKED trigger_counter (.5 .5 .5) ? nomessage
                    300: Acts as an intermediary for an action that takes multiple inputs.
                    301: 
                    302: If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
                    303: 
                    304: After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
                    305: */
                    306: 
                    307: void trigger_counter_use(edict_t *self, edict_t *other, edict_t *activator)
                    308: {
                    309:        if (self->count == 0)
                    310:                return;
                    311:        
                    312:        self->count--;
                    313: 
                    314:        if (self->count)
                    315:        {
                    316:                if (! (self->spawnflags & 1))
                    317:                {
                    318:                        gi.centerprintf(activator, "%i more to go...", self->count);
                    319:                        gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0);
                    320:                }
                    321:                return;
                    322:        }
                    323:        
                    324:        if (! (self->spawnflags & 1))
                    325:        {
                    326:                gi.centerprintf(activator, "Sequence completed!");
                    327:                gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0);
                    328:        }
                    329:        self->activator = activator;
                    330:        multi_trigger (self);
                    331: }
                    332: 
                    333: void SP_trigger_counter (edict_t *self)
                    334: {
                    335:        self->wait = -1;
                    336:        if (!self->count)
                    337:                self->count = 2;
                    338: 
                    339:        self->use = trigger_counter_use;
                    340: }
                    341: 
                    342: 
                    343: /*
                    344: ==============================================================================
                    345: 
                    346: trigger_always
                    347: 
                    348: ==============================================================================
                    349: */
                    350: 
                    351: /*QUAKED trigger_always (.5 .5 .5) (-8 -8 -8) (8 8 8)
                    352: This trigger will always fire.  It is activated by the world.
                    353: */
                    354: void SP_trigger_always (edict_t *ent)
                    355: {
                    356:        // we must have some delay to make sure our use targets are present
                    357:        if (ent->delay < 0.2)
                    358:                ent->delay = 0.2;
                    359:        G_UseTargets(ent, ent);
                    360: }
                    361: 
                    362: 
                    363: /*
                    364: ==============================================================================
                    365: 
                    366: trigger_push
                    367: 
                    368: ==============================================================================
                    369: */
                    370: #if 0
                    371: #define PUSH_ONCE              1
                    372: 
                    373: static int windsound;
                    374: 
                    375: void trigger_push_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
                    376: {
                    377:        if (strcmp(other->classname, "grenade") == 0)
                    378:        {
                    379:                VectorScale (self->movedir, self->speed * 10, other->velocity);
                    380:        }
                    381:        else if (other->health > 0)
                    382:        {
                    383:                VectorScale (self->movedir, self->speed * 10, other->velocity);
                    384: 
                    385:                if (other->client)
                    386:                {
                    387:                        // don't take falling damage immediately from this
                    388:                        VectorCopy (other->velocity, other->client->oldvelocity);
                    389:                        if (other->fly_sound_debounce_time < level.time)
                    390:                        {
                    391:                                other->fly_sound_debounce_time = level.time + 1.5;
                    392:                                gi.sound (other, CHAN_AUTO, windsound, 1, ATTN_NORM, 0);
                    393:                        }
                    394:                }
                    395:        }
                    396:        if (self->spawnflags & PUSH_ONCE)
                    397:                G_FreeEdict (self);
                    398: }
                    399: 
                    400: void SP_trigger_push (edict_t *self)
                    401: {
                    402:        InitTrigger (self);
                    403:        windsound = gi.soundindex ("misc/windfly.wav");
                    404:        self->touch = trigger_push_touch;
                    405:        if (!self->speed)
                    406:                self->speed = 1000;
                    407:        gi.linkentity (self);
                    408: }
                    409: #endif
                    410: 
                    411: // RAFAEL
                    412: #define PUSH_ONCE  1
                    413: 
                    414: static int windsound;
                    415: 
                    416: void trigger_push_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
                    417: {
                    418:        if (strcmp(other->classname, "grenade") == 0)
                    419:        {
                    420:                VectorScale (self->movedir, self->speed * 10, other->velocity);
                    421:        }
                    422:        else if (other->health > 0)
                    423:        {       
                    424:                VectorScale (self->movedir, self->speed * 10, other->velocity);
                    425: 
                    426:                if (other->client)
                    427:                {
                    428:                        // don't take falling damage immediately from this
                    429:                        VectorCopy (other->velocity, other->client->oldvelocity);
                    430:                        if (other->fly_sound_debounce_time < level.time)
                    431:                        {
                    432:                                other->fly_sound_debounce_time = level.time + 1.5;
                    433:                                gi.sound (other, CHAN_AUTO, windsound, 1, ATTN_NORM, 0);
                    434:                        }
                    435:                }
                    436:        }
                    437:        if (self->spawnflags & PUSH_ONCE)
                    438:        G_FreeEdict (self);
                    439: }
                    440: 
                    441: 
                    442: /*QUAKED trigger_push (.5 .5 .5) ? PUSH_ONCE PUSH_PLUS PUSH_RAMP
                    443: Pushes the player
                    444: "speed"  defaults to 1000
                    445: "wait"  defaults to 10 must use PUSH_PLUS  used for on
                    446: */
                    447: 
                    448: void trigger_push_active (edict_t *self);
                    449: 
                    450: void trigger_effect (edict_t *self)
                    451: {
                    452:        vec3_t  origin;
                    453:        vec3_t  size;
                    454:        int             i;
                    455:        
                    456:        VectorScale (self->size, 0.5, size);
                    457:        VectorAdd (self->absmin, size, origin);
                    458:        
                    459:        for (i=0; i<10; i++)
                    460:        {
                    461:                origin[2] += (self->speed * 0.01) * (i + random());
                    462:                gi.WriteByte (svc_temp_entity);
                    463:                gi.WriteByte (TE_TUNNEL_SPARKS);
                    464:                gi.WriteByte (1);
                    465:                gi.WritePosition (origin);
                    466:                gi.WriteDir (vec3_origin);
                    467:                gi.WriteByte (0x74 + (rand()&7));
                    468:                gi.multicast (self->s.origin, MULTICAST_PVS);
                    469:        }
                    470: 
                    471: }
                    472: 
                    473: void trigger_push_inactive (edict_t *self)
                    474: {
                    475:        if (self->delay > level.time)
                    476:        {
                    477:                self->nextthink = level.time + 0.1;
                    478:        }
                    479:        else
                    480:        {
                    481:                self->touch = trigger_push_touch;
                    482:                self->think = trigger_push_active;
                    483:                self->nextthink = level.time + 0.1;
                    484:                self->delay = self->nextthink + self->wait;  
                    485:        }
                    486: }
                    487: 
                    488: void trigger_push_active (edict_t *self)
                    489: {
                    490:        if (self->delay > level.time)
                    491:        {
                    492:                self->nextthink = level.time + 0.1;
                    493:                trigger_effect (self);
                    494:        }
                    495:        else
                    496:        {
                    497:                self->touch = NULL;
                    498:                self->think = trigger_push_inactive;
                    499:                self->nextthink = level.time + 0.1;
                    500:                self->delay = self->nextthink + self->wait;  
                    501:        }
                    502: }
                    503: 
                    504: void SP_trigger_push (edict_t *self)
                    505: {
                    506:        InitTrigger (self);
                    507:        windsound = gi.soundindex ("misc/windfly.wav");
                    508:        self->touch = trigger_push_touch;
                    509:        
                    510:        if (self->spawnflags & 2)
                    511:        {
                    512:                if (!self->wait)
                    513:                        self->wait = 10;
                    514:   
                    515:                self->think = trigger_push_active;
                    516:                self->nextthink = level.time + 0.1;
                    517:                self->delay = self->nextthink + self->wait;
                    518:        }
                    519: 
                    520:        if (!self->speed)
                    521:                self->speed = 1000;
                    522:        
                    523:        gi.linkentity (self);
                    524: 
                    525: }
                    526: 
                    527: /*
                    528: ==============================================================================
                    529: 
                    530: trigger_hurt
                    531: 
                    532: ==============================================================================
                    533: */
                    534: 
                    535: /*QUAKED trigger_hurt (.5 .5 .5) ? START_OFF TOGGLE SILENT NO_PROTECTION SLOW
                    536: Any entity that touches this will be hurt.
                    537: 
                    538: It does dmg points of damage each server frame
                    539: 
                    540: SILENT                 supresses playing the sound
                    541: SLOW                   changes the damage rate to once per second
                    542: NO_PROTECTION  *nothing* stops the damage
                    543: 
                    544: "dmg"                  default 5 (whole numbers only)
                    545: 
                    546: */
                    547: void hurt_use (edict_t *self, edict_t *other, edict_t *activator)
                    548: {
                    549:        if (self->solid == SOLID_NOT)
                    550:                self->solid = SOLID_TRIGGER;
                    551:        else
                    552:                self->solid = SOLID_NOT;
                    553:        gi.linkentity (self);
                    554: 
                    555:        if (!(self->spawnflags & 2))
                    556:                self->use = NULL;
                    557: }
                    558: 
                    559: 
                    560: void hurt_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
                    561: {
                    562:        int             dflags;
                    563: 
                    564:        if (!other->takedamage)
                    565:                return;
                    566: 
                    567:        if (self->timestamp > level.time)
                    568:                return;
                    569: 
                    570:        if (self->spawnflags & 16)
                    571:                self->timestamp = level.time + 1;
                    572:        else
                    573:                self->timestamp = level.time + FRAMETIME;
                    574: 
                    575:        if (!(self->spawnflags & 4))
                    576:        {
                    577:                if ((level.framenum % 10) == 0)
                    578:                        gi.sound (other, CHAN_AUTO, self->noise_index, 1, ATTN_NORM, 0);
                    579:        }
                    580: 
                    581:        if (self->spawnflags & 8)
                    582:                dflags = DAMAGE_NO_PROTECTION;
                    583:        else
                    584:                dflags = 0;
                    585:        T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, self->dmg, dflags, MOD_TRIGGER_HURT);
                    586: }
                    587: 
                    588: void SP_trigger_hurt (edict_t *self)
                    589: {
                    590:        InitTrigger (self);
                    591: 
                    592:        self->noise_index = gi.soundindex ("world/electro.wav");
                    593:        self->touch = hurt_touch;
                    594: 
                    595:        if (!self->dmg)
                    596:                self->dmg = 5;
                    597: 
                    598:        if (self->spawnflags & 1)
                    599:                self->solid = SOLID_NOT;
                    600:        else
                    601:                self->solid = SOLID_TRIGGER;
                    602: 
                    603:        if (self->spawnflags & 2)
                    604:                self->use = hurt_use;
                    605: 
                    606:        gi.linkentity (self);
                    607: }
                    608: 
                    609: 
                    610: /*
                    611: ==============================================================================
                    612: 
                    613: trigger_gravity
                    614: 
                    615: ==============================================================================
                    616: */
                    617: 
                    618: /*QUAKED trigger_gravity (.5 .5 .5) ?
                    619: Changes the touching entites gravity to
                    620: the value of "gravity".  1.0 is standard
                    621: gravity for the level.
                    622: */
                    623: 
                    624: void trigger_gravity_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
                    625: {
                    626:        other->gravity = self->gravity;
                    627: }
                    628: 
                    629: void SP_trigger_gravity (edict_t *self)
                    630: {
                    631:        if (st.gravity == 0)
                    632:        {
                    633:                gi.dprintf("trigger_gravity without gravity set at %s\n", vtos(self->s.origin));
                    634:                G_FreeEdict  (self);
                    635:                return;
                    636:        }
                    637: 
                    638:        InitTrigger (self);
                    639:        self->gravity = atoi(st.gravity);
                    640:        self->touch = trigger_gravity_touch;
                    641: }
                    642: 
                    643: 
                    644: /*
                    645: ==============================================================================
                    646: 
                    647: trigger_monsterjump
                    648: 
                    649: ==============================================================================
                    650: */
                    651: 
                    652: /*QUAKED trigger_monsterjump (.5 .5 .5) ?
                    653: Walking monsters that touch this will jump in the direction of the trigger's angle
                    654: "speed" default to 200, the speed thrown forward
                    655: "height" default to 200, the speed thrown upwards
                    656: */
                    657: 
                    658: void trigger_monsterjump_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
                    659: {
                    660:        if (other->flags & (FL_FLY | FL_SWIM) )
                    661:                return;
                    662:        if (other->svflags & SVF_DEADMONSTER)
                    663:                return;
                    664:        if ( !(other->svflags & SVF_MONSTER))
                    665:                return;
                    666: 
                    667: // set XY even if not on ground, so the jump will clear lips
                    668:        other->velocity[0] = self->movedir[0] * self->speed;
                    669:        other->velocity[1] = self->movedir[1] * self->speed;
                    670:        
                    671:        if (!other->groundentity)
                    672:                return;
                    673:        
                    674:        other->groundentity = NULL;
                    675:        other->velocity[2] = self->movedir[2];
                    676: }
                    677: 
                    678: void SP_trigger_monsterjump (edict_t *self)
                    679: {
                    680:        if (!self->speed)
                    681:                self->speed = 200;
                    682:        if (!st.height)
                    683:                st.height = 200;
                    684:        if (self->s.angles[YAW] == 0)
                    685:                self->s.angles[YAW] = 360;
                    686:        InitTrigger (self);
                    687:        self->touch = trigger_monsterjump_touch;
                    688:        self->movedir[2] = st.height;
                    689: }
                    690: 

unix.superglobalmegacorp.com

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