• New Horizons on Maelstrom
    Maelstrom New Horizons


    Visit our website www.piratehorizons.com to quickly find download links for the newest versions of our New Horizons mods Beyond New Horizons and Maelstrom New Horizons!

AICannon.c

bearcat

Landlubber
Hi guys, could someone of the coders explain me this part of the <b>AICannon.c</b> in deep, please?

// calculate recharge time for cannon
float Cannon_GetRechargeTime()
{
aref aCharacter = GetEventData();
ref rCannon = GetCannonByType(sti(aCharacter.Ship.Cannons.Type));
float fCannonSkill = stf(aCharacter.TmpSkill.Cannons); // 0.1 to 1.0
if (!CheckAttribute(rCannon, "ReloadTime"))
{
string CannonType = GetCannonName(sti(aCharacter.Ship.Cannons.Type));
if (CannonType != "No Cannons") trace("Cannon " + CannonType + " has no reloadTime!"); // LDH - don't need trace if no cannons
return 20.0; // LDH - changed from 1.0 so a real cannon will have a reasonable reload time, just in case
} // NK 05-07-18 fix for "No Cannons"
float fReloadTime = sti(rCannon.ReloadTime); // reload time in seconds

float fMultiply = AIShip_isPerksUse(aCharacter.TmpPerks.FastReload, 1.0, 0.<img src="style_emoticons/<#EMO_DIR#>/cool.gif" style="vertical-align:middle" emoid="8)" border="0" alt="cool.gif" />;
fMultiply = AIShip_isPerksUse(aCharacter.TmpPerks.ImmediateReload, fMultiply, 0.5);
// boal ReloadTime for cannons is influenced by Ship Crew -->
//fMultiply = fMultiply * Bring2RangeNoCheck(4.0, 1.0, 0.0, 1.0, stf(aCharacter.Ship.Crew.MinRatio));
// Ship.Crew.Quantity - ñêîêà íàðîäó ñåé÷àñ
// Ship.Crew.Morale - òåêóùàÿ ìîðàëü 0..99 45 - ñðåäíÿÿ
// Ship.maxcrew
// Ship.MinCrew
// aCharacter.skill.Leadership - ñòðîêà ñ ÷èñëîì
float cQ = GetCrewQuantity(aCharacter);
//float cMC = GetMaxCrewQuantity(aCharacter);
float cCM = 70;
if(CheckAttribute(aCharacter,"Ship.Crew.Morale")) cCM = sti(aCharacter.Ship.Crew.Morale);
// unneeded due to damage scaling based on crew qty NK 04-09-15
/*if(cMC)
{
fReloadTime = fReloadTime * (1 + (1 - cQ / cMC) * 4);
}*/
// NK can qty 05-04-18 -->
// now do crew qty scaling for above MIN_CREW_FOR_ALL_GUNS
int mcq = GetMinCrewQuantity(aCharacter);
if(mcq)
{
int canqty = GetCannonQuantity(&aCharacter);
if(canqty)
{
float crewratio = makefloat(cQ) / makefloat(mcq*5); //yes can be >1!
ref rship = GetShipByType(GetCharacterShipType(&aCharacter));
aref arship; makearef(arship, aCharacter.ship);
int fullqty = GetLocalShipAttrib(&arship, rship, "MaxCanQty");
crewratio = crewratio * makefloat(fullqty) / makefloat(canqty); // so if can qty decreases, not as much crew needed.
if(crewratio > MIN_CREW_FOR_ALL_GUNS)
{
fReloadTime *= Bring2Range(1.0, 1/(1.5*BEST_RATE_FOR_ALL_CREW), MIN_CREW_FOR_ALL_GUNS, 1.5, crewratio);
}
}
else { fReloadTime *= 10; }
}
//else { trace("char " + aCharacter.id + " name " + aCharacter.lastname + " has 0 mincq!"); }
// NK <--
fReloadTime = fReloadTime * (1 + (1 - cCM / 70) / 10);
//Log_SetStringToLog(aCharacter.id);
// debug info
//if( aCharacter.id == "Blaze")
//{
//Log_SetStringToLog("RTime "+fReloadTime+" Multiply "+ fMultiply +" CannonSkill " + fCannonSkill +" q "+aCharacter.Ship.Crew.Quantity+" m "+sti(refBaseShip.MaxCrew) + " ml "+aCharacter.Ship.Crew.Morale);
//}
// boal ReloadTime for cannons is influenced by Ship Crew <--

return fMultiply * (fReloadTime - fCannonSkill * (fReloadTime / 4.0));
}

i would like to know what at all influence the reloadtime of the ships cannons!

did the AICannon.c only influence the AI or even the Players ship?

especially this two lines of the code i don´t understand:

1)

