#include "sail_msg.h" #define MAX_FORTS 16 #define MIN_CANNON_DAMAGE_DISTANCE 20.0 object AIFort; object Forts[MAX_FORTS]; object FortsBlots[MAX_FORTS]; int iNumForts = 0; void DeleteFortEnvironment() { if (isEntity(&AIFort)) { DeleteClass(&AIFort); } for (int i=0; i= 3) { bFortRessurect = true; } break; case FORT_DEAD: iDeadDays = Fort_GetDeadDays(rCharacter); if (iDeadDays >= 7) { bFortRessurect = true; } break; } if (iDeadDays > 0) { rCharacter.Ship.Crew.Quantity = iDeadDays * 200 + rand(100); } if (bFortRessurect) { SetFortCharacterCaptured(rCharacter, false); iFortMode = FORT_NORMAL; rCharacter.Ship.Crew.Quantity = 900 + rand(600); } rCharacter.Fort.Mode = iFortMode; rCharacter.Fort.PlayerDamage = 0.0; // player damage Event("eSwitchPerks", "l", iFortCharacter); // Perks Ship_UpdateTmpSkills(rCharacter); Fort_CheckAttributes(rCharacter); AIFort.MinCannonDamageDistance = MIN_CANNON_DAMAGE_DISTANCE; // in meters rCharacter.Ship.Crew.MinRatio = 1.0; rCharacter.Ship.Name = arLocator.fortname; rCharacter.Ship.Type = SHIP_FORT; SetCharacterGoods(rCharacter, GOOD_BOMBS, 34000); // create fort blot CreateEntity(&FortsBlots[iNumForts - 1], "blots"); SendMessage(&FortsBlots[iNumForts - 1], "lia", MSG_BLOTS_SETMODEL, &Forts[iNumForts - 1], rCharacter); LayerAddObject(SEA_EXECUTE, &Forts[iNumForts], 10001); LayerAddObject(SEA_REALIZE, &Forts[iNumForts], 10001); SendMessage(&AIFort, "laaaii", AI_MESSAGE_ADD_FORT, rIsland, arLocator, rCharacter, &Forts[iNumForts-1], &FortsBlots[iNumForts-1]); // flags int iNation = sti(rCharacter.nation); ref rNation = GetNationByType(iNation); SendMessage(&Flag, "lil", MSG_FLAG_INIT, &Forts[iNumForts - 1], iNation); // install flag on fort //Trace("Character with id: '" + rCharacter.id + "' and nation: '" + rNation.Name + "', assigned to fort: '" + arLocator.name + "'"); ReloadProgressUpdate(); } } } void Fort_CreateEvent() { int iCannonsNum; aref rCharacter; rCharacter = GetEventData(); iCannonsNum = GetEventData(); rCharacter.Fort.Cannons.Quantity = iCannonsNum; rCharacter.Ship.HP = iCannonsNum * 100; rCharacter.Fort.HP = rCharacter.Ship.HP; } int Fort_GetCannonsQuantity(ref rFortCharacter) { if (!CheckAttribute(rFortCharacter, "Fort.Cannons.Quantity")) { return 0; } return sti(rFortCharacter.Fort.Cannons.Quantity); } float Fort_CannonDamage() { float x, y, z; aref aFortLabel; ref rBallCharacter, rFortCharacter; int iNumAllCannons, iNumDamagedCannons; int iExp = 0; float fDistance, fDamage; int iBallCharacterIndex = GetEventData(); int iFortCharacterIndex = GetEventData(); rBallCharacter = GetCharacter(iBallCharacterIndex); rFortCharacter = GetCharacter(iFortCharacterIndex); aFortLabel = GetEventData(); iNumAllCannons = GetEventData(); iNumDamagedCannons = GetEventData(); x = GetEventData(); y = GetEventData(); z = GetEventData(); fDistance = GetEventData(); // distance to cannon fDamage = GetEventData(); // current cannon damage 0.0% .. 100.0% if (iBallCharacterIndex == iFortCharacterIndex) { return fDamage; } int iCompanionQuantity = GetCompanionQuantity(rBallCharacter); int iFortMode = sti(rFortCharacter.Fort.Mode); if (iFortMode != FORT_NORMAL) { return fDamage; } float fDistanceMul = pow(0.035, fDistance / MIN_CANNON_DAMAGE_DISTANCE); ref rCannon = GetCannonByType(sti(rBallCharacter.Ship.Cannons.Type)); float fCannonDamageMultiply = stf(rCannon.DamageMultiply) * fDistanceMul; ref rBall = GetGoodByType(sti(AIBalls.CurrentBallType)); //CreateParticleSystem("blast",x,y,z,0.0,0.0,0.0,0); float fHullDamage = stf(rBall.DamageHull) * fCannonDamageMultiply * 0.4; float fCrewDamage = stf(rBall.DamageCrew) * fCannonDamageMultiply; rFortCharacter.Ship.HP = (1.0 - MakeFloat(iNumDamagedCannons) / MakeFloat(iNumAllCannons)) * stf(rFortCharacter.Fort.HP); rFortCharacter.Ship.Crew.Quantity = stf(rFortCharacter.Ship.Crew.Quantity) - fCrewDamage; float fDamagePiece = fHullDamage + (frnd() - 0.5) * fHullDamage * 0.4; fDamage = fDamage + fDamagePiece; if (iBallCharacterIndex == GetMainCharacterIndex()) { int iRelation = SeaAI_GetRelation(iFortCharacterIndex, iBallCharacterIndex); if (iRelation != RELATION_ENEMY) { float fCurPlayerDamage = stf(rFortCharacter.Fort.PlayerDamage); if (iRelation == RELATION_FRIEND) { fCurPlayerDamage = fCurPlayerDamage + fDamagePiece * 0.8; } if (iRelation == RELATION_NEUTRAL) { fCurPlayerDamage = fCurPlayerDamage + fDamagePiece * 0.5; } if (fCurPlayerDamage >= 100.0) { SetCharacterRelationBoth(iBallCharacterIndex, iFortCharacterIndex, RELATION_ENEMY); SetNationRelation2MainCharacter(sti(rFortCharacter.Nation), RELATION_ENEMY); UpdateRelations(); } rFortCharacter.Fort.PlayerDamage = fCurPlayerDamage; } } //AddCharacterExp(rBallCharacter, MakeInt(fHullDamage)); bool bImmortal = LAi_IsImmortal(rFortCharacter); if (fDamage >= 100.0) { Play3DSound("fort_cann_explode", x, y, z); CreateBlast(x, y, z); CreateParticleSystem("blast_inv", x, y, z, 0.0, 0.0, 0.0, 0); CreateParticleSystem("blast", x, y, z, 0.0, 0.0, 0.0, 0); if (!bImmortal) { iNumDamagedCannons++; fDamage = 100.0; switch (rand(1)) { case 0: CreateParticleSystem("fort_fire", x, y, z, -1.57, 0.0, 0.0, 0); CreateParticleSystem("fort_smoke", x, y, z, -1.57, 0.0, 0.0, 0); break; case 1: CreateParticleSystem("fort_fire", x, y, z, -1.57, 0.0, 0.0, 0); CreateParticleSystem("fort_gray_smoke", x, y, z, -1.57, 0.0, 0.0, 0); break; } } else { fDamage = 0.0; } iExp = MakeInt(1000 / iCompanionQuantity); if (iBallCharacterIndex == GetMainCharacterIndex()) { object oRes; string sCannonString = LanguageConvertString(iSeaSectionLang, "Fort_cannon"); string sExp = iExp; Event(PARSE_STRING, "asls", &oRes, sCannonString, 1, sExp); Log_SetStringToLog(oRes.Str); } AddCharacterExp(rBallCharacter, iExp); } if (iNumDamagedCannons >= iNumAllCannons / 2) { Fort_SetAbordageMode(rBallCharacter, rFortCharacter); } return fDamage; } void Fort_SetAbordageMode(ref rKillerCharacter, ref rFortCharacter) { // open for abordage rFortCharacter.Fort.Mode = FORT_ABORDAGE; // data of frot die rFortCharacter.Fort.DieTime.Year = GetDataYear(); rFortCharacter.Fort.DieTime.Month = GetDataMonth(); rFortCharacter.Fort.DieTime.Day = GetDataDay(); rFortCharacter.Fort.DieTime.Time = GetTime(); Event(FORT_DESTROYED, "l", sti(rFortCharacter.index)); int iExp = 20000; AddCharacterExp(rKillerCharacter, iExp); // Fort destroy log object oRes; string sFortName = XI_ConvertString(rFortCharacter.Ship.Name); string sFortString = LanguageConvertString(iSeaSectionLang, "Fort_destroy"); string sExp = iExp; Event(PARSE_STRING, "aslss", &oRes, sFortString, 2, sFortName, sExp); Log_SetStringToLog(oRes.Str); } void Fort_SetCharacter(ref rCharacter, string sIslandID, string sLocationGroup, string sLocationLocator) { int iCharacterIndex = Fort_FindCharacter(sIslandID, sLocationGroup, sLocationLocator); if (iCharacterIndex != -1) { ChangeCharacterAddress(&Characters[iCharacterIndex], "None", ""); } ChangeCharacterAddressGroup(rCharacter, sIslandID, sLocationGroup, sLocationLocator); rCharacter.Ship.Type = SHIP_FORT; Fort_CheckAttributes(rCharacter); } void Fort_CheckAttributes(ref rCharacter) { if (!CheckAttribute(rCharacter, "Ship.Cannons.Type")) { rCharacter.Ship.Cannons.Type = CANNON_TYPE_CULVERINE_LBS24; } if (!CheckAttribute(rCharacter, "Ship.Cannons.Charge.Type")) { rCharacter.Ship.Cannons.Charge.Type = GOOD_BOMBS; } if (!CheckAttribute(rCharacter, "Fort.Cannons.Type.1")) { rCharacter.Fort.Cannons.Type.1 = CANNON_TYPE_CULVERINE_LBS24; } if (!CheckAttribute(rCharacter, "Fort.Cannons.Type.2")) { rCharacter.Fort.Cannons.Type.2 = CANNON_TYPE_CANNON_LBS32; } }