existing. But you do need to restart the game after you made a change (so closing the game and opening it again in windows).
With only these lines left, the stuttering disappears completely!
void Ship_HullHitEvent()
{
float fHP;
int iBallType = sti(AIBalls.CurrentBallType);
aref rShipObject = GetEventData();
int iBallCharacterIndex = GetEventData();
int iOurCharacterIndex = GetEventData();
ref rBallCharacter = GetCharacter(iBallCharacterIndex);
ref rOurCharacter = GetCharacter(iOurCharacterIndex);
rOurCharacter.Ship.LastBallCharacter = iBallCharacterIndex;
rBallCharacter.Ship.lasttgt = iOurCharacterIndex; // NK 04-09-16 to see who AI is attacking
int iCompanion = GetCompanionNumber(rBallCharacter, iOurCharacterIndex);
float x = GetEventData();
float y = GetEventData();
float z = GetEventData();
int iFirePlaceIndex = GetEventData();
float fFirePlaceDistance = GetEventData();
bool bDead = LAi_IsDead(rOurCharacter);
bool bSeriousBoom = false;
bool bInflame = false;
// NK 05-04-18 to handle relation change for REAL_CANNONS
if(iBallCharacterIndex == GetMainCharacterIndex() && USE_REAL_CANNONS && EXTRA_HIT_CHECK && rOurCharacter.ship.type != SHIP_FORT_NAME)
{
int currel = SeaAI_GetRelation(iOurCharacterIndex, iBallCharacterIndex) ;
if(currel != RELATION_ENEMY && !CheckAttribute(rOurCharacter,"surrendered")) // NK surrender 05-04-20
{
aref aShips; makearef(aShips, rBallCharacter.SeaAI.Update.Ships);
int iShipsNum = GetAttributesNum(aShips);
int s;
bool enemy = false;
for (s=0; s<iShipsNum; s++)
{
aref aShip = GetAttributeN(aShips, s);
if (sti(aShip.relation) == RELATION_ENEMY) { enemy = true; break; }
}
ref cmdr = Group_GetGroupCommander(GetGroupIDFromCharacter(&rOurCharacter));
if (!enemy) {
Event(SHIP_FIRE_ACTION, "iil", &rOurCharacter, &cmdr, currel); // if there's no enemy, then you have no excuse.
} else {
if (!CheckAttribute(rOurCharacter, "numhits")) {
rOurCharacter.numhits = 1;
} else {
int curhits = sti(rOurCharacter.numhits); // max of cqty / 2 hits.
if (curhits > GetCannonMaxQuantity(&rBallCharacter) / 2) {
Event(SHIP_FIRE_ACTION, "iil", &rOurCharacter, &cmdr, currel);
} else {
curhits++;
rOurCharacter.numhits = curhits;
}
}
}
}
}
if(iBallCharacterIndex != GetMainCharacterIndex() && CheckAttribute(rOurCharacter,"surrendered")) return; // NK because AI doesn't respect surrender. 05-04-23
// NK <--
// Cannon damage multiply
ref rCannon = GetCannonByType(sti(rBallCharacter.Ship.Cannons.Type));
float maxqty, fCannonDamageMultiply;
// THIS IS NOT NEEDED ANY MORE. But the comment is left and the code commented. NK 04-09-15 to simulate fewer crew manning fewer guns. Hence reload rate will now go back to constant.
// KNB 05-02-04 changed this a bit: there is no penalty for >60% crew and the minimum damage is 10%
// now use cannon qty rather than crew mult. 05-04-18
// KK -->
fCannonDamageMultiply = stf(rCannon.DamageMultiply);
if(USE_REAL_CANNONS)
{
// KNB 04-01-17 distance/aspect based damage multipliers -->
float fShotDistance = Ship_GetDistance2D(rBallCharacter, rOurCharacter);
if(fShotDistance < 0) fShotDistance = 500; // NK for when dist < 0 05-04-15
if (rOurCharacter.Ship.Type != SHIP_FORT_NAME && rBallCharacter.Ship.Type != SHIP_FORT_NAME)
{
float fShotSpeed = rCannon.SpeedV0 * stf(Goods[iBallType].SpeedV0);
float fBallAngle = 0;
float fOurAngle = 0;
fCannonDamageMultiply *= 2 * pow(1-1/(2.25*fShotSpeed),fShotDistance); // 2x at point blank, decreasing exponentially with range
if (iBallType != GOOD_GRAPES)
{
if(CheckAttribute(rOurCharacter,"ship.ang.y")) // NK for checking atttributes first before we need CheckAttribute(rBallCharacter,"ship.ang.y") && to
{
// NK now get angle from AIBalls, this requires reversing of the B2R.
fBallAngle = clampangle(stf(AIBalls.Dir)+PI); fOurAngle = stf(rOurCharacter.Ship.Ang.y);
fCannonDamageMultiply *= Bring2Range(0.50, 2.0, 0.0, 1.0, abs(GetDotProduct(fBallAngle,fOurAngle))); //50%-200% depending on angle
}
}
}
}
// <-- KNB
// <-- KK
if (sti(rBallCharacter.TmpPerks.CriticalShoot) && rand(19)==10) { bSeriousBoom = true; } // +5%
if (sti(rBallCharacter.TmpPerks.CannonProfessional) && rand(9)==4) { bSeriousBoom = true; } // +10%
ref rBall = GetGoodByType(iBallType);
switch (iBallType)
{
// TIH --> this section adjusted to be a bit more understandable in setting, and reasonable in graphics Nov13'06
// Removal of "CreateBlastM()" function due to that function causing a CTD in battles Nov12'06
// NK add USE_PARTICLES switch // TIH changed to own switch SHIPHIT_PARTICLES 7-7-06
// Ball_impact and splinters by MM
// By MM, Flames and Critical hits only present on bombs now. // changed to add a rare chance (otherwise what's the POINT of the PERKS?)
case GOOD_BALLS:
if (rand(1)) { bSeriousBoom = false; }// pref toggle and 50% chance a possible critical hit is allowed
if (rand(32) == 1) { bInflame = true; }// pref toggle and 3% chance ship catches on fire from hit
Play3DSound("ball2bort", x, y, z);
switch(SHIPHIT_PARTICLES)
{
case 0: CreateParticleSystem("blast", x, y, z, 0.0, 0.0, 0.0, 0); break; // one orange puff // stock behavior
case 1:
CreateParticleSystem("ball_impact", x, y, z, 0.0, 0.0, 0.0, 0); // two small gray puffs
break;
case 2:
CreateParticleSystem("ball_impact_enhanced", x, y, z, 0.0, 0.0, 0.0, 0); // wood dust
CreateParticleSystem("splinters_enhanced", x, y, z, 0.0, 0.0, 0.0, 0); // twenty-four small splinters
CreateParticleSystem("splinters2_enhanced", x, y, z, 0.0, 0.0, 0.0, 0); // twenty-four medium splinters
break;
case 3:
CreateBlast(x,y,z); // excessive plume of planks and barrels, causing big water splashes
CreateParticleSystem("ball_impact", x, y, z, 0.0, 0.0, 0.0, 0); // two small gray puffs
CreateParticleSystem("splinters2", x, y, z, 0.0, 0.0, 0.0, 0); // six medium splinters
CreateParticleSystem("splinters3", x, y, z, 0.0, 0.0, 0.0, 0); // five large splinters
CreateParticleSystem("flyers", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("flyers2", x, y, z, 0.0, 0.0, 0.0, 0);
break;
}
break;
case GOOD_GRAPES:
bSeriousBoom = false;
bInflame = false;
Play3DSound("grapes2bort", x, y, z);
switch(SHIPHIT_PARTICLES)
{
case 0: CreateParticleSystem("blast", x, y, z, 0.0, 0.0, 0.0, 0); break; // one orange puff // stock behavior
case 1:
CreateParticleSystem("ball_impact", x, y, z, 0.0, 0.0, 0.0, 0);
break;
case 2:
CreateParticleSystem("ball_impact", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("splinters", x, y, z, 0.0, 0.0, 0.0, 0);
break;
case 3:
CreateBlast(x,y,z);
CreateParticleSystem("ball_impact", x, y, z, 0.0, 0.0, 0.0, 0);
break;
}
break;
case GOOD_KNIPPELS:
bSeriousBoom = false;
bInflame = false;
Play3DSound("knippel2bort", x, y, z);
switch(SHIPHIT_PARTICLES)
{
case 0: CreateParticleSystem("blast", x, y, z, 0.0, 0.0, 0.0, 0); break; // one orange puff // stock behavior
case 1:
CreateParticleSystem("ball_impact", x, y, z, 0.0, 0.0, 0.0, 0);
break;
case 2:
CreateParticleSystem("ball_impact", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("splinters", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("splinters2", x, y, z, 0.0, 0.0, 0.0, 0);
break;
case 3:
CreateBlast(x,y,z);
CreateParticleSystem("ball_impact", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("flyers", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("flyers2", x, y, z, 0.0, 0.0, 0.0, 0);
break;
}
break;
case GOOD_BOMBS:
if (rand(20) == 10) { bSeriousBoom = true; }
if (rand(2) == 1) { bInflame = true; }
Play3DSound("bomb2bort", x, y, z);
switch(SHIPHIT_PARTICLES)
{
case 0: CreateParticleSystem("blast", x, y, z, 0.0, 0.0, 0.0, 0); break; // one orange puff // stock behavior
case 1:
CreateParticleSystem("blast", x, y, z, 0.0, 0.0, 0.0, 0);
break;
case 2:
CreateBlast(x,y,z);
CreateParticleSystem("blast", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("flyers", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("flyers2", x, y, z, 0.0, 0.0, 0.0, 0);
break;
case 3:
CreateBlast(x,y,z);
CreateParticleSystem("blast", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("blast_inv", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("splinters2", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("splinters3", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("flyers", x, y, z, 0.0, 0.0, 0.0, 0);
CreateParticleSystem("flyers2", x, y, z, 0.0, 0.0, 0.0, 0);
break;
}
break;
// TIH <-- end adjustment
}
// PB: Queen Anne's Revenge -->
if(sti(GetAttribute(AIBalls, "GreekFire")))
{
bInflame = true;
LogIt("Greek Fire hits the " + rOurCharacter.ship.name + "!")
}
// PB: Queen Anne's Revenge <--
if (sti(rOurCharacter.TmpPerks.ShipDefenceProfessional) && frnd() < PROSHIPDEF_NOCRITCH) { bSeriousBoom = false; } // no seriouse boom, NK 05-04-19 add setting
if (!bDead)
{
float fCrewDamage;
if (USE_REAL_CANNONS)
fCrewDamage = stf(rBall.DamageCrew) * fCannonDamageMultiply * AIShip_isPerksUse(rBallCharacter.TmpPerks.CrewDamageUp, 1.0, 1.10); // 1.15 KNB;
else
fCrewDamage = stf(rBall.DamageCrew) * fCannonDamageMultiply * AIShip_isPerksUse(rBallCharacter.TmpPerks.CrewDamageUp, 1.0, 1.15);
// KK -->
//trace("fCrewDamage="+fCrewDamage);
}
}