Example #1
0
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;
}