Просмотр исходного кода

Falling damage support.
Inspired by nBd's code.

_DS_ 15 лет назад
Родитель
Сommit
95004c43c3

+ 6 - 0
L2_GameServer/java/com/l2jserver/Config.java

@@ -429,6 +429,7 @@ public final class Config
 	public static int MIN_MONSTER_ANIMATION;
 	public static int MAX_MONSTER_ANIMATION;
 	public static int COORD_SYNCHRONIZE;
+	public static boolean ENABLE_FALLING_DAMAGE;
 	public static boolean GRIDS_ALWAYS_ON;
 	public static int GRID_NEIGHBOR_TURNON_TIME;
 	public static int GRID_NEIGHBOR_TURNOFF_TIME;
@@ -1706,6 +1707,10 @@ public final class Config
 					DEBUG_PATH = Boolean.parseBoolean(General.getProperty("DebugPath", "False"));
 					FORCE_GEODATA = Boolean.parseBoolean(General.getProperty("ForceGeodata", "True"));
 					COORD_SYNCHRONIZE = Integer.parseInt(General.getProperty("CoordSynchronize", "-1"));
+
+					String str = General.getProperty("EnableFallingDamage", "auto");
+					ENABLE_FALLING_DAMAGE = "auto".equalsIgnoreCase(str) ? GEODATA > 0 : Boolean.parseBoolean(str);
+
 					ZONE_TOWN = Integer.parseInt(General.getProperty("ZoneTown", "0"));
 					ACTIVATE_POSITION_RECORDER = Boolean.parseBoolean(General.getProperty("ActivatePositionRecorder", "False"));
 					DEFAULT_GLOBAL_CHAT = General.getProperty("GlobalChat", "ON");
@@ -2799,6 +2804,7 @@ public final class Config
 		else if (pName.equalsIgnoreCase("AnnounceMammonSpawn")) ANNOUNCE_MAMMON_SPAWN = Boolean.parseBoolean(pValue);
 
 		else if (pName.equalsIgnoreCase("AltGameTiredness")) ALT_GAME_TIREDNESS = Boolean.parseBoolean(pValue);
+		else if (pName.equalsIgnoreCase("EnableFallingDamage")) ENABLE_FALLING_DAMAGE = Boolean.parseBoolean(pValue);
 		else if (pName.equalsIgnoreCase("AltGameCreation")) ALT_GAME_CREATION = Boolean.parseBoolean(pValue);
 		else if (pName.equalsIgnoreCase("AltGameCreationSpeed")) ALT_GAME_CREATION_SPEED = Double.parseDouble(pValue);
 		else if (pName.equalsIgnoreCase("AltGameCreationXpRate")) ALT_GAME_CREATION_XP_RATE = Double.parseDouble(pValue);

+ 42 - 1
L2_GameServer/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -803,7 +803,11 @@ public final class L2PcInstance extends L2Playable
 	private int _clientY;
 	private int _clientZ;
 	private int _clientHeading;
-	
+
+	// during fall validations will be disabled for 10 ms.
+	private static final int FALLING_VALIDATION_DELAY = 10000;
+	private long _fallingTimestamp = 0;
+
 	private int _movieId = 0;
 	
 	private Future<?> _PvPRegTask;
@@ -10029,6 +10033,7 @@ public final class L2PcInstance extends L2Playable
 		if (getAI() != null)
 			getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
 
+		setFalling(); // prevent receive falling damage
         _observerMode = false;
 		setObserverCords(0, 0, 0);
 		sendPacket(new ObservationReturn(this));
@@ -14651,6 +14656,42 @@ public final class L2PcInstance extends L2Playable
 		_clientHeading=val;
 	}
 
+	/**
+	 * Return true if character falling now
+	 * On the start of fall return false for correct coord sync !
+	 */
+	public final boolean isFalling(int z)
+	{
+		if (isDead()
+				|| isFlying()
+				|| isFlyingMounted()
+				|| isInsideZone(ZONE_WATER))
+			return false;
+
+		if (System.currentTimeMillis() < _fallingTimestamp)
+			return true;
+
+		final int deltaZ = getZ() - z;
+		if (deltaZ <= getBaseTemplate().getFallHeight())
+			return false;
+
+		final int damage = (int)Formulas.calcFallDam(this, deltaZ);
+		if (damage > 0)
+			sendPacket(new SystemMessage(SystemMessageId.FALL_DAMAGE_S1).addNumber(damage));
+
+		setFalling();
+
+		return false;
+	}
+
+	/**
+	 * Set falling timestamp
+	 */
+	public final void setFalling()
+	{
+		_fallingTimestamp = System.currentTimeMillis() + FALLING_VALIDATION_DELAY;
+	}
+
 	/**
 	 * @return the _movieId
 	 */

+ 4 - 1
L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/ValidatePosition.java

@@ -111,11 +111,14 @@ public class ValidatePosition extends L2GameClientPacket
 			return;
 		}
 
+		if (activeChar.isFalling(_z))
+			return; // disable validations during fall to avoid "jumping"
+
 		dx = _x - realX;
 		dy = _y - realY;
 		dz = _z - realZ;
 		diffSq = (dx*dx + dy*dy);
-		
+
 		L2Party party = activeChar.getParty();
 		if(party != null && activeChar.getLastPartyPositionDistance(_x, _y, _z) > 150)
 		{

+ 17 - 0
L2_GameServer/java/com/l2jserver/gameserver/skills/Formulas.java

@@ -2879,4 +2879,21 @@ public final class Formulas
 
 		return reflect;
 	}
+
+    /**
+     * Calculate and apply damage caused by falling, character will not die
+     * @param cha
+     * @param fallHeight
+     * @return
+     */
+    public static double calcFallDam(L2Character cha, int fallHeight)
+    {
+    	if (!Config.ENABLE_FALLING_DAMAGE || fallHeight < 0)
+    		return 0;
+
+    	final double damage = cha.calcStat(Stats.FALL, fallHeight * cha.getMaxHp() / 1000, null, null);
+		cha.reduceCurrentHp(Math.min(damage, cha.getCurrentHp() - 1), null, false, true, null);
+
+		return damage;
+    }
 }

+ 1 - 0
L2_GameServer/java/com/l2jserver/gameserver/skills/Stats.java

@@ -100,6 +100,7 @@ public enum Stats
 	
 	// stats of various abilities
 	BREATH("breath"),
+	FALL("fall"),
 	//
 	AGGRESSION("aggression"), // locks a mob on tank caster
 	BLEED("bleed"), // by daggers, like poison

+ 5 - 0
L2_GameServer/java/com/l2jserver/gameserver/templates/chars/L2PcTemplate.java

@@ -132,4 +132,9 @@ public class L2PcTemplate extends L2CharTemplate
 			return _equipped;
 		}
 	}
+
+	public final int getFallHeight()
+	{
+		return 333; // TODO: unhardcode it
+	}
 }

+ 12 - 0
L2_GameServer/java/config/General.properties

@@ -376,6 +376,18 @@ ForceGeodata = True
 CoordSynchronize = -1
 
 
+# ---------------------------------------------------------------------------
+# Falling Damage
+# ---------------------------------------------------------------------------
+# Allow characters to receive damage from falling.
+# CoordSynchronize = 2 is recommended.
+# True - enabled.
+# False - disabled.
+# Auto - True if geodata enabled and False if disabled.
+# Default: Auto
+EnableFallingDamage = Auto
+
+
 # ---------------------------------------------------------------------------
 # Features
 # ---------------------------------------------------------------------------