Index: rts/Lua/LuaUnitDefs.cpp =================================================================== --- rts/Lua/LuaUnitDefs.cpp (revision 4614) +++ rts/Lua/LuaUnitDefs.cpp (working copy) @@ -768,6 +768,15 @@ ADD_FLOAT("waterline", ud.waterline); ADD_FLOAT("maxWaterDepth", ud.maxWaterDepth); + ADD_FLOAT("flankingBonusMode", ud.flankingBonusMode); + ADD_FLOAT("flankingBonusMax", ud.flankingBonusMax); + ADD_FLOAT("flankingBonusMin", ud.flankingBonusMin); + ADD_FLOAT("flankingBonusMode", ud.flankingBonusMax); + ADD_FLOAT("flankingBonusDirX", ud.flankingBonusDir.x); + ADD_FLOAT("flankingBonusDirY", ud.flankingBonusDir.y); + ADD_FLOAT("flankingBonusDirZ", ud.flankingBonusDir.z); + ADD_FLOAT("flankingBonusMobilityAdd", ud.flankingBonusMobilityAdd); + ADD_INT("armorType", ud.armorType); ADD_FLOAT("armoredMultiple", ud.armoredMultiple); Index: rts/Sim/ModInfo.cpp =================================================================== --- rts/Sim/ModInfo.cpp (revision 4614) +++ rts/Sim/ModInfo.cpp (working copy) @@ -86,6 +86,17 @@ // We already set the defaults so we should be able to ignore this // Other optional mod rules MUST set their defaults... } + //Get the flanking bonus default option + flankingBonusModeDefault = 1; + try + { + TdfParser flankingBonusOptions("gamedata/modrules.tdf"); + flankingBonusModeDefault = atoi(flankingBonusOptions.SGetValueDef("1", "FLANKINGBONUS\\FlankingBonusModeDefault").c_str()); + } catch(content_error) // If the modrules.tdf isnt found + { + // We already set the defaults so we should be able to ignore this + // Other optional mod rules MUST set their defaults... + } } CModInfo::~CModInfo() {} Index: rts/Sim/ModInfo.h =================================================================== --- rts/Sim/ModInfo.h (revision 4614) +++ rts/Sim/ModInfo.h (working copy) @@ -32,6 +32,9 @@ int fireAtKilled; //1 = units fire at enemies running Killed() script, 0 = units ignore such enemies int fireAtCrashing; //1 = units fire at crashing aircrafts, 0 = units ignore crashing aircrafts + int flankingBonusModeDefault; //0=no flanking bonus; 1=global coords, mobile; 2=unit coords, mobile; 3=unit coords, locked + float experienceMultDefault; //normally 1.0, 0.0 disables units getting automatice experience from attacks + }; extern CModInfo *modInfo; Index: rts/Sim/Units/COB/CobInstance.cpp =================================================================== --- rts/Sim/Units/COB/CobInstance.cpp (revision 4614) +++ rts/Sim/Units/COB/CobInstance.cpp (working copy) @@ -12,6 +12,7 @@ #include "Map/Ground.h" #include "Rendering/UnitModels/3DOParser.h" #include "Rendering/UnitModels/s3oParser.h" +#include "Sim/Misc/LosHandler.h" #include "Sim/Misc/RadarHandler.h" #include "Sim/MoveTypes/MoveType.h" #include "Sim/Projectiles/ExplosionGenerator.h" @@ -98,8 +99,15 @@ #define CURRENT_FUEL 93 // set or get #define TRANSPORT_ID 94 // get #define SHIELD_POWER 95 // set or get +#define PLAY_SOUND 96 // get, so multiple args can be passed +#define PLAY_SOUND_LOCATION 97 // get, so multiple args can be passed +#define ALPHA_THRESHOLD 98 // set or get #define COB_ID 100 // get -#define ALPHA_THRESHOLD 103 // set or get +#define FLANK_B_MODE 101 // set or get +#define FLANK_B_DIR 102 // set or get, set is through get for multiple args +#define FLANK_B_MOBILITY_ADD 103 // set or get +#define FLANK_B_MAX_DAMAGE 104 // set or get +#define FLANK_B_MIN_DAMAGE 105 // set or get // * NOTE: [LUA0 - LUA9] are defined in CobThread.cpp as [110 - 119] @@ -1125,6 +1133,48 @@ case ALPHA_THRESHOLD: { return int(unit->alphaThreshold * 255); } + case PLAY_SOUND: + switch(p3) { + case 0: + if (!loshandler->InAirLos(unit->pos,gu->myAllyTeam)) {return 0;} + break; + case 1: + if (!(unit->losStatus[gu->myAllyTeam] & LOS_INLOS)) {return 0;} + break; + case 2: + if (!(unit->losStatus[gu->myAllyTeam] & (LOS_INLOS | LOS_INRADAR))) {return 0;} + break; + case 3: + break; + case 4: + if (unit->allyteam != gu->myAllyTeam) {return 0;} + break; + case 5: + if (unit->team != gu->myTeam) {return 0;} + break; + case 6: + if (unit->allyteam == gu->myAllyTeam) {return 0;} + break; + } + logOutput.Print("Playing %i %i %i", p1, p2, script.sounds[p1]); + if (p4 == 0) { + sound->PlaySample(script.sounds[p1], unit->pos, p2); + }else{ + sound->PlaySample(script.sounds[p1], p2); + } + return 0; + case PLAY_SOUND_LOCATION: { + float3 soundloc; + soundloc.x = UNPACKX(p3); + soundloc.y = UNPACKZ(p3); + if (p3 == 0) { + soundloc.z = ground->GetHeight(UNPACKX(p3), UNPACKZ(p3)); + }else{ + soundloc.z = float(p4)/COBSCALE; + } + sound->PlaySample(script.sounds[p1], soundloc, float(p2)/COBSCALE); + return 0; + } case COB_ID: { if (p1 == 0) { return unit->unitDef->cobID; @@ -1133,6 +1183,25 @@ return (u == NULL) ? -1 : u->unitDef->cobID; } } + case FLANK_B_MODE: + return unit->flankingBonusMode; + case FLANK_B_DIR: + switch(p1){ + case -2: unit->flankingBonusDir=float3(p2/(float)COBSCALE,p3/(float)COBSCALE,p4/(float)COBSCALE); + case 1: return int(unit->flankingBonusDir.x * COBSCALE); + case 2: return int(unit->flankingBonusDir.y * COBSCALE); + case 3: return int(unit->flankingBonusDir.z * COBSCALE); + case 11: unit->flankingBonusDir.x=(p2/(float)COBSCALE); return p2; + case 12: unit->flankingBonusDir.y=(p2/(float)COBSCALE); return p2; + case 13: unit->flankingBonusDir.z=(p2/(float)COBSCALE); return p2; + default: return(-1); + } + case FLANK_B_MOBILITY_ADD: + return int(unit->flankingBonusMobilityAdd * COBSCALE); + case FLANK_B_MAX_DAMAGE: + return int((unit->flankingBonusAvgDamage + unit->flankingBonusDifDamage) * COBSCALE); + case FLANK_B_MIN_DAMAGE: + return int((unit->flankingBonusAvgDamage - unit->flankingBonusDifDamage) * COBSCALE); default: logOutput.Print("CobError: Unknown get constant %d (params = %d %d %d %d)", val, p1, p2, p3, p4); @@ -1339,6 +1408,22 @@ unit->alphaThreshold = float(param) / 255.0f; break; } + case FLANK_B_MODE: + unit->flankingBonusMode=param; + break; + case FLANK_B_DIR: + break; + case FLANK_B_MOBILITY_ADD: + unit->flankingBonusMobilityAdd=(param/(float)COBSCALE); + break; + case FLANK_B_MAX_DAMAGE: + unit->flankingBonusAvgDamage=(param/(float)COBSCALE+(unit->flankingBonusAvgDamage - unit->flankingBonusDifDamage))*0.5f; + unit->flankingBonusDifDamage=(param/(float)COBSCALE-(unit->flankingBonusAvgDamage - unit->flankingBonusDifDamage))*0.5f; + break; + case FLANK_B_MIN_DAMAGE: + unit->flankingBonusAvgDamage=((unit->flankingBonusAvgDamage + unit->flankingBonusDifDamage)+param/(float)COBSCALE)*0.5f; + unit->flankingBonusDifDamage=((unit->flankingBonusAvgDamage + unit->flankingBonusDifDamage)-param/(float)COBSCALE)*0.5f; + break; default: { logOutput.Print("CobError: Unknown set constant %d", val); } Index: rts/Sim/Units/Unit.cpp =================================================================== --- rts/Sim/Units/Unit.cpp (revision 4614) +++ rts/Sim/Units/Unit.cpp (working copy) @@ -124,8 +124,12 @@ userAttackPos(0,0,0), crashing(false), cob(0), - bonusShieldDir(1,0,0), - bonusShieldSaved(10), + flankingBonusMode(0), + flankingBonusDir(1,0,0), + flankingBonusAvgDamage(1.4f), + flankingBonusDifDamage(.5f), + flankingBonusMobility(10), + flankingBonusMobilityAdd(.01), group(0), lastDamage(-100), lastFireWeapon(0), @@ -429,7 +433,7 @@ } recentDamage*=0.9f; - bonusShieldSaved+=0.005f; + flankingBonusMobility+=flankingBonusMobilityAdd; if(stunned) return; @@ -629,7 +633,6 @@ } } - bonusShieldSaved += 0.05f; residualImpulse *= 0.6f; if (scriptCloak >= 3) { @@ -743,22 +746,33 @@ float damage=damages[armorType]; - if(damage<0){ -// logOutput.Print("Negative damage"); - return; + if(damage>0){ + if(attacker){ + SetLastAttacker(attacker); + if (flankingBonusMode) { + float3 adir=attacker->pos-pos; + adir.Normalize(); + if (flankingBonusMode == 1) { //mode 1 = global coordinates, mobile + flankingBonusDir+=adir*flankingBonusMobility; + flankingBonusDir.Normalize(); + flankingBonusMobility=0; + damage*=flankingBonusAvgDamage-adir.dot(flankingBonusDir)*flankingBonusDifDamage; + }else{ + float3 adirRelative; + adirRelative.x = adir.dot(rightdir); + adirRelative.y = adir.dot(updir); + adirRelative.z = adir.dot(frontdir); + if (flankingBonusMode == 2) { //mode 2 = unit coordinates, mobile + flankingBonusDir += adirRelative * flankingBonusMobility; + flankingBonusDir.Normalize(); + flankingBonusMobility=0; + } //modes 2 and 3 both use this; 3 is unit coordinates, immobile + damage*=flankingBonusAvgDamage-adirRelative.dot(flankingBonusDir)*flankingBonusDifDamage; + } + } + } } - 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; - } - damage*=curArmorMultiple; float3 hitDir = impulse; @@ -790,54 +804,70 @@ 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(damages.paralyzeDamageTime) { + if (damages.paralyzeDamageTime > 0) { + if (paralyzeDamage > health) { + if(paralyzeDamage < health + (maxHealth*0.025f*damages.paralyzeDamageTime)) { + //make sure the weapon can do any paralysis damage before adding it; can't just do the min or a weak paralysis weapon could undo a strong one + paralyzeDamage = min((paralyzeDamage + damage), (health + (maxHealth*0.025f*damages.paralyzeDamageTime))); + experienceMod = 0.0f; //no experience for extra paralysis + } + }else{ + paralyzeDamage+=damage; + experienceMod=0.1f; //reduce experience for paralyzers + if (paralyzeDamage < health) { + stunned = false; + } } + }else{ + if (paralyzeDamage == 0) { + experienceMod = 0.0f; //no experience when not healing + }else{ + paralyzeDamage = max(0.0f, paralyzeDamage + damage); + experienceMod = 0.1f; + } } } else { - // 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; + 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; } - 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->ExperienceChange(); - ENTER_UNSYNCED; - if (((!unitDef->isCommander && uh->lastDamageWarning+100frameNum) || - (unitDef->isCommander && uh->lastCmdDamageWarning+100frameNum)) - && (team == gu->myTeam) && !camera->InView(midPos,radius+50) && !gu->spectatingFullView) { - logOutput.Print("%s is being attacked",unitDef->humanName.c_str()); - logOutput.SetLastMsgPos(pos); + if (damage > 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->ExperienceChange(); + ENTER_UNSYNCED; + if (((!unitDef->isCommander && uh->lastDamageWarning+100frameNum) || + (unitDef->isCommander && uh->lastCmdDamageWarning+100frameNum)) + && (team == gu->myTeam) && !camera->InView(midPos,radius+50) && !gu->spectatingFullView) { + logOutput.Print("%s is being attacked",unitDef->humanName.c_str()); + logOutput.SetLastMsgPos(pos); - if (unitDef->isCommander || uh->lastDamageWarning + 150 < gs->frameNum) { - int soundIdx = unitDef->sounds.underattack.getRandomIdx(); - if (soundIdx >= 0) { - sound->PlaySample( - unitDef->sounds.underattack.getID(soundIdx), - unitDef->isCommander? 4: 2); + if (unitDef->isCommander || uh->lastDamageWarning + 150 < gs->frameNum) { + int soundIdx = unitDef->sounds.underattack.getRandomIdx(); + if (soundIdx >= 0) { + sound->PlaySample( + unitDef->sounds.underattack.getID(soundIdx), + unitDef->isCommander? 4: 2); + } } - } - minimap->AddNotification(pos,float3(1,0.3f,0.3f),unitDef->isCommander? 1: 0.5f); //todo: make compatible with new gui + minimap->AddNotification(pos,float3(1,0.3f,0.3f),unitDef->isCommander? 1: 0.5f); //todo: make compatible with new gui - uh->lastDamageWarning=gs->frameNum; - if(unitDef->isCommander) - uh->lastCmdDamageWarning=gs->frameNum; + uh->lastDamageWarning=gs->frameNum; + if(unitDef->isCommander) + uh->lastCmdDamageWarning=gs->frameNum; + } + ENTER_SYNCED; } - ENTER_SYNCED; } luaCallIns.UnitDamaged(this, attacker, damage, !!damages.paralyzeDamageTime); @@ -2275,8 +2305,12 @@ CR_MEMBER(falling), CR_MEMBER(fallSpeed), - CR_MEMBER(bonusShieldDir), - CR_MEMBER(bonusShieldSaved), + CR_MEMBER(flankingBonusMode), + CR_MEMBER(flankingBonusDir), + CR_MEMBER(flankingBonusAvgDamage), + CR_MEMBER(flankingBonusDifDamage), + CR_MEMBER(flankingBonusMobility), + CR_MEMBER(flankingBonusMobilityAdd), CR_MEMBER(armoredState), CR_MEMBER(armoredMultiple), Index: rts/Sim/Units/Unit.h =================================================================== --- rts/Sim/Units/Unit.h (revision 4614) +++ rts/Sim/Units/Unit.h (working copy) @@ -293,8 +293,12 @@ bool falling; //for units being dropped from transports (parachute drops) float fallSpeed; - 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) + int flankingBonusMode; //0=no flanking bonus; 1=global coords, mobile; 2=unit coords, mobile; 3=unit coords, locked + float3 flankingBonusDir; //units takes less damage when attacked from this dir (encourage flanking fire) + float flankingBonusMobility; //how much the lowest damage direction of the flanking bonus can turn upon an attack (zeroed when attacked, slowly increases) + float flankingBonusMobilityAdd; //how much ability of the flanking bonus direction to move builds up each frame + float flankingBonusAvgDamage; //average factor to multiply damage by + float flankingBonusDifDamage; //(max damage - min damage)/2 bool armoredState; float armoredMultiple; Index: rts/Sim/Units/UnitDef.h =================================================================== --- rts/Sim/Units/UnitDef.h (revision 4614) +++ rts/Sim/Units/UnitDef.h (working copy) @@ -173,6 +173,12 @@ float armoredMultiple; int armorType; + int flankingBonusMode; //0=no flanking bonus; 1=global coords, mobile; 2=unit coords, mobile; 3=unit coords, locked + float3 flankingBonusDir; //units takes less damage when attacked from this dir (encourage flanking fire) + float flankingBonusMax; //damage factor for the least protected direction + float flankingBonusMin; //damage factor for the most protected direction + float flankingBonusMobilityAdd; //how much the ability of the flanking bonus direction to move builds up each frame + UnitModelDef model; float collisionSphereScale; float3 collisionSphereOffset; Index: rts/Sim/Units/UnitDefHandler.cpp =================================================================== --- rts/Sim/Units/UnitDefHandler.cpp (revision 4614) +++ rts/Sim/Units/UnitDefHandler.cpp (working copy) @@ -20,6 +20,7 @@ #include "Sim/Misc/CategoryHandler.h" #include "Sim/Misc/DamageArrayHandler.h" #include "Sim/Misc/SensorHandler.h" +#include "Sim/ModInfo.h" #include "Sim/Projectiles/ExplosionGenerator.h" #include "Sim/Weapons/WeaponDefHandler.h" #include "System/LogOutput.h" @@ -305,10 +306,18 @@ ud.captureSpeed = udTable.GetFloat("captureSpeed", ud.buildSpeed); ud.terraformSpeed = udTable.GetFloat("terraformSpeed", ud.buildSpeed); + ud.flankingBonusMode = udTable.GetFloat("flankingBonusMode", modInfo->flankingBonusModeDefault); + ud.flankingBonusMax = udTable.GetFloat("flankingBonusMax", 1.9); + ud.flankingBonusMin = udTable.GetFloat("flankingBonusMin", .9); + ud.flankingBonusDir = udTable.GetFloat3("flankingBonusDir", float3(0.0f, 0.0f, 1.0f)); + ud.flankingBonusMobilityAdd = udTable.GetFloat("flankingBonusMobilityAdd", 0.01f); + ud.armoredMultiple = udTable.GetFloat("damageModifier", 1.0f); ud.armorType=damageArrayHandler->GetTypeFromName(ud.name); // logOutput.Print("unit %s has armor %i",ud.name.c_str(),ud.armorType); + + ud.radarRadius = udTable.GetInt("radarDistance", 0); ud.sonarRadius = udTable.GetInt("sonarDistance", 0); ud.jammerRadius = udTable.GetInt("radarDistanceJam", 0); Index: rts/Sim/Units/UnitLoader.cpp =================================================================== --- rts/Sim/Units/UnitLoader.cpp (revision 4614) +++ rts/Sim/Units/UnitLoader.cpp (working copy) @@ -151,6 +151,12 @@ 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->flankingBonusMode = ud->flankingBonusMode; + unit->flankingBonusDir = ud->flankingBonusDir; + unit->flankingBonusMobility = ud->flankingBonusMobilityAdd * 1000; + unit->flankingBonusMobilityAdd = ud->flankingBonusMobilityAdd; + unit->flankingBonusAvgDamage = (ud->flankingBonusMax + ud->flankingBonusMin) * 0.5f; + unit->flankingBonusDifDamage = (ud->flankingBonusMax - ud->flankingBonusMin) * 0.5f; if(ud->highTrajectoryType==1) unit->useHighTrajectory=true;