fReloadTime *= Bring2Range(1.0, 1/(1.5*BEST_RATE_FOR_ALL_CREW), MIN_CREW_FOR_ALL_GUNS, 1.5, crewratio);

2)

Log_SetStringToLog("RTime "+fReloadTime+" Multiply "+ fMultiply +" CannonSkill " + fCannonSkill +" q "+aCharacter.Ship.Crew.Quantity+" m "+sti(refBaseShip.MaxCrew) + " ml "+aCharacter.Ship.Crew.Morale);

Thanks a million!

CU THOMAS
 
Yes. AICannon.c it's used for both: player and AI.

1) fReloadTime *= Bring2Range(1.0, 1/(1.5*BEST_RATE_FOR_ALL_CREW), MIN_CREW_FOR_ALL_GUNS, 1.5, crewratio);

IIRC Bring2Range it's an utility function to "cut" the values returned by an operation in order to fit into a predertermined range. Don't remember exactly which sintax, so I can't right now explain "exactly" what that line does.
Anyway, it's important to notice that it's relationing (it's that english? ) the reloading time with the amount of crew the ship has. If you have only a token crew, expect to take a long time to reload.


2) Log_SetStringToLog("RTime "+fReloadTime+" Multiply "+ fMultiply +" CannonSkill " + fCannonSkill +" q "+aCharacter.Ship.Crew.Quantity+" m "+sti(refBaseShip.MaxCrew) + " ml "+aCharacter.Ship.Crew.Morale);

