| Attached Files | 
 fix_cannon_range.patch  (1,497 bytes) 2007-07-21 00:00   Index: rts/Sim/Weapons/Cannon.cpp
===================================================================
--- rts/Sim/Weapons/Cannon.cpp	(revision 4053)
+++ rts/Sim/Weapons/Cannon.cpp	(working copy)
@@ -238,6 +238,7 @@
 float CCannon::GetRange2D(float yDiff) const
 {
 	float root1 = 1 + 2*gs->gravity*yDiff/(projectileSpeed*projectileSpeed);
+	logOutput << "root1 " << root1 << "dH " << yDiff << "\n";
 	if(root1 < 0){
 		return 0;
 	} else {
Index: rts/Sim/Weapons/Weapon.cpp
===================================================================
--- rts/Sim/Weapons/Weapon.cpp	(revision 4053)
+++ rts/Sim/Weapons/Weapon.cpp	(working copy)
@@ -550,7 +550,7 @@
 		return false;
 
 	float3 dif=pos-weaponPos;
-	float heightDiff;
+	float heightDiff; // negative when target below owner
 
 	if (targetBorder != 0 && unit) {
 		float3 diff(dif);
@@ -564,16 +564,16 @@
 			//logOutput << "outside\n";
 		}
 		//geometricObjects->AddLine(weaponMuzzlePos, weaponMuzzlePos+dif, 3, 0, 16);
-		heightDiff = owner->pos.y - (weaponPos.y + dif.y);
+		heightDiff = (weaponPos.y + dif.y) - owner->pos.y;
 	} else {
-		heightDiff = owner->pos.y - pos.y;
+		heightDiff = pos.y - owner->pos.y;
 	}
 
 	float r;
 	if (!unit || cylinderTargetting < 0.01) {
-		r=GetRange2D(heightDiff);
+		r=GetRange2D(heightDiff*heightMod);
 	} else {
-		if (cylinderTargetting * unit->radius > heightDiff) {
+		if (cylinderTargetting * unit->radius > fabs(heightDiff)*heightMod) {
 			r = GetRange2D(0);
 		} else {
 			r = 0;
 fix_cannon_range_v2.patch  (2,084 bytes) 2007-07-21 11:21   Index: rts/Sim/Weapons/Weapon.cpp
===================================================================
--- rts/Sim/Weapons/Weapon.cpp	(revision 4053)
+++ rts/Sim/Weapons/Weapon.cpp	(working copy)
@@ -25,6 +25,7 @@
 #include "Sim/MoveTypes/TAAirMoveType.h"
 #include "creg/STL_List.h"
 #include "mmgr.h"
+#include "float3.h"
 
 CR_BIND_DERIVED(CWeapon, CObject, (NULL));
 
@@ -550,7 +551,7 @@
 		return false;
 
 	float3 dif=pos-weaponPos;
-	float heightDiff;
+	float heightDiff; // negative when target below owner
 
 	if (targetBorder != 0 && unit) {
 		float3 diff(dif);
@@ -564,16 +565,16 @@
 			//logOutput << "outside\n";
 		}
 		//geometricObjects->AddLine(weaponMuzzlePos, weaponMuzzlePos+dif, 3, 0, 16);
-		heightDiff = owner->pos.y - (weaponPos.y + dif.y);
+		heightDiff = (weaponPos.y + dif.y) - owner->pos.y;
 	} else {
-		heightDiff = owner->pos.y - pos.y;
+		heightDiff = pos.y - owner->pos.y;
 	}
 
 	float r;
 	if (!unit || cylinderTargetting < 0.01) {
-		r=GetRange2D(heightDiff);
+		r=GetRange2D(heightDiff*heightMod);
 	} else {
-		if (cylinderTargetting * unit->radius > heightDiff) {
+		if (cylinderTargetting * unit->radius > fabs(heightDiff)*heightMod) {
 			r = GetRange2D(0);
 		} else {
 			r = 0;
Index: rts/Sim/Weapons/WeaponDefHandler.cpp
===================================================================
--- rts/Sim/Weapons/WeaponDefHandler.cpp	(revision 4053)
+++ rts/Sim/Weapons/WeaponDefHandler.cpp	(working copy)
@@ -325,9 +325,14 @@
 	sunparser->GetDef(weaponDefs[id].visuals.pulseSpeed, "1", weaponname + "\\pulseSpeed");
 	sunparser->GetDef(weaponDefs[id].largeBeamLaser, "0", weaponname + "\\largeBeamLaser");
 
-	weaponDefs[id].heightmod = 0.2f;
-	if(weaponDefs[id].type == "Cannon")
-		weaponDefs[id].heightmod = 0.8f;
+	std::string hmod = sunparser->SGetValueDef("", weaponname+"\\heightmod");
+	if (hmod == "") {
+		weaponDefs[id].heightmod = 0.2f;
+		if(weaponDefs[id].type == "Cannon")
+			weaponDefs[id].heightmod = 0.8f;
+	} else {
+		weaponDefs[id].heightmod = atof(hmod.c_str());
+	}
 
 	weaponDefs[id].supplycost = 0.0f;
 
 more_fixes_to_weapons.patch  (1,550 bytes) 2007-07-25 19:14   Index: rts/Rendering/GL/glExtra.cpp
===================================================================
--- rts/Rendering/GL/glExtra.cpp	(revision 4092)
+++ rts/Rendering/GL/glExtra.cpp	(working copy)
@@ -55,7 +55,7 @@
 		pos.y = ground->GetHeight(pos.x, pos.z);
 		float heightDiff = (pos.y - center.y)/2;
 		rad -= heightDiff * slope;
-		float adjRadius = weapon ? weapon->GetRange2D(heightDiff) : rad;
+		float adjRadius = weapon ? weapon->GetRange2D(heightDiff*weapon->heightMod) : rad;
 		float adjustment = rad/2;
 		float ydiff = 0;
 		int j;
@@ -72,7 +72,7 @@
 			ydiff = fabs(pos.y - newY);
 			pos.y = newY;
 			heightDiff = (pos.y - center.y);
-			adjRadius = weapon ? weapon->GetRange2D(heightDiff) : rad;
+			adjRadius = weapon ? weapon->GetRange2D(heightDiff*weapon->heightMod) : rad;
 		}
 		pos.x = center.x + (sinR * adjRadius);
 		pos.z = center.z + (cosR * adjRadius);
Index: rts/Sim/Weapons/WeaponDefHandler.cpp
===================================================================
--- rts/Sim/Weapons/WeaponDefHandler.cpp	(revision 4092)
+++ rts/Sim/Weapons/WeaponDefHandler.cpp	(working copy)
@@ -327,9 +327,12 @@
 
 	std::string hmod = sunparser->SGetValueDef("", weaponname+"\\heightmod");
 	if (hmod == "") {
-		weaponDefs[id].heightmod = 0.2f;
 		if(weaponDefs[id].type == "Cannon")
 			weaponDefs[id].heightmod = 0.8f;
+		else if (weaponDefs[id].type == "BeamLaser")
+			weaponDefs[id].heightmod = 1.0f;
+		else
+			weaponDefs[id].heightmod = 0.2f;
 	} else {
 		weaponDefs[id].heightmod = atof(hmod.c_str());
 	}
 more_cannon_range_tweaks.patch  (6,037 bytes) 2007-08-06 19:17   Index: rts/Lua/LuaWeaponDefs.cpp
===================================================================
--- rts/Lua/LuaWeaponDefs.cpp	(revision 4143)
+++ rts/Lua/LuaWeaponDefs.cpp	(working copy)
@@ -549,6 +549,7 @@
 	ADD_FLOAT("targetBorder", wd.targetBorder);
 	ADD_FLOAT("cylinderTargetting", wd.cylinderTargetting);
 	ADD_FLOAT("minIntensity", wd.minIntensity);
+	ADD_FLOAT("heightBoostFactor", wd.heightBoostFactor);
 
 //	CExplosionGenerator *explosionGenerator;
 
Index: rts/Sim/Units/UnitLoader.cpp
===================================================================
--- rts/Sim/Units/UnitLoader.cpp	(revision 4143)
+++ rts/Sim/Units/UnitLoader.cpp	(working copy)
@@ -466,6 +466,7 @@
 	weapon->targetBorder = weapondef->targetBorder;
 	weapon->cylinderTargetting = weapondef->cylinderTargetting;
 	weapon->minIntensity = weapondef->minIntensity;
+	weapon->heightBoostFactor = weapondef->heightBoostFactor;
 	weapon->collisionFlags = weapondef->collisionFlags;
 	weapon->Init();
 
Index: rts/Sim/Weapons/Cannon.cpp
===================================================================
--- rts/Sim/Weapons/Cannon.cpp	(revision 4143)
+++ rts/Sim/Weapons/Cannon.cpp	(working copy)
@@ -26,6 +26,7 @@
 	CR_MEMBER(minPredict),
 	CR_MEMBER(highTrajectory),
 	CR_MEMBER(selfExplode),
+	CR_MEMBER(rangeFactor),
 	CR_RESERVED(16)
 	));
 
@@ -37,6 +38,7 @@
 : CWeapon(owner)
 {
 	highTrajectory=false;
+	rangeFactor = 1;
 }
 
 void CCannon::Init(void)
@@ -48,6 +50,18 @@
 		maxPredict=projectileSpeed*1.41f/-gs->gravity;
 	}
 	CWeapon::Init();
+
+	// initialize range factor
+	rangeFactor = 1;
+	rangeFactor = (float)range/GetRange2D(0);
+	// do not extend range if the modder specified speed too low
+	// for the projectile to reach specified range
+	if (rangeFactor > 1.f)
+		rangeFactor = 1.f;
+	// some magical (but working) equations
+	// TODO find something better?
+	if (heightBoostFactor < 0.f)
+		heightBoostFactor = (2.f - rangeFactor)/sqrt(rangeFactor);
 }
 
 CCannon::~CCannon()
@@ -237,10 +251,18 @@
 
 float CCannon::GetRange2D(float yDiff) const
 {
-	float root1 = 1 + 2*gs->gravity*yDiff/(projectileSpeed*projectileSpeed);
+	const float factor = 0.7071067f; // sin pi/4 == cos pi/4
+	const float speed2d = projectileSpeed*factor; // speed in one direction in max-range case
+	const float speed2dSq = speed2d*speed2d;
+
+	if (yDiff < 0)
+		// smooth a bit but keep working with short range units
+		yDiff *= heightBoostFactor * min(1.f, -yDiff/min(200.f, range*0.5f));
+
+	float root1 = speed2dSq + 2*gs->gravity*yDiff;
 	if(root1 < 0){
 		return 0;
 	} else {
-		return range * sqrt(root1);
+		return rangeFactor*(speed2dSq + speed2d*sqrt(root1))/(-gs->gravity);
 	}
 }
Index: rts/Sim/Weapons/Cannon.h
===================================================================
--- rts/Sim/Weapons/Cannon.h	(revision 4143)
+++ rts/Sim/Weapons/Cannon.h	(working copy)
@@ -7,9 +7,12 @@
 
 #include "Weapon.h"
 
-class CCannon : public CWeapon  
+class CCannon : public CWeapon
 {
 	CR_DECLARE(CCannon);
+protected:
+	float rangeFactor;	/// this is used to keep range true to range tag
+
 public:
 	CCannon(CUnit* owner);
 	virtual ~CCannon();
Index: rts/Sim/Weapons/Weapon.cpp
===================================================================
--- rts/Sim/Weapons/Weapon.cpp	(revision 4143)
+++ rts/Sim/Weapons/Weapon.cpp	(working copy)
@@ -87,6 +87,7 @@
 	CR_MEMBER(targetBorder),
 	CR_MEMBER(cylinderTargetting),
 	CR_MEMBER(minIntensity),
+	CR_MEMBER(heightBoostFactor),
 	CR_MEMBER(collisionFlags),
 	CR_MEMBER(fuelUsage),
 	CR_MEMBER(weaponNum),
@@ -159,6 +160,7 @@
 	targetBorder(0.f),
 	cylinderTargetting(0.f),
 	minIntensity(0.f),
+	heightBoostFactor(-1.f),
 	collisionFlags(0),
 	fuelUsage(0)
 {
Index: rts/Sim/Weapons/Weapon.h
===================================================================
--- rts/Sim/Weapons/Weapon.h	(revision 4143)
+++ rts/Sim/Weapons/Weapon.h	(working copy)
@@ -129,6 +129,7 @@
 	float targetBorder;  // if nonzero, targetting units will TryTarget at the edge of collision sphere (radius*tag value, [-1;1]) instead of its centre
 	float cylinderTargetting;	//if greater than 0, range will be checked in a cylinder (height=unitradius*cylinderTargetting) instead of a sphere
 	float minIntensity;	// for beamlasers - always hit with some minimum intensity (a damage coeffcient normally dependent on distance). do not confuse with intensity tag, it's completely unrelated.
+	float heightBoostFactor;	//controls cannon range height boost. default: -1 -- automatically calculate a more or less sane value
 
 	unsigned int collisionFlags;
 
Index: rts/Sim/Weapons/WeaponDefHandler.cpp
===================================================================
--- rts/Sim/Weapons/WeaponDefHandler.cpp	(revision 4143)
+++ rts/Sim/Weapons/WeaponDefHandler.cpp	(working copy)
@@ -383,6 +383,8 @@
 		weaponDefs[id].visuals.colorMap = CColorMap::LoadFromDefString(colormap);
 	}
 
+	sunparser->GetDef(weaponDefs[id].heightBoostFactor, "-1", weaponname + "\\HeightBoostFactor");
+
 	//get some weapon specific defaults
 	if(weaponDefs[id].type=="Cannon"){
 		//CExplosiveProjectile
Index: rts/Sim/Weapons/WeaponDefHandler.h
===================================================================
--- rts/Sim/Weapons/WeaponDefHandler.h	(revision 4143)
+++ rts/Sim/Weapons/WeaponDefHandler.h	(working copy)
@@ -178,6 +178,7 @@
 	float targetBorder;		//if nonzero, targetting units will TryTarget at the edge of collision sphere (radius*tag value, [-1;1]) instead of its centre
 	float cylinderTargetting;	//if greater than 0, range will be checked in a cylinder (height=unitradius*cylinderTargetting) instead of a sphere
 	float minIntensity;		// for beamlasers - always hit with some minimum intensity (a damage coeffcient normally dependent on distance). do not confuse with intensity tag, it's completely unrelated.
+	float heightBoostFactor;	//controls cannon range height boost. default: -1 -- automatically calculate a more or less sane value
 
 	unsigned int collisionFlags;
 
 | 
|---|