Index: rts/Game/GameHelper.cpp =================================================================== --- rts/Game/GameHelper.cpp (revision 3879) +++ rts/Game/GameHelper.cpp (working copy) @@ -109,8 +109,8 @@ float dist1 = dist; if (dist1 > radius) dist1 = radius; - float mod =(radius-dist1)/(radius-dist1*edgeEffectiveness); - float mod2=(radius-dist2)/(radius-dist2*edgeEffectiveness); + float mod =(dist1*edgeEffectiveness+radius-dist1)/(radius); + float mod2=(dist2*edgeEffectiveness+radius-dist2)/(radius); dif/=dist; // dist > (*ui)->radius+0.1f, see above dif.y+=0.12f; Index: rts/Sim/Units/COB/CobInstance.cpp =================================================================== --- rts/Sim/Units/COB/CobInstance.cpp (revision 3879) +++ rts/Sim/Units/COB/CobInstance.cpp (working copy) @@ -97,6 +97,11 @@ #define DO_SEISMIC_PING 92 // get #define CURRENT_FUEL 93 // set or get #define TRANSPORT_ID 94 // get +#define BONUS_SHIELD_MODE 95 // set or get +#define BONUS_SHIELD_DIR 96 // set or get through get, for multiple args +#define BONUS_SHIELD_SAVED_ADD 97 // set or get +#define BONUS_SHIELD_MAX_DAMAGE 98 // set or get +#define BONUS_SHIELD_MIN_DAMAGE 99 // set or get CCobInstance::CCobInstance(CCobFile& _script, CUnit* _unit) : script(_script) @@ -1091,6 +1096,25 @@ return (int)(unit->currentFuel * COBSCALE); case TRANSPORT_ID: return unit->transporter?unit->transporter->id:-1; + case BONUS_SHIELD_MODE: + return unit->bonusShieldMode; + case BONUS_SHIELD_DIR: + switch(p1){ + case -2: unit->bonusShieldDir=float3(p2/(float)COBSCALE,p3/(float)COBSCALE,p4/(float)COBSCALE); + case 1: return int(unit->bonusShieldDir.x * COBSCALE); + case 2: return int(unit->bonusShieldDir.y * COBSCALE); + case 3: return int(unit->bonusShieldDir.z * COBSCALE); + case 11: unit->bonusShieldDir.x=(p2/(float)COBSCALE); return p2; + case 12: unit->bonusShieldDir.y=(p2/(float)COBSCALE); return p2; + case 13: unit->bonusShieldDir.z=(p2/(float)COBSCALE); return p2; + default: return(-1); + } + case BONUS_SHIELD_SAVED_ADD: + return int(unit->bonusShieldSavedAdd * COBSCALE); + case BONUS_SHIELD_MAX_DAMAGE: + return int((unit->bonusShieldAvgDamage + unit->bonusShieldDifDamage) * COBSCALE); + case BONUS_SHIELD_MIN_DAMAGE: + return int((unit->bonusShieldAvgDamage - unit->bonusShieldDifDamage) * COBSCALE); default: logOutput.Print("CobError: Unknown get constant %d (params = %d %d %d %d)", val, p1, p2, p3, p4); @@ -1242,6 +1266,22 @@ case CURRENT_FUEL: unit->currentFuel = param / (float) COBSCALE; break; + case BONUS_SHIELD_MODE: + unit->bonusShieldMode=param; + break; + case BONUS_SHIELD_DIR: + break; + case BONUS_SHIELD_SAVED_ADD: + unit->bonusShieldSavedAdd=(param/(float)COBSCALE); + break; + case BONUS_SHIELD_MAX_DAMAGE: + unit->bonusShieldAvgDamage=(param/(float)COBSCALE+(unit->bonusShieldAvgDamage - unit->bonusShieldDifDamage))/0.5f; + unit->bonusShieldDifDamage=(param/(float)COBSCALE-(unit->bonusShieldAvgDamage - unit->bonusShieldDifDamage))/0.5f; + break; + case BONUS_SHIELD_MIN_DAMAGE: + unit->bonusShieldAvgDamage=((unit->bonusShieldAvgDamage + unit->bonusShieldDifDamage)+param/(float)COBSCALE)/0.5f; + unit->bonusShieldDifDamage=((unit->bonusShieldAvgDamage + unit->bonusShieldDifDamage)-param/(float)COBSCALE)/0.5f; + break; } #endif } Index: rts/Sim/Units/Unit.cpp =================================================================== --- rts/Sim/Units/Unit.cpp (revision 3879) +++ rts/Sim/Units/Unit.cpp (working copy) @@ -123,8 +123,12 @@ userAttackPos(0,0,0), crashing(false), cob(0), + bonusShieldMode(1), bonusShieldDir(1,0,0), - bonusShieldSaved(10), + bonusShieldSaved(0), + bonusShieldSavedAdd(0.05f), + bonusShieldAvgDamage(1.4f), + bonusShieldDifDamage(0.5f), group(0), lastDamage(-100), lastFireWeapon(0), @@ -389,7 +393,7 @@ moveType->Update(); recentDamage*=0.9f; - bonusShieldSaved+=0.005f; + bonusShieldSaved+=bonusShieldSavedAdd; if(stunned) return; @@ -577,7 +581,6 @@ health=maxHealth; } - bonusShieldSaved+=0.05f; residualImpulse*=0.6f; if (scriptCloak >= 3) { @@ -686,22 +689,38 @@ float damage=damages[armorType]; - if(damage<0){ -// logOutput.Print("Negative damage"); - return; - } + if(damage>0){ - if(attacker){ - SetLastAttacker(attacker); - float3 adir=attacker->pos-pos; - adir.Normalize(); - bonusShieldDir+=adir*bonusShieldSaved; //not the best way to do it(but fast) - bonusShieldDir.Normalize(); -// logOutput.Print("shield mult %f %f %i %i", 2-adir.dot(bonusShieldDir),bonusShieldSaved,id,attacker->id); - bonusShieldSaved=0; - damage*=1.4f-adir.dot(bonusShieldDir)*0.5f; + if(attacker && bonusShieldMode){ + SetLastAttacker(attacker); + float3 adir=attacker->pos-pos; + adir.Normalize(); + if(bonusShieldMode==1){ + bonusShieldDir+=adir*bonusShieldSaved; //not the best way to do it(but fast) + bonusShieldDir.Normalize(); + bonusShieldSaved=0; + damage*=bonusShieldAvgDamage-adir.dot(bonusShieldDir)*bonusShieldDifDamage; + }else{ + if(bonusShieldMode==2){ + float3 globalToUnitx=(float3(1,0,0)*(rightdir.x*bonusShieldDir.x)+float3(0,1,0)* + (updir.x*bonusShieldDir.y)+float3(0,0,1)*(frontdir.x*bonusShieldDir.z)); + float3 globalToUnity=(float3(1,0,0)*(rightdir.y*bonusShieldDir.x)+float3(0,1,0)* + (updir.y*bonusShieldDir.y)+float3(0,0,1)*(frontdir.y*bonusShieldDir.z)); + float3 globalToUnitz=(float3(1,0,0)*(rightdir.z*bonusShieldDir.x)+float3(0,1,0)* + (updir.z*bonusShieldDir.y)+float3(0,0,1)*(frontdir.z*bonusShieldDir.z)); + bonusShieldDir+=(globalToUnitx*adir.x+globalToUnity*adir.y+globalToUnitz*adir.z)*bonusShieldSaved; + bonusShieldDir.Normalize(); + } + damage*=bonusShieldAvgDamage-adir.dot(rightdir*bonusShieldDir.x+updir*bonusShieldDir.y + +frontdir*bonusShieldDir.z)*bonusShieldDifDamage; + } + } + + restTime=0; } + float experienceMod=1; + damage*=curArmorMultiple; float3 hitDir = impulse; @@ -729,34 +748,47 @@ cob->Call(COBFN_HitByWeapon, cobargs); } - restTime=0; - - float experienceMod=1; - if(damages.paralyzeDamageTime){ - paralyzeDamage+=damage; - experienceMod=0.1f; //reduce experience for paralyzers - if(health-paralyzeDamage<0){ - if(stunned) - experienceMod=0; //dont get any experience for paralyzing paralyzed enemy - stunned=true; - if(paralyzeDamage>health+(maxHealth*0.025f*damages.paralyzeDamageTime)){ - paralyzeDamage=health+(maxHealth*0.025f*damages.paralyzeDamageTime); + if(damage>0){ + paralyzeDamage+=damage; + experienceMod=0.1f; //reduce experience for paralyzers + if(health-paralyzeDamage<0){ + if(stunned) + experienceMod=0; //dont get any experience for paralyzing paralyzed enemy + stunned=true; + if(paralyzeDamage>health+(maxHealth*0.025f*damages.paralyzeDamageTime)){ + paralyzeDamage=health+(maxHealth*0.025f*damages.paralyzeDamageTime); + } } + }else{ + if(paralyzeDamage>0){ + experienceMod=0.1f; //gives experience for healing paralysis + }else{ + experienceMod=0; + } } } else { - // Dont log overkill damage (so dguns/nukes etc dont inflate values) - float statsdamage = std::min(health, damage); - if (attacker) + if(damage>0){ + // Dont log overkill damage (so dguns/nukes etc dont inflate values) + float statsdamage = std::min(health, damage); + if (attacker) gs->Team(attacker->team)->currentStats.damageDealt += statsdamage; - gs->Team(team)->currentStats.damageReceived += statsdamage; - health-=damage; + gs->Team(team)->currentStats.damageReceived += statsdamage; + health-=damage; + }else{ + if(maxHealth>health){ + health=std::min(maxHealth,health-=damage); + experienceMod=0.1f; //units get some, but not much, experience for healing + }else{ + experienceMod=0; + } + } } recentDamage+=damage; if(attacker!=0 && !gs->Ally(allyteam,attacker->allyteam)){ // logOutput.Print("%s has %f/%f h attacker %s do %f d",tooltip.c_str(),health,maxHealth,attacker->tooltip.c_str(),damage); - attacker->experience+=0.1f*power/attacker->power*(damage+min(0.f,health))/maxHealth*experienceMod; + attacker->experience+=0.1f*power/attacker->power*(fabs(damage)+min(0.f,health))/maxHealth*experienceMod; attacker->ExperienceChange(); ENTER_UNSYNCED; if (((!unitDef->isCommander && uh->lastDamageWarning+100frameNum) || Index: rts/Sim/Units/Unit.h =================================================================== --- rts/Sim/Units/Unit.h (revision 3879) +++ rts/Sim/Units/Unit.h (working copy) @@ -266,8 +266,12 @@ bool crashing; bool isDead; //prevent damage from hitting an already dead unit (causing multi wreck etc) + int bonusShieldMode; //0=no bonus shield; 1=global coords, mobile; 2=unit coords, mobile (calculation heavy); 3=unit coords, locked; float3 bonusShieldDir; //units takes less damage when attacked from this dir (encourage flanking fire) float bonusShieldSaved; //how much the bonus shield can turn upon an attack(zeroed when attacked, slowly increase) + float bonusShieldSavedAdd; //how much bonusShieldSaved builds up each slowupdate + float bonusShieldAvgDamage; //average factor to multiply damage by + float bonusShieldDifDamage; //(max damage - min damage)/2 bool armoredState; float armoredMultiple; Index: rts/Sim/Units/UnitDef.h =================================================================== --- rts/Sim/Units/UnitDef.h (revision 3879) +++ rts/Sim/Units/UnitDef.h (working copy) @@ -345,6 +345,12 @@ float refuelTime; //time to fully refuel unit float minAirBasePower; //min build power for airbases that this aircraft can land on + int bonusShieldMode; //whether the bonusShield is active + float3 bonusShieldDir; //units takes less damage when attacked from this dir (encourage flanking fire) + float bonusShieldSavedAdd; //how much bonusShieldSaved builds up each update (and 10x as much each slowupdate) + float bonusShieldMaxDamage; //maximum factor to multiply damage by + float bonusShieldMinDamage; //minimum factor to multiply damage by + std::vector sfxExplGens; //list of explosiongenerators for use in scripts int maxThisUnit; //number of units of this type allowed simultaniously in the game Index: rts/Sim/Units/UnitDefHandler.cpp =================================================================== --- rts/Sim/Units/UnitDefHandler.cpp (revision 3879) +++ rts/Sim/Units/UnitDefHandler.cpp (working copy) @@ -434,6 +434,12 @@ tdfparser.GetDef(ud.refuelTime, "5", "UNITINFO\\refueltime"); tdfparser.GetDef(ud.minAirBasePower, "0", "UNITINFO\\minairbasepower"); + tdfparser.GetDef(ud.bonusShieldMode, "1", "UNITINFO\\bonusShieldMode"); + ud.bonusShieldDir=tdfparser.GetFloat3(float3(1,0,0), "UNITINFO\\bonusShieldDir"); + tdfparser.GetDef(ud.bonusShieldSavedAdd, "0.005", "UNITINFO\\bonusShieldSavedAdd"); + tdfparser.GetDef(ud.bonusShieldMaxDamage, "1.9", "UNITINFO\\bonusShieldMaxDamage"); + tdfparser.GetDef(ud.bonusShieldMinDamage, "0.9", "UNITINFO\\bonusShieldMinDamage"); + tdfparser.GetTDef(ud.maxThisUnit, MAX_UNITS, "UNITINFO\\UnitRestricted"); if (gameSetup) { Index: rts/Sim/Units/UnitLoader.cpp =================================================================== --- rts/Sim/Units/UnitLoader.cpp (revision 3879) +++ rts/Sim/Units/UnitLoader.cpp (working copy) @@ -153,6 +153,13 @@ unit->armorType=ud->armorType; unit->floatOnWater = ud->floater || (ud->movedata && ((ud->movedata->moveType == MoveData::Hover_Move) || (ud->movedata->moveType == MoveData::Ship_Move))); unit->maxSpeed = ud->speed/30.0; + unit->bonusShieldMode=ud->bonusShieldMode; + unit->bonusShieldDir=ud->bonusShieldDir; + unit->bonusShieldDir.Normalize(); + unit->bonusShieldSaved=ud->bonusShieldSavedAdd*1000; + unit->bonusShieldSavedAdd=ud->bonusShieldSavedAdd; + unit->bonusShieldAvgDamage=(ud->bonusShieldMaxDamage + ud->bonusShieldMinDamage)*0.5f; + unit->bonusShieldDifDamage=(ud->bonusShieldMaxDamage - ud->bonusShieldMinDamage)*0.5f; if(ud->highTrajectoryType==1) unit->useHighTrajectory=true; Index: rts/Sim/Weapons/WeaponDefHandler.cpp =================================================================== --- rts/Sim/Weapons/WeaponDefHandler.cpp (revision 3879) +++ rts/Sim/Weapons/WeaponDefHandler.cpp (working copy) @@ -247,9 +247,6 @@ weaponDefs[id].areaOfEffect=atof(sunparser->SGetValueDef("8", weaponname + "\\areaofeffect").c_str())*0.5f; weaponDefs[id].edgeEffectiveness=atof(sunparser->SGetValueDef("0", weaponname + "\\edgeEffectiveness").c_str()); - // prevent 0/0 division in CGameHelper::Explosion - if (weaponDefs[id].edgeEffectiveness > 0.999f) - weaponDefs[id].edgeEffectiveness = 0.999f; weaponDefs[id].projectilespeed = atof(sunparser->SGetValueDef("0", weaponname + "\\weaponvelocity").c_str())/GAME_SPEED; weaponDefs[id].startvelocity = max(0.01f,(float)atof(sunparser->SGetValueDef("0", weaponname + "\\startvelocity").c_str())/GAME_SPEED); weaponDefs[id].weaponacceleration = atof(sunparser->SGetValueDef("0", weaponname + "\\weaponacceleration").c_str())/GAME_SPEED/GAME_SPEED;