This line it's just for debugging. That's the reason it's commented.
Uncommented, will write a line in the log (don't remember exactly which file of the three) stating: Reload time, a multiplier, the cannonskill of the captain of the ship firing, the actual number of crew of the firing ship, the maximum crew allowed for that ship, and the actual morale of the firing crew.


BTW this routine is heavily commented, and we should clean out a little bit.
HTH.

Kblack


<!--quoteo(post=168944:date=Oct 27 2006, 02:36 PM:name=12punder)--><div class='quotetop'>QUOTE(12punder @ Oct 27 2006, 02:36 PM) [snapback]168944[/snapback]</div><div class='quotemain'><!--quotec-->
Hi guys, could someone of the coders explain me this part of the <b>AICannon.c</b> in deep, please?

// calculate recharge time for cannon
float Cannon_GetRechargeTime()
{
aref aCharacter = GetEventData();
ref rCannon = GetCannonByType(sti(aCharacter.Ship.Cannons.Type));
float fCannonSkill = stf(aCharacter.TmpSkill.Cannons); // 0.1 to 1.0
if (!CheckAttribute(rCannon, "ReloadTime"))
{
string CannonType = GetCannonName(sti(aCharacter.Ship.Cannons.Type));
if (CannonType != "No Cannons") trace("Cannon " + CannonType + " has no reloadTime!"); // LDH - don't need trace if no cannons
return 20.0; // LDH - changed from 1.0 so a real cannon will have a reasonable reload time, just in case
} // NK 05-07-18 fix for "No Cannons"
float fReloadTime = sti(rCannon.ReloadTime); // reload time in seconds

float fMultiply = AIShip_isPerksUse(aCharacter.TmpPerks.FastReload, 1.0, 0.<img src="style_emoticons/<#EMO_DIR#>/cool.gif" style="vertical-align:middle" emoid="8)" border="0" alt="cool.gif" />;
fMultiply = AIShip_isPerksUse(aCharacter.TmpPerks.ImmediateReload, fMultiply, 0.5);
// boal ReloadTime for cannons is influenced by Ship Crew -->
//fMultiply = fMultiply * Bring2RangeNoCheck(4.0, 1.0, 0.0, 1.0, stf(aCharacter.Ship.Crew.MinRatio));
// Ship.Crew.Quantity - ñêîêà íàðîäó ñåé÷àñ
// Ship.Crew.Morale - òåêóùàÿ ìîðàëü 0..99 45 - ñðåäíÿÿ
// Ship.maxcrew
// Ship.MinCrew
// aCharacter.skill.Leadership - ñòðîêà ñ ÷èñëîì
float cQ = GetCrewQuantity(aCharacter);
//float cMC = GetMaxCrewQuantity(aCharacter);
float cCM = 70;
if(CheckAttribute(aCharacter,"Ship.Crew.Morale")) cCM = sti(aCharacter.Ship.Crew.Morale);
// unneeded due to damage scaling based on crew qty NK 04-09-15
/*if(cMC)
{
fReloadTime = fReloadTime * (1 + (1 - cQ / cMC) * 4);
}*/
// NK can qty 05-04-18 -->
// now do crew qty scaling for above MIN_CREW_FOR_ALL_GUNS
int mcq = GetMinCrewQuantity(aCharacter);
if(mcq)
{
int canqty = GetCannonQuantity(&aCharacter);
if(canqty)
{
float crewratio = makefloat(cQ) / makefloat(mcq*5); //yes can be >1!
ref rship = GetShipByType(GetCharacterShipType(&aCharacter));
aref arship; makearef(arship, aCharacter.ship);
int fullqty = GetLocalShipAttrib(&arship, rship, "MaxCanQty");
crewratio = crewratio * makefloat(fullqty) / makefloat(canqty); // so if can qty decreases, not as much crew needed.
if(crewratio > MIN_CREW_FOR_ALL_GUNS)
{
fReloadTime *= Bring2Range(1.0, 1/(1.5*BEST_RATE_FOR_ALL_CREW), MIN_CREW_FOR_ALL_GUNS, 1.5, crewratio);
}
}
else { fReloadTime *= 10; }
}
//else { trace("char " + aCharacter.id + " name " + aCharacter.lastname + " has 0 mincq!"); }
// NK <--
fReloadTime = fReloadTime * (1 + (1 - cCM / 70) / 10);
//Log_SetStringToLog(aCharacter.id);
// debug info
//if( aCharacter.id == "Blaze")
//{
//Log_SetStringToLog("RTime "+fReloadTime+" Multiply "+ fMultiply +" CannonSkill " + fCannonSkill +" q "+aCharacter.Ship.Crew.Quantity+" m "+sti(refBaseShip.MaxCrew) + " ml "+aCharacter.Ship.Crew.Morale);
//}
// boal ReloadTime for cannons is influenced by Ship Crew <--

return fMultiply * (fReloadTime - fCannonSkill * (fReloadTime / 4.0));
}

i would like to know what at all influence the reloadtime of the ships cannons!

did the AICannon.c only influence the AI or even the Players ship?

especially this two lines of the code i don´t understand:

1)

fReloadTime *= Bring2Range(1.0, 1/(1.5*BEST_RATE_FOR_ALL_CREW), MIN_CREW_FOR_ALL_GUNS, 1.5, crewratio);

2)

Log_SetStringToLog("RTime "+fReloadTime+" Multiply "+ fMultiply +" CannonSkill " + fCannonSkill +" q "+aCharacter.Ship.Crew.Quantity+" m "+sti(refBaseShip.MaxCrew) + " ml "+aCharacter.Ship.Crew.Morale);

