#include <u.h>#include <libc.h>#include <stdio.h>#include "../dat.h"#include "../fns.h" /*QUAKED func_group (0 0 0) ?Used to group brushes together just for editor convenience.*/ //===================================================== void Use_Areaportal (edict_t *ent, edict_t */*other*/, edict_t */*activator*/){ ent->count ^= 1; // toggle state// gi.dprintf ("portalstate: %i = %i\n", ent->style, ent->count); gi.SetAreaPortalState (ent->style, ent->count);} /*QUAKED func_areaportal (0 0 0) ? This is a non-visible object that divides the world intoareas that are seperated when this portal is not activated.Usually enclosed in the middle of a door.*/void SP_func_areaportal (edict_t *ent){ ent->use = Use_Areaportal; ent->count = 0; // always start closed;} //===================================================== /*=================Misc functions=================*/void VelocityForDamage (int damage, vec3_t v){ v[0] = 100.0 * crandom(); v[1] = 100.0 * crandom(); v[2] = 200.0 + 100.0 * qrandom(); if (damage < 50) VectorScale (v, 0.7, v); else VectorScale (v, 1.2, v);} void ClipGibVelocity (edict_t *ent){ if (ent->velocity[0] < -300) ent->velocity[0] = -300; else if (ent->velocity[0] > 300) ent->velocity[0] = 300; if (ent->velocity[1] < -300) ent->velocity[1] = -300; else if (ent->velocity[1] > 300) ent->velocity[1] = 300; if (ent->velocity[2] < 200) ent->velocity[2] = 200; // always some upwards else if (ent->velocity[2] > 500) ent->velocity[2] = 500;} /*=================gibs=================*/void gib_think (edict_t *self){ self->s.frame++; self->nextthink = level.time + FRAMETIME; if (self->s.frame == 10) { self->think = G_FreeEdict; self->nextthink = level.time + 8 + qrandom()*10; }} void gib_touch (edict_t *self, edict_t */*other*/, cplane_t *plane, csurface_t */*surf*/){ vec3_t normal_angles, right; if (!self->groundentity) return; self->touch = NULL; if (plane) { gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/fhit3.wav"), 1, ATTN_NORM, 0); vectoangles (plane->normal, normal_angles); AngleVectors (normal_angles, NULL, right, NULL); vectoangles (right, self->s.angles); if (self->s.modelindex == sm_meat_index) { self->s.frame++; self->think = gib_think; self->nextthink = level.time + FRAMETIME; } }} void gib_die (edict_t *self, edict_t */*inflictor*/, edict_t */*attacker*/, int /*damage*/, vec3_t /*point*/){ G_FreeEdict (self);} void ThrowGib (edict_t *self, char *gibname, int damage, int type){ edict_t *gib; vec3_t vd; vec3_t origin; vec3_t size; float vscale; gib = G_Spawn(); VectorScale (self->size, 0.5, size); VectorAdd (self->absmin, size, origin); gib->s.origin[0] = origin[0] + crandom() * size[0]; gib->s.origin[1] = origin[1] + crandom() * size[1]; gib->s.origin[2] = origin[2] + crandom() * size[2]; gi.setmodel (gib, gibname); gib->solid = SOLID_NOT; gib->s.effects |= EF_GIB; gib->flags |= FL_NO_KNOCKBACK; gib->takedamage = DAMAGE_YES; gib->die = gib_die; if (type == GIB_ORGANIC) { gib->movetype = MOVETYPE_TOSS; gib->touch = gib_touch; vscale = 0.5; } else { gib->movetype = MOVETYPE_BOUNCE; vscale = 1.0; } VelocityForDamage (damage, vd); VectorMA (self->velocity, vscale, vd, gib->velocity); ClipGibVelocity (gib); gib->avelocity[0] = qrandom()*600; gib->avelocity[1] = qrandom()*600; gib->avelocity[2] = qrandom()*600; gib->think = G_FreeEdict; gib->nextthink = level.time + 10 + qrandom()*10; gi.linkentity (gib);} void ThrowHead (edict_t *self, char *gibname, int damage, int type){ vec3_t vd; float vscale; self->s.skinnum = 0; self->s.frame = 0; VectorClear (self->mins); VectorClear (self->maxs); self->s.modelindex2 = 0; gi.setmodel (self, gibname); self->solid = SOLID_NOT; self->s.effects |= EF_GIB; self->s.effects &= ~EF_FLIES; self->s.sound = 0; self->flags |= FL_NO_KNOCKBACK; self->svflags &= ~SVF_MONSTER; self->takedamage = DAMAGE_YES; self->die = gib_die; if (type == GIB_ORGANIC) { self->movetype = MOVETYPE_TOSS; self->touch = gib_touch; vscale = 0.5; } else { self->movetype = MOVETYPE_BOUNCE; vscale = 1.0; } VelocityForDamage (damage, vd); VectorMA (self->velocity, vscale, vd, self->velocity); ClipGibVelocity (self); self->avelocity[YAW] = crandom()*600; self->think = G_FreeEdict; self->nextthink = level.time + 10 + qrandom()*10; gi.linkentity (self);} void ThrowClientHead (edict_t *self, int damage){ vec3_t vd; char *gibname; if (rand()&1) { gibname = "models/objects/gibs/head2/tris.md2"; self->s.skinnum = 1; // second skin is player } else { gibname = "models/objects/gibs/skull/tris.md2"; self->s.skinnum = 0; } self->s.origin[2] += 32; self->s.frame = 0; gi.setmodel (self, gibname); VectorSet (self->mins, -16, -16, 0); VectorSet (self->maxs, 16, 16, 16); self->takedamage = DAMAGE_NO; self->solid = SOLID_NOT; self->s.effects = EF_GIB; self->s.sound = 0; self->flags |= FL_NO_KNOCKBACK; self->movetype = MOVETYPE_BOUNCE; VelocityForDamage (damage, vd); VectorAdd (self->velocity, vd, self->velocity); if (self->client) // bodies in the queue don't have a client anymore { self->client->anim_priority = ANIM_DEATH; self->client->anim_end = self->s.frame; } else { self->think = NULL; self->nextthink = 0; } gi.linkentity (self);} /*=================debris=================*/void debris_die (edict_t *self, edict_t */*inflictor*/, edict_t */*attacker*/, int /*damage*/, vec3_t /*point*/){ G_FreeEdict (self);} void ThrowDebris (edict_t *self, char *modelname, float speed, vec3_t origin){ edict_t *chunk; vec3_t v; chunk = G_Spawn(); VectorCopy (origin, chunk->s.origin); gi.setmodel (chunk, modelname); v[0] = 100 * crandom(); v[1] = 100 * crandom(); v[2] = 100 + 100 * crandom(); VectorMA (self->velocity, speed, v, chunk->velocity); chunk->movetype = MOVETYPE_BOUNCE; chunk->solid = SOLID_NOT; chunk->avelocity[0] = qrandom()*600; chunk->avelocity[1] = qrandom()*600; chunk->avelocity[2] = qrandom()*600; chunk->think = G_FreeEdict; chunk->nextthink = level.time + 5 + qrandom()*5; chunk->s.frame = 0; chunk->flags = 0; chunk->classname = "debris"; chunk->takedamage = DAMAGE_YES; chunk->die = debris_die; gi.linkentity (chunk);} void BecomeExplosion1 (edict_t *self){ gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_EXPLOSION1); gi.WritePosition (self->s.origin); gi.multicast (self->s.origin, MULTICAST_PVS); G_FreeEdict (self);} void BecomeExplosion2 (edict_t *self){ gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_EXPLOSION2); gi.WritePosition (self->s.origin); gi.multicast (self->s.origin, MULTICAST_PVS); G_FreeEdict (self);} /*QUAKED path_corner (.5 .3 0) (-8 -8 -8) (8 8 8) TELEPORTTarget: next path cornerPathtarget: gets used when an entity that has this path_corner targeted touches it*/ void path_corner_touch (edict_t *self, edict_t *other, cplane_t */*plane*/, csurface_t */*surf*/){ vec3_t v; edict_t *next; if (other->movetarget != self) return; if (other->enemy) return; if (self->pathtarget) { char *savetarget; savetarget = self->target; self->target = self->pathtarget; G_UseTargets (self, other); self->target = savetarget; } if (self->target) next = G_PickTarget(self->target); else next = NULL; if ((next) && (next->spawnflags & 1)) { VectorCopy (next->s.origin, v); v[2] += next->mins[2]; v[2] -= other->mins[2]; VectorCopy (v, other->s.origin); next = G_PickTarget(next->target); other->s.event = EV_OTHER_TELEPORT; } other->goalentity = other->movetarget = next; if (self->wait) { other->monsterinfo.pausetime = level.time + self->wait; other->monsterinfo.stand (other); return; } if (!other->movetarget) { other->monsterinfo.pausetime = level.time + 100000000; other->monsterinfo.stand (other); } else { VectorSubtract (other->goalentity->s.origin, other->s.origin, v); other->ideal_yaw = vectoyaw (v); }} void SP_path_corner (edict_t *self){ if (!self->targetname) { gi.dprintf ("path_corner with no targetname at %s\n", vtos(self->s.origin)); G_FreeEdict (self); return; } self->solid = SOLID_TRIGGER; self->touch = path_corner_touch; VectorSet (self->mins, -8, -8, -8); VectorSet (self->maxs, 8, 8, 8); self->svflags |= SVF_NOCLIENT; gi.linkentity (self);} /*QUAKED point_combat (0.5 0.3 0) (-8 -8 -8) (8 8 8) HoldMakes this the target of a monster and it will head herewhen first activated before going after the activator. Ifhold is selected, it will stay here.*/void point_combat_touch (edict_t *self, edict_t *other, cplane_t */*plane*/, csurface_t */*surf*/){ edict_t *activator; if (other->movetarget != self) return; if (self->target) { other->target = self->target; other->goalentity = other->movetarget = G_PickTarget(other->target); if (!other->goalentity) { gi.dprintf("%s at %s target %s does not exist\n", self->classname, vtos(self->s.origin), self->target); other->movetarget = self; } self->target = NULL; } else if ((self->spawnflags & 1) && !(other->flags & (FL_SWIM|FL_FLY))) { other->monsterinfo.pausetime = level.time + 100000000; other->monsterinfo.aiflags |= AI_STAND_GROUND; other->monsterinfo.stand (other); } if (other->movetarget == self) { other->target = NULL; other->movetarget = NULL; other->goalentity = other->enemy; other->monsterinfo.aiflags &= ~AI_COMBAT_POINT; } if (self->pathtarget) { char *savetarget; savetarget = self->target; self->target = self->pathtarget; if (other->enemy && other->enemy->client) activator = other->enemy; else if (other->oldenemy && other->oldenemy->client) activator = other->oldenemy; else if (other->activator && other->activator->client) activator = other->activator; else activator = other; G_UseTargets (self, activator); self->target = savetarget; }} void SP_point_combat (edict_t *self){ if (deathmatch->value) { G_FreeEdict (self); return; } self->solid = SOLID_TRIGGER; self->touch = point_combat_touch; VectorSet (self->mins, -8, -8, -16); VectorSet (self->maxs, 8, 8, 16); self->svflags = SVF_NOCLIENT; gi.linkentity (self);}; /*QUAKED viewthing (0 .5 .8) (-8 -8 -8) (8 8 8)Just for the debugging level. Don't use*/void TH_viewthing(edict_t *ent){ ent->s.frame = (ent->s.frame + 1) % 7; ent->nextthink = level.time + FRAMETIME;} void SP_viewthing(edict_t *ent){ gi.dprintf ("viewthing spawned\n"); ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; ent->s.renderfx = RF_FRAMELERP; VectorSet (ent->mins, -16, -16, -24); VectorSet (ent->maxs, 16, 16, 32); ent->s.modelindex = gi.modelindex ("models/objects/banner/tris.md2"); gi.linkentity (ent); ent->nextthink = level.time + 0.5; ent->think = TH_viewthing; return;} /*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4)Used as a positional target for spotlights, etc.Lines 1–500 of 1857. Load more
#include <u.h> #include <libc.h> #include <stdio.h> #include "../dat.h" #include "../fns.h" /*QUAKED func_group (0 0 0) ? Used to group brushes together just for editor convenience. */ //===================================================== void Use_Areaportal (edict_t *ent, edict_t */*other*/, edict_t */*activator*/) { ent->count ^= 1; // toggle state // gi.dprintf ("portalstate: %i = %i\n", ent->style, ent->count); gi.SetAreaPortalState (ent->style, ent->count); } /*QUAKED func_areaportal (0 0 0) ? This is a non-visible object that divides the world into areas that are seperated when this portal is not activated. Usually enclosed in the middle of a door. */ void SP_func_areaportal (edict_t *ent) { ent->use = Use_Areaportal; ent->count = 0; // always start closed; } //===================================================== /* ================= Misc functions ================= */ void VelocityForDamage (int damage, vec3_t v) { v[0] = 100.0 * crandom(); v[1] = 100.0 * crandom(); v[2] = 200.0 + 100.0 * qrandom(); if (damage < 50) VectorScale (v, 0.7, v); else VectorScale (v, 1.2, v); } void ClipGibVelocity (edict_t *ent) { if (ent->velocity[0] < -300) ent->velocity[0] = -300; else if (ent->velocity[0] > 300) ent->velocity[0] = 300; if (ent->velocity[1] < -300) ent->velocity[1] = -300; else if (ent->velocity[1] > 300) ent->velocity[1] = 300; if (ent->velocity[2] < 200) ent->velocity[2] = 200; // always some upwards else if (ent->velocity[2] > 500) ent->velocity[2] = 500; } /* ================= gibs ================= */ void gib_think (edict_t *self) { self->s.frame++; self->nextthink = level.time + FRAMETIME; if (self->s.frame == 10) { self->think = G_FreeEdict; self->nextthink = level.time + 8 + qrandom()*10; } } void gib_touch (edict_t *self, edict_t */*other*/, cplane_t *plane, csurface_t */*surf*/) { vec3_t normal_angles, right; if (!self->groundentity) return; self->touch = NULL; if (plane) { gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/fhit3.wav"), 1, ATTN_NORM, 0); vectoangles (plane->normal, normal_angles); AngleVectors (normal_angles, NULL, right, NULL); vectoangles (right, self->s.angles); if (self->s.modelindex == sm_meat_index) { self->s.frame++; self->think = gib_think; self->nextthink = level.time + FRAMETIME; } } } void gib_die (edict_t *self, edict_t */*inflictor*/, edict_t */*attacker*/, int /*damage*/, vec3_t /*point*/) { G_FreeEdict (self); } void ThrowGib (edict_t *self, char *gibname, int damage, int type) { edict_t *gib; vec3_t vd; vec3_t origin; vec3_t size; float vscale; gib = G_Spawn(); VectorScale (self->size, 0.5, size); VectorAdd (self->absmin, size, origin); gib->s.origin[0] = origin[0] + crandom() * size[0]; gib->s.origin[1] = origin[1] + crandom() * size[1]; gib->s.origin[2] = origin[2] + crandom() * size[2]; gi.setmodel (gib, gibname); gib->solid = SOLID_NOT; gib->s.effects |= EF_GIB; gib->flags |= FL_NO_KNOCKBACK; gib->takedamage = DAMAGE_YES; gib->die = gib_die; if (type == GIB_ORGANIC) { gib->movetype = MOVETYPE_TOSS; gib->touch = gib_touch; vscale = 0.5; } else { gib->movetype = MOVETYPE_BOUNCE; vscale = 1.0; } VelocityForDamage (damage, vd); VectorMA (self->velocity, vscale, vd, gib->velocity); ClipGibVelocity (gib); gib->avelocity[0] = qrandom()*600; gib->avelocity[1] = qrandom()*600; gib->avelocity[2] = qrandom()*600; gib->think = G_FreeEdict; gib->nextthink = level.time + 10 + qrandom()*10; gi.linkentity (gib); } void ThrowHead (edict_t *self, char *gibname, int damage, int type) { vec3_t vd; float vscale; self->s.skinnum = 0; self->s.frame = 0; VectorClear (self->mins); VectorClear (self->maxs); self->s.modelindex2 = 0; gi.setmodel (self, gibname); self->solid = SOLID_NOT; self->s.effects |= EF_GIB; self->s.effects &= ~EF_FLIES; self->s.sound = 0; self->flags |= FL_NO_KNOCKBACK; self->svflags &= ~SVF_MONSTER; self->takedamage = DAMAGE_YES; self->die = gib_die; if (type == GIB_ORGANIC) { self->movetype = MOVETYPE_TOSS; self->touch = gib_touch; vscale = 0.5; } else { self->movetype = MOVETYPE_BOUNCE; vscale = 1.0; } VelocityForDamage (damage, vd); VectorMA (self->velocity, vscale, vd, self->velocity); ClipGibVelocity (self); self->avelocity[YAW] = crandom()*600; self->think = G_FreeEdict; self->nextthink = level.time + 10 + qrandom()*10; gi.linkentity (self); } void ThrowClientHead (edict_t *self, int damage) { vec3_t vd; char *gibname; if (rand()&1) { gibname = "models/objects/gibs/head2/tris.md2"; self->s.skinnum = 1; // second skin is player } else { gibname = "models/objects/gibs/skull/tris.md2"; self->s.skinnum = 0; } self->s.origin[2] += 32; self->s.frame = 0; gi.setmodel (self, gibname); VectorSet (self->mins, -16, -16, 0); VectorSet (self->maxs, 16, 16, 16); self->takedamage = DAMAGE_NO; self->solid = SOLID_NOT; self->s.effects = EF_GIB; self->s.sound = 0; self->flags |= FL_NO_KNOCKBACK; self->movetype = MOVETYPE_BOUNCE; VelocityForDamage (damage, vd); VectorAdd (self->velocity, vd, self->velocity); if (self->client) // bodies in the queue don't have a client anymore { self->client->anim_priority = ANIM_DEATH; self->client->anim_end = self->s.frame; } else { self->think = NULL; self->nextthink = 0; } gi.linkentity (self); } /* ================= debris ================= */ void debris_die (edict_t *self, edict_t */*inflictor*/, edict_t */*attacker*/, int /*damage*/, vec3_t /*point*/) { G_FreeEdict (self); } void ThrowDebris (edict_t *self, char *modelname, float speed, vec3_t origin) { edict_t *chunk; vec3_t v; chunk = G_Spawn(); VectorCopy (origin, chunk->s.origin); gi.setmodel (chunk, modelname); v[0] = 100 * crandom(); v[1] = 100 * crandom(); v[2] = 100 + 100 * crandom(); VectorMA (self->velocity, speed, v, chunk->velocity); chunk->movetype = MOVETYPE_BOUNCE; chunk->solid = SOLID_NOT; chunk->avelocity[0] = qrandom()*600; chunk->avelocity[1] = qrandom()*600; chunk->avelocity[2] = qrandom()*600; chunk->think = G_FreeEdict; chunk->nextthink = level.time + 5 + qrandom()*5; chunk->s.frame = 0; chunk->flags = 0; chunk->classname = "debris"; chunk->takedamage = DAMAGE_YES; chunk->die = debris_die; gi.linkentity (chunk); } void BecomeExplosion1 (edict_t *self) { gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_EXPLOSION1); gi.WritePosition (self->s.origin); gi.multicast (self->s.origin, MULTICAST_PVS); G_FreeEdict (self); } void BecomeExplosion2 (edict_t *self) { gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_EXPLOSION2); gi.WritePosition (self->s.origin); gi.multicast (self->s.origin, MULTICAST_PVS); G_FreeEdict (self); } /*QUAKED path_corner (.5 .3 0) (-8 -8 -8) (8 8 8) TELEPORT Target: next path corner Pathtarget: gets used when an entity that has this path_corner targeted touches it */ void path_corner_touch (edict_t *self, edict_t *other, cplane_t */*plane*/, csurface_t */*surf*/) { vec3_t v; edict_t *next; if (other->movetarget != self) return; if (other->enemy) return; if (self->pathtarget) { char *savetarget; savetarget = self->target; self->target = self->pathtarget; G_UseTargets (self, other); self->target = savetarget; } if (self->target) next = G_PickTarget(self->target); else next = NULL; if ((next) && (next->spawnflags & 1)) { VectorCopy (next->s.origin, v); v[2] += next->mins[2]; v[2] -= other->mins[2]; VectorCopy (v, other->s.origin); next = G_PickTarget(next->target); other->s.event = EV_OTHER_TELEPORT; } other->goalentity = other->movetarget = next; if (self->wait) { other->monsterinfo.pausetime = level.time + self->wait; other->monsterinfo.stand (other); return; } if (!other->movetarget) { other->monsterinfo.pausetime = level.time + 100000000; other->monsterinfo.stand (other); } else { VectorSubtract (other->goalentity->s.origin, other->s.origin, v); other->ideal_yaw = vectoyaw (v); } } void SP_path_corner (edict_t *self) { if (!self->targetname) { gi.dprintf ("path_corner with no targetname at %s\n", vtos(self->s.origin)); G_FreeEdict (self); return; } self->solid = SOLID_TRIGGER; self->touch = path_corner_touch; VectorSet (self->mins, -8, -8, -8); VectorSet (self->maxs, 8, 8, 8); self->svflags |= SVF_NOCLIENT; gi.linkentity (self); } /*QUAKED point_combat (0.5 0.3 0) (-8 -8 -8) (8 8 8) Hold Makes this the target of a monster and it will head here when first activated before going after the activator. If hold is selected, it will stay here. */ void point_combat_touch (edict_t *self, edict_t *other, cplane_t */*plane*/, csurface_t */*surf*/) { edict_t *activator; if (other->movetarget != self) return; if (self->target) { other->target = self->target; other->goalentity = other->movetarget = G_PickTarget(other->target); if (!other->goalentity) { gi.dprintf("%s at %s target %s does not exist\n", self->classname, vtos(self->s.origin), self->target); other->movetarget = self; } self->target = NULL; } else if ((self->spawnflags & 1) && !(other->flags & (FL_SWIM|FL_FLY))) { other->monsterinfo.pausetime = level.time + 100000000; other->monsterinfo.aiflags |= AI_STAND_GROUND; other->monsterinfo.stand (other); } if (other->movetarget == self) { other->target = NULL; other->movetarget = NULL; other->goalentity = other->enemy; other->monsterinfo.aiflags &= ~AI_COMBAT_POINT; } if (self->pathtarget) { char *savetarget; savetarget = self->target; self->target = self->pathtarget; if (other->enemy && other->enemy->client) activator = other->enemy; else if (other->oldenemy && other->oldenemy->client) activator = other->oldenemy; else if (other->activator && other->activator->client) activator = other->activator; else activator = other; G_UseTargets (self, activator); self->target = savetarget; } } void SP_point_combat (edict_t *self) { if (deathmatch->value) { G_FreeEdict (self); return; } self->solid = SOLID_TRIGGER; self->touch = point_combat_touch; VectorSet (self->mins, -8, -8, -16); VectorSet (self->maxs, 8, 8, 16); self->svflags = SVF_NOCLIENT; gi.linkentity (self); }; /*QUAKED viewthing (0 .5 .8) (-8 -8 -8) (8 8 8) Just for the debugging level. Don't use */ void TH_viewthing(edict_t *ent) { ent->s.frame = (ent->s.frame + 1) % 7; ent->nextthink = level.time + FRAMETIME; } void SP_viewthing(edict_t *ent) { gi.dprintf ("viewthing spawned\n"); ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; ent->s.renderfx = RF_FRAMELERP; VectorSet (ent->mins, -16, -16, -24); VectorSet (ent->maxs, 16, 16, 32); ent->s.modelindex = gi.modelindex ("models/objects/banner/tris.md2"); gi.linkentity (ent); ent->nextthink = level.time + 0.5; ent->think = TH_viewthing; return; } /*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4) Used as a positional target for spotlights, etc.