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