Annotation of quake2/xatrix/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 (!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((stricmp(level.mapname, "fact1") == 0) && (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) 1 2 3 4 5 6
                    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:        ent->flags = self->flags;
                    368:        VectorCopy (self->s.origin, ent->s.origin);
                    369:        VectorCopy (self->s.angles, ent->s.angles);
                    370:        ED_CallSpawn (ent);
                    371:        gi.unlinkentity (ent);
                    372:        KillBox (ent);
                    373:        gi.linkentity (ent);
                    374:        if (self->speed)
                    375:                VectorCopy (self->movedir, ent->velocity);
                    376: }
                    377: 
                    378: void SP_target_spawner (edict_t *self)
                    379: {
                    380:        self->use = use_target_spawner;
                    381:        self->svflags = SVF_NOCLIENT;
                    382:        if (self->speed)
                    383:        {
                    384:                G_SetMovedir (self->s.angles, self->movedir);
                    385:                VectorScale (self->movedir, self->speed, self->movedir);
                    386:        }
                    387: }
                    388: 
                    389: //==========================================================
                    390: 
                    391: /*QUAKED target_blaster (1 0 0) (-8 -8 -8) (8 8 8) NOTRAIL NOEFFECTS
                    392: Fires a blaster bolt in the set direction when triggered.
                    393: 
                    394: dmg            default is 15
                    395: speed  default is 1000
                    396: */
                    397: 
                    398: void use_target_blaster (edict_t *self, edict_t *other, edict_t *activator)
                    399: {
                    400:        int effect;
                    401: 
                    402:        if (self->spawnflags & 2)
                    403:                effect = 0;
                    404:        else if (self->spawnflags & 1)
                    405:                effect = EF_HYPERBLASTER;
                    406:        else
                    407:                effect = EF_BLASTER;
                    408: 
                    409:        fire_blaster (self, self->s.origin, self->movedir, self->dmg, self->speed, EF_BLASTER, MOD_TARGET_BLASTER);
                    410:        gi.sound (self, CHAN_VOICE, self->noise_index, 1, ATTN_NORM, 0);
                    411: }
                    412: 
                    413: void SP_target_blaster (edict_t *self)
                    414: {
                    415:        self->use = use_target_blaster;
                    416:        G_SetMovedir (self->s.angles, self->movedir);
                    417:        self->noise_index = gi.soundindex ("weapons/laser2.wav");
                    418: 
                    419:        if (!self->dmg)
                    420:                self->dmg = 15;
                    421:        if (!self->speed)
                    422:                self->speed = 1000;
                    423: 
                    424:        self->svflags = SVF_NOCLIENT;
                    425: }
                    426: 
                    427: 
                    428: //==========================================================
                    429: 
                    430: /*QUAKED target_crosslevel_trigger (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8
                    431: 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.
                    432: */
                    433: void trigger_crosslevel_trigger_use (edict_t *self, edict_t *other, edict_t *activator)
                    434: {
                    435:        game.serverflags |= self->spawnflags;
                    436:        G_FreeEdict (self);
                    437: }
                    438: 
                    439: void SP_target_crosslevel_trigger (edict_t *self)
                    440: {
                    441:        self->svflags = SVF_NOCLIENT;
                    442:        self->use = trigger_crosslevel_trigger_use;
                    443: }
                    444: 
                    445: /*QUAKED target_crosslevel_target (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8
                    446: Triggered by a trigger_crosslevel elsewhere within a unit.  If multiple triggers are checked, all must be true.  Delay, target and
                    447: killtarget also work.
                    448: 
                    449: "delay"                delay before using targets if the trigger has been activated (default 1)
                    450: */
                    451: void target_crosslevel_target_think (edict_t *self)
                    452: {
                    453:        if (self->spawnflags == (game.serverflags & SFL_CROSS_TRIGGER_MASK & self->spawnflags))
                    454:        {
                    455:                G_UseTargets (self, self);
                    456:                G_FreeEdict (self);
                    457:        }
                    458: }
                    459: 
                    460: void SP_target_crosslevel_target (edict_t *self)
                    461: {
                    462:        if (! self->delay)
                    463:                self->delay = 1;
                    464:        self->svflags = SVF_NOCLIENT;
                    465: 
                    466:        self->think = target_crosslevel_target_think;
                    467:        self->nextthink = level.time + self->delay;
                    468: }
                    469: 
                    470: //==========================================================
                    471: 
                    472: /*QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON RED GREEN BLUE YELLOW ORANGE FAT
                    473: When triggered, fires a laser.  You can either set a target
                    474: or a direction.
                    475: */
                    476: 
                    477: void target_laser_think (edict_t *self)
                    478: {
                    479:        edict_t *ignore;
                    480:        vec3_t  start;
                    481:        vec3_t  end;
                    482:        trace_t tr;
                    483:        vec3_t  point;
                    484:        vec3_t  last_movedir;
                    485:        int             count;
                    486: 
                    487:        if (self->spawnflags & 0x80000000)
                    488:                count = 8;
                    489:        else
                    490:                count = 4;
                    491: 
                    492:        if (self->enemy)
                    493:        {
                    494:                VectorCopy (self->movedir, last_movedir);
                    495:                VectorMA (self->enemy->absmin, 0.5, self->enemy->size, point);
                    496:                VectorSubtract (point, self->s.origin, self->movedir);
                    497:                VectorNormalize (self->movedir);
                    498:                if (!VectorCompare(self->movedir, last_movedir))
                    499:                        self->spawnflags |= 0x80000000;
                    500:        }
                    501: 
                    502:        ignore = self;
                    503:        VectorCopy (self->s.origin, start);
                    504:        VectorMA (start, 2048, self->movedir, end);
                    505:        while(1)
                    506:        {
                    507:                tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);
                    508: 
                    509:                if (!tr.ent)
                    510:                        break;
                    511: 
                    512:                // hurt it if we can
                    513:                if ((tr.ent->takedamage) && !(tr.ent->flags & FL_IMMUNE_LASER))
                    514:                        T_Damage (tr.ent, self, self->activator, self->movedir, tr.endpos, vec3_origin, self->dmg, 1, DAMAGE_ENERGY, MOD_TARGET_LASER);
                    515: 
                    516:                // if we hit something that's not a monster or player or is immune to lasers, we're done
                    517:                if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client))
                    518:                {
                    519:                        if (self->spawnflags & 0x80000000)
                    520:                        {
                    521:                                self->spawnflags &= ~0x80000000;
                    522:                                gi.WriteByte (svc_temp_entity);
                    523:                                gi.WriteByte (TE_LASER_SPARKS);
                    524:                                gi.WriteByte (count);
                    525:                                gi.WritePosition (tr.endpos);
                    526:                                gi.WriteDir (tr.plane.normal);
                    527:                                gi.WriteByte (self->s.skinnum);
                    528:                                gi.multicast (tr.endpos, MULTICAST_PVS);
                    529:                        }
                    530:                        break;
                    531:                }
                    532: 
                    533:                ignore = tr.ent;
                    534:                VectorCopy (tr.endpos, start);
                    535:        }
                    536: 
                    537:        VectorCopy (tr.endpos, self->s.old_origin);
                    538: 
                    539:        self->nextthink = level.time + FRAMETIME;
                    540: }
                    541: 
                    542: void target_laser_on (edict_t *self)
                    543: {
                    544:        if (!self->activator)
                    545:                self->activator = self;
                    546:        self->spawnflags |= 0x80000001;
                    547:        self->svflags &= ~SVF_NOCLIENT;
                    548:        target_laser_think (self);
                    549: }
                    550: 
                    551: void target_laser_off (edict_t *self)
                    552: {
                    553:        self->spawnflags &= ~1;
                    554:        self->svflags |= SVF_NOCLIENT;
                    555:        self->nextthink = 0;
                    556: }
                    557: 
                    558: void target_laser_use (edict_t *self, edict_t *other, edict_t *activator)
                    559: {
                    560:        self->activator = activator;
                    561:        if (self->spawnflags & 1)
                    562:                target_laser_off (self);
                    563:        else
                    564:                target_laser_on (self);
                    565: }
                    566: 
                    567: void target_laser_start (edict_t *self)
                    568: {
                    569:        edict_t *ent;
                    570: 
                    571:        self->movetype = MOVETYPE_NONE;
                    572:        self->solid = SOLID_NOT;
                    573:        self->s.renderfx |= RF_BEAM|RF_TRANSLUCENT;
                    574:        self->s.modelindex = 1;                 // must be non-zero
                    575: 
                    576:        // set the beam diameter
                    577:        if (self->spawnflags & 64)
                    578:                self->s.frame = 16;
                    579:        else
                    580:                self->s.frame = 4;
                    581: 
                    582:        // set the color
                    583:        if (self->spawnflags & 2)
                    584:                self->s.skinnum = 0xf2f2f0f0;
                    585:        else if (self->spawnflags & 4)
                    586:                self->s.skinnum = 0xd0d1d2d3;
                    587:        else if (self->spawnflags & 8)
                    588:                self->s.skinnum = 0xf3f3f1f1;
                    589:        else if (self->spawnflags & 16)
                    590:                self->s.skinnum = 0xdcdddedf;
                    591:        else if (self->spawnflags & 32)
                    592:                self->s.skinnum = 0xe0e1e2e3;
                    593: 
                    594:        if (!self->enemy)
                    595:        {
                    596:                if (self->target)
                    597:                {
                    598:                        ent = G_Find (NULL, FOFS(targetname), self->target);
                    599:                        if (!ent)
                    600:                                gi.dprintf ("%s at %s: %s is a bad target\n", self->classname, vtos(self->s.origin), self->target);
                    601:                        self->enemy = ent;
                    602:                }
                    603:                else
                    604:                {
                    605:                        G_SetMovedir (self->s.angles, self->movedir);
                    606:                }
                    607:        }
                    608:        self->use = target_laser_use;
                    609:        self->think = target_laser_think;
                    610: 
                    611:        if (!self->dmg)
                    612:                self->dmg = 1;
                    613: 
                    614:        VectorSet (self->mins, -8, -8, -8);
                    615:        VectorSet (self->maxs, 8, 8, 8);
                    616:        gi.linkentity (self);
                    617: 
                    618:        if (self->spawnflags & 1)
                    619:                target_laser_on (self);
                    620:        else
                    621:                target_laser_off (self);
                    622: }
                    623: 
                    624: void SP_target_laser (edict_t *self)
                    625: {
                    626:        // let everything else get spawned before we start firing
                    627:        self->think = target_laser_start;
                    628:        self->nextthink = level.time + 1;
                    629: }
                    630: 
                    631: 
                    632: // RAFAEL 15-APR-98
                    633: /*QUAKED target_mal_laser (1 0 0) (-4 -4 -4) (4 4 4) START_ON RED GREEN BLUE YELLOW ORANGE FAT
                    634: Mal's laser
                    635: */
                    636: void target_mal_laser_on (edict_t *self)
                    637: {
                    638:        if (!self->activator)
                    639:                self->activator = self;
                    640:        self->spawnflags |= 0x80000001;
                    641:        self->svflags &= ~SVF_NOCLIENT;
                    642:        // target_laser_think (self);
                    643:        self->nextthink = level.time + self->wait + self->delay;
                    644: }
                    645: 
                    646: void target_mal_laser_off (edict_t *self)
                    647: {
                    648:        self->spawnflags &= ~1;
                    649:        self->svflags |= SVF_NOCLIENT;
                    650:        self->nextthink = 0;
                    651: }
                    652: 
                    653: void target_mal_laser_use (edict_t *self, edict_t *other, edict_t *activator)
                    654: {
                    655:        self->activator = activator;
                    656:        if (self->spawnflags & 1)
                    657:                target_mal_laser_off (self);
                    658:        else
                    659:                target_mal_laser_on (self);
                    660: }
                    661: 
                    662: void mal_laser_think (edict_t *self)
                    663: {
                    664:        target_laser_think (self);
                    665:        self->nextthink = level.time + self->wait + 0.1;
                    666:        self->spawnflags |= 0x80000000;
                    667: }
                    668: 
                    669: void SP_target_mal_laser (edict_t *self)
                    670: {
                    671:        self->movetype = MOVETYPE_NONE;
                    672:        self->solid = SOLID_NOT;
                    673:        self->s.renderfx |= RF_BEAM|RF_TRANSLUCENT;
                    674:        self->s.modelindex = 1;                 // must be non-zero
                    675: 
                    676:        // set the beam diameter
                    677:        if (self->spawnflags & 64)
                    678:                self->s.frame = 16;
                    679:        else
                    680:                self->s.frame = 4;
                    681: 
                    682:        // set the color
                    683:        if (self->spawnflags & 2)
                    684:                self->s.skinnum = 0xf2f2f0f0;
                    685:        else if (self->spawnflags & 4)
                    686:                self->s.skinnum = 0xd0d1d2d3;
                    687:        else if (self->spawnflags & 8)
                    688:                self->s.skinnum = 0xf3f3f1f1;
                    689:        else if (self->spawnflags & 16)
                    690:                self->s.skinnum = 0xdcdddedf;
                    691:        else if (self->spawnflags & 32)
                    692:                self->s.skinnum = 0xe0e1e2e3;
                    693: 
                    694:        G_SetMovedir (self->s.angles, self->movedir);
                    695:        
                    696:        if (!self->delay)
                    697:                self->delay = 0.1;
                    698: 
                    699:        if (!self->wait)
                    700:                self->wait = 0.1;
                    701: 
                    702:        if (!self->dmg)
                    703:                self->dmg = 5;
                    704: 
                    705:        VectorSet (self->mins, -8, -8, -8);
                    706:        VectorSet (self->maxs, 8, 8, 8);
                    707:        
                    708:        self->nextthink = level.time + self->delay;
                    709:        self->think = mal_laser_think;
                    710: 
                    711:        self->use = target_mal_laser_use;
                    712: 
                    713:        gi.linkentity (self);
                    714: 
                    715:        if (self->spawnflags & 1)
                    716:                target_mal_laser_on (self);
                    717:        else
                    718:                target_mal_laser_off (self);
                    719: }
                    720: // END 15-APR-98
                    721: 
                    722: //==========================================================
                    723: 
                    724: /*QUAKED target_lightramp (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE
                    725: speed          How many seconds the ramping will take
                    726: message                two letters; starting lightlevel and ending lightlevel
                    727: */
                    728: 
                    729: void target_lightramp_think (edict_t *self)
                    730: {
                    731:        char    style[2];
                    732: 
                    733:        style[0] = 'a' + self->movedir[0] + (level.time - self->timestamp) / FRAMETIME * self->movedir[2];
                    734:        style[1] = 0;
                    735:        gi.configstring (CS_LIGHTS+self->enemy->style, style);
                    736: 
                    737:        if ((level.time - self->timestamp) < self->speed)
                    738:        {
                    739:                self->nextthink = level.time + FRAMETIME;
                    740:        }
                    741:        else if (self->spawnflags & 1)
                    742:        {
                    743:                char    temp;
                    744: 
                    745:                temp = self->movedir[0];
                    746:                self->movedir[0] = self->movedir[1];
                    747:                self->movedir[1] = temp;
                    748:                self->movedir[2] *= -1;
                    749:        }
                    750: }
                    751: 
                    752: void target_lightramp_use (edict_t *self, edict_t *other, edict_t *activator)
                    753: {
                    754:        if (!self->enemy)
                    755:        {
                    756:                edict_t         *e;
                    757: 
                    758:                // check all the targets
                    759:                e = NULL;
                    760:                while (1)
                    761:                {
                    762:                        e = G_Find (e, FOFS(targetname), self->target);
                    763:                        if (!e)
                    764:                                break;
                    765:                        if (strcmp(e->classname, "light") != 0)
                    766:                        {
                    767:                                gi.dprintf("%s at %s ", self->classname, vtos(self->s.origin));
                    768:                                gi.dprintf("target %s (%s at %s) is not a light\n", self->target, e->classname, vtos(e->s.origin));
                    769:                        }
                    770:                        else
                    771:                        {
                    772:                                self->enemy = e;
                    773:                        }
                    774:                }
                    775: 
                    776:                if (!self->enemy)
                    777:                {
                    778:                        gi.dprintf("%s target %s not found at %s\n", self->classname, self->target, vtos(self->s.origin));
                    779:                        G_FreeEdict (self);
                    780:                        return;
                    781:                }
                    782:        }
                    783: 
                    784:        self->timestamp = level.time;
                    785:        target_lightramp_think (self);
                    786: }
                    787: 
                    788: void SP_target_lightramp (edict_t *self)
                    789: {
                    790:        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])
                    791:        {
                    792:                gi.dprintf("target_lightramp has bad ramp (%s) at %s\n", self->message, vtos(self->s.origin));
                    793:                G_FreeEdict (self);
                    794:                return;
                    795:        }
                    796: 
                    797:        if (deathmatch->value)
                    798:        {
                    799:                G_FreeEdict (self);
                    800:                return;
                    801:        }
                    802: 
                    803:        if (!self->target)
                    804:        {
                    805:                gi.dprintf("%s with no target at %s\n", self->classname, vtos(self->s.origin));
                    806:                G_FreeEdict (self);
                    807:                return;
                    808:        }
                    809: 
                    810:        self->svflags |= SVF_NOCLIENT;
                    811:        self->use = target_lightramp_use;
                    812:        self->think = target_lightramp_think;
                    813: 
                    814:        self->movedir[0] = self->message[0] - 'a';
                    815:        self->movedir[1] = self->message[1] - 'a';
                    816:        self->movedir[2] = (self->movedir[1] - self->movedir[0]) / (self->speed / FRAMETIME);
                    817: }
                    818: 
                    819: //==========================================================
                    820: 
                    821: /*QUAKED target_earthquake (1 0 0) (-8 -8 -8) (8 8 8)
                    822: When triggered, this initiates a level-wide earthquake.
                    823: All players and monsters are affected.
                    824: "speed"                severity of the quake (default:200)
                    825: "count"                duration of the quake (default:5)
                    826: */
                    827: 
                    828: void target_earthquake_think (edict_t *self)
                    829: {
                    830:        int             i;
                    831:        edict_t *e;
                    832: 
                    833:        if (self->last_move_time < level.time)
                    834:        {
                    835:                gi.positioned_sound (self->s.origin, self, CHAN_AUTO, self->noise_index, 1.0, ATTN_NONE, 0);
                    836:                self->last_move_time = level.time + 0.5;
                    837:        }
                    838: 
                    839:        for (i=1, e=g_edicts+i; i < globals.num_edicts; i++,e++)
                    840:        {
                    841:                if (!e->inuse)
                    842:                        continue;
                    843:                if (!e->client)
                    844:                        continue;
                    845:                if (!e->groundentity)
                    846:                        continue;
                    847: 
                    848:                e->groundentity = NULL;
                    849:                e->velocity[0] += crandom()* 150;
                    850:                e->velocity[1] += crandom()* 150;
                    851:                e->velocity[2] = self->speed * (100.0 / e->mass);
                    852:        }
                    853: 
                    854:        if (level.time < self->timestamp)
                    855:                self->nextthink = level.time + FRAMETIME;
                    856: }
                    857: 
                    858: void target_earthquake_use (edict_t *self, edict_t *other, edict_t *activator)
                    859: {
                    860:        self->timestamp = level.time + self->count;
                    861:        self->nextthink = level.time + FRAMETIME;
                    862:        self->activator = activator;
                    863:        self->last_move_time = 0;
                    864: }
                    865: 
                    866: void SP_target_earthquake (edict_t *self)
                    867: {
                    868:        if (!self->targetname)
                    869:                gi.dprintf("untargeted %s at %s\n", self->classname, vtos(self->s.origin));
                    870: 
                    871:        if (!self->count)
                    872:                self->count = 5;
                    873: 
                    874:        if (!self->speed)
                    875:                self->speed = 200;
                    876: 
                    877:        self->svflags |= SVF_NOCLIENT;
                    878:        self->think = target_earthquake_think;
                    879:        self->use = target_earthquake_use;
                    880: 
                    881:        self->noise_index = gi.soundindex ("world/quake.wav");
                    882: }

unix.superglobalmegacorp.com

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