← Home SEEBIE90 DOCS
The GTG Safe Zone mod is published under the Arma Public License (APL)Example code is free to useSuggestions: Discord to the author

GTG Safe Zone

Invulnerability

The reliable part of the zone is a few lines in the damage manager: if the entity is protected right now, the hit is dropped. This runs where damage is computed, so no client can argue with it.

In plain wordsDamage is thrown away per hit, on the server, by a hook in the damage manager. Nothing is switched off, so nothing has to be switched back on.

A hook, not a switch

The damage manager has an event that is called for every hit before the damage is applied. Its documentation says what the return value means: true if the damage should be discarded. That is the whole mechanism. It is stateless – it is evaluated per hit and leaves nothing behind.

Example code – free to useMyAD_ZoneGuard.c
class MyAD_ZoneGuard
{
	// Should this hit be thrown away?
	static bool ShouldDiscard(IEntity victim, EDamageType type, float value, Instigator instigator)
	{
		// First of all, note who is attacking - see "Shooting from inside". This is the one place every hit on a
		// character or a vehicle passes, so it must happen before any of the early returns below.
		MyAD_Forfeit.NoteAttacker(instigator, type, value);

		if (!victim)
			return false;

		// Healing runs through the same function as damage. Block it, and nobody can be treated
		// in the one place the wounded are brought to.
		if (type == EDamageType.HEALING || type == EDamageType.REGENERATION)
			return false;

		// The engine documents the damage value as possibly negative for healing damage - let that through
		// whatever the type says. A negative value cannot hurt anybody.
		if (value < 0)
			return false;

		MyAD_Zone zone = MyAD_Zone.FindShieldingZoneOf(victim);
		if (!zone)
			return false;

		// Bleeding is damage already done that keeps running, not a new attack.
		// Let it run unless the zone is set to stop it.
		if (type == EDamageType.BLEEDING && !zone.StopsBleeding())
			return false;

		return true;
	}
}

Why not switch damage handling off

The other way to make somebody invulnerable is EnableDamageHandling(false), and it is the way vanilla spawn protection goes. It is also a switch, one per entity, with exactly one value. Spawn protection writes it. The Game Master's damage attribute writes it. A zone that writes it as well fights both of them: whoever wrote last wins, and leaving the zone would switch on damage that somebody else had deliberately switched off.

The hook has no such problem. It never changes the entity. When the hit comes, the zone looks at where the victim is and who it is, and answers for that one hit.

Hook the class that is really used

It looks natural to extend the common base class and be done. But the damage manager of a character overrides the hook itself and does not call the base class in it. A change to the base is never reached for characters. Extend each class that matters, one at a time – and always call super when the zone has no opinion.

Example code – free to use
modded class SCR_CharacterDamageManagerComponent
{
	override bool HijackDamageHandling(notnull BaseDamageContext damageContext)
	{
		if (MyAD_ZoneGuard.ShouldDiscard(GetOwner(), damageContext.damageType, damageContext.damageValue, damageContext.instigator))
			return true;			// true = discard this hit

		return super.HijackDamageHandling(damageContext);
	}
}

modded class SCR_VehicleDamageManagerComponent
{
	override bool HijackDamageHandling(notnull BaseDamageContext damageContext)
	{
		if (MyAD_ZoneGuard.ShouldDiscard(GetOwner(), damageContext.damageType, damageContext.damageValue, damageContext.instigator))
			return true;

		return super.HijackDamageHandling(damageContext);
	}
}
NoteVehicles are protected by the same function: a vehicle that stands in the zone and does not belong to an enemy is invulnerable as well.

Where it runs, and what that means

Damage is computed on the authority. This check is therefore the real enforcement of the zone: a modified client can ignore the action lock, but it cannot get damage past this check. That is also why the invulnerability stays in effect during an alarm – the alarm releases the weapons, not the damage.

PitfallAnyone inside the zone is protected from the Game Master, too. To kill somebody on purpose, switch the zone off for a moment.
Example code on this page is free to use in your own projects (credit appreciated). The GTG Safe Zone mod is published under the Arma Public License (APL). Suggestions: Discord. Arma Reforger / Enfusion are trademarks of Bohemia Interactive.
Impressum · Privacy Policy