Annotation of quake2/xatrix/g_trigger.c, revision 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.