Thanks a million!

CU THOMAS
<!--QuoteEnd--></div><!--QuoteEEnd-->
 
Perhaps if you just asked what you wanted to know, we could answer it better. It's beyond the scope of this forum to teach you C programming, sorry.

In any case, I've rewritten the function totally, but Pieter hasn't added it to the build yet.

Hook
 
Here's how my modified Cannon_GetRechargeTime() function does it:

1. Get the normal reload time for the specific cannons installed.
1a. The normal reload time is multiplied by a user settable number for those who think cannons reload too quickly.
2. Adjust reload time for crew losses.
2a. Long guns are assumed to require half weight of shot in number of crew to load.
2b. Carronades are assumed to require 1/6 the weight of shot in number of crew to load.
2c. For example, if your ship has 12 pound long guns, it will require 6 crewmen to load each one.
2d. If the user wishes it, the crew will be reduced by "minimum sail crew" before deciding how many crew are left to load guns.
2e. The min sail crew is assumed to be 1% of the hull hit points.
2f. The reload time is increased if minimum gun crew is not available by the ratio of crew needed to crew available.
2g. Reload time is capped at 10 minutes, just in case.
3. Reload time is adjusted for perks. 20% faster for fast reload, 50% faster for immediate reload.
4. Reload time is adjusted for morale. This can make reloading up to 20% faster or slower depending on the crew morale.
5. The reload time is adjusted for cannon skill. It's 5% faster for each skill level.

The current function does similar things but in different ways. Crew losses, perks, morale and cannon skill all go into determining the final reload times of the guns.

Hook
 
Thanks guys for the fast answers!

sorry for my bad english! you guys don´t speak germen, arn´t you? <img src="style_emoticons/<#EMO_DIR#>/icon_wink.gif" style="vertical-align:middle" emoid=";)" border="0" alt="icon_wink.gif" /> <img src="style_emoticons/<#EMO_DIR#>/whistling.gif" style="vertical-align:middle" emoid=":wp" border="0" alt="whistling.gif" />

@ Hook where can i download your rewritten part?

