/* Damage entities within a specific radius. */ void Entity_RadiusDamage(edict_t *eInflictor,float fRadius,int iDamage,int iDamageType) { int i; float fDistance; vec3_t vOrigin; edict_t *eTarget = Engine.Server_FindRadius(eInflictor->v.origin,fRadius); Engine.WriteByte(MSG_BROADCAST,SVC_TEMPENTITY); Engine.WriteByte(MSG_BROADCAST,CTE_EXPLOSION); for(i = 0; i < 3; i++) Engine.WriteCoord(MSG_BROADCAST,eInflictor->v.origin[i]); do { if(eTarget->v.bTakeDamage) { int i; for(i = 0; i < 3; i++) vOrigin[i] = eTarget->v.origin[i]+(eTarget->v.mins[i]+eTarget->v.maxs[i])*0.5f; Math_VectorSubtract(eInflictor->v.origin,vOrigin,vOrigin); fDistance = 0.5f*(float)Math_VectorLength(vOrigin); if(fDistance > 0) { Math_VectorInverse(vOrigin); Math_VectorAdd(eTarget->v.velocity,vOrigin,eTarget->v.velocity); // [15/7/2013] Reduce the damage by distance ~hogsy fDistance = (float)iDamage-(100.0f/fDistance); // [15/8/2013] Less damage for the inflictor ~hogsy if(eTarget == eInflictor) fDistance = fDistance/2.0f; if(fDistance > 0) if(Entity_CanDamage(eInflictor,eTarget, iDamageType)) MONSTER_Damage(eTarget,eInflictor,(int)fDistance,iDamageType); } } eTarget = eTarget->v.chain; } while(eTarget); }
/* Returns the range from an entity to a target. */ float MONSTER_GetRange(edict_t *ent,vec3_t target) { // [12/4/2012] Revised ~hogsy vec3_t spot,spot1,spot2; spot1[0] = ent->v.origin[0]+ent->v.view_ofs[0]; spot1[1] = ent->v.origin[1]+ent->v.view_ofs[1]; spot1[2] = ent->v.origin[2]+ent->v.view_ofs[2]; spot2[0] = target[0]; //+ target->v.view_ofs[0]; spot2[1] = target[1]; //+ target->v.view_ofs[1]; spot2[2] = target[2]; //+ target->v.view_ofs[2]; Math_VectorSubtract(spot1,spot2,spot); // [4/2/2013] Shouldn't this be a float rather than a double? Oh well, whatever you say, Carmack ~hogsy return (float)Math_VectorLength(spot); }
/* Damage entities within a specific radius. */ void Entity_RadiusDamage(ServerEntity_t *eInflictor, float fRadius, int iDamage, int iDamageType) { int i; float fDistance; MathVector3f_t vOrigin; ServerEntity_t *eTarget = Engine.Server_FindRadius(eInflictor->v.origin, fRadius); do { if(eTarget->v.bTakeDamage) { for(i = 0; i < 3; i++) vOrigin[i] = eTarget->v.origin[i]+(eTarget->v.mins[i]+eTarget->v.maxs[i])*0.5f; Math_VectorSubtract(eInflictor->v.origin,vOrigin,vOrigin); fDistance = 0.5f*(float)Math_VectorLength(vOrigin); if(fDistance > 0) { Math_VectorInverse(vOrigin); Math_VectorAdd(eTarget->v.velocity,vOrigin,eTarget->v.velocity); // Reduce the damage by distance. fDistance = (float)iDamage-(100.0f/fDistance); // Less damage for the inflictor. if(eTarget == eInflictor) fDistance = fDistance/2.0f; if(fDistance > 0) Entity_Damage(eTarget,eInflictor,(int)fDistance,iDamageType); } } eTarget = eTarget->v.chain; } while(eTarget); }
void Waypoint_Spawn(MathVector3f_t vOrigin,WaypointType_t type) { #ifdef DEBUG_WAYPOINT char *cModelName = WAYPOINT_MODEL_BASE; #endif int iPointContents; Waypoint_t *wPoint; /* TODO If we're between two other waypoints and they can be seen then slot ourselves in so that we act as the last waypoint instead. */ iPointContents = Engine.Server_PointContents(vOrigin); // [17/6/2012] Check that this area is safe ~hogsy if(iPointContents == BSP_CONTENTS_SOLID) { Engine.Con_Warning("Failed to place waypoint, position is within a solid!\n"); return; } { Waypoint_t *wVisibleWaypoint = Waypoint_GetByVisibility(vOrigin); // [30/1/2013] Oops! Check we actually have a visible waypoint!! ~hogsy if(wVisibleWaypoint) { MathVector3f_t vDistance; Math_VectorSubtract(wVisibleWaypoint->position,vOrigin,vDistance); if(Math_VectorLength(vDistance) < MONSTER_RANGE_MEDIUM) { Engine.Con_Printf("Invalid waypoint position!\n"); return; } } } wPoint = Waypoint_Allocate(); if(!wPoint) { Engine.Con_Warning("Failed to allocate waypoint!\n"); return; } Math_VectorCopy(vOrigin,wPoint->position); wPoint->number = waypoint_count; wPoint->bOpen = false; wPoint->next = Waypoint_GetByNumber(wPoint->number+1); wPoint->last = Waypoint_GetByNumber(wPoint->number-1); wPoint->wType = type; switch(type) { case WAYPOINT_ITEM: wPoint->cName = "item"; #ifdef DEBUG_WAYPOINT cModelName = WAYPOINT_MODEL_ITEM; #endif break; case WAYPOINT_CLIMB: wPoint->cName = "climb"; // TODO: Check that there's a ladder nearby. #ifdef DEBUG_WAYPOINT cModelName = WAYPOINT_MODEL_CLIMB; #endif break; case WAYPOINT_COVER: wPoint->cName = "cover"; // [27/12/2012] TODO: Check that this is actually cover ~hogsy break; case WAYPOINT_TYPE_JUMP: wPoint->cName = "jump"; // [27/12/2012] TODO: Check if this is actually a jump by tracing out ahead ~hogsy #ifdef DEBUG_WAYPOINT cModelName = WAYPOINT_MODEL_JUMP; #endif break; case WAYPOINT_TYPE_SWIM: if(iPointContents != BSP_CONTENTS_WATER) { Engine.Con_Warning("Waypoint with type swim not within water contents (%i %i %i)!", (int)vOrigin[0], (int)vOrigin[1], (int)vOrigin[2]); Waypoint_Delete(wPoint); return; } wPoint->cName = "swim"; #ifdef DEBUG_WAYPOINT cModelName = WAYPOINT_MODEL_SWIM; #endif break; case WAYPOINT_TYPE_DEFAULT: wPoint->cName = "default"; break; case WAYPOINT_SPAWN: wPoint->cName = "spawn"; break; default: Engine.Con_Warning("Unknown waypoint type (%i)!\n",type); Waypoint_Delete(wPoint); return; } // [30/1/2013] Pathetic reordering... Ugh ~hogsy if(!wPoint->last) { wPoint->last = Waypoint_GetByVisibility(vOrigin); if(!wPoint->last) { Engine.Con_Warning("Failed to get another visible waypoint! (%i)\n",wPoint->number); return; } } else if(wPoint->last != wPoint && wPoint->last->next) wPoint->last->next = wPoint; #ifdef DEBUG_WAYPOINT wPoint->eDebug = Entity_Spawn(); if(wPoint->eDebug) { wPoint->eDebug->v.effects = EF_MOTION_ROTATE; Entity_SetModel(wPoint->eDebug,cModelName); Entity_SetSizeVector(wPoint->eDebug,g_mvOrigin3f,g_mvOrigin3f); Entity_SetOrigin(wPoint->eDebug,wPoint->position); } Engine.Con_DPrintf("Waypoint placed (%i %i %i)\n", (int)wPoint->position[0], (int)wPoint->position[1], (int)wPoint->position[2]); Engine.Con_DPrintf(" number: %i\n",wPoint->number); Engine.Con_DPrintf(" type: %i\n",wPoint->wType); #endif }