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

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

unix.superglobalmegacorp.com

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