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

1.1       root        1: #include "g_local.h"
                      2: 
                      3: /*QUAKED target_temp_entity (1 0 0) (-8 -8 -8) (8 8 8)
                      4: Fire an origin based temp entity event to the clients.
                      5: "style"                type byte
                      6: */
                      7: void Use_Target_Tent (edict_t *ent, edict_t *other, edict_t *activator)
                      8: {
                      9:        gi.WriteByte (svc_temp_entity);
                     10:        gi.WriteByte (ent->style);
                     11:        gi.WritePosition (ent->s.origin);
                     12:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                     13: }
                     14: 
                     15: void SP_target_temp_entity (edict_t *ent)
                     16: {
                     17:        ent->use = Use_Target_Tent;
                     18: }
                     19: 
                     20: 
                     21: //==========================================================
                     22: 
                     23: //==========================================================
                     24: 
                     25: /*QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off reliable
                     26: "noise"                wav file to play
                     27: "attenuation"
                     28: -1 = none, send to whole level
                     29: 1 = normal fighting sounds
                     30: 2 = idle sound level
                     31: 3 = ambient sound level
                     32: "volume"       0.0 to 1.0
                     33: 
                     34: Normal sounds play each time the target is used.  The reliable flag can be set for crucial voiceovers.
                     35: 
                     36: Looped sounds are always atten 3 / vol 1, and the use function toggles it on/off.
                     37: Multiple identical looping sounds will just increase volume without any speed cost.
                     38: */
                     39: void Use_Target_Speaker (edict_t *ent, edict_t *other, edict_t *activator)
                     40: {
                     41:        int             chan;
                     42: 
                     43:        if (ent->spawnflags & 3)
                     44:        {       // looping sound toggles
                     45:                if (ent->s.sound)
                     46:                        ent->s.sound = 0;       // turn it off
                     47:                else
                     48:                        ent->s.sound = ent->noise_index;        // start it
                     49:        }
                     50:        else
                     51:        {       // normal sound
                     52:                if (ent->spawnflags & 4)
                     53:                        chan = CHAN_VOICE|CHAN_RELIABLE;
                     54:                else
                     55:                        chan = CHAN_VOICE;
                     56:                // use a positioned_sound, because this entity won't normally be
                     57:                // sent to any clients because it is invisible
                     58:                gi.positioned_sound (ent->s.origin, ent, chan, ent->noise_index, ent->volume, ent->attenuation, 0);
                     59:        }
                     60: }
                     61: 
                     62: void SP_target_speaker (edict_t *ent)
                     63: {
                     64:        char    buffer[MAX_QPATH];
                     65: 
                     66:        if(!st.noise)
                     67:        {
                     68:                gi.dprintf("target_speaker with no noise set at %s\n", vtos(ent->s.origin));
                     69:                return;
                     70:        }
                     71:        if (!strstr (st.noise, ".wav"))
                     72:                Com_sprintf (buffer, sizeof(buffer), "%s.wav", st.noise);
                     73:        else
                     74:                strncpy (buffer, st.noise, sizeof(buffer));
                     75:        ent->noise_index = gi.soundindex (buffer);
                     76: 
                     77:        if (!ent->volume)
                     78:                ent->volume = 1.0;
                     79: 
                     80:        if (!ent->attenuation)
                     81:                ent->attenuation = 1.0;
                     82:        else if (ent->attenuation == -1)        // use -1 so 0 defaults to 1
                     83:                ent->attenuation = 0;
                     84: 
                     85:        // check for prestarted looping sound
                     86:        if (ent->spawnflags & 1)
                     87:                ent->s.sound = ent->noise_index;
                     88: 
                     89:        ent->use = Use_Target_Speaker;
                     90: 
                     91:        // must link the entity so we get areas and clusters so
                     92:        // the server can determine who to send updates to
                     93:        gi.linkentity (ent);
                     94: }
                     95: 
                     96: 
                     97: //==========================================================
                     98: 
                     99: void Use_Target_Help (edict_t *ent, edict_t *other, edict_t *activator)
                    100: {
                    101:        if (ent->spawnflags & 1)
                    102:                strncpy (game.helpmessage1, ent->message, sizeof(game.helpmessage2)-1);
                    103:        else
                    104:                strncpy (game.helpmessage2, ent->message, sizeof(game.helpmessage1)-1);
                    105: 
                    106:        game.helpchanged++;
                    107: }
                    108: 
                    109: /*QUAKED target_help (1 0 1) (-16 -16 -24) (16 16 24) help1
                    110: When fired, the "message" key becomes the current personal computer string, and the message light will be set on all clients status bars.
                    111: */
                    112: void SP_target_help(edict_t *ent)
                    113: {
                    114:        if (deathmatch->value)
                    115:        {       // auto-remove for deathmatch
                    116:                G_FreeEdict (ent);
                    117:                return;
                    118:        }
                    119: 
                    120:        if (!ent->message)
                    121:        {
                    122:                gi.dprintf ("%s with no message at %s\n", ent->classname, vtos(ent->s.origin));
                    123:                G_FreeEdict (ent);
                    124:                return;
                    125:        }
                    126:        ent->use = Use_Target_Help;
                    127: }
                    128: 
                    129: //==========================================================
                    130: 
                    131: /*QUAKED target_secret (1 0 1) (-8 -8 -8) (8 8 8)
                    132: Counts a secret found.
                    133: These are single use targets.
                    134: */
                    135: void use_target_secret (edict_t *ent, edict_t *other, edict_t *activator)
                    136: {
                    137:        gi.sound (ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0);
                    138: 
                    139:        level.found_secrets++;
                    140: 
                    141:        G_UseTargets (ent, activator);
                    142:        G_FreeEdict (ent);
                    143: }
                    144: 
                    145: void SP_target_secret (edict_t *ent)
                    146: {
                    147:        if (deathmatch->value)
                    148:        {       // auto-remove for deathmatch
                    149:                G_FreeEdict (ent);
                    150:                return;
                    151:        }
                    152: 
                    153:        ent->use = use_target_secret;
                    154:        if (!st.noise)
                    155:                st.noise = "misc/secret.wav";
                    156:        ent->noise_index = gi.soundindex (st.noise);
                    157:        ent->svflags = SVF_NOCLIENT;
                    158:        level.total_secrets++;
                    159:        // map bug hack
                    160:        if (!Q_stricmp(level.mapname, "mine3") && ent->s.origin[0] == 280 && ent->s.origin[1] == -2048 && ent->s.origin[2] == -624)
                    161:                ent->message = "You have found a secret area.";
                    162: }
                    163: 
                    164: //==========================================================
                    165: 
                    166: /*QUAKED target_goal (1 0 1) (-8 -8 -8) (8 8 8)
                    167: Counts a goal completed.
                    168: These are single use targets.
                    169: */
                    170: void use_target_goal (edict_t *ent, edict_t *other, edict_t *activator)
                    171: {
                    172:        gi.sound (ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0);
                    173: 
                    174:        level.found_goals++;
                    175: 
                    176:        if (level.found_goals == level.total_goals)
                    177:                gi.configstring (CS_CDTRACK, "0");
                    178: 
                    179:        G_UseTargets (ent, activator);
                    180:        G_FreeEdict (ent);
                    181: }
                    182: 
                    183: void SP_target_goal (edict_t *ent)
                    184: {
                    185:        if (deathmatch->value)
                    186:        {       // auto-remove for deathmatch
                    187:                G_FreeEdict (ent);
                    188:                return;
                    189:        }
                    190: 
                    191:        ent->use = use_target_goal;
                    192:        if (!st.noise)
                    193:                st.noise = "misc/secret.wav";
                    194:        ent->noise_index = gi.soundindex (st.noise);
                    195:        ent->svflags = SVF_NOCLIENT;
                    196:        level.total_goals++;
                    197: }
                    198: 
                    199: //==========================================================
                    200: 
                    201: 
                    202: /*QUAKED target_explosion (1 0 0) (-8 -8 -8) (8 8 8)
                    203: Spawns an explosion temporary entity when used.
                    204: 
                    205: "delay"                wait this long before going off
                    206: "dmg"          how much radius damage should be done, defaults to 0
                    207: */
                    208: void target_explosion_explode (edict_t *self)
                    209: {
                    210:        float           save;
                    211: 
                    212:        gi.WriteByte (svc_temp_entity);
                    213:        gi.WriteByte (TE_EXPLOSION1);
                    214:        gi.WritePosition (self->s.origin);
                    215:        gi.multicast (self->s.origin, MULTICAST_PHS);
                    216: 
                    217:        T_RadiusDamage (self, self->activator, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE);
                    218: 
                    219:        save = self->delay;
                    220:        self->delay = 0;
                    221:        G_UseTargets (self, self->activator);
                    222:        self->delay = save;
                    223: }
                    224: 
                    225: void use_target_explosion (edict_t *self, edict_t *other, edict_t *activator)
                    226: {
                    227:        self->activator = activator;
                    228: 
                    229:        if (!self->delay)
                    230:        {
                    231:                target_explosion_explode (self);
                    232:                return;
                    233:        }
                    234: 
                    235:        self->think = target_explosion_explode;
                    236:        self->nextthink = level.time + self->delay;
                    237: }
                    238: 
                    239: void SP_target_explosion (edict_t *ent)
                    240: {
                    241:        ent->use = use_target_explosion;
                    242:        ent->svflags = SVF_NOCLIENT;
                    243: }
                    244: 
                    245: 
                    246: //==========================================================
                    247: 
                    248: /*QUAKED target_changelevel (1 0 0) (-8 -8 -8) (8 8 8)
                    249: Changes level to "map" when fired
                    250: */
                    251: void use_target_changelevel (edict_t *self, edict_t *other, edict_t *activator)
                    252: {
                    253:        if (level.intermissiontime)
                    254:                return;         // already activated
                    255: 
                    256:        if (!deathmatch->value && !coop->value)
                    257:        {
                    258:                if (g_edicts[1].health <= 0)
                    259:                        return;
                    260:        }
                    261: 
                    262:        // if noexit, do a ton of damage to other
                    263:        if (deathmatch->value && !( (int)dmflags->value & DF_ALLOW_EXIT) && other != world)
                    264:        {
                    265:                T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 10 * other->max_health, 1000, 0, MOD_EXIT);
                    266:                return;
                    267:        }
                    268: 
                    269:        // if multiplayer, let everyone know who hit the exit
                    270:        if (deathmatch->value)
                    271:        {
                    272:                if (activator && activator->client)
                    273:                        gi.bprintf (PRINT_HIGH, "%s exited the level.\n", activator->client->pers.netname);
                    274:        }
                    275: 
                    276:        // if going to a new unit, clear cross triggers
                    277:        if (strstr(self->map, "*"))     
                    278:                game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK);
                    279: 
                    280:        BeginIntermission (self);
                    281: }
                    282: 
                    283: void SP_target_changelevel (edict_t *ent)
                    284: {
                    285:        if (!ent->map)
                    286:        {
                    287:                gi.dprintf("target_changelevel with no map at %s\n", vtos(ent->s.origin));
                    288:                G_FreeEdict (ent);
                    289:                return;
                    290:        }
                    291: 
                    292:        // ugly hack because *SOMEBODY* screwed up their map
                    293:    if((Q_stricmp(level.mapname, "fact1") == 0) && (Q_stricmp(ent->map, "fact3") == 0))
                    294:           ent->map = "fact3$secret1";
                    295: 
                    296:        ent->use = use_target_changelevel;
                    297:        ent->svflags = SVF_NOCLIENT;
                    298: }
                    299: 
                    300: 
                    301: //==========================================================
                    302: 
                    303: /*QUAKED target_splash (1 0 0) (-8 -8 -8) (8 8 8)
                    304: Creates a particle splash effect when used.
                    305: 
                    306: Set "sounds" to one of the following:
                    307:   1) sparks
                    308:   2) blue water
                    309:   3) brown water
                    310:   4) slime
                    311:   5) lava
                    312:   6) blood
                    313: 
                    314: "count"        how many pixels in the splash
                    315: "dmg"  if set, does a radius damage at this location when it splashes
                    316:                useful for lava/sparks
                    317: */
                    318: 
                    319: void use_target_splash (edict_t *self, edict_t *other, edict_t *activator)
                    320: {
                    321:        gi.WriteByte (svc_temp_entity);
                    322:        gi.WriteByte (TE_SPLASH);
                    323:        gi.WriteByte (self->count);
                    324:        gi.WritePosition (self->s.origin);
                    325:        gi.WriteDir (self->movedir);
                    326:        gi.WriteByte (self->sounds);
                    327:        gi.multicast (self->s.origin, MULTICAST_PVS);
                    328: 
                    329:        if (self->dmg)
                    330:                T_RadiusDamage (self, activator, self->dmg, NULL, self->dmg+40, MOD_SPLASH);
                    331: }
                    332: 
                    333: void SP_target_splash (edict_t *self)
                    334: {
                    335:        self->use = use_target_splash;
                    336:        G_SetMovedir (self->s.angles, self->movedir);
                    337: 
                    338:        if (!self->count)
                    339:                self->count = 32;
                    340: 
                    341:        self->svflags = SVF_NOCLIENT;
                    342: }
                    343: 
                    344: 
                    345: //==========================================================
                    346: 
                    347: /*QUAKED target_spawner (1 0 0) (-8 -8 -8) (8 8 8)
                    348: Set target to the type of entity you want spawned.
                    349: Useful for spawning monsters and gibs in the factory levels.
                    350: 
                    351: For monsters:
                    352:        Set direction to the facing you want it to have.
                    353: 
                    354: For gibs:
                    355:        Set direction if you want it moving and
                    356:        speed how fast it should be moving otherwise it
                    357:        will just be dropped
                    358: */
                    359: void ED_CallSpawn (edict_t *ent);
                    360: 
                    361: void use_target_spawner (edict_t *self, edict_t *other, edict_t *activator)
                    362: {
                    363:        edict_t *ent;
                    364: 
                    365:        ent = G_Spawn();
                    366:        ent->classname = self->target;
                    367:        VectorCopy (self->s.origin, ent->s.origin);
                    368:        VectorCopy (self->s.angles, ent->s.angles);
                    369:        ED_CallSpawn (ent);
                    370:        gi.unlinkentity (ent);
                    371:        KillBox (ent);
                    372:        gi.linkentity (ent);
                    373:        if (self->speed)
                    374:                VectorCopy (self->movedir, ent->velocity);
                    375: }
                    376: 
                    377: void SP_target_spawner (edict_t *self)
                    378: {
                    379:        self->use = use_target_spawner;
                    380:        self->svflags = SVF_NOCLIENT;
                    381:        if (self->speed)
                    382:        {
                    383:                G_SetMovedir (self->s.angles, self->movedir);
                    384:                VectorScale (self->movedir, self->speed, self->movedir);
                    385:        }
                    386: }
                    387: 
                    388: //==========================================================
                    389: 
                    390: /*QUAKED target_blaster (1 0 0) (-8 -8 -8) (8 8 8) NOTRAIL NOEFFECTS
                    391: Fires a blaster bolt in the set direction when triggered.
                    392: 
                    393: dmg            default is 15
                    394: speed  default is 1000
                    395: */
                    396: 
                    397: void use_target_blaster (edict_t *self, edict_t *other, edict_t *activator)
                    398: {
                    399:        int effect;
                    400: 
                    401:        if (self->spawnflags & 2)
                    402:                effect = 0;
                    403:        else if (self->spawnflags & 1)
                    404:                effect = EF_HYPERBLASTER;
                    405:        else
                    406:                effect = EF_BLASTER;
                    407: 
                    408:        fire_blaster (self, self->s.origin, self->movedir, self->dmg, self->speed, EF_BLASTER, MOD_TARGET_BLASTER);
                    409:        gi.sound (self, CHAN_VOICE, self->noise_index, 1, ATTN_NORM, 0);
                    410: }
                    411: 
                    412: void SP_target_blaster (edict_t *self)
                    413: {
                    414:        self->use = use_target_blaster;
                    415:        G_SetMovedir (self->s.angles, self->movedir);
                    416:        self->noise_index = gi.soundindex ("weapons/laser2.wav");
                    417: 
                    418:        if (!self->dmg)
                    419:                self->dmg = 15;
                    420:        if (!self->speed)
                    421:                self->speed = 1000;
                    422: 
                    423:        self->svflags = SVF_NOCLIENT;
                    424: }
                    425: 
                    426: 
                    427: //==========================================================
                    428: 
                    429: /*QUAKED target_crosslevel_trigger (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8
                    430: Once this trigger is touched/used, any trigger_crosslevel_target with the same trigger number is automatically used when a level is started within the same unit.  It is OK to check multiple triggers.  Message, delay, target, and killtarget also work.
                    431: */
                    432: void trigger_crosslevel_trigger_use (edict_t *self, edict_t *other, edict_t *activator)
                    433: {
                    434:        game.serverflags |= self->spawnflags;
                    435:        G_FreeEdict (self);
                    436: }
                    437: 
                    438: void SP_target_crosslevel_trigger (edict_t *self)
                    439: {
                    440:        self->svflags = SVF_NOCLIENT;
                    441:        self->use = trigger_crosslevel_trigger_use;
                    442: }
                    443: 
                    444: /*QUAKED target_crosslevel_target (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8
                    445: Triggered by a trigger_crosslevel elsewhere within a unit.  If multiple triggers are checked, all must be true.  Delay, target and
                    446: killtarget also work.
                    447: 
                    448: "delay"                delay before using targets if the trigger has been activated (default 1)
                    449: */
                    450: void target_crosslevel_target_think (edict_t *self)
                    451: {
                    452:        if (self->spawnflags == (game.serverflags & SFL_CROSS_TRIGGER_MASK & self->spawnflags))
                    453:        {
                    454:                G_UseTargets (self, self);
                    455:                G_FreeEdict (self);
                    456:        }
                    457: }
                    458: 
                    459: void SP_target_crosslevel_target (edict_t *self)
                    460: {
                    461:        if (! self->delay)
                    462:                self->delay = 1;
                    463:        self->svflags = SVF_NOCLIENT;
                    464: 
                    465:        self->think = target_crosslevel_target_think;
                    466:        self->nextthink = level.time + self->delay;
                    467: }
                    468: 
                    469: //==========================================================
                    470: 
                    471: /*QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON RED GREEN BLUE YELLOW ORANGE FAT WINDOWSTOP
                    472: When triggered, fires a laser.  You can either set a target
                    473: or a direction.
                    474: 
                    475: WINDOWSTOP - stops at CONTENTS_WINDOW
                    476: */
                    477: 
                    478: //======
                    479: // PGM
                    480: #define LASER_ON                       0x0001
                    481: #define LASER_RED                      0x0002
                    482: #define LASER_GREEN                    0x0004
                    483: #define LASER_BLUE                     0x0008
                    484: #define LASER_YELLOW           0x0010
                    485: #define LASER_ORANGE           0x0020
                    486: #define LASER_FAT                      0x0040
                    487: #define LASER_STOPWINDOW       0x0080
                    488: // PGM
                    489: //======
                    490: 
                    491: void target_laser_think (edict_t *self)
                    492: {
                    493:        edict_t *ignore;
                    494:        vec3_t  start;
                    495:        vec3_t  end;
                    496:        trace_t tr;
                    497:        vec3_t  point;
                    498:        vec3_t  last_movedir;
                    499:        int             count;
                    500: 
                    501:        if (self->spawnflags & 0x80000000)
                    502:                count = 8;
                    503:        else
                    504:                count = 4;
                    505: 
                    506:        if (self->enemy)
                    507:        {
                    508:                VectorCopy (self->movedir, last_movedir);
                    509:                VectorMA (self->enemy->absmin, 0.5, self->enemy->size, point);
                    510:                VectorSubtract (point, self->s.origin, self->movedir);
                    511:                VectorNormalize (self->movedir);
                    512:                if (!VectorCompare(self->movedir, last_movedir))
                    513:                        self->spawnflags |= 0x80000000;
                    514:        }
                    515: 
                    516:        ignore = self;
                    517:        VectorCopy (self->s.origin, start);
                    518:        VectorMA (start, 2048, self->movedir, end);
                    519:        while(1)
                    520:        {
                    521: //======
                    522: // PGM
                    523:                if(self->spawnflags & LASER_STOPWINDOW)
                    524:                        tr = gi.trace (start, NULL, NULL, end, ignore, MASK_SHOT);
                    525:                else
                    526:                        tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);
                    527: // PGM
                    528: //======
                    529: 
                    530:                if (!tr.ent)
                    531:                        break;
                    532: 
                    533:                // hurt it if we can
                    534:                if ((tr.ent->takedamage) && !(tr.ent->flags & FL_IMMUNE_LASER))
                    535:                        T_Damage (tr.ent, self, self->activator, self->movedir, tr.endpos, vec3_origin, self->dmg, 1, DAMAGE_ENERGY, MOD_TARGET_LASER);
                    536: 
                    537:                // if we hit something that's not a monster or player or is immune to lasers, we're done
                    538: //             if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client))
                    539:                //PMM added SVF_DAMAGEABLE
                    540:                if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client) && !(tr.ent->svflags & SVF_DAMAGEABLE))
                    541:                {
                    542:                        if (self->spawnflags & 0x80000000)
                    543:                        {
                    544:                                self->spawnflags &= ~0x80000000;
                    545:                                gi.WriteByte (svc_temp_entity);
                    546:                                gi.WriteByte (TE_LASER_SPARKS);
                    547:                                gi.WriteByte (count);
                    548:                                gi.WritePosition (tr.endpos);
                    549:                                gi.WriteDir (tr.plane.normal);
                    550:                                gi.WriteByte (self->s.skinnum);
                    551:                                gi.multicast (tr.endpos, MULTICAST_PVS);
                    552:                        }
                    553:                        break;
                    554:                }
                    555: 
                    556:                ignore = tr.ent;
                    557:                VectorCopy (tr.endpos, start);
                    558:        }
                    559: 
                    560:        VectorCopy (tr.endpos, self->s.old_origin);
                    561: 
                    562:        self->nextthink = level.time + FRAMETIME;
                    563: }
                    564: 
                    565: void target_laser_on (edict_t *self)
                    566: {
                    567:        if (!self->activator)
                    568:                self->activator = self;
                    569:        self->spawnflags |= 0x80000001;
                    570:        self->svflags &= ~SVF_NOCLIENT;
                    571:        target_laser_think (self);
                    572: }
                    573: 
                    574: void target_laser_off (edict_t *self)
                    575: {
                    576:        self->spawnflags &= ~1;
                    577:        self->svflags |= SVF_NOCLIENT;
                    578:        self->nextthink = 0;
                    579: }
                    580: 
                    581: void target_laser_use (edict_t *self, edict_t *other, edict_t *activator)
                    582: {
                    583:        self->activator = activator;
                    584:        if (self->spawnflags & 1)
                    585:                target_laser_off (self);
                    586:        else
                    587:                target_laser_on (self);
                    588: }
                    589: 
                    590: void target_laser_start (edict_t *self)
                    591: {
                    592:        edict_t *ent;
                    593: 
                    594:        self->movetype = MOVETYPE_NONE;
                    595:        self->solid = SOLID_NOT;
                    596:        self->s.renderfx |= RF_BEAM|RF_TRANSLUCENT;
                    597:        self->s.modelindex = 1;                 // must be non-zero
                    598: 
                    599:        // set the beam diameter
                    600:        if (self->spawnflags & 64)
                    601:                self->s.frame = 16;
                    602:        else
                    603:                self->s.frame = 4;
                    604: 
                    605:        // set the color
                    606:        if (self->spawnflags & 2)
                    607:                self->s.skinnum = 0xf2f2f0f0;
                    608:        else if (self->spawnflags & 4)
                    609:                self->s.skinnum = 0xd0d1d2d3;
                    610:        else if (self->spawnflags & 8)
                    611:                self->s.skinnum = 0xf3f3f1f1;
                    612:        else if (self->spawnflags & 16)
                    613:                self->s.skinnum = 0xdcdddedf;
                    614:        else if (self->spawnflags & 32)
                    615:                self->s.skinnum = 0xe0e1e2e3;
                    616: 
                    617:        if (!self->enemy)
                    618:        {
                    619:                if (self->target)
                    620:                {
                    621:                        ent = G_Find (NULL, FOFS(targetname), self->target);
                    622:                        if (!ent)
                    623:                                gi.dprintf ("%s at %s: %s is a bad target\n", self->classname, vtos(self->s.origin), self->target);
                    624:                        self->enemy = ent;
                    625:                }
                    626:                else
                    627:                {
                    628:                        G_SetMovedir (self->s.angles, self->movedir);
                    629:                }
                    630:        }
                    631:        self->use = target_laser_use;
                    632:        self->think = target_laser_think;
                    633: 
                    634:        if (!self->dmg)
                    635:                self->dmg = 1;
                    636: 
                    637:        VectorSet (self->mins, -8, -8, -8);
                    638:        VectorSet (self->maxs, 8, 8, 8);
                    639:        gi.linkentity (self);
                    640: 
                    641:        if (self->spawnflags & 1)
                    642:                target_laser_on (self);
                    643:        else
                    644:                target_laser_off (self);
                    645: }
                    646: 
                    647: void SP_target_laser (edict_t *self)
                    648: {
                    649:        // let everything else get spawned before we start firing
                    650:        self->think = target_laser_start;
                    651:        self->nextthink = level.time + 1;
                    652: }
                    653: 
                    654: //==========================================================
                    655: 
                    656: /*QUAKED target_lightramp (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE
                    657: speed          How many seconds the ramping will take
                    658: message                two letters; starting lightlevel and ending lightlevel
                    659: */
                    660: 
                    661: void target_lightramp_think (edict_t *self)
                    662: {
                    663:        char    style[2];
                    664: 
                    665:        style[0] = 'a' + self->movedir[0] + (level.time - self->timestamp) / FRAMETIME * self->movedir[2];
                    666:        style[1] = 0;
                    667:        gi.configstring (CS_LIGHTS+self->enemy->style, style);
                    668: 
                    669:        if ((level.time - self->timestamp) < self->speed)
                    670:        {
                    671:                self->nextthink = level.time + FRAMETIME;
                    672:        }
                    673:        else if (self->spawnflags & 1)
                    674:        {
                    675:                char    temp;
                    676: 
                    677:                temp = self->movedir[0];
                    678:                self->movedir[0] = self->movedir[1];
                    679:                self->movedir[1] = temp;
                    680:                self->movedir[2] *= -1;
                    681:        }
                    682: }
                    683: 
                    684: void target_lightramp_use (edict_t *self, edict_t *other, edict_t *activator)
                    685: {
                    686:        if (!self->enemy)
                    687:        {
                    688:                edict_t         *e;
                    689: 
                    690:                // check all the targets
                    691:                e = NULL;
                    692:                while (1)
                    693:                {
                    694:                        e = G_Find (e, FOFS(targetname), self->target);
                    695:                        if (!e)
                    696:                                break;
                    697:                        if (strcmp(e->classname, "light") != 0)
                    698:                        {
                    699:                                gi.dprintf("%s at %s ", self->classname, vtos(self->s.origin));
                    700:                                gi.dprintf("target %s (%s at %s) is not a light\n", self->target, e->classname, vtos(e->s.origin));
                    701:                        }
                    702:                        else
                    703:                        {
                    704:                                self->enemy = e;
                    705:                        }
                    706:                }
                    707: 
                    708:                if (!self->enemy)
                    709:                {
                    710:                        gi.dprintf("%s target %s not found at %s\n", self->classname, self->target, vtos(self->s.origin));
                    711:                        G_FreeEdict (self);
                    712:                        return;
                    713:                }
                    714:        }
                    715: 
                    716:        self->timestamp = level.time;
                    717:        target_lightramp_think (self);
                    718: }
                    719: 
                    720: void SP_target_lightramp (edict_t *self)
                    721: {
                    722:        if (!self->message || strlen(self->message) != 2 || self->message[0] < 'a' || self->message[0] > 'z' || self->message[1] < 'a' || self->message[1] > 'z' || self->message[0] == self->message[1])
                    723:        {
                    724:                gi.dprintf("target_lightramp has bad ramp (%s) at %s\n", self->message, vtos(self->s.origin));
                    725:                G_FreeEdict (self);
                    726:                return;
                    727:        }
                    728: 
                    729:        if (deathmatch->value)
                    730:        {
                    731:                G_FreeEdict (self);
                    732:                return;
                    733:        }
                    734: 
                    735:        if (!self->target)
                    736:        {
                    737:                gi.dprintf("%s with no target at %s\n", self->classname, vtos(self->s.origin));
                    738:                G_FreeEdict (self);
                    739:                return;
                    740:        }
                    741: 
                    742:        self->svflags |= SVF_NOCLIENT;
                    743:        self->use = target_lightramp_use;
                    744:        self->think = target_lightramp_think;
                    745: 
                    746:        self->movedir[0] = self->message[0] - 'a';
                    747:        self->movedir[1] = self->message[1] - 'a';
                    748:        self->movedir[2] = (self->movedir[1] - self->movedir[0]) / (self->speed / FRAMETIME);
                    749: }
                    750: 
                    751: //==========================================================
                    752: 
                    753: /*QUAKED target_earthquake (1 0 0) (-8 -8 -8) (8 8 8) SILENT
                    754: When triggered, this initiates a level-wide earthquake.
                    755: All players and monsters are affected.
                    756: "speed"                severity of the quake (default:200)
                    757: "count"                duration of the quake (default:5)
                    758: */
                    759: 
                    760: void target_earthquake_think (edict_t *self)
                    761: {
                    762:        int             i;
                    763:        edict_t *e;
                    764: 
                    765:        if(!(self->spawnflags & 1))                                     // PGM
                    766:        {                                                                                       // PGM
                    767:                if (self->last_move_time < level.time)
                    768:                {
                    769:                        gi.positioned_sound (self->s.origin, self, CHAN_AUTO, self->noise_index, 1.0, ATTN_NONE, 0);
                    770:                        self->last_move_time = level.time + 0.5;
                    771:                }
                    772:        }                                                                                       // PGM
                    773: 
                    774:        for (i=1, e=g_edicts+i; i < globals.num_edicts; i++,e++)
                    775:        {
                    776:                if (!e->inuse)
                    777:                        continue;
                    778:                if (!e->client)
                    779:                        continue;
                    780:                if (!e->groundentity)
                    781:                        continue;
                    782: 
                    783:                e->groundentity = NULL;
                    784:                e->velocity[0] += crandom()* 150;
                    785:                e->velocity[1] += crandom()* 150;
                    786:                e->velocity[2] = self->speed * (100.0 / e->mass);
                    787:        }
                    788: 
                    789:        if (level.time < self->timestamp)
                    790:                self->nextthink = level.time + FRAMETIME;
                    791: }
                    792: 
                    793: void target_earthquake_use (edict_t *self, edict_t *other, edict_t *activator)
                    794: {
                    795:        // PGM
                    796:        if(g_showlogic && g_showlogic->value)
                    797:                gi.dprintf("earthquake: %0.1f\n", self->speed);
                    798:        // PGM
                    799: 
                    800:        self->timestamp = level.time + self->count;
                    801:        self->nextthink = level.time + FRAMETIME;
                    802:        self->activator = activator;
                    803:        self->last_move_time = 0;
                    804: }
                    805: 
                    806: void SP_target_earthquake (edict_t *self)
                    807: {
                    808:        if (!self->targetname)
                    809:                gi.dprintf("untargeted %s at %s\n", self->classname, vtos(self->s.origin));
                    810: 
                    811:        if (!self->count)
                    812:                self->count = 5;
                    813: 
                    814:        if (!self->speed)
                    815:                self->speed = 200;
                    816: 
                    817:        self->svflags |= SVF_NOCLIENT;
                    818:        self->think = target_earthquake_think;
                    819:        self->use = target_earthquake_use;
                    820: 
                    821:        if(!(self->spawnflags & 1))                                                                     // PGM
                    822:                self->noise_index = gi.soundindex ("world/quake.wav");
                    823: }

unix.superglobalmegacorp.com

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