Attached Files |
-
targetBorder.diff (10,828 bytes) 2007-06-17 15:05
Index: Lua/LuaWeaponDefs.cpp
===================================================================
--- Lua/LuaWeaponDefs.cpp (revision 3823)
+++ Lua/LuaWeaponDefs.cpp (working copy)
@@ -75,7 +75,7 @@
HSTR_PUSH(L, "__index");
lua_pushlightuserdata(L, (void*)wd);
lua_pushcclosure(L, WeaponDefIndex, 1);
- lua_rawset(L, -3); // closure
+ lua_rawset(L, -3); // closure
HSTR_PUSH(L, "__newindex");
lua_pushlightuserdata(L, (void*)wd);
@@ -110,7 +110,7 @@
static int WeaponDefIndex(lua_State* L)
{
- // not a default value
+ // not a default value
if (!lua_isstring(L, 2)) {
lua_rawget(L, 1);
return 1;
@@ -119,7 +119,7 @@
const char* name = lua_tostring(L, 2);
ParamMap::const_iterator it = paramMap.find(name);
- // not a default value
+ // not a default value
if (paramMap.find(name) == paramMap.end()) {
lua_rawget(L, 1);
return 1;
@@ -171,7 +171,7 @@
const char* name = lua_tostring(L, 2);
ParamMap::const_iterator it = paramMap.find(name);
-
+
// not a default value, set it
if (paramMap.find(name) == paramMap.end()) {
lua_rawset(L, 1);
@@ -186,7 +186,7 @@
luaL_error(L, "Attempt to write WeaponDefs[%d].%s", wd->id, name);
return 0;
}
-
+
// Definition editing
const DataElement& elem = it->second;
const char* p = ((const char*)wd) + elem.offset;
@@ -217,7 +217,7 @@
luaL_error(L, "ERROR_TYPE in WeaponDefs __newindex");
}
}
-
+
return 0;
}
@@ -266,7 +266,7 @@
}
// start the user parameters,
// remove the internal key and push a nil
- lua_settop(L, 1);
+ lua_settop(L, 1);
lua_pushnil(L);
}
}
@@ -314,8 +314,8 @@
LuaPushNamedNumber(L, typeList[i].c_str(), d.damages[i]);
}
lua_rawset(L, -3);
-
- return 1;
+
+ return 1;
}
@@ -417,9 +417,9 @@
static bool InitParamMap()
{
- paramMap["next"] = DataElement(READONLY_TYPE);
- paramMap["pairs"] = DataElement(READONLY_TYPE);
-
+ paramMap["next"] = DataElement(READONLY_TYPE);
+ paramMap["pairs"] = DataElement(READONLY_TYPE);
+
// dummy WeaponDef for offset generation
const WeaponDef wd;
const char* start = ADDRESS(wd);
@@ -481,7 +481,7 @@
ADD_BOOL("noAutoTarget", wd.noAutoTarget);
ADD_BOOL("manualFire", wd.manualfire);
ADD_INT("targetable", wd.targetable);
- ADD_BOOL("stockpile", wd.stockpile);
+ ADD_BOOL("stockpile", wd.stockpile);
ADD_INT("interceptor", wd.interceptor);
ADD_FLOAT("coverageRange", wd.coverageRange);
@@ -541,6 +541,7 @@
ADD_INT("interceptedByShieldType", wd.interceptedByShieldType);
ADD_BOOL("avoidFriendly", wd.avoidFriendly);
+ ADD_FLOAT("targetBorder", wd.targetBorder);
// CExplosionGenerator *explosionGenerator;
Index: Sim/Units/CommandAI/MobileCAI.cpp
===================================================================
--- Sim/Units/CommandAI/MobileCAI.cpp (revision 3823)
+++ Sim/Units/CommandAI/MobileCAI.cpp (working copy)
@@ -36,6 +36,7 @@
commandPos2(ZeroVector),
lastPC(-1),
cancelDistance(1024),
+ lastCloseInTry(-1),
slowGuard(false),
moveDir(gs->randFloat() > 0.5)
{
@@ -597,7 +598,10 @@
float3 diff = owner->pos - orderTarget->pos;
// if w->AttackUnit() returned true then we are already
// in range with our biggest weapon so stop moving
- if (b2) {
+ // also make sure that we're not locked in close-in/in-range state loop
+ // due to rotates invoked by in-range or out-of-range states
+ // FIXME kill magic frame number
+ if (b2 && gs->frameNum > lastCloseInTry + 40) {
StopMove();
owner->AttackUnit(orderTarget, c.id == CMD_DGUN);
owner->moveType->KeepPointingTo(orderTarget,
@@ -631,6 +635,7 @@
> (10 + orderTarget->pos.distance2D(owner->pos) * 0.2f)) {
float3 fix = orderTarget->pos + owner->posErrorVector * 128;
SetGoal(fix, owner->pos);
+ lastCloseInTry = gs->frameNum;
}
}
Index: Sim/Units/CommandAI/MobileCAI.h
===================================================================
--- Sim/Units/CommandAI/MobileCAI.h (revision 3823)
+++ Sim/Units/CommandAI/MobileCAI.h (working copy)
@@ -57,6 +57,7 @@
protected:
int cancelDistance;
+ int lastCloseInTry;
bool slowGuard;
bool moveDir;
void PushOrUpdateReturnFight() {
Index: Sim/Units/UnitDef.h
===================================================================
--- Sim/Units/UnitDef.h (revision 3823)
+++ Sim/Units/UnitDef.h (working copy)
@@ -89,7 +89,7 @@
int imageSizeX;
int imageSizeY;
std::string buildpicname;
-
+
UnitDef* decoyDef;
int aihint;
@@ -256,7 +256,7 @@
MoveData* movedata;
// unsigned char* yardmapLevels[6];
unsigned char* yardmaps[4]; //Iterations of the Ymap for building rotation
-
+
int xsize; //each size is 8 units
int ysize; //each size is 8 units
Index: Sim/Units/UnitLoader.cpp
===================================================================
--- Sim/Units/UnitLoader.cpp (revision 3823)
+++ Sim/Units/UnitLoader.cpp (working copy)
@@ -464,6 +464,7 @@
weapon->fuelUsage = udw->fuelUsage;
weapon->avoidFriendly = weapondef->avoidFriendly;
weapon->avoidFeature = weapondef->avoidFeature;
+ weapon->targetBorder = weapondef->targetBorder;
weapon->collisionFlags = weapondef->collisionFlags;
weapon->Init();
Index: Sim/Weapons/BeamLaser.cpp
===================================================================
--- Sim/Weapons/BeamLaser.cpp (revision 3823)
+++ Sim/Weapons/BeamLaser.cpp (working copy)
@@ -85,6 +85,7 @@
}
float3 dir=pos-weaponPos;
+
float length=dir.Length();
if(length==0)
return true;
@@ -133,6 +134,7 @@
}
}
dir+=(salvoError)*(1-owner->limExperience*0.7f);
+
dir.Normalize();
FireInternal(dir, false);
@@ -152,6 +154,11 @@
bool tryAgain=true;
CUnit* hit;
+
+ if (targetType == Target_Unit && targetUnit && targetBorder != 0) {
+ maxLength += targetUnit->radius*targetBorder;
+ }
+
for(int tries=0;tries<5 && tryAgain;++tries){
tryAgain=false;
hit=0;
@@ -172,6 +179,7 @@
tryAgain=true;
}
}
+
hitPos=curPos+dir*length;
float baseAlpha=weaponDef->intensity*255;
Index: Sim/Weapons/Weapon.cpp
===================================================================
--- Sim/Weapons/Weapon.cpp (revision 3823)
+++ Sim/Weapons/Weapon.cpp (working copy)
@@ -83,6 +83,7 @@
CR_MEMBER(hasCloseTarget),
CR_MEMBER(avoidFriendly),
CR_MEMBER(avoidFeature),
+ CR_MEMBER(targetBorder),
CR_MEMBER(collisionFlags),
CR_MEMBER(fuelUsage)));
@@ -149,6 +150,7 @@
hasCloseTarget(false),
avoidFriendly(true),
avoidFeature(true),
+ targetBorder(false),
collisionFlags(0),
fuelUsage(0)
{
@@ -541,8 +548,14 @@
return false;
float3 dif=pos-weaponPos;
+ float r=GetRange2D(owner->pos.y-pos.y);
- float r=GetRange2D(owner->pos.y-pos.y);
+ if (targetBorder != 0 && unit) {
+ float3 diff(dif);
+ diff.Normalize();
+ dif -= diff*(unit->radius*targetBorder); // a little bit inside the sphere
+ }
+
if(dif.SqLength2D()>=r*r)
return false;
Index: Sim/Weapons/Weapon.h
===================================================================
--- Sim/Weapons/Weapon.h (revision 3823)
+++ Sim/Weapons/Weapon.h (working copy)
@@ -118,12 +118,13 @@
int lastErrorVectorUpdate;
CWeapon* slavedTo; //use this weapon to choose target
-
+
float3 mainDir; //main aim dir of weapon
float maxMainDirAngleDif; //how far away from main aim dir the weapon can aim at something (as an acos value)
bool avoidFriendly; //if true tried to avoid friendly Units when aiming.
bool avoidFeature; //if true try to avoid Features while aiming.
+ float targetBorder; // if nonzero, targetting units will TryTarget at the edge of collision sphere (radius*tag value, [-1;1]) instead of its centre
unsigned int collisionFlags;
float fuelUsage;
Index: Sim/Weapons/WeaponDefHandler.cpp
===================================================================
--- Sim/Weapons/WeaponDefHandler.cpp (revision 3823)
+++ Sim/Weapons/WeaponDefHandler.cpp (working copy)
@@ -91,6 +91,16 @@
if(!collideFeature)
weaponDefs[id].collisionFlags+=COLLISION_NOFEATURE;
+ sunparser->GetDef(weaponDefs[id].targetBorder, "0", weaponname + "\\TargetBorder");
+ if (weaponDefs[id].targetBorder > 1.f) {
+ logOutput.Print("warning: targetBorder truncated to 1 (was %f)", weaponDefs[id].targetBorder);
+ weaponDefs[id].targetBorder = 1.f;
+ } else if (weaponDefs[id].targetBorder < -1.f) {
+ logOutput.Print("warning: targetBorder truncated to -1 (was %f)", weaponDefs[id].targetBorder);
+ weaponDefs[id].targetBorder = -1.f;
+ }
+
+
sunparser->GetDef(weaponDefs[id].dropped, "0", weaponname + "\\dropped");
sunparser->GetDef(lineofsight, "0", weaponname + "\\lineofsight");
sunparser->GetDef(ballistic, "0", weaponname + "\\ballistic");
@@ -119,7 +129,7 @@
sunparser->GetDef(weaponDefs[id].laserflaresize, "15", weaponname + "\\laserflaresize");
sunparser->GetDef(weaponDefs[id].intensity, "0.9", weaponname + "\\intensity");
sunparser->GetDef(weaponDefs[id].duration, "0.05", weaponname + "\\duration");
-
+
sunparser->GetDef(weaponDefs[id].visuals.sizeDecay, "0", weaponname + "\\sizeDecay");
sunparser->GetDef(weaponDefs[id].visuals.alphaDecay, "1", weaponname + "\\alphaDecay");
sunparser->GetDef(weaponDefs[id].visuals.separation, "1", weaponname + "\\separation");
@@ -576,7 +586,7 @@
if (inverted == true) {
for(int i=0; i < damageArrayHandler->numTypes; ++i) {
-
+
dynDamages[i] = damages[i] - (1 - pow(1 / range * travDist, exp)) * damages[i];
if (damageMin > 0) {
@@ -591,7 +601,7 @@
}
else {
for(int i=0; i < damageArrayHandler->numTypes; ++i) {
-
+
dynDamages[i] = (1 - pow(1 / range * travDist, exp)) * damages[i];
if (damageMin > 0) {
Index: Sim/Weapons/WeaponDefHandler.h
===================================================================
--- Sim/Weapons/WeaponDefHandler.h (revision 3823)
+++ Sim/Weapons/WeaponDefHandler.h (working copy)
@@ -86,7 +86,7 @@
bool manualfire; //use dgun button
int interceptor; //anti nuke
int targetable; //nuke (can be shot by interceptor)
- bool stockpile;
+ bool stockpile;
float coverageRange; //range of anti nuke
float intensity;
@@ -138,7 +138,7 @@
float tilelength;
float scrollspeed;
float pulseSpeed;
-
+
int stages;
float alphaDecay;
float sizeDecay;
@@ -172,6 +172,7 @@
bool avoidFriendly; //if true try to avoid friendly Units when aiming.
bool avoidFeature; //if true try to avoid Features while aiming.
+ float targetBorder; //if nonzero, targetting units will TryTarget at the edge of collision sphere (radius*tag value, [-1;1]) instead of its centre
unsigned int collisionFlags;
CExplosionGenerator *explosionGenerator; // can be zero for default explosions
-
targetborder_minintensity_cylinderTargetting_and_weaponMuzzlePos.diff (32,157 bytes) 2007-06-22 19:01
Index: rts/Game/GameHelper.cpp
===================================================================
--- rts/Game/GameHelper.cpp (revision 3829)
+++ rts/Game/GameHelper.cpp (working copy)
@@ -209,16 +209,17 @@
closeLength=length;
float3 closeVect=dif-dir*closeLength;
- float rad=(*ui)->radius;
- float tmp = rad * rad - closeVect.SqLength();
- if(tmp > 0 && length>closeLength+sqrt(tmp)){
+ /*float rad=(*ui)->radius;
+ float tmp = rad * rad - closeVect.SqLength();*/
+
+ /*if(tmp > 0 && length>closeLength+sqrt(tmp)){
length=closeLength-sqrt(tmp)*0.5f;
hit=*ui;
- }
-/* if(closeVect.SqLength() < (*ui)->sqRadius){
+ }*/
+ if(closeVect.SqLength() < (*ui)->sqRadius){
length=closeLength;
hit=*ui;
- }*/
+ }
}
}
return length;
Index: rts/Lua/LuaWeaponDefs.cpp
===================================================================
--- rts/Lua/LuaWeaponDefs.cpp (revision 3829)
+++ rts/Lua/LuaWeaponDefs.cpp (working copy)
@@ -75,7 +75,7 @@
HSTR_PUSH(L, "__index");
lua_pushlightuserdata(L, (void*)wd);
lua_pushcclosure(L, WeaponDefIndex, 1);
- lua_rawset(L, -3); // closure
+ lua_rawset(L, -3); // closure
HSTR_PUSH(L, "__newindex");
lua_pushlightuserdata(L, (void*)wd);
@@ -110,7 +110,7 @@
static int WeaponDefIndex(lua_State* L)
{
- // not a default value
+ // not a default value
if (!lua_isstring(L, 2)) {
lua_rawget(L, 1);
return 1;
@@ -119,7 +119,7 @@
const char* name = lua_tostring(L, 2);
ParamMap::const_iterator it = paramMap.find(name);
- // not a default value
+ // not a default value
if (paramMap.find(name) == paramMap.end()) {
lua_rawget(L, 1);
return 1;
@@ -171,7 +171,7 @@
const char* name = lua_tostring(L, 2);
ParamMap::const_iterator it = paramMap.find(name);
-
+
// not a default value, set it
if (paramMap.find(name) == paramMap.end()) {
lua_rawset(L, 1);
@@ -186,7 +186,7 @@
luaL_error(L, "Attempt to write WeaponDefs[%d].%s", wd->id, name);
return 0;
}
-
+
// Definition editing
const DataElement& elem = it->second;
const char* p = ((const char*)wd) + elem.offset;
@@ -217,7 +217,7 @@
luaL_error(L, "ERROR_TYPE in WeaponDefs __newindex");
}
}
-
+
return 0;
}
@@ -266,7 +266,7 @@
}
// start the user parameters,
// remove the internal key and push a nil
- lua_settop(L, 1);
+ lua_settop(L, 1);
lua_pushnil(L);
}
}
@@ -314,8 +314,8 @@
LuaPushNamedNumber(L, typeList[i].c_str(), d.damages[i]);
}
lua_rawset(L, -3);
-
- return 1;
+
+ return 1;
}
@@ -417,9 +417,9 @@
static bool InitParamMap()
{
- paramMap["next"] = DataElement(READONLY_TYPE);
- paramMap["pairs"] = DataElement(READONLY_TYPE);
-
+ paramMap["next"] = DataElement(READONLY_TYPE);
+ paramMap["pairs"] = DataElement(READONLY_TYPE);
+
// dummy WeaponDef for offset generation
const WeaponDef wd;
const char* start = ADDRESS(wd);
@@ -481,7 +481,7 @@
ADD_BOOL("noAutoTarget", wd.noAutoTarget);
ADD_BOOL("manualFire", wd.manualfire);
ADD_INT("targetable", wd.targetable);
- ADD_BOOL("stockpile", wd.stockpile);
+ ADD_BOOL("stockpile", wd.stockpile);
ADD_INT("interceptor", wd.interceptor);
ADD_FLOAT("coverageRange", wd.coverageRange);
@@ -541,6 +541,9 @@
ADD_INT("interceptedByShieldType", wd.interceptedByShieldType);
ADD_BOOL("avoidFriendly", wd.avoidFriendly);
+ ADD_FLOAT("targetBorder", wd.targetBorder);
+ ADD_FLOAT("cylinderTargetting", wd.cylinderTargetting);
+ ADD_FLOAT("minIntensity", wd.minIntensity);
// CExplosionGenerator *explosionGenerator;
Index: rts/Sim/Projectiles/ProjectileHandler.cpp
===================================================================
--- rts/Sim/Projectiles/ProjectileHandler.cpp (revision 3829)
+++ rts/Sim/Projectiles/ProjectileHandler.cpp (working copy)
@@ -31,8 +31,8 @@
CProjectileHandler* ph;
using namespace std;
-extern GLfloat FogBlack[];
-extern GLfloat FogLand[];
+extern GLfloat FogBlack[];
+extern GLfloat FogLand[];
CR_BIND(CProjectileHandler,);
@@ -137,7 +137,7 @@
wrecktex = textureAtlas->GetTextureWithBackup( "wrecktexture", "circularthingy" );
plasmatex = textureAtlas->GetTextureWithBackup( "plasmatexture", "circularthingy" );
-
+
groundFXAtlas = SAFE_NEW CTextureAtlas(2048, 2048);
//add all textures in groundfx section
ptex = resources.GetAllValues("resources\\graphics\\groundfx");
@@ -328,9 +328,9 @@
int numFlyingPieces = 0;
int drawnPieces = 0;
-
+
/* Putting in, say, viewport culling will deserve refactoring. */
-
+
/* 3DO */
unitDrawer->SetupForUnitDrawing();
@@ -376,27 +376,27 @@
for (int textureType = 1; textureType < flyings3oPieces.size(); textureType++){
/* TODO Skip this if there's no FlyingPieces. */
-
+
texturehandler->SetS3oTexture(textureType);
-
+
for (int team = 0; team < flyings3oPieces[textureType].size(); team++){
FlyingPiece_List * fpl = flyings3oPieces[textureType][team];
-
+
unitDrawer->SetS3OTeamColour(team);
-
+
va->Initialize();
-
+
numFlyingPieces += fpl->size();
-
+
for(std::list<FlyingPiece*>::iterator pi=fpl->begin();pi!=fpl->end();++pi){
CMatrix44f m;
m.Rotate((*pi)->rot,(*pi)->rotAxis);
float3 interPos=(*pi)->pos+(*pi)->speed*gu->timeOffset;
-
+
SS3OVertex * verts = (*pi)->verts;
-
+
float3 tp, tn;
-
+
for (int i = 0; i < 4; i++){
tp=m.Mul(verts[i].pos);
tn=m.Mul(verts[i].normal);
@@ -408,9 +408,9 @@
va->DrawArrayTN(GL_QUADS);
}
}
-
+
unitDrawer->CleanUpS3ODrawing();
-
+
/*
* TODO Nearly cut here.
*/
@@ -565,7 +565,7 @@
if(readmap->groundBlockingObjectMap[square]!=unit)
continue;
}
- //adjust projectile position so explosion happens at the correct position
+ //adjust projectile position so explosion happens at the correct position
p->pos = p->pos + p->speed*closeTime;
p->Collision(*ui);
break;
@@ -603,7 +603,7 @@
}
}
}
- }
+ }
}
void CProjectileHandler::AddGroundFlash(CGroundFlash* flash)
@@ -687,7 +687,7 @@
flyings3oPieces[textureType].push_back(fpl);
flyingPieces.push_back(fpl);
}
-
+
pieceList=flyings3oPieces[textureType][team];
FlyingPiece* fp=new FlyingPiece;
@@ -745,7 +745,7 @@
glDisable(GL_ALPHA_TEST);
glDisable(GL_FOG);
- unsigned char col[4];
+ unsigned char col[4];
float time=gu->lastFrameTime*gs->speedFactor*3;
float speed=1;
float size=1;
Index: rts/Sim/Projectiles/WeaponProjectile.cpp
===================================================================
--- rts/Sim/Projectiles/WeaponProjectile.cpp (revision 3829)
+++ rts/Sim/Projectiles/WeaponProjectile.cpp (working copy)
@@ -45,7 +45,7 @@
interceptTarget=0;
}
-CWeaponProjectile::CWeaponProjectile(const float3& pos,const float3& speed,CUnit* owner, CUnit* target,const float3 &targetPos, WeaponDef *weaponDef,CWeaponProjectile* interceptTarget, bool synced) :
+CWeaponProjectile::CWeaponProjectile(const float3& pos,const float3& speed,CUnit* owner, CUnit* target,const float3 &targetPos, WeaponDef *weaponDef,CWeaponProjectile* interceptTarget, bool synced) :
CProjectile(pos,speed,owner, synced),
weaponDef(weaponDef),
weaponDefName(weaponDef?weaponDef->name:std::string("")),
@@ -120,7 +120,7 @@
DamageArray dynDamages;
if (weaponDef->dynDamageExp > 0)
dynDamages = weaponDefHandler->DynamicDamages(weaponDef->damages, startpos, pos, weaponDef->dynDamageRange>0?weaponDef->dynDamageRange:weaponDef->range, weaponDef->dynDamageExp, weaponDef->dynDamageMin, weaponDef->dynDamageInverted);
-
+
helper->Explosion(pos,weaponDef->dynDamageExp>0?dynDamages:weaponDef->damages,weaponDef->areaOfEffect,weaponDef->edgeEffectiveness,weaponDef->explosionSpeed,owner,true,weaponDef->noExplode? 0.3f:1,weaponDef->noExplode || weaponDef->noSelfDamage, weaponDef->explosionGenerator,0,impactDir, weaponDef->id);
}
@@ -155,7 +155,7 @@
DamageArray dynDamages;
if (weaponDef->dynDamageExp > 0)
dynDamages = weaponDefHandler->DynamicDamages(weaponDef->damages, startpos, pos, weaponDef->dynDamageRange>0?weaponDef->dynDamageRange:weaponDef->range, weaponDef->dynDamageExp, weaponDef->dynDamageMin, weaponDef->dynDamageInverted);
-
+
helper->Explosion(pos,weaponDef->dynDamageExp>0?dynDamages:weaponDef->damages,weaponDef->areaOfEffect,weaponDef->edgeEffectiveness,weaponDef->explosionSpeed,owner,true,weaponDef->noExplode? 0.3f:1,weaponDef->noExplode,weaponDef->explosionGenerator,unit,impactDir, weaponDef->id);
}
@@ -226,7 +226,7 @@
transMatrix[12]=interPos.x;
transMatrix[13]=interPos.y;
transMatrix[14]=interPos.z;
- glMultMatrixf(&transMatrix[0]);
+ glMultMatrixf(&transMatrix[0]);
glCallList(modelDispList);
glPopMatrix();
Index: rts/Sim/Units/CommandAI/MobileCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/MobileCAI.cpp (revision 3829)
+++ rts/Sim/Units/CommandAI/MobileCAI.cpp (working copy)
@@ -42,6 +42,8 @@
CR_MEMBER(commandPos1),
CR_MEMBER(commandPos2),
+ CR_MEMBER(lastCloseInTry),
+
CR_MEMBER(cancelDistance),
CR_MEMBER(slowGuard),
CR_MEMBER(moveDir)
@@ -61,6 +63,7 @@
commandPos2(ZeroVector),
lastPC(-1),
cancelDistance(1024),
+ lastCloseInTry(-1),
slowGuard(false),
moveDir(gs->randFloat() > 0.5),
lastUserGoal(0,0,0)
@@ -81,6 +84,7 @@
commandPos2(ZeroVector),
lastPC(-1),
cancelDistance(1024),
+ lastCloseInTry(-1),
slowGuard(false),
moveDir(gs->randFloat() > 0.5)
{
@@ -582,7 +586,8 @@
// check if we have valid target parameter and that we aren't attacking ourselves
if (uh->units[unitID] != 0 && uh->units[unitID] != owner) {
float3 fix = uh->units[unitID]->pos + owner->posErrorVector * 128;
- SetGoal(fix, owner->pos);
+ float3 diff = float3(fix - owner->pos).Normalize();
+ SetGoal(fix - diff*uh->units[unitID]->radius, owner->pos);
// get ID of attack-order target unit
orderTarget = uh->units[unitID];
AddDeathDependence(orderTarget);
@@ -626,6 +631,7 @@
//bool b1 = owner->AttackUnit(orderTarget, c.id == CMD_DGUN);
bool b2 = false;
bool b3 = false;
+ float edgeFactor = 0.f; // percent offset to target center
if (owner->weapons.size() > 0) {
if (!(c.options & ALT_KEY) && SkipParalyzeTarget(orderTarget)) {
@@ -638,15 +644,21 @@
// can hit target with our first (meanest) one
b2 = w->TryTargetRotate(orderTarget, c.id == CMD_DGUN);
b3 = (w->range - (w->relWeaponPos).Length()) > (orderTarget->pos.distance(owner->pos));
+ edgeFactor = fabs(w->targetBorder);
}
float3 diff = owner->pos - orderTarget->pos;
// if w->AttackUnit() returned true then we are already
// in range with our biggest weapon so stop moving
+ // also make sure that we're not locked in close-in/in-range state loop
+ // due to rotates invoked by in-range or out-of-range states
if (b2) {
StopMove();
owner->AttackUnit(orderTarget, c.id == CMD_DGUN);
- owner->moveType->KeepPointingTo(orderTarget,
- min((float) (owner->losRadius * SQUARE_SIZE * 2), owner->maxRange * 0.9f), true);
+ // FIXME kill magic frame number
+ if (gs->frameNum > lastCloseInTry + MAX_CLOSE_IN_RETRY_TICKS) {
+ owner->moveType->KeepPointingTo(orderTarget,
+ min((float) (owner->losRadius * SQUARE_SIZE * 2), owner->maxRange * 0.9f), true);
+ }
}
// if (((first weapon range minus first weapon length greater than distance to target
@@ -675,7 +687,10 @@
else if ((orderTarget->pos + owner->posErrorVector * 128).distance2D(goalPos)
> (10 + orderTarget->pos.distance2D(owner->pos) * 0.2f)) {
float3 fix = orderTarget->pos + owner->posErrorVector * 128;
- SetGoal(fix, owner->pos);
+ float3 norm = float3(fix - owner->pos).Normalize();
+ SetGoal(fix - norm*(orderTarget->radius*edgeFactor*0.8f), owner->pos);
+ if (lastCloseInTry < gs->frameNum + MAX_CLOSE_IN_RETRY_TICKS)
+ lastCloseInTry = gs->frameNum;
}
}
Index: rts/Sim/Units/CommandAI/MobileCAI.h
===================================================================
--- rts/Sim/Units/CommandAI/MobileCAI.h (revision 3829)
+++ rts/Sim/Units/CommandAI/MobileCAI.h (working copy)
@@ -59,6 +59,7 @@
protected:
int cancelDistance;
+ int lastCloseInTry;
bool slowGuard;
bool moveDir;
void PushOrUpdateReturnFight() {
@@ -66,5 +67,6 @@
}
};
+#define MAX_CLOSE_IN_RETRY_TICKS 30
#endif /* MOBILECAI_H */
Index: rts/Sim/Units/UnitLoader.cpp
===================================================================
--- rts/Sim/Units/UnitLoader.cpp (revision 3829)
+++ rts/Sim/Units/UnitLoader.cpp (working copy)
@@ -466,6 +466,9 @@
weapon->fuelUsage = udw->fuelUsage;
weapon->avoidFriendly = weapondef->avoidFriendly;
weapon->avoidFeature = weapondef->avoidFeature;
+ weapon->targetBorder = weapondef->targetBorder;
+ weapon->cylinderTargetting = weapondef->cylinderTargetting;
+ weapon->minIntensity = weapondef->minIntensity;
weapon->collisionFlags = weapondef->collisionFlags;
weapon->Init();
Index: rts/Sim/Weapons/BeamLaser.cpp
===================================================================
--- rts/Sim/Weapons/BeamLaser.cpp (revision 3829)
+++ rts/Sim/Weapons/BeamLaser.cpp (working copy)
@@ -42,6 +42,7 @@
{
if(targetType!=Target_None){
weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x;
+ weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x;
if(!onlyForward){
wantedDir=targetPos-weaponPos;
wantedDir.Normalize();
@@ -84,7 +85,8 @@
return false;
}
- float3 dir=pos-weaponPos;
+ float3 dir=pos-weaponMuzzlePos;
+
float length=dir.Length();
if(length==0)
return true;
@@ -92,14 +94,14 @@
dir/=length;
if(!onlyForward){ //skip ground col testing for aircrafts
- float g=ground->LineGroundCol(weaponPos,pos);
+ float g=ground->LineGroundCol(weaponMuzzlePos,pos);
if(g>0 && g<length*0.9f)
return false;
}
- if(avoidFeature && helper->LineFeatureCol(weaponPos,dir,length))
+ if(avoidFeature && helper->LineFeatureCol(weaponMuzzlePos,dir,length))
return false;
- if(avoidFriendly && helper->TestCone(weaponPos,dir,length,(accuracy+sprayangle)*(1-owner->limExperience*0.7f),owner->allyteam,owner))
+ if(avoidFriendly && helper->TestCone(weaponMuzzlePos,dir,length,(accuracy+sprayangle)*(1-owner->limExperience*0.7f),owner->allyteam,owner))
return false;
return true;
}
@@ -125,7 +127,7 @@
if(salvoLeft==salvoSize-1){
if(fireSoundId)
sound->PlaySample(fireSoundId,owner,fireSoundVolume);
- dir=targetPos-weaponPos;
+ dir=targetPos-weaponMuzzlePos;
dir.Normalize();
oldDir=dir;
} else {
@@ -133,6 +135,7 @@
}
}
dir+=(salvoError)*(1-owner->limExperience*0.7f);
+
dir.Normalize();
FireInternal(dir, false);
@@ -145,13 +148,27 @@
if(owner->directControl)
rangeMod=0.95f;
#endif
+
float maxLength=range*rangeMod;
float curLength=0;
- float3 curPos=weaponPos;
+ float3 curPos=weaponMuzzlePos;
float3 hitPos;
bool tryAgain=true;
CUnit* hit;
+
+ // increase range if targets are searched for in a cylinder
+ if (cylinderTargetting > 0.01) {
+ const float3 up(0, owner->radius*cylinderTargetting, 0);
+ const float uplen = up.dot(dir);
+ maxLength = sqrt(maxLength*maxLength + uplen*uplen);
+ }
+
+ // increase range if targetting edge of hitsphere
+ if (targetType == Target_Unit && targetUnit && targetBorder != 0) {
+ maxLength += targetUnit->radius*targetBorder;
+ }
+
for(int tries=0;tries<5 && tryAgain;++tries){
tryAgain=false;
hit=0;
@@ -172,6 +189,7 @@
tryAgain=true;
}
}
+
hitPos=curPos+dir*length;
float baseAlpha=weaponDef->intensity*255;
@@ -187,12 +205,20 @@
curLength+=length;
dir=newDir;
}
- float intensity=1-(curLength)/(range*2);
+
+ // fix negative damage when hitting big spheres
+ float actualRange = range;
+ if (hit && targetBorder > 0) {
+ actualRange += hit->radius*targetBorder;
+ }
+ // make it possible to always hit with some minimal intensity (melee weapons have use for that)
+ float intensity=max(minIntensity, 1-(curLength)/(actualRange*2));
+
if(curLength<maxLength) {
// Dynamic Damage
DamageArray dynDamages;
if (weaponDef->dynDamageExp > 0)
- dynDamages = weaponDefHandler->DynamicDamages(weaponDef->damages, weaponPos, curPos, weaponDef->dynDamageRange>0?weaponDef->dynDamageRange:weaponDef->range, weaponDef->dynDamageExp, weaponDef->dynDamageMin, weaponDef->dynDamageInverted);
+ dynDamages = weaponDefHandler->DynamicDamages(weaponDef->damages, weaponMuzzlePos, curPos, weaponDef->dynDamageRange>0?weaponDef->dynDamageRange:weaponDef->range, weaponDef->dynDamageExp, weaponDef->dynDamageMin, weaponDef->dynDamageInverted);
helper->Explosion(hitPos, weaponDef->dynDamageExp>0?dynDamages*(intensity*damageMul):weaponDef->damages*(intensity*damageMul), areaOfEffect, weaponDef->edgeEffectiveness, weaponDef->explosionSpeed,owner, true, 1.0f, false, weaponDef->explosionGenerator, hit, dir, weaponDef->id);
}
Index: rts/Sim/Weapons/Weapon.cpp
===================================================================
--- rts/Sim/Weapons/Weapon.cpp (revision 3829)
+++ rts/Sim/Weapons/Weapon.cpp (working copy)
@@ -56,9 +56,11 @@
CR_MEMBER(subClassReady),
CR_MEMBER(onlyForward),
CR_MEMBER(weaponPos),
+ CR_MEMBER(weaponMuzzlePos),
CR_MEMBER(lastRequest),
CR_MEMBER(damages),
CR_MEMBER(relWeaponPos),
+ CR_MEMBER(relWeaponMuzzlePos),
CR_MEMBER(muzzleFlareSize),
CR_MEMBER(lastTargetRetry),
CR_MEMBER(areaOfEffect),
@@ -83,6 +85,9 @@
CR_MEMBER(hasCloseTarget),
CR_MEMBER(avoidFriendly),
CR_MEMBER(avoidFeature),
+ CR_MEMBER(targetBorder),
+ CR_MEMBER(cylinderTargetting),
+ CR_MEMBER(minIntensity),
CR_MEMBER(collisionFlags),
CR_MEMBER(fuelUsage),
CR_MEMBER(weaponNum)
@@ -127,8 +132,10 @@
subClassReady(true),
onlyForward(false),
weaponPos(0,0,0),
+ weaponMuzzlePos(0,0,0),
lastRequest(0),
relWeaponPos(0,1,0),
+ relWeaponMuzzlePos(0,1,0),
muzzleFlareSize(1),
lastTargetRetry(-100),
areaOfEffect(1),
@@ -151,6 +158,9 @@
hasCloseTarget(false),
avoidFriendly(true),
avoidFeature(true),
+ targetBorder(0.f),
+ cylinderTargetting(0.f),
+ minIntensity(0.f),
collisionFlags(0),
fuelUsage(0)
{
@@ -164,15 +174,20 @@
void CWeapon::Update()
{
+ // do not fire at cloaked units
+ if(targetType == Target_Unit && targetUnit && targetUnit->isCloaked) {
+ HoldFire();
+ return;
+ }
+
if(hasCloseTarget){
std::vector<int> args;
args.push_back(0);
- if(useWeaponPosForAim){
- owner->cob->Call(COBFN_QueryPrimary+weaponNum,args);
- } else {
- owner->cob->Call(COBFN_AimFromPrimary+weaponNum,args);
- }
+ owner->cob->Call(COBFN_AimFromPrimary+weaponNum,args);
relWeaponPos=owner->localmodel->GetPiecePos(args[0]);
+
+ owner->cob->Call(COBFN_QueryPrimary+weaponNum,args);
+ relWeaponMuzzlePos=owner->localmodel->GetPiecePos(args[0]);
}
if(targetType==Target_Unit){
@@ -249,15 +264,15 @@
&& subClassReady
&& reloadStatus<=gs->frameNum
&& (!weaponDef->stockpile || numStockpiled)
- && (weaponDef->waterweapon || weaponPos.y>0)
+ && (weaponDef->waterweapon || weaponMuzzlePos.y>0)
&& (owner->unitDef->maxFuel==0 || owner->currentFuel > 0)
){
if ((weaponDef->stockpile || (gs->Team(owner->team)->metal>=metalFireCost && gs->Team(owner->team)->energy>=energyFireCost))) {
std::vector<int> args;
args.push_back(0);
owner->cob->Call(COBFN_QueryPrimary+weaponNum,args);
- relWeaponPos=owner->localmodel->GetPiecePos(args[0]);
- weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x;
+ relWeaponMuzzlePos=owner->localmodel->GetPiecePos(args[0]);
+ weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x;
useWeaponPosForAim=reloadTime/16+8;
if(TryTarget(targetPos,haveUserTarget,targetUnit)){
@@ -310,10 +325,16 @@
std::vector<int> args;
args.push_back(0);
- owner->cob->Call(/*COBFN_AimFromPrimary+weaponNum/*/COBFN_QueryPrimary+weaponNum/**/,args);
+ owner->cob->Call(COBFN_AimFromPrimary+weaponNum,args);
relWeaponPos=owner->localmodel->GetPiecePos(args[0]);
+
+ owner->cob->Call(/*COBFN_AimFromPrimary+weaponNum*/COBFN_QueryPrimary+weaponNum/**/,args);
+ relWeaponMuzzlePos=owner->localmodel->GetPiecePos(args[0]);
+
weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x;
+ weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x;
+
// logOutput.Print("RelPosFire %f %f %f",relWeaponPos.x,relWeaponPos.y,relWeaponPos.z);
if (owner->unitDef->decloakOnFire && (owner->scriptCloak <= 2)) {
@@ -353,9 +374,9 @@
if(!weaponDef->waterweapon && pos.y<1)
pos.y=1;
- weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x;
- if(weaponPos.y<ground->GetHeight2(weaponPos.x,weaponPos.z))
- weaponPos=owner->pos+UpVector*10; //hope that we are underground because we are a popup weapon and will come above ground later
+ weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x;
+ if(weaponMuzzlePos.y<ground->GetHeight2(weaponMuzzlePos.x,weaponMuzzlePos.z))
+ weaponMuzzlePos=owner->pos+UpVector*10; //hope that we are underground because we are a popup weapon and will come above ground later
if(!TryTarget(pos,userTarget,0))
return false;
@@ -378,8 +399,10 @@
weaponPos= owner->pos + owner->frontdir * relWeaponPos.z
+ owner->updir * relWeaponPos.y + owner->rightdir * relWeaponPos.x;
- if(weaponPos.y < ground->GetHeight2(weaponPos.x, weaponPos.z))
- weaponPos = owner->pos + UpVector * 10;
+ weaponMuzzlePos= owner->pos + owner->frontdir * relWeaponMuzzlePos.z
+ + owner->updir * relWeaponMuzzlePos.y + owner->rightdir * relWeaponMuzzlePos.x;
+ if(weaponMuzzlePos.y < ground->GetHeight2(weaponMuzzlePos.x, weaponMuzzlePos.z))
+ weaponMuzzlePos = owner->pos + UpVector * 10;
//hope that we are underground because we are a popup weapon and will come above ground later
if(!unit){
@@ -427,18 +450,17 @@
#endif
std::vector<int> args;
args.push_back(0);
- if(useWeaponPosForAim){
- owner->cob->Call(COBFN_QueryPrimary+weaponNum,args);
- if(useWeaponPosForAim>1)
- useWeaponPosForAim--;
- } else {
- owner->cob->Call(COBFN_AimFromPrimary+weaponNum,args);
- }
+ owner->cob->Call(COBFN_AimFromPrimary+weaponNum,args);
relWeaponPos=owner->localmodel->GetPiecePos(args[0]);
weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x;
- if(weaponPos.y<ground->GetHeight2(weaponPos.x,weaponPos.z))
- weaponPos=owner->pos+UpVector*10; //hope that we are underground because we are a popup weapon and will come above ground later
+ owner->cob->Call(COBFN_QueryPrimary+weaponNum,args);
+ relWeaponMuzzlePos=owner->localmodel->GetPiecePos(args[0]);
+ weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x;
+
+ if(weaponMuzzlePos.y<ground->GetHeight2(weaponMuzzlePos.x,weaponMuzzlePos.z))
+ weaponMuzzlePos=owner->pos+UpVector*10; //hope that we are underground because we are a popup weapon and will come above ground later
+
predictSpeedMod=1+(gs->randFloat()-0.5f)*2*(1-owner->limExperience);
if((targetPos-weaponPos).SqLength() < relWeaponPos.SqLength()*16)
@@ -542,9 +564,33 @@
if(weaponDef->stockpile && !numStockpiled)
return false;
- float3 dif=pos-weaponPos;
+ float3 dif=pos-weaponMuzzlePos;
- float r=GetRange2D(owner->pos.y-pos.y);
+ if (targetBorder != 0 && unit) {
+ float3 diff(dif);
+ diff.Normalize();
+ // weapon inside target sphere
+ if (dif.SqLength() < unit->sqRadius*targetBorder*targetBorder) {
+ dif -= diff*(dif.Length() - 10); // a hack
+ //logOutput << "inside\n";
+ } else {
+ dif -= diff*(unit->radius*targetBorder);
+ //logOutput << "outside\n";
+ }
+ //geometricObjects->AddLine(weaponMuzzlePos, weaponMuzzlePos+dif, 3, 0, 16);
+ }
+
+ float r;
+ if (!unit || cylinderTargetting < 0.01) {
+ r=GetRange2D(owner->pos.y-pos.y);
+ } else {
+ if (cylinderTargetting * unit->radius > owner->pos.y-pos.y) {
+ r = GetRange2D(0);
+ } else {
+ r = 0;
+ }
+ }
+
if(dif.SqLength2D()>=r*r)
return false;
@@ -586,11 +632,13 @@
owner->frontdir = GetVectorFromHeading(owner->heading);
owner->rightdir = owner->frontdir.cross(owner->updir);
weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x;
+ weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x;
bool val = TryTarget(tempTargetPos,userTarget,unit);
owner->frontdir = tempfrontdir;
owner->rightdir = temprightdir;
owner->heading = tempHeadding;
weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x;
+ weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x;
return val;
}
@@ -616,11 +664,13 @@
owner->frontdir = GetVectorFromHeading(owner->heading);
owner->rightdir = owner->frontdir.cross(owner->updir);
weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x;
+ weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x;
bool val = TryTarget(pos, userTarget, 0);
owner->frontdir = tempfrontdir;
owner->rightdir = temprightdir;
owner->heading = tempHeadding;
weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x;
+ weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x;
return val;
}
@@ -631,6 +681,10 @@
owner->cob->Call(COBFN_AimFromPrimary+weaponNum,args);
relWeaponPos=owner->localmodel->GetPiecePos(args[0]);
weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x;
+
+ owner->cob->Call(COBFN_QueryPrimary+weaponNum,args);
+ relWeaponMuzzlePos=owner->localmodel->GetPiecePos(args[0]);
+ weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x;
// logOutput.Print("RelPos %f %f %f",relWeaponPos.x,relWeaponPos.y,relWeaponPos.z);
if (range > owner->maxRange) {
Index: rts/Sim/Weapons/Weapon.h
===================================================================
--- rts/Sim/Weapons/Weapon.h (revision 3829)
+++ rts/Sim/Weapons/Weapon.h (working copy)
@@ -60,6 +60,10 @@
float3 relWeaponPos; //weaponpos relative to the unit
float3 weaponPos; //absolute weapon pos
+
+ float3 relWeaponMuzzlePos; //position of the firepoint
+ float3 weaponMuzzlePos;
+
float muzzleFlareSize; //size of muzzle flare if drawn
int useWeaponPosForAim; //sometimes weapon pos is better to use than aimpos
bool hasCloseTarget; //might need to update weapon pos more often when enemy is near
@@ -119,12 +123,17 @@
int lastErrorVectorUpdate;
CWeapon* slavedTo; //use this weapon to choose target
-
+
float3 mainDir; //main aim dir of weapon
float maxMainDirAngleDif; //how far away from main aim dir the weapon can aim at something (as an acos value)
bool avoidFriendly; //if true tried to avoid friendly Units when aiming.
bool avoidFeature; //if true try to avoid Features while aiming.
+
+ 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.
+
unsigned int collisionFlags;
float fuelUsage;
Index: rts/Sim/Weapons/WeaponDefHandler.cpp
===================================================================
--- rts/Sim/Weapons/WeaponDefHandler.cpp (revision 3829)
+++ rts/Sim/Weapons/WeaponDefHandler.cpp (working copy)
@@ -91,6 +91,17 @@
if(!collideFeature)
weaponDefs[id].collisionFlags+=COLLISION_NOFEATURE;
+ sunparser->GetDef(weaponDefs[id].targetBorder, "0", weaponname + "\\TargetBorder");
+ if (weaponDefs[id].targetBorder > 1.f) {
+ logOutput.Print("warning: targetBorder truncated to 1 (was %f)", weaponDefs[id].targetBorder);
+ weaponDefs[id].targetBorder = 1.f;
+ } else if (weaponDefs[id].targetBorder < -1.f) {
+ logOutput.Print("warning: targetBorder truncated to -1 (was %f)", weaponDefs[id].targetBorder);
+ weaponDefs[id].targetBorder = -1.f;
+ }
+ sunparser->GetDef(weaponDefs[id].cylinderTargetting, "0", weaponname + "\\CylinderTargetting");
+ sunparser->GetDef(weaponDefs[id].minIntensity, "0", weaponname + "\\MinIntensity");
+
sunparser->GetDef(weaponDefs[id].dropped, "0", weaponname + "\\dropped");
sunparser->GetDef(lineofsight, "0", weaponname + "\\lineofsight");
sunparser->GetDef(ballistic, "0", weaponname + "\\ballistic");
@@ -119,7 +130,7 @@
sunparser->GetDef(weaponDefs[id].laserflaresize, "15", weaponname + "\\laserflaresize");
sunparser->GetDef(weaponDefs[id].intensity, "0.9", weaponname + "\\intensity");
sunparser->GetDef(weaponDefs[id].duration, "0.05", weaponname + "\\duration");
-
+
sunparser->GetDef(weaponDefs[id].visuals.sizeDecay, "0", weaponname + "\\sizeDecay");
sunparser->GetDef(weaponDefs[id].visuals.alphaDecay, "1", weaponname + "\\alphaDecay");
sunparser->GetDef(weaponDefs[id].visuals.separation, "1", weaponname + "\\separation");
@@ -576,7 +587,7 @@
if (inverted == true) {
for(int i=0; i < damageArrayHandler->numTypes; ++i) {
-
+
dynDamages[i] = damages[i] - (1 - pow(1 / range * travDist, exp)) * damages[i];
if (damageMin > 0) {
@@ -591,7 +602,7 @@
}
else {
for(int i=0; i < damageArrayHandler->numTypes; ++i) {
-
+
dynDamages[i] = (1 - pow(1 / range * travDist, exp)) * damages[i];
if (damageMin > 0) {
Index: rts/Sim/Weapons/WeaponDefHandler.h
===================================================================
--- rts/Sim/Weapons/WeaponDefHandler.h (revision 3829)
+++ rts/Sim/Weapons/WeaponDefHandler.h (working copy)
@@ -86,7 +86,7 @@
bool manualfire; //use dgun button
int interceptor; //anti nuke
int targetable; //nuke (can be shot by interceptor)
- bool stockpile;
+ bool stockpile;
float coverageRange; //range of anti nuke
float intensity;
@@ -138,7 +138,7 @@
float tilelength;
float scrollspeed;
float pulseSpeed;
-
+
int stages;
float alphaDecay;
float sizeDecay;
@@ -172,6 +172,11 @@
bool avoidFriendly; //if true try to avoid friendly Units when aiming.
bool avoidFeature; //if true try to avoid Features while aiming.
+
+ 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.
+
unsigned int collisionFlags;
CExplosionGenerator *explosionGenerator; // can be zero for default explosions
-
targetborder_minintensity_cylinderTargetting_and_weaponMuzzlePos_v2.patch (21,890 bytes) 2007-06-24 00:40
Index: Game/GameHelper.cpp
===================================================================
--- Game/GameHelper.cpp (revision 3842)
+++ Game/GameHelper.cpp (working copy)
@@ -209,16 +209,17 @@
closeLength=length;
float3 closeVect=dif-dir*closeLength;
- float rad=(*ui)->radius;
- float tmp = rad * rad - closeVect.SqLength();
- if(tmp > 0 && length>closeLength+sqrt(tmp)){
+ /*float rad=(*ui)->radius;
+ float tmp = rad * rad - closeVect.SqLength();*/
+
+ /*if(tmp > 0 && length>closeLength+sqrt(tmp)){
length=closeLength-sqrt(tmp)*0.5f;
hit=*ui;
- }
-/* if(closeVect.SqLength() < (*ui)->sqRadius){
+ }*/
+ if(closeVect.SqLength() < (*ui)->sqRadius){
length=closeLength;
hit=*ui;
- }*/
+ }
}
}
return length;
Index: Lua/LuaWeaponDefs.cpp
===================================================================
--- Lua/LuaWeaponDefs.cpp (revision 3842)
+++ Lua/LuaWeaponDefs.cpp (working copy)
@@ -75,7 +75,7 @@
HSTR_PUSH(L, "__index");
lua_pushlightuserdata(L, (void*)wd);
lua_pushcclosure(L, WeaponDefIndex, 1);
- lua_rawset(L, -3); // closure
+ lua_rawset(L, -3); // closure
HSTR_PUSH(L, "__newindex");
lua_pushlightuserdata(L, (void*)wd);
@@ -110,7 +110,7 @@
static int WeaponDefIndex(lua_State* L)
{
- // not a default value
+ // not a default value
if (!lua_isstring(L, 2)) {
lua_rawget(L, 1);
return 1;
@@ -119,7 +119,7 @@
const char* name = lua_tostring(L, 2);
ParamMap::const_iterator it = paramMap.find(name);
- // not a default value
+ // not a default value
if (paramMap.find(name) == paramMap.end()) {
lua_rawget(L, 1);
return 1;
@@ -171,7 +171,7 @@
const char* name = lua_tostring(L, 2);
ParamMap::const_iterator it = paramMap.find(name);
-
+
// not a default value, set it
if (paramMap.find(name) == paramMap.end()) {
lua_rawset(L, 1);
@@ -186,7 +186,7 @@
luaL_error(L, "Attempt to write WeaponDefs[%d].%s", wd->id, name);
return 0;
}
-
+
// Definition editing
const DataElement& elem = it->second;
const char* p = ((const char*)wd) + elem.offset;
@@ -217,7 +217,7 @@
luaL_error(L, "ERROR_TYPE in WeaponDefs __newindex");
}
}
-
+
return 0;
}
@@ -266,7 +266,7 @@
}
// start the user parameters,
// remove the internal key and push a nil
- lua_settop(L, 1);
+ lua_settop(L, 1);
lua_pushnil(L);
}
}
@@ -314,8 +314,8 @@
LuaPushNamedNumber(L, typeList[i].c_str(), d.damages[i]);
}
lua_rawset(L, -3);
-
- return 1;
+
+ return 1;
}
@@ -417,9 +417,9 @@
static bool InitParamMap()
{
- paramMap["next"] = DataElement(READONLY_TYPE);
- paramMap["pairs"] = DataElement(READONLY_TYPE);
-
+ paramMap["next"] = DataElement(READONLY_TYPE);
+ paramMap["pairs"] = DataElement(READONLY_TYPE);
+
// dummy WeaponDef for offset generation
const WeaponDef wd;
const char* start = ADDRESS(wd);
@@ -481,7 +481,7 @@
ADD_BOOL("noAutoTarget", wd.noAutoTarget);
ADD_BOOL("manualFire", wd.manualfire);
ADD_INT("targetable", wd.targetable);
- ADD_BOOL("stockpile", wd.stockpile);
+ ADD_BOOL("stockpile", wd.stockpile);
ADD_INT("interceptor", wd.interceptor);
ADD_FLOAT("coverageRange", wd.coverageRange);
@@ -541,6 +541,9 @@
ADD_INT("interceptedByShieldType", wd.interceptedByShieldType);
ADD_BOOL("avoidFriendly", wd.avoidFriendly);
+ ADD_FLOAT("targetBorder", wd.targetBorder);
+ ADD_FLOAT("cylinderTargetting", wd.cylinderTargetting);
+ ADD_FLOAT("minIntensity", wd.minIntensity);
// CExplosionGenerator *explosionGenerator;
Index: Sim/Projectiles/ProjectileHandler.cpp
===================================================================
--- Sim/Projectiles/ProjectileHandler.cpp (revision 3842)
+++ Sim/Projectiles/ProjectileHandler.cpp (working copy)
@@ -31,8 +31,8 @@
CProjectileHandler* ph;
using namespace std;
-extern GLfloat FogBlack[];
-extern GLfloat FogLand[];
+extern GLfloat FogBlack[];
+extern GLfloat FogLand[];
CR_BIND(CProjectileHandler,);
@@ -137,7 +137,7 @@
wrecktex = textureAtlas->GetTextureWithBackup( "wrecktexture", "circularthingy" );
plasmatex = textureAtlas->GetTextureWithBackup( "plasmatexture", "circularthingy" );
-
+
groundFXAtlas = SAFE_NEW CTextureAtlas(2048, 2048);
//add all textures in groundfx section
ptex = resources.GetAllValues("resources\\graphics\\groundfx");
@@ -328,9 +328,9 @@
int numFlyingPieces = 0;
int drawnPieces = 0;
-
+
/* Putting in, say, viewport culling will deserve refactoring. */
-
+
/* 3DO */
unitDrawer->SetupForUnitDrawing();
@@ -376,27 +376,27 @@
for (int textureType = 1; textureType < flyings3oPieces.size(); textureType++){
/* TODO Skip this if there's no FlyingPieces. */
-
+
texturehandler->SetS3oTexture(textureType);
-
+
for (int team = 0; team < flyings3oPieces[textureType].size(); team++){
FlyingPiece_List * fpl = flyings3oPieces[textureType][team];
-
+
unitDrawer->SetS3OTeamColour(team);
-
+
va->Initialize();
-
+
numFlyingPieces += fpl->size();
-
+
for(std::list<FlyingPiece*>::iterator pi=fpl->begin();pi!=fpl->end();++pi){
CMatrix44f m;
m.Rotate((*pi)->rot,(*pi)->rotAxis);
float3 interPos=(*pi)->pos+(*pi)->speed*gu->timeOffset;
-
+
SS3OVertex * verts = (*pi)->verts;
-
+
float3 tp, tn;
-
+
for (int i = 0; i < 4; i++){
tp=m.Mul(verts[i].pos);
tn=m.Mul(verts[i].normal);
@@ -408,9 +408,9 @@
va->DrawArrayTN(GL_QUADS);
}
}
-
+
unitDrawer->CleanUpS3ODrawing();
-
+
/*
* TODO Nearly cut here.
*/
@@ -565,7 +565,7 @@
if(readmap->groundBlockingObjectMap[square]!=unit)
continue;
}
- //adjust projectile position so explosion happens at the correct position
+ //adjust projectile position so explosion happens at the correct position
p->pos = p->pos + p->speed*closeTime;
p->Collision(*ui);
break;
@@ -603,7 +603,7 @@
}
}
}
- }
+ }
}
void CProjectileHandler::AddGroundFlash(CGroundFlash* flash)
@@ -687,7 +687,7 @@
flyings3oPieces[textureType].push_back(fpl);
flyingPieces.push_back(fpl);
}
-
+
pieceList=flyings3oPieces[textureType][team];
FlyingPiece* fp=new FlyingPiece;
@@ -745,7 +745,7 @@
glDisable(GL_ALPHA_TEST);
glDisable(GL_FOG);
- unsigned char col[4];
+ unsigned char col[4];
float time=gu->lastFrameTime*gs->speedFactor*3;
float speed=1;
float size=1;
Index: Sim/Projectiles/WeaponProjectile.cpp
===================================================================
--- Sim/Projectiles/WeaponProjectile.cpp (revision 3842)
+++ Sim/Projectiles/WeaponProjectile.cpp (working copy)
@@ -45,7 +45,7 @@
interceptTarget=0;
}
-CWeaponProjectile::CWeaponProjectile(const float3& pos,const float3& speed,CUnit* owner, CUnit* target,const float3 &targetPos, WeaponDef *weaponDef,CWeaponProjectile* interceptTarget, bool synced) :
+CWeaponProjectile::CWeaponProjectile(const float3& pos,const float3& speed,CUnit* owner, CUnit* target,const float3 &targetPos, WeaponDef *weaponDef,CWeaponProjectile* interceptTarget, bool synced) :
CProjectile(pos,speed,owner, synced),
weaponDef(weaponDef),
weaponDefName(weaponDef?weaponDef->name:std::string("")),
@@ -120,7 +120,7 @@
DamageArray dynDamages;
if (weaponDef->dynDamageExp > 0)
dynDamages = weaponDefHandler->DynamicDamages(weaponDef->damages, startpos, pos, weaponDef->dynDamageRange>0?weaponDef->dynDamageRange:weaponDef->range, weaponDef->dynDamageExp, weaponDef->dynDamageMin, weaponDef->dynDamageInverted);
-
+
helper->Explosion(pos,weaponDef->dynDamageExp>0?dynDamages:weaponDef->damages,weaponDef->areaOfEffect,weaponDef->edgeEffectiveness,weaponDef->explosionSpeed,owner,true,weaponDef->noExplode? 0.3f:1,weaponDef->noExplode || weaponDef->noSelfDamage, weaponDef->explosionGenerator,0,impactDir, weaponDef->id);
}
@@ -155,7 +155,7 @@
DamageArray dynDamages;
if (weaponDef->dynDamageExp > 0)
dynDamages = weaponDefHandler->DynamicDamages(weaponDef->damages, startpos, pos, weaponDef->dynDamageRange>0?weaponDef->dynDamageRange:weaponDef->range, weaponDef->dynDamageExp, weaponDef->dynDamageMin, weaponDef->dynDamageInverted);
-
+
helper->Explosion(pos,weaponDef->dynDamageExp>0?dynDamages:weaponDef->damages,weaponDef->areaOfEffect,weaponDef->edgeEffectiveness,weaponDef->explosionSpeed,owner,true,weaponDef->noExplode? 0.3f:1,weaponDef->noExplode,weaponDef->explosionGenerator,unit,impactDir, weaponDef->id);
}
@@ -226,7 +226,7 @@
transMatrix[12]=interPos.x;
transMatrix[13]=interPos.y;
transMatrix[14]=interPos.z;
- glMultMatrixf(&transMatrix[0]);
+ glMultMatrixf(&transMatrix[0]);
glCallList(modelDispList);
glPopMatrix();
Index: Sim/Units/CommandAI/MobileCAI.cpp
===================================================================
--- Sim/Units/CommandAI/MobileCAI.cpp (revision 3842)
+++ Sim/Units/CommandAI/MobileCAI.cpp (working copy)
@@ -42,6 +42,8 @@
CR_MEMBER(commandPos1),
CR_MEMBER(commandPos2),
+ CR_MEMBER(lastCloseInTry),
+
CR_MEMBER(cancelDistance),
CR_MEMBER(slowGuard),
CR_MEMBER(moveDir)
@@ -61,6 +63,7 @@
commandPos2(ZeroVector),
lastPC(-1),
cancelDistance(1024),
+ lastCloseInTry(-1),
slowGuard(false),
moveDir(gs->randFloat() > 0.5),
lastUserGoal(0,0,0)
@@ -81,6 +84,7 @@
commandPos2(ZeroVector),
lastPC(-1),
cancelDistance(1024),
+ lastCloseInTry(-1),
slowGuard(false),
moveDir(gs->randFloat() > 0.5)
{
@@ -582,7 +586,8 @@
// check if we have valid target parameter and that we aren't attacking ourselves
if (uh->units[unitID] != 0 && uh->units[unitID] != owner) {
float3 fix = uh->units[unitID]->pos + owner->posErrorVector * 128;
- SetGoal(fix, owner->pos);
+ float3 diff = float3(fix - owner->pos).Normalize();
+ SetGoal(fix - diff*uh->units[unitID]->radius, owner->pos);
// get ID of attack-order target unit
orderTarget = uh->units[unitID];
AddDeathDependence(orderTarget);
@@ -626,6 +631,7 @@
//bool b1 = owner->AttackUnit(orderTarget, c.id == CMD_DGUN);
bool b2 = false;
bool b3 = false;
+ float edgeFactor = 0.f; // percent offset to target center
if (owner->weapons.size() > 0) {
if (!(c.options & ALT_KEY) && SkipParalyzeTarget(orderTarget)) {
@@ -638,15 +644,21 @@
// can hit target with our first (meanest) one
b2 = w->TryTargetRotate(orderTarget, c.id == CMD_DGUN);
b3 = (w->range - (w->relWeaponPos).Length()) > (orderTarget->pos.distance(owner->pos));
+ edgeFactor = fabs(w->targetBorder);
}
float3 diff = owner->pos - orderTarget->pos;
// if w->AttackUnit() returned true then we are already
// in range with our biggest weapon so stop moving
+ // also make sure that we're not locked in close-in/in-range state loop
+ // due to rotates invoked by in-range or out-of-range states
if (b2) {
StopMove();
owner->AttackUnit(orderTarget, c.id == CMD_DGUN);
- owner->moveType->KeepPointingTo(orderTarget,
- min((float) (owner->losRadius * SQUARE_SIZE * 2), owner->maxRange * 0.9f), true);
+ // FIXME kill magic frame number
+ if (gs->frameNum > lastCloseInTry + MAX_CLOSE_IN_RETRY_TICKS) {
+ owner->moveType->KeepPointingTo(orderTarget,
+ min((float) (owner->losRadius * SQUARE_SIZE * 2), owner->maxRange * 0.9f), true);
+ }
}
// if (((first weapon range minus first weapon length greater than distance to target
@@ -675,7 +687,10 @@
else if ((orderTarget->pos + owner->posErrorVector * 128).distance2D(goalPos)
> (10 + orderTarget->pos.distance2D(owner->pos) * 0.2f)) {
float3 fix = orderTarget->pos + owner->posErrorVector * 128;
- SetGoal(fix, owner->pos);
+ float3 norm = float3(fix - owner->pos).Normalize();
+ SetGoal(fix - norm*(orderTarget->radius*edgeFactor*0.8f), owner->pos);
+ if (lastCloseInTry < gs->frameNum + MAX_CLOSE_IN_RETRY_TICKS)
+ lastCloseInTry = gs->frameNum;
}
}
Index: Sim/Units/CommandAI/MobileCAI.h
===================================================================
--- Sim/Units/CommandAI/MobileCAI.h (revision 3842)
+++ Sim/Units/CommandAI/MobileCAI.h (working copy)
@@ -59,6 +59,7 @@
protected:
int cancelDistance;
+ int lastCloseInTry;
bool slowGuard;
bool moveDir;
void PushOrUpdateReturnFight() {
@@ -66,5 +67,6 @@
}
};
+#define MAX_CLOSE_IN_RETRY_TICKS 30
#endif /* MOBILECAI_H */
Index: Sim/Units/UnitLoader.cpp
===================================================================
--- Sim/Units/UnitLoader.cpp (revision 3842)
+++ Sim/Units/UnitLoader.cpp (working copy)
@@ -466,6 +466,9 @@
weapon->fuelUsage = udw->fuelUsage;
weapon->avoidFriendly = weapondef->avoidFriendly;
weapon->avoidFeature = weapondef->avoidFeature;
+ weapon->targetBorder = weapondef->targetBorder;
+ weapon->cylinderTargetting = weapondef->cylinderTargetting;
+ weapon->minIntensity = weapondef->minIntensity;
weapon->collisionFlags = weapondef->collisionFlags;
weapon->Init();
Index: Sim/Weapons/BeamLaser.cpp
===================================================================
--- Sim/Weapons/BeamLaser.cpp (revision 3842)
+++ Sim/Weapons/BeamLaser.cpp (working copy)
@@ -85,6 +85,7 @@
}
float3 dir=pos-weaponPos;
+
float length=dir.Length();
if(length==0)
return true;
@@ -133,6 +134,7 @@
}
}
dir+=(salvoError)*(1-owner->limExperience*0.7f);
+
dir.Normalize();
FireInternal(dir, false);
@@ -145,6 +147,7 @@
if(owner->directControl)
rangeMod=0.95f;
#endif
+
float maxLength=range*rangeMod;
float curLength=0;
float3 curPos=weaponPos;
@@ -152,6 +155,19 @@
bool tryAgain=true;
CUnit* hit;
+
+ // increase range if targets are searched for in a cylinder
+ if (cylinderTargetting > 0.01) {
+ const float3 up(0, owner->radius*cylinderTargetting, 0);
+ const float uplen = up.dot(dir);
+ maxLength = sqrt(maxLength*maxLength + uplen*uplen);
+ }
+
+ // increase range if targetting edge of hitsphere
+ if (targetType == Target_Unit && targetUnit && targetBorder != 0) {
+ maxLength += targetUnit->radius*targetBorder;
+ }
+
for(int tries=0;tries<5 && tryAgain;++tries){
tryAgain=false;
hit=0;
@@ -172,6 +188,7 @@
tryAgain=true;
}
}
+
hitPos=curPos+dir*length;
float baseAlpha=weaponDef->intensity*255;
@@ -187,7 +204,15 @@
curLength+=length;
dir=newDir;
}
- float intensity=1-(curLength)/(range*2);
+
+ // fix negative damage when hitting big spheres
+ float actualRange = range;
+ if (hit && targetBorder > 0) {
+ actualRange += hit->radius*targetBorder;
+ }
+ // make it possible to always hit with some minimal intensity (melee weapons have use for that)
+ float intensity=max(minIntensity, 1-(curLength)/(actualRange*2));
+
if(curLength<maxLength) {
// Dynamic Damage
DamageArray dynDamages;
Index: Sim/Weapons/MeleeWeapon.cpp
===================================================================
--- Sim/Weapons/MeleeWeapon.cpp (revision 3842)
+++ Sim/Weapons/MeleeWeapon.cpp (working copy)
@@ -34,7 +34,9 @@
void CMeleeWeapon::Fire(void)
{
if(targetType==Target_Unit){
- targetUnit->DoDamage(damages,owner,ZeroVector,weaponDef->id);
+ float3 impulseDir = targetUnit->pos-weaponPos;
+ impulseDir.Normalize();
+ targetUnit->DoDamage(damages,owner,impulseDir,weaponDef->id);
if(fireSoundId)
sound->PlaySample(fireSoundId,owner,fireSoundVolume);
}
Index: Sim/Weapons/Weapon.cpp
===================================================================
--- Sim/Weapons/Weapon.cpp (revision 3842)
+++ Sim/Weapons/Weapon.cpp (working copy)
@@ -83,6 +83,9 @@
CR_MEMBER(hasCloseTarget),
CR_MEMBER(avoidFriendly),
CR_MEMBER(avoidFeature),
+ CR_MEMBER(targetBorder),
+ CR_MEMBER(cylinderTargetting),
+ CR_MEMBER(minIntensity),
CR_MEMBER(collisionFlags),
CR_MEMBER(fuelUsage),
CR_MEMBER(weaponNum)
@@ -151,6 +154,9 @@
hasCloseTarget(false),
avoidFriendly(true),
avoidFeature(true),
+ targetBorder(0.f),
+ cylinderTargetting(0.f),
+ minIntensity(0.f),
collisionFlags(0),
fuelUsage(0)
{
@@ -164,6 +170,12 @@
void CWeapon::Update()
{
+ // do not fire at cloaked units
+ if(targetType == Target_Unit && targetUnit && targetUnit->isCloaked) {
+ HoldFire();
+ return;
+ }
+
if(hasCloseTarget){
std::vector<int> args;
args.push_back(0);
@@ -544,7 +556,31 @@
float3 dif=pos-weaponPos;
- float r=GetRange2D(owner->pos.y-pos.y);
+ if (targetBorder != 0 && unit) {
+ float3 diff(dif);
+ diff.Normalize();
+ // weapon inside target sphere
+ if (dif.SqLength() < unit->sqRadius*targetBorder*targetBorder) {
+ dif -= diff*(dif.Length() - 10); // a hack
+ //logOutput << "inside\n";
+ } else {
+ dif -= diff*(unit->radius*targetBorder);
+ //logOutput << "outside\n";
+ }
+ //geometricObjects->AddLine(weaponMuzzlePos, weaponMuzzlePos+dif, 3, 0, 16);
+ }
+
+ float r;
+ if (!unit || cylinderTargetting < 0.01) {
+ r=GetRange2D(owner->pos.y-pos.y);
+ } else {
+ if (cylinderTargetting * unit->radius > owner->pos.y-pos.y) {
+ r = GetRange2D(0);
+ } else {
+ r = 0;
+ }
+ }
+
if(dif.SqLength2D()>=r*r)
return false;
Index: Sim/Weapons/Weapon.h
===================================================================
--- Sim/Weapons/Weapon.h (revision 3842)
+++ Sim/Weapons/Weapon.h (working copy)
@@ -119,12 +119,17 @@
int lastErrorVectorUpdate;
CWeapon* slavedTo; //use this weapon to choose target
-
+
float3 mainDir; //main aim dir of weapon
float maxMainDirAngleDif; //how far away from main aim dir the weapon can aim at something (as an acos value)
bool avoidFriendly; //if true tried to avoid friendly Units when aiming.
bool avoidFeature; //if true try to avoid Features while aiming.
+
+ 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.
+
unsigned int collisionFlags;
float fuelUsage;
Index: Sim/Weapons/WeaponDefHandler.cpp
===================================================================
--- Sim/Weapons/WeaponDefHandler.cpp (revision 3842)
+++ Sim/Weapons/WeaponDefHandler.cpp (working copy)
@@ -91,6 +91,17 @@
if(!collideFeature)
weaponDefs[id].collisionFlags+=COLLISION_NOFEATURE;
+ sunparser->GetDef(weaponDefs[id].targetBorder, "0", weaponname + "\\TargetBorder");
+ if (weaponDefs[id].targetBorder > 1.f) {
+ logOutput.Print("warning: targetBorder truncated to 1 (was %f)", weaponDefs[id].targetBorder);
+ weaponDefs[id].targetBorder = 1.f;
+ } else if (weaponDefs[id].targetBorder < -1.f) {
+ logOutput.Print("warning: targetBorder truncated to -1 (was %f)", weaponDefs[id].targetBorder);
+ weaponDefs[id].targetBorder = -1.f;
+ }
+ sunparser->GetDef(weaponDefs[id].cylinderTargetting, "0", weaponname + "\\CylinderTargetting");
+ sunparser->GetDef(weaponDefs[id].minIntensity, "0", weaponname + "\\MinIntensity");
+
sunparser->GetDef(weaponDefs[id].dropped, "0", weaponname + "\\dropped");
sunparser->GetDef(lineofsight, "0", weaponname + "\\lineofsight");
sunparser->GetDef(ballistic, "0", weaponname + "\\ballistic");
@@ -119,7 +130,7 @@
sunparser->GetDef(weaponDefs[id].laserflaresize, "15", weaponname + "\\laserflaresize");
sunparser->GetDef(weaponDefs[id].intensity, "0.9", weaponname + "\\intensity");
sunparser->GetDef(weaponDefs[id].duration, "0.05", weaponname + "\\duration");
-
+
sunparser->GetDef(weaponDefs[id].visuals.sizeDecay, "0", weaponname + "\\sizeDecay");
sunparser->GetDef(weaponDefs[id].visuals.alphaDecay, "1", weaponname + "\\alphaDecay");
sunparser->GetDef(weaponDefs[id].visuals.separation, "1", weaponname + "\\separation");
@@ -576,7 +587,7 @@
if (inverted == true) {
for(int i=0; i < damageArrayHandler->numTypes; ++i) {
-
+
dynDamages[i] = damages[i] - (1 - pow(1 / range * travDist, exp)) * damages[i];
if (damageMin > 0) {
@@ -591,7 +602,7 @@
}
else {
for(int i=0; i < damageArrayHandler->numTypes; ++i) {
-
+
dynDamages[i] = (1 - pow(1 / range * travDist, exp)) * damages[i];
if (damageMin > 0) {
Index: Sim/Weapons/WeaponDefHandler.h
===================================================================
--- Sim/Weapons/WeaponDefHandler.h (revision 3842)
+++ Sim/Weapons/WeaponDefHandler.h (working copy)
@@ -86,7 +86,7 @@
bool manualfire; //use dgun button
int interceptor; //anti nuke
int targetable; //nuke (can be shot by interceptor)
- bool stockpile;
+ bool stockpile;
float coverageRange; //range of anti nuke
float intensity;
@@ -138,7 +138,7 @@
float tilelength;
float scrollspeed;
float pulseSpeed;
-
+
int stages;
float alphaDecay;
float sizeDecay;
@@ -172,6 +172,11 @@
bool avoidFriendly; //if true try to avoid friendly Units when aiming.
bool avoidFeature; //if true try to avoid Features while aiming.
+
+ 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.
+
unsigned int collisionFlags;
CExplosionGenerator *explosionGenerator; // can be zero for default explosions
-
targetborder_minintensity_cylinderTargetting_and_weaponMuzzlePos_v3.patch (23,250 bytes) 2007-06-25 16:27
Index: Game/GameHelper.cpp
===================================================================
--- Game/GameHelper.cpp (revision 3848)
+++ Game/GameHelper.cpp (working copy)
@@ -209,16 +209,17 @@
closeLength=length;
float3 closeVect=dif-dir*closeLength;
- float rad=(*ui)->radius;
- float tmp = rad * rad - closeVect.SqLength();
- if(tmp > 0 && length>closeLength+sqrt(tmp)){
+ /*float rad=(*ui)->radius;
+ float tmp = rad * rad - closeVect.SqLength();*/
+
+ /*if(tmp > 0 && length>closeLength+sqrt(tmp)){
length=closeLength-sqrt(tmp)*0.5f;
hit=*ui;
- }
-/* if(closeVect.SqLength() < (*ui)->sqRadius){
+ }*/
+ if(closeVect.SqLength() < (*ui)->sqRadius){
length=closeLength;
hit=*ui;
- }*/
+ }
}
}
return length;
Index: Lua/LuaWeaponDefs.cpp
===================================================================
--- Lua/LuaWeaponDefs.cpp (revision 3848)
+++ Lua/LuaWeaponDefs.cpp (working copy)
@@ -75,7 +75,7 @@
HSTR_PUSH(L, "__index");
lua_pushlightuserdata(L, (void*)wd);
lua_pushcclosure(L, WeaponDefIndex, 1);
- lua_rawset(L, -3); // closure
+ lua_rawset(L, -3); // closure
HSTR_PUSH(L, "__newindex");
lua_pushlightuserdata(L, (void*)wd);
@@ -110,7 +110,7 @@
static int WeaponDefIndex(lua_State* L)
{
- // not a default value
+ // not a default value
if (!lua_isstring(L, 2)) {
lua_rawget(L, 1);
return 1;
@@ -119,7 +119,7 @@
const char* name = lua_tostring(L, 2);
ParamMap::const_iterator it = paramMap.find(name);
- // not a default value
+ // not a default value
if (paramMap.find(name) == paramMap.end()) {
lua_rawget(L, 1);
return 1;
@@ -171,7 +171,7 @@
const char* name = lua_tostring(L, 2);
ParamMap::const_iterator it = paramMap.find(name);
-
+
// not a default value, set it
if (paramMap.find(name) == paramMap.end()) {
lua_rawset(L, 1);
@@ -186,7 +186,7 @@
luaL_error(L, "Attempt to write WeaponDefs[%d].%s", wd->id, name);
return 0;
}
-
+
// Definition editing
const DataElement& elem = it->second;
const char* p = ((const char*)wd) + elem.offset;
@@ -217,7 +217,7 @@
luaL_error(L, "ERROR_TYPE in WeaponDefs __newindex");
}
}
-
+
return 0;
}
@@ -266,7 +266,7 @@
}
// start the user parameters,
// remove the internal key and push a nil
- lua_settop(L, 1);
+ lua_settop(L, 1);
lua_pushnil(L);
}
}
@@ -314,8 +314,8 @@
LuaPushNamedNumber(L, typeList[i].c_str(), d.damages[i]);
}
lua_rawset(L, -3);
-
- return 1;
+
+ return 1;
}
@@ -417,9 +417,9 @@
static bool InitParamMap()
{
- paramMap["next"] = DataElement(READONLY_TYPE);
- paramMap["pairs"] = DataElement(READONLY_TYPE);
-
+ paramMap["next"] = DataElement(READONLY_TYPE);
+ paramMap["pairs"] = DataElement(READONLY_TYPE);
+
// dummy WeaponDef for offset generation
const WeaponDef wd;
const char* start = ADDRESS(wd);
@@ -481,7 +481,7 @@
ADD_BOOL("noAutoTarget", wd.noAutoTarget);
ADD_BOOL("manualFire", wd.manualfire);
ADD_INT("targetable", wd.targetable);
- ADD_BOOL("stockpile", wd.stockpile);
+ ADD_BOOL("stockpile", wd.stockpile);
ADD_INT("interceptor", wd.interceptor);
ADD_FLOAT("coverageRange", wd.coverageRange);
@@ -541,6 +541,9 @@
ADD_INT("interceptedByShieldType", wd.interceptedByShieldType);
ADD_BOOL("avoidFriendly", wd.avoidFriendly);
+ ADD_FLOAT("targetBorder", wd.targetBorder);
+ ADD_FLOAT("cylinderTargetting", wd.cylinderTargetting);
+ ADD_FLOAT("minIntensity", wd.minIntensity);
// CExplosionGenerator *explosionGenerator;
Index: Sim/MoveTypes/groundmovetype.cpp
===================================================================
--- Sim/MoveTypes/groundmovetype.cpp (revision 3848)
+++ Sim/MoveTypes/groundmovetype.cpp (working copy)
@@ -194,7 +194,7 @@
{
skidding = true;
}
-
+
if(skidding){
UpdateSkid();
return;
@@ -415,6 +415,7 @@
tracefile << "Start moving called: ";
tracefile << owner->pos.x << " " << owner->pos.y << " " << owner->pos.z << " " << owner->id << "\n";
#endif
+
if(progressState == Active) {
StopEngine();
}
@@ -609,7 +610,7 @@
float3& speed=owner->speed;
float3& pos=owner->pos;
SyncedFloat3& midPos=owner->midPos;
-
+
if(flying){
speed.y+=gs->gravity;
if(midPos.y < 0)
@@ -665,11 +666,11 @@
speed+=newForce;
speedf = speed.Length();
speed *= 1 - (.1*dir.y);
- } else
+ } else
{
speed*=(speedf-speedReduction)/speedf;
}
-
+
float remTime=speedf/speedReduction-1;
float rp=floor(skidRotPos2+skidRotSpeed2*remTime+0.5f);
skidRotSpeed2=(remTime+1 == 0 ) ? 0 : (rp-skidRotPos2)/(remTime+1);
Index: Sim/Projectiles/ProjectileHandler.cpp
===================================================================
--- Sim/Projectiles/ProjectileHandler.cpp (revision 3848)
+++ Sim/Projectiles/ProjectileHandler.cpp (working copy)
@@ -31,8 +31,8 @@
CProjectileHandler* ph;
using namespace std;
-extern GLfloat FogBlack[];
-extern GLfloat FogLand[];
+extern GLfloat FogBlack[];
+extern GLfloat FogLand[];
CR_BIND(CProjectileHandler,);
@@ -137,7 +137,7 @@
wrecktex = textureAtlas->GetTextureWithBackup( "wrecktexture", "circularthingy" );
plasmatex = textureAtlas->GetTextureWithBackup( "plasmatexture", "circularthingy" );
-
+
groundFXAtlas = SAFE_NEW CTextureAtlas(2048, 2048);
//add all textures in groundfx section
ptex = resources.GetAllValues("resources\\graphics\\groundfx");
@@ -328,9 +328,9 @@
int numFlyingPieces = 0;
int drawnPieces = 0;
-
+
/* Putting in, say, viewport culling will deserve refactoring. */
-
+
/* 3DO */
unitDrawer->SetupForUnitDrawing();
@@ -376,27 +376,27 @@
for (int textureType = 1; textureType < flyings3oPieces.size(); textureType++){
/* TODO Skip this if there's no FlyingPieces. */
-
+
texturehandler->SetS3oTexture(textureType);
-
+
for (int team = 0; team < flyings3oPieces[textureType].size(); team++){
FlyingPiece_List * fpl = flyings3oPieces[textureType][team];
-
+
unitDrawer->SetS3OTeamColour(team);
-
+
va->Initialize();
-
+
numFlyingPieces += fpl->size();
-
+
for(std::list<FlyingPiece*>::iterator pi=fpl->begin();pi!=fpl->end();++pi){
CMatrix44f m;
m.Rotate((*pi)->rot,(*pi)->rotAxis);
float3 interPos=(*pi)->pos+(*pi)->speed*gu->timeOffset;
-
+
SS3OVertex * verts = (*pi)->verts;
-
+
float3 tp, tn;
-
+
for (int i = 0; i < 4; i++){
tp=m.Mul(verts[i].pos);
tn=m.Mul(verts[i].normal);
@@ -408,9 +408,9 @@
va->DrawArrayTN(GL_QUADS);
}
}
-
+
unitDrawer->CleanUpS3ODrawing();
-
+
/*
* TODO Nearly cut here.
*/
@@ -565,7 +565,7 @@
if(readmap->groundBlockingObjectMap[square]!=unit)
continue;
}
- //adjust projectile position so explosion happens at the correct position
+ //adjust projectile position so explosion happens at the correct position
p->pos = p->pos + p->speed*closeTime;
p->Collision(*ui);
break;
@@ -603,7 +603,7 @@
}
}
}
- }
+ }
}
void CProjectileHandler::AddGroundFlash(CGroundFlash* flash)
@@ -687,7 +687,7 @@
flyings3oPieces[textureType].push_back(fpl);
flyingPieces.push_back(fpl);
}
-
+
pieceList=flyings3oPieces[textureType][team];
FlyingPiece* fp=new FlyingPiece;
@@ -745,7 +745,7 @@
glDisable(GL_ALPHA_TEST);
glDisable(GL_FOG);
- unsigned char col[4];
+ unsigned char col[4];
float time=gu->lastFrameTime*gs->speedFactor*3;
float speed=1;
float size=1;
Index: Sim/Projectiles/WeaponProjectile.cpp
===================================================================
--- Sim/Projectiles/WeaponProjectile.cpp (revision 3848)
+++ Sim/Projectiles/WeaponProjectile.cpp (working copy)
@@ -45,7 +45,7 @@
interceptTarget=0;
}
-CWeaponProjectile::CWeaponProjectile(const float3& pos,const float3& speed,CUnit* owner, CUnit* target,const float3 &targetPos, WeaponDef *weaponDef,CWeaponProjectile* interceptTarget, bool synced) :
+CWeaponProjectile::CWeaponProjectile(const float3& pos,const float3& speed,CUnit* owner, CUnit* target,const float3 &targetPos, WeaponDef *weaponDef,CWeaponProjectile* interceptTarget, bool synced) :
CProjectile(pos,speed,owner, synced),
weaponDef(weaponDef),
weaponDefName(weaponDef?weaponDef->name:std::string("")),
@@ -120,7 +120,7 @@
DamageArray dynDamages;
if (weaponDef->dynDamageExp > 0)
dynDamages = weaponDefHandler->DynamicDamages(weaponDef->damages, startpos, pos, weaponDef->dynDamageRange>0?weaponDef->dynDamageRange:weaponDef->range, weaponDef->dynDamageExp, weaponDef->dynDamageMin, weaponDef->dynDamageInverted);
-
+
helper->Explosion(pos,weaponDef->dynDamageExp>0?dynDamages:weaponDef->damages,weaponDef->areaOfEffect,weaponDef->edgeEffectiveness,weaponDef->explosionSpeed,owner,true,weaponDef->noExplode? 0.3f:1,weaponDef->noExplode || weaponDef->noSelfDamage, weaponDef->explosionGenerator,0,impactDir, weaponDef->id);
}
@@ -155,7 +155,7 @@
DamageArray dynDamages;
if (weaponDef->dynDamageExp > 0)
dynDamages = weaponDefHandler->DynamicDamages(weaponDef->damages, startpos, pos, weaponDef->dynDamageRange>0?weaponDef->dynDamageRange:weaponDef->range, weaponDef->dynDamageExp, weaponDef->dynDamageMin, weaponDef->dynDamageInverted);
-
+
helper->Explosion(pos,weaponDef->dynDamageExp>0?dynDamages:weaponDef->damages,weaponDef->areaOfEffect,weaponDef->edgeEffectiveness,weaponDef->explosionSpeed,owner,true,weaponDef->noExplode? 0.3f:1,weaponDef->noExplode,weaponDef->explosionGenerator,unit,impactDir, weaponDef->id);
}
@@ -226,7 +226,7 @@
transMatrix[12]=interPos.x;
transMatrix[13]=interPos.y;
transMatrix[14]=interPos.z;
- glMultMatrixf(&transMatrix[0]);
+ glMultMatrixf(&transMatrix[0]);
glCallList(modelDispList);
glPopMatrix();
Index: Sim/Units/CommandAI/MobileCAI.cpp
===================================================================
--- Sim/Units/CommandAI/MobileCAI.cpp (revision 3848)
+++ Sim/Units/CommandAI/MobileCAI.cpp (working copy)
@@ -42,6 +42,8 @@
CR_MEMBER(commandPos1),
CR_MEMBER(commandPos2),
+ CR_MEMBER(lastCloseInTry),
+
CR_MEMBER(cancelDistance),
CR_MEMBER(slowGuard),
CR_MEMBER(moveDir)
@@ -61,6 +63,7 @@
commandPos2(ZeroVector),
lastPC(-1),
cancelDistance(1024),
+ lastCloseInTry(-1),
slowGuard(false),
moveDir(gs->randFloat() > 0.5),
lastUserGoal(0,0,0)
@@ -81,6 +84,7 @@
commandPos2(ZeroVector),
lastPC(-1),
cancelDistance(1024),
+ lastCloseInTry(-1),
slowGuard(false),
moveDir(gs->randFloat() > 0.5)
{
@@ -582,7 +586,8 @@
// check if we have valid target parameter and that we aren't attacking ourselves
if (uh->units[unitID] != 0 && uh->units[unitID] != owner) {
float3 fix = uh->units[unitID]->pos + owner->posErrorVector * 128;
- SetGoal(fix, owner->pos);
+ float3 diff = float3(fix - owner->pos).Normalize();
+ SetGoal(fix - diff*uh->units[unitID]->radius, owner->pos);
// get ID of attack-order target unit
orderTarget = uh->units[unitID];
AddDeathDependence(orderTarget);
@@ -626,6 +631,7 @@
//bool b1 = owner->AttackUnit(orderTarget, c.id == CMD_DGUN);
bool b2 = false;
bool b3 = false;
+ float edgeFactor = 0.f; // percent offset to target center
if (owner->weapons.size() > 0) {
if (!(c.options & ALT_KEY) && SkipParalyzeTarget(orderTarget)) {
@@ -638,15 +644,21 @@
// can hit target with our first (meanest) one
b2 = w->TryTargetRotate(orderTarget, c.id == CMD_DGUN);
b3 = (w->range - (w->relWeaponPos).Length()) > (orderTarget->pos.distance(owner->pos));
+ edgeFactor = fabs(w->targetBorder);
}
float3 diff = owner->pos - orderTarget->pos;
// if w->AttackUnit() returned true then we are already
// in range with our biggest weapon so stop moving
+ // also make sure that we're not locked in close-in/in-range state loop
+ // due to rotates invoked by in-range or out-of-range states
if (b2) {
StopMove();
owner->AttackUnit(orderTarget, c.id == CMD_DGUN);
- owner->moveType->KeepPointingTo(orderTarget,
- min((float) (owner->losRadius * SQUARE_SIZE * 2), owner->maxRange * 0.9f), true);
+ // FIXME kill magic frame number
+ if (gs->frameNum > lastCloseInTry + MAX_CLOSE_IN_RETRY_TICKS) {
+ owner->moveType->KeepPointingTo(orderTarget,
+ min((float) (owner->losRadius * SQUARE_SIZE * 2), owner->maxRange * 0.9f), true);
+ }
}
// if (((first weapon range minus first weapon length greater than distance to target
@@ -675,7 +687,10 @@
else if ((orderTarget->pos + owner->posErrorVector * 128).distance2D(goalPos)
> (10 + orderTarget->pos.distance2D(owner->pos) * 0.2f)) {
float3 fix = orderTarget->pos + owner->posErrorVector * 128;
- SetGoal(fix, owner->pos);
+ float3 norm = float3(fix - owner->pos).Normalize();
+ SetGoal(fix - norm*(orderTarget->radius*edgeFactor*0.8f), owner->pos);
+ if (lastCloseInTry < gs->frameNum + MAX_CLOSE_IN_RETRY_TICKS)
+ lastCloseInTry = gs->frameNum;
}
}
Index: Sim/Units/CommandAI/MobileCAI.h
===================================================================
--- Sim/Units/CommandAI/MobileCAI.h (revision 3848)
+++ Sim/Units/CommandAI/MobileCAI.h (working copy)
@@ -59,6 +59,7 @@
protected:
int cancelDistance;
+ int lastCloseInTry;
bool slowGuard;
bool moveDir;
void PushOrUpdateReturnFight() {
@@ -66,5 +67,6 @@
}
};
+#define MAX_CLOSE_IN_RETRY_TICKS 30
#endif /* MOBILECAI_H */
Index: Sim/Units/UnitLoader.cpp
===================================================================
--- Sim/Units/UnitLoader.cpp (revision 3848)
+++ Sim/Units/UnitLoader.cpp (working copy)
@@ -466,6 +466,9 @@
weapon->fuelUsage = udw->fuelUsage;
weapon->avoidFriendly = weapondef->avoidFriendly;
weapon->avoidFeature = weapondef->avoidFeature;
+ weapon->targetBorder = weapondef->targetBorder;
+ weapon->cylinderTargetting = weapondef->cylinderTargetting;
+ weapon->minIntensity = weapondef->minIntensity;
weapon->collisionFlags = weapondef->collisionFlags;
weapon->Init();
Index: Sim/Weapons/BeamLaser.cpp
===================================================================
--- Sim/Weapons/BeamLaser.cpp (revision 3848)
+++ Sim/Weapons/BeamLaser.cpp (working copy)
@@ -85,6 +85,7 @@
}
float3 dir=pos-weaponPos;
+
float length=dir.Length();
if(length==0)
return true;
@@ -133,6 +134,7 @@
}
}
dir+=(salvoError)*(1-owner->limExperience*0.7f);
+
dir.Normalize();
FireInternal(dir, false);
@@ -145,6 +147,7 @@
if(owner->directControl)
rangeMod=0.95f;
#endif
+
float maxLength=range*rangeMod;
float curLength=0;
float3 curPos=weaponPos;
@@ -152,6 +155,19 @@
bool tryAgain=true;
CUnit* hit;
+
+ // increase range if targets are searched for in a cylinder
+ if (cylinderTargetting > 0.01) {
+ const float3 up(0, owner->radius*cylinderTargetting, 0);
+ const float uplen = up.dot(dir);
+ maxLength = sqrt(maxLength*maxLength + uplen*uplen);
+ }
+
+ // increase range if targetting edge of hitsphere
+ if (targetType == Target_Unit && targetUnit && targetBorder != 0) {
+ maxLength += targetUnit->radius*targetBorder;
+ }
+
for(int tries=0;tries<5 && tryAgain;++tries){
tryAgain=false;
hit=0;
@@ -172,6 +188,7 @@
tryAgain=true;
}
}
+
hitPos=curPos+dir*length;
float baseAlpha=weaponDef->intensity*255;
@@ -187,7 +204,15 @@
curLength+=length;
dir=newDir;
}
- float intensity=1-(curLength)/(range*2);
+
+ // fix negative damage when hitting big spheres
+ float actualRange = range;
+ if (hit && targetBorder > 0) {
+ actualRange += hit->radius*targetBorder;
+ }
+ // make it possible to always hit with some minimal intensity (melee weapons have use for that)
+ float intensity=max(minIntensity, 1-(curLength)/(actualRange*2));
+
if(curLength<maxLength) {
// Dynamic Damage
DamageArray dynDamages;
Index: Sim/Weapons/MeleeWeapon.cpp
===================================================================
--- Sim/Weapons/MeleeWeapon.cpp (revision 3848)
+++ Sim/Weapons/MeleeWeapon.cpp (working copy)
@@ -34,7 +34,9 @@
void CMeleeWeapon::Fire(void)
{
if(targetType==Target_Unit){
- targetUnit->DoDamage(damages,owner,ZeroVector,weaponDef->id);
+ float3 impulseDir = targetUnit->pos-weaponPos;
+ impulseDir.Normalize();
+ targetUnit->DoDamage(damages,owner,impulseDir,weaponDef->id);
if(fireSoundId)
sound->PlaySample(fireSoundId,owner,fireSoundVolume);
}
Index: Sim/Weapons/Weapon.cpp
===================================================================
--- Sim/Weapons/Weapon.cpp (revision 3848)
+++ Sim/Weapons/Weapon.cpp (working copy)
@@ -83,6 +83,9 @@
CR_MEMBER(hasCloseTarget),
CR_MEMBER(avoidFriendly),
CR_MEMBER(avoidFeature),
+ CR_MEMBER(targetBorder),
+ CR_MEMBER(cylinderTargetting),
+ CR_MEMBER(minIntensity),
CR_MEMBER(collisionFlags),
CR_MEMBER(fuelUsage),
CR_MEMBER(weaponNum)
@@ -151,6 +154,9 @@
hasCloseTarget(false),
avoidFriendly(true),
avoidFeature(true),
+ targetBorder(0.f),
+ cylinderTargetting(0.f),
+ minIntensity(0.f),
collisionFlags(0),
fuelUsage(0)
{
@@ -164,6 +170,12 @@
void CWeapon::Update()
{
+ // do not fire at cloaked units
+ if(targetType == Target_Unit && targetUnit && targetUnit->isCloaked) {
+ HoldFire();
+ return;
+ }
+
if(hasCloseTarget){
std::vector<int> args;
args.push_back(0);
@@ -544,7 +556,31 @@
float3 dif=pos-weaponPos;
- float r=GetRange2D(owner->pos.y-pos.y);
+ if (targetBorder != 0 && unit) {
+ float3 diff(dif);
+ diff.Normalize();
+ // weapon inside target sphere
+ if (dif.SqLength() < unit->sqRadius*targetBorder*targetBorder) {
+ dif -= diff*(dif.Length() - 10); // a hack
+ //logOutput << "inside\n";
+ } else {
+ dif -= diff*(unit->radius*targetBorder);
+ //logOutput << "outside\n";
+ }
+ //geometricObjects->AddLine(weaponMuzzlePos, weaponMuzzlePos+dif, 3, 0, 16);
+ }
+
+ float r;
+ if (!unit || cylinderTargetting < 0.01) {
+ r=GetRange2D(owner->pos.y-pos.y);
+ } else {
+ if (cylinderTargetting * unit->radius > owner->pos.y-pos.y) {
+ r = GetRange2D(0);
+ } else {
+ r = 0;
+ }
+ }
+
if(dif.SqLength2D()>=r*r)
return false;
Index: Sim/Weapons/Weapon.h
===================================================================
--- Sim/Weapons/Weapon.h (revision 3848)
+++ Sim/Weapons/Weapon.h (working copy)
@@ -119,12 +119,17 @@
int lastErrorVectorUpdate;
CWeapon* slavedTo; //use this weapon to choose target
-
+
float3 mainDir; //main aim dir of weapon
float maxMainDirAngleDif; //how far away from main aim dir the weapon can aim at something (as an acos value)
bool avoidFriendly; //if true tried to avoid friendly Units when aiming.
bool avoidFeature; //if true try to avoid Features while aiming.
+
+ 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.
+
unsigned int collisionFlags;
float fuelUsage;
Index: Sim/Weapons/WeaponDefHandler.cpp
===================================================================
--- Sim/Weapons/WeaponDefHandler.cpp (revision 3848)
+++ Sim/Weapons/WeaponDefHandler.cpp (working copy)
@@ -91,6 +91,8 @@
if(!collideFeature)
weaponDefs[id].collisionFlags+=COLLISION_NOFEATURE;
+ sunparser->GetDef(weaponDefs[id].minIntensity, "0", weaponname + "\\MinIntensity");
+
sunparser->GetDef(weaponDefs[id].dropped, "0", weaponname + "\\dropped");
sunparser->GetDef(lineofsight, "0", weaponname + "\\lineofsight");
sunparser->GetDef(ballistic, "0", weaponname + "\\ballistic");
@@ -119,7 +121,7 @@
sunparser->GetDef(weaponDefs[id].laserflaresize, "15", weaponname + "\\laserflaresize");
sunparser->GetDef(weaponDefs[id].intensity, "0.9", weaponname + "\\intensity");
sunparser->GetDef(weaponDefs[id].duration, "0.05", weaponname + "\\duration");
-
+
sunparser->GetDef(weaponDefs[id].visuals.sizeDecay, "0", weaponname + "\\sizeDecay");
sunparser->GetDef(weaponDefs[id].visuals.alphaDecay, "1", weaponname + "\\alphaDecay");
sunparser->GetDef(weaponDefs[id].visuals.separation, "1", weaponname + "\\separation");
@@ -188,6 +190,15 @@
// logOutput.Print("%s as %s",weaponname.c_str(),weaponDefs[id].type.c_str());
+ sunparser->GetDef(weaponDefs[id].targetBorder, (weaponDefs[id].type == "Melee"?"1":"0"), weaponname + "\\TargetBorder");
+ if (weaponDefs[id].targetBorder > 1.f) {
+ logOutput.Print("warning: targetBorder truncated to 1 (was %f)", weaponDefs[id].targetBorder);
+ weaponDefs[id].targetBorder = 1.f;
+ } else if (weaponDefs[id].targetBorder < -1.f) {
+ logOutput.Print("warning: targetBorder truncated to -1 (was %f)", weaponDefs[id].targetBorder);
+ weaponDefs[id].targetBorder = -1.f;
+ }
+ sunparser->GetDef(weaponDefs[id].cylinderTargetting, (weaponDefs[id].type == "Melee"?"1":"0"), weaponname + "\\CylinderTargetting");
weaponDefs[id].range = atof(sunparser->SGetValueDef("10", weaponname + "\\range").c_str());
@@ -576,7 +587,7 @@
if (inverted == true) {
for(int i=0; i < damageArrayHandler->numTypes; ++i) {
-
+
dynDamages[i] = damages[i] - (1 - pow(1 / range * travDist, exp)) * damages[i];
if (damageMin > 0) {
@@ -591,7 +602,7 @@
}
else {
for(int i=0; i < damageArrayHandler->numTypes; ++i) {
-
+
dynDamages[i] = (1 - pow(1 / range * travDist, exp)) * damages[i];
if (damageMin > 0) {
Index: Sim/Weapons/WeaponDefHandler.h
===================================================================
--- Sim/Weapons/WeaponDefHandler.h (revision 3848)
+++ Sim/Weapons/WeaponDefHandler.h (working copy)
@@ -86,7 +86,7 @@
bool manualfire; //use dgun button
int interceptor; //anti nuke
int targetable; //nuke (can be shot by interceptor)
- bool stockpile;
+ bool stockpile;
float coverageRange; //range of anti nuke
float intensity;
@@ -138,7 +138,7 @@
float tilelength;
float scrollspeed;
float pulseSpeed;
-
+
int stages;
float alphaDecay;
float sizeDecay;
@@ -172,6 +172,11 @@
bool avoidFriendly; //if true try to avoid friendly Units when aiming.
bool avoidFeature; //if true try to avoid Features while aiming.
+
+ 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.
+
unsigned int collisionFlags;
CExplosionGenerator *explosionGenerator; // can be zero for default explosions
|
---|