what i loke to now is: - what else determining the final reload time -> morale, crew, cannon skill, the original reload time in <b>Cannons_init.c</b> (what about the other skills - maybe leadership, does it influence the reload time?

what like to have is that i have my initial reload time (cannons_init.c) when my ship have enough crew for all guns (als hook say 6 men * number of guns + min crew for sailing) if crew is more than this a little less reload time, if its below that -> reload time increase
- than the 2 perks (20% and 50%)
- and 5% +/- reload thime for min/max morale
 
am i right that i only need to change this 3 lines to get what i whant?

<b>original</b>:

fReloadTime = fReloadTime * (1 + (1 - cQ / cMC) * 2); CREW

fReloadTime = fReloadTime * (1 + (1 - cCM / 45) / 5); MORAL

return fMultiply * (fReloadTime - fCannonSkill * (fReloadTime / 2.0)); CANNONSKILL

<b>how i changed it</b>:

for examle 4lb guns have 40 seconds basic reloadtime

fReloadTime = fReloadTime * (1 + (1 - cQ / cMC) * <b>4</b>); e.g. 70% crew

-> 40sec * (1+(1-70/100) = 52 sec

fReloadTime = fReloadTime * (1 + (1 - cCM / <b>70</b>) /<b>10</b>); e.g. moral 35

-> 52*(1+(1-35/70)/10 = 54.6 sec

return fMultiply * (fReloadTime - fCannonSkill * (fReloadTime /<b> 4.0</b>)); e.g. skill 5

-> not sure about this line (54.6 - 0.5 * (54.6 / 4) = <b>47,775 sec</b> reload time in the end, right?

...but i tested it and got much lower reload times although i´ve changed TIMESCALAR_SEA to 1 in <i>Internalsettings.h</i>

Cu thomas
 
<!--quoteo(post=169082:date=Oct 28 2006, 11:37 AM:name=12punder)--><div class='quotetop'>QUOTE(12punder @ Oct 28 2006, 11:37 AM) [snapback]169082[/snapback]</div><div class='quotemain'><!--quotec-->-> 40sec * (1+(1-70/100) = 52 sec

...but i tested it and got much lower reload times although i´ve changed TIMESCALAR_SEA to 1 in <i>Internalsettings.h</i>
<!--QuoteEnd--></div><!--QuoteEEnd-->
-> 52*(1+(1-35/70)/10 = 54.6 sec <--- This isn't 54.6 seconds, it's 7.8 seconds.

The reason they used 45 in that equation is that 45 is considered "normal" morale. If your crew is above 45 morale, they reload faster. If below 45, they reload slower.

-> 40sec * (1+(1-70/100) = 52 sec <--- You forgot to multiply by 4

Changing TIMESCALAR_SEA won't affect reload times, it will just change the rate at which the clock updates. Normally you won't even see what this does unless you have something set up to display the time. The biggest change you'd notice is that weather updates don't happen as often.

-> 40sec * (1+(1-70/100<b>*4</b>) = 208 sec
-> 208*(1+(1-35/70)/10 = 31.2 sec
-> (31.2 - 0.5 * (31.2 / 4) = 27.3 sec

This final number is multiplied by fMultiply, which is your perks. 1.0 for no perk, .8 for fast reload, .5 for immediate reload.

If you're trying to make cannon reload take longer, change:

float fReloadTime = sti(rCannon.ReloadTime); // reload time in seconds

... to ...

float fReloadTime = sti(rCannon.ReloadTime)<b> * 2.0</b>; // reload time in seconds

... and change 2.0 to whatever you want the reload time to be multiplied by. With 2.0 the cannons will take twice as long to reload, with no other changes to the code.

Hook
 
<!--quoteo(post=169110:date=Oct 29 2006, 12:15 AM:name=Hook)--><div class='quotetop'>QUOTE(Hook @ Oct 29 2006, 12:15 AM) [snapback]169110[/snapback]</div><div class='quotemain'><!--quotec-->

-> 52*(1+(1-35/70)/10 = 54.6 sec <--- This isn't 54.6 seconds, it's 7.8 seconds.

<!--QuoteEnd--></div><!--QuoteEEnd-->

Oh i forgot some brackets it should look like this (it was already late <img src="style_emoticons/<#EMO_DIR#>/wink.gif" style="vertical-align:middle" emoid=";)" border="0" alt="wink.gif" /> )


Finally:
-> 40sec * (1+(1-70/100)<b>*4)</b> = 88 sec
-> 88*(1+(1-35/70)/10<b>)</b> = 92.4 sec
-> (92.4 - 0.5 * (31.2 / 4)<b>)</b> = <u>80.85</u> sec

hope that right now?

@ Hook where can i download your code (12lb cannon need 6 men ...)

P.s Do other skills like leadership for example influence reload speed ?

thanks again

THOMAS
 
My AICannon.c code isn't posted anywhere. I've sent it to Pieter for inclusion in the mods, and he's holding off until build 13 is stable. There are enough bugs in the current build without the possibility of my cannon code introducing more. I've changed more than just reaload times.

Leadership does not influence reload times.

If you want to see my current rechargetime code, here it is. Replace the old function with this one, but make a backup first.

<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->
#define RELOAD_TIME_MULTIPLIER 1.0
#define USE_MINSAILCREW         1

// calculate recharge time for cannon
// LDH --> 10Sep06 considerable rewrite for crew losses, added RELOAD_TIME_MULTIPLIER
float Cannon_GetRechargeTime()
{
    aref    aCharacter = GetEventData();
    ref     rCannon = GetCannonByType(sti(aCharacter.Ship.Cannons.Type));
    float   fCannonSkill = stf(aCharacter.TmpSkill.Cannons);    // 0.1 to 1.0
    if (!CheckAttribute(rCannon, "ReloadTime"))
    {
        string CannonType = GetCannonName(sti(aCharacter.Ship.Cannons.Type));
        if (CannonType != "No Cannons") trace("Cannon " + CannonType + " has no reloadTime!");  // LDH - don't need trace if no cannons
        return 20.0;    // LDH - changed from 1.0 so a real cannon will have a reasonable reload time, just in case
    } // NK 05-07-18 fix for "No Cannons"

    // Get standard reload time
    // LDH longer reload times 10Sep06
    float   fReloadTime = sti(rCannon.ReloadTime) * RELOAD_TIME_MULTIPLIER; // reload time in seconds

    // Adjust for perks
    float fMultiply = AIShip_isPerksUse(aCharacter.TmpPerks.FastReload, 1.0, 0.8);      // 20% faster for fast reload perk OR...
    fMultiply = AIShip_isPerksUse(aCharacter.TmpPerks.ImmediateReload, fMultiply, 0.5); // 50% faster for immediate reload perk

    // Adjust for cannon skill
    fMultiply *= (1.0 - fCannonSkill / 2.0);    // 5% faster for each cannon skill level

    if (strleft(aCharacter.ship.name, 5) == "fort_")    // Forts don't need crew restrictions or morale, just perks and cannon skill
    {
        return fMultiply * fReloadTime;
    }

    // Adjust for morale
    float CrewMorale = MORALE_NORMAL;
    if(CheckAttribute(aCharacter,"Ship.Crew.Morale")) CrewMorale = sti(aCharacter.Ship.Crew.Morale);
    fMultiply *= (1.0 + (1.0 - CrewMorale / MORALE_NORMAL) / 5.0);          // +/- 20% based on morale

    // Adjust for crew losses
    float CrewPerGun = stf(rCannon.caliber);
    if (rCannon.type == CANNON_NAME_LONG)
        CrewPerGun = CrewPerGun / 2.0;  // 12 pounder takes 6 crew, for example
    else
        CrewPerGun = CrewPerGun / 6.0;  // carronades take fewer crew and are normally twice the caliber of the long guns they replace
        // Note that if the player doesn't have USE_REAL_CANNONS set, the CrewPerGun is divided by 6 as well
    CrewPerGun = fclamp(1.0, 10.0, CrewPerGun);     // gun crew no less than 1 and no more than 10

    int CanQty = GetCannonQuantity(&aCharacter);
    float CrewRequired = CrewPerGun * CanQty;
    CrewRequired = CrewRequired / 2.0;      // We're only loading one broadside at a time.  We can adjust this later if needed.

    int CrewQuantity  = GetCrewQuantity(aCharacter);
    if (USE_MINSAILCREW)
    {
        int MinSailCrew = GetCharacterShipHP(aCharacter)/100;   // crew needed for sailing, intentionally not using mininum crew here
        if (MinSailCrew == 100000/100) MinSailCrew = 100;       // Black Pearl is a special case
        CrewQuantity -= MinSailCrew;
    }

    if (CrewRequired > CrewQuantity)
    {
        if (CrewQuantity > CrewPerGun)      // avoids division by zero as well
        {
            fReloadTime *= (CrewRequired / CrewQuantity);   // half the required crew takes twice as long to load
        }
        else
        {
            fReloadTime *= (CrewRequired / CrewPerGun);     // detail one gun crew from the MinSailCrew
        }
    }
    if (fReloadTime > 600.0) fReloadTime = 600.0;   // cap it at 10 minutes, will be adjusted below

    // Factor in cannon skill, perks and morale calculated above
    return fMultiply * fReloadTime;
}
// LDH <--
<!--c2--></div><!--ec2-->

Hook
 
Very nice. Thanks for making that code snippet available to all of us, Hook. Very appreciated.

Cap'n Drow
 
Back
Top