void Entity_Damage(ServerEntity_t *seEntity, ServerEntity_t *seInflictor, int iDamage, DamageType_t dtType) { // Don't bother if there's no actual damage inflicted. if (iDamage <= 0) return; // Only continue if we can damage the entity. if (!Entity_CanDamage(seInflictor, seEntity, dtType)) return; // If it's a monster or player, hand it over to the monster code. if (Entity_IsMonster(seEntity) || Entity_IsPlayer(seEntity)) { Monster_Damage(seEntity, seInflictor, iDamage, dtType); return; } // Otherwise we'll do our own thing here... seEntity->v.iHealth -= iDamage; if (seEntity->v.iHealth <= 0) { if (seEntity->local.KilledFunction) seEntity->local.KilledFunction(seEntity, seInflictor); return; } if (seEntity->local.DamagedFunction) seEntity->local.DamagedFunction(seEntity, seInflictor); }
void Point_MessageCenter(ServerEntity_t *eEntity) { if(!eEntity->local.activator || (!Entity_IsPlayer(eEntity) && eEntity->local.activator->v.iHealth <= 0)) return; Engine.CenterPrint(eEntity->local.activator,eEntity->v.message); }
void MONSTER_Damage(edict_t *target,edict_t *inflictor,int iDamage, int iDamageType) { /* TODO If the new inflicted damage is greater than the last amount, we're a monster and the attacker is client (or other) then we should change our target to this other entity as it's most likely more dangerous! Suggested that amount of damage should multiply on each call and then slowly decrease after sometime. */ if(!target->v.bTakeDamage || (target->v.flags & FL_GODMODE) || !Entity_CanDamage(inflictor, target, iDamageType)) return; // [28/8/2012] Blood is now handled here :) ~hogsy if(target->local.bBleed) { char cBlood[6]; PARTICLE_BLOOD(cBlood); Engine.Particle(target->v.origin,target->v.velocity,10.0f,cBlood,20); } // [3/10/2012] Only do this for clients ~hogsy if(Entity_IsPlayer(inflictor)) { #ifdef GAME_OPENKATANA if(inflictor->local.power_finished > Server.dTime) iDamage *= 3; #endif // [3/10/2012] Half the amount of damage we can inflict in hard ~hogsy // [15/11/2012] Removed vita check here... Vita should not be acting like armor! ~hogsy if(cvServerSkill.value >= 3) iDamage /= 2; } else if(Entity_IsMonster(inflictor)) { // [3/10/2012] Double if we're a monster ~hogsy if(cvServerSkill.value >= 3) iDamage *= 2; } if(Entity_IsMonster(target)) // [27/4/2014] Automatically wake us up if asleep ~hogsy if(target->monster.iState == STATE_ASLEEP) Monster_SetState(target,STATE_AWAKE); target->v.iHealth -= iDamage; if(target->v.iHealth <= 0) Monster_Killed(target,inflictor); else if(target->monster.think_pain) target->monster.think_pain(target,inflictor); }
void Area_PushTouch(ServerEntity_t *area, ServerEntity_t *other) { // [9/12/2013] TODO: Make this optional? Would be cool to throw monsters and other crap around... ~hogsy if(!Entity_IsPlayer(other)) { return; } other->v.velocity = area->v.movedir * (area->local.speed * 10); if(area->v.spawnflags & AREA_PUSH_ONCE) { Entity_Remove(area); } }
void Area_ChangeLevelTouch(ServerEntity_t *area, ServerEntity_t *other) { // [2/1/2013] TODO: If coop wait for other players? ~hogsy if(!Entity_IsPlayer(other)) { return; } #if 0 // [2/1/2013] Because we don't want to trigger it multiple times within the delay!!! ~hogsy area->v.solid = SOLID_NOT; area->v.think = Area_ChangelevelStart; area->v.nextthink = Server.time+area->local.delay; #else area->Physics.solid = SOLID_NOT; // [2/1/2013] Change the level! ~hogsy g_engine->Server_ChangeLevel(area->v.targetname); #endif }
/* Called when a monster/entity gets killed. */ void Monster_Killed(edict_t *eTarget,edict_t *eAttacker) { if(eTarget->monster.iState == STATE_DEAD) return; if(Entity_IsMonster(eTarget)) { WriteByte(MSG_ALL,SVC_KILLEDMONSTER); Server.iMonsters--; eAttacker->v.iScore++; #if 0 // Update number of frags for client. Engine.SetMessageEntity(eAttacker); Engine.WriteByte(MSG_ONE,SVC_UPDATESTAT); Engine.WriteByte(MSG_ONE,STAT_FRAGS); Engine.WriteByte(MSG_ONE,eAttacker->v.iScore); #endif } else if(Entity_IsPlayer(eAttacker) && bIsMultiplayer) { char *cDeathMessage = "%s was killed by %s\n"; if(eTarget == eAttacker) { cDeathMessage = "%s killed himself!\n"; eAttacker->v.iScore--; } else if(Entity_IsPlayer(eTarget) && bIsCooperative) { cDeathMessage = "%s was tk'd by %s (what a dick, huh?)"; eAttacker->v.iScore--; } // [2/9/2012] Did we kill someone while dead? ~hogsy else { eAttacker->v.iScore++; // [15/12/2013] Extra points! ~hogsy if(eAttacker->v.iHealth <= 0) { // [3/10/2012] TODO: Play sound ~hogsy Engine.CenterPrint(eAttacker,"FROM BEYOND THE GRAVE!\n"); cDeathMessage = "%s was killed from beyond the grave by %s\n"; eAttacker->v.iScore += 2; } // [15/12/2013] Extra points! ~hogsy if(!(eTarget->v.flags & FL_ONGROUND)) { // [25/6/2012] TODO: Play sound ~hogsy Engine.CenterPrint(eAttacker,"WATCH THEM DROP!\n"); cDeathMessage = "%s was shot out of the air by %s\n"; eAttacker->v.iScore += 2; } } // Update number of frags for client. Engine.SetMessageEntity(eAttacker); Engine.WriteByte(MSG_ONE,SVC_UPDATESTAT); Engine.WriteByte(MSG_ONE,STAT_FRAGS); Engine.WriteByte(MSG_ONE,eAttacker->v.iScore); // TODO: move Kill messages into mode_deathmatch (?) Create Weapon specific kill messages and more variations! ~eukos Engine.Server_BroadcastPrint(cDeathMessage,eTarget->v.netname,eAttacker->v.netname); } else eTarget->v.bTakeDamage = false; #ifdef GAME_OPENKATANA // [22/4/2014] Drop the currently equipped item for the player to pick up! ~hogsy { Weapon_t *wActive = Weapon_GetCurrentWeapon(eTarget); if(wActive && (wActive->iItem != WEAPON_LASERS)) { edict_t *eDroppedItem = Entity_Spawn(); Math_VectorCopy(eTarget->v.origin,eDroppedItem->v.origin); eDroppedItem->local.style = wActive->iItem; Item_Spawn(eDroppedItem); } } #endif if(eTarget->monster.think_die) eTarget->monster.think_die(eTarget,eAttacker); // Update our current state. eTarget->monster.iState = STATE_DEAD; }