2022-04-30 09:41:17 -04:00
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.objects ;
import engine.Enum ;
import engine.Enum.ProtectionState ;
import engine.Enum.SiegePhase ;
import engine.Enum.SiegeResult ;
import engine.InterestManagement.HeightMap ;
2024-12-28 05:41:33 -06:00
import engine.InterestManagement.InterestManager ;
2022-04-30 09:41:17 -04:00
import engine.InterestManagement.WorldGrid ;
import engine.db.archive.BaneRecord ;
import engine.db.archive.DataWarehouse ;
2024-12-28 05:41:33 -06:00
import engine.gameManager.* ;
2022-04-30 09:41:17 -04:00
import engine.job.JobScheduler ;
import engine.jobs.ActivateBaneJob ;
import engine.jobs.BaneDefaultTimeJob ;
import engine.math.Vector3fImmutable ;
2024-12-31 14:32:48 -06:00
import engine.net.Dispatch ;
2022-04-30 09:41:17 -04:00
import engine.net.DispatchMessage ;
import engine.net.client.ClientConnection ;
2024-12-31 14:32:48 -06:00
import engine.net.client.msg.CityDataMsg ;
2022-04-30 09:41:17 -04:00
import engine.net.client.msg.PlaceAssetMsg ;
import engine.net.client.msg.chat.ChatSystemMsg ;
import engine.server.MBServerStatics ;
import org.joda.time.DateTime ;
import org.pmw.tinylog.Logger ;
import java.sql.ResultSet ;
import java.sql.SQLException ;
import java.util.ArrayList ;
import java.util.Date ;
2025-01-03 20:09:48 -06:00
import java.util.HashSet ;
2022-04-30 09:41:17 -04:00
import java.util.concurrent.ConcurrentHashMap ;
public final class Bane {
2023-07-15 09:23:48 -04:00
public static ConcurrentHashMap < Integer , Bane > banes = new ConcurrentHashMap <> ( MBServerStatics . CHM_INIT_CAP , MBServerStatics . CHM_LOAD , MBServerStatics . CHM_THREAD_LOW );
2022-04-30 09:41:17 -04:00
private final int cityUUID ;
private final int stoneUUID ;
2023-07-15 09:23:48 -04:00
private int ownerUUID ;
2022-04-30 09:41:17 -04:00
private DateTime placementDate = null ;
private DateTime liveDate = null ;
private BaneDefaultTimeJob defaultTimeJob ;
2024-12-28 07:39:15 -06:00
public boolean timeSet = false ;
public boolean daySet = false ;
public boolean capSet = false ;
public int capSize = 10 ;
2022-04-30 09:41:17 -04:00
// Internal cache for banes
2023-07-15 09:23:48 -04:00
private ActivateBaneJob activateBaneJob ;
2022-04-30 09:41:17 -04:00
/**
* ResultSet Constructor
*/
public Bane ( ResultSet rs ) throws SQLException {
Date sqlDateTime ;
ActivateBaneJob abtj ;
this . cityUUID = rs . getInt ( "cityUUID" );
this . ownerUUID = rs . getInt ( "ownerUUID" );
this . stoneUUID = rs . getInt ( "stoneUUID" );
2024-12-28 07:39:15 -06:00
this . timeSet = rs . getInt ( "time_set" ) == 1 ;
this . daySet = rs . getInt ( "day_set" ) == 1 ;
this . capSet = rs . getInt ( "cap_set" ) == 1 ;
this . capSize = rs . getInt ( "cap_size" );
2022-04-30 09:41:17 -04:00
sqlDateTime = rs . getTimestamp ( "placementDate" );
if ( sqlDateTime != null )
this . placementDate = new DateTime ( sqlDateTime );
sqlDateTime = rs . getTimestamp ( "liveDate" );
if ( sqlDateTime != null )
this . liveDate = new DateTime ( sqlDateTime );
switch ( this . getSiegePhase ()) {
case CHALLENGE :
break ;
case WAR :
// cancel old job if exists
if ( this . activateBaneJob != null )
this . activateBaneJob . cancelJob ();
abtj = new ActivateBaneJob ( cityUUID );
JobScheduler . getInstance (). scheduleJob ( abtj , this . liveDate . getMillis ());
this . activateBaneJob = abtj ;
break ;
case STANDOFF :
// cancel old job if exists
if ( this . activateBaneJob != null )
this . activateBaneJob . cancelJob ();
abtj = new ActivateBaneJob ( cityUUID );
JobScheduler . getInstance (). scheduleJob ( abtj , this . liveDate . getMillis ());
this . activateBaneJob = abtj ;
break ;
}
2024-12-28 05:21:10 -06:00
//add bane commander NPC
2024-12-31 20:06:31 -06:00
//summonBaneCommander(this);
2022-04-30 09:41:17 -04:00
}
public static boolean summonBanestone ( PlayerCharacter player , ClientConnection origin , int rank ) {
Guild baningGuild ;
Zone cityZone ;
City targetCity ;
ArrayList < Bane > nationBanes ;
baningGuild = player . getGuild ();
2023-01-21 09:28:30 -05:00
if ( baningGuild . getNation (). isEmptyGuild ()) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 55 , "" ); // You must be in a Nation
2022-04-30 09:41:17 -04:00
return false ;
}
if ( baningGuild . getNation (). isNPCGuild ()) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 72 , "" ); // Cannot be in an NPC nation
2022-04-30 09:41:17 -04:00
return false ;
}
if ( GuildStatusController . isInnerCouncil ( player . getGuildStatus ()) == false ) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 10 , "" ); // You must be a guild leader
2022-04-30 09:41:17 -04:00
return false ;
}
2023-05-07 10:20:53 -04:00
// Cannot place banestone underwater;
2022-04-30 09:41:17 -04:00
if ( HeightMap . isLocUnderwater ( player . getLoc ())) {
PlaceAssetMsg . sendPlaceAssetError ( origin , 6 , "" ); // Cannot place underwater
return false ;
}
2023-05-07 10:20:53 -04:00
// figure out which city zone we are standing on.
2022-04-30 09:41:17 -04:00
targetCity = ZoneManager . getCityAtLocation ( player . getLoc ());
if ( targetCity == null ) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 59 , "" ); // No city to siege at this location!
2022-04-30 09:41:17 -04:00
return false ;
}
if ( targetCity . isSafeHold ()) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 15 , "" ); // Cannot place assets in peace zone
2022-04-30 09:41:17 -04:00
return false ;
}
if ( targetCity . getRank () > rank ) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 60 , "" ); // Bane rank is too low
2022-04-30 09:41:17 -04:00
return false ;
}
cityZone = targetCity . getParent ();
// Cannot place assets on a dead tree
if (( cityZone . isPlayerCity ()) &&
( City . getCity ( cityZone . getPlayerCityUUID ()). getTOL (). getRank () == - 1 )) {
PlaceAssetMsg . sendPlaceAssetError ( origin , 1 , "Cannot bane a dead tree!" );
return false ;
}
if ( baningGuild . getNation () == targetCity . getGuild (). getNation ()) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 20 , "" ); //Cannot bane yourself!
2022-04-30 09:41:17 -04:00
return false ;
}
if ( targetCity . getTOL () == null ) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 65 , "" ); // Cannot find tree to target
2022-04-30 09:41:17 -04:00
return false ;
}
if ( targetCity . getBane () != null ) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 23 , "" ); // Tree is already baned.
2022-04-30 09:41:17 -04:00
return false ;
}
if ( getBaneByAttackerGuild ( baningGuild ) != null ) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 1 , "Your guild has already placed a bane!" );
2022-04-30 09:41:17 -04:00
return false ;
}
nationBanes = getBanesByNation ( baningGuild . getNation ());
// A nation can only have 3 concurrent banes
if ( nationBanes . size () == 3 ) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 64 , "" ); // Your nation is already at war and your limit has been reached
2022-04-30 09:41:17 -04:00
return false ;
}
if ( targetCity . isLocationOnCityGrid ( player . getLoc ()) == true ) {
2023-07-15 09:23:48 -04:00
PlaceAssetMsg . sendPlaceAssetError ( origin , 1 , "Cannot place banestone on city grid." );
2022-04-30 09:41:17 -04:00
return false ;
}
Blueprint blueprint = Blueprint . getBlueprint ( 24300 ); // Banestone
//Let's drop a banestone!
Vector3fImmutable localLocation = ZoneManager . worldToLocal ( player . getLoc (), cityZone );
if ( localLocation == null ) {
PlaceAssetMsg . sendPlaceAssetError ( player . getClientConnection (), 1 , "A Serious error has occurred. Please post details for to ensure transaction integrity" );
Logger . info ( "Failed to Convert World coordinates to local zone coordinates" );
return false ;
}
Building stone = DbManager . BuildingQueries . CREATE_BUILDING (
cityZone . getObjectUUID (), player . getObjectUUID (), blueprint . getName (), blueprint . getBlueprintUUID (),
localLocation , 1 . 0f , blueprint . getMaxHealth ( rank ), ProtectionState . PROTECTED , 0 , rank ,
null , blueprint . getBlueprintUUID (), 1 , 0 . 0f );
if ( stone == null ) {
PlaceAssetMsg . sendPlaceAssetError ( player . getClientConnection (), 1 , "A Serious error has occurred. Please post details for to ensure transaction integrity" );
return false ;
}
stone . addEffectBit (( 1 << 19 ));
stone . setMaxHitPoints ( stone . getBlueprint (). getMaxHealth ( stone . getRank ()));
stone . setCurrentHitPoints ( stone . getMaxHitPoints ());
BuildingManager . setUpgradeDateTime ( stone , null , 0 );
//Make the bane
Bane bane = makeBane ( player , targetCity , stone );
if ( bane == null ) {
//delete bane stone, failed to make bane object
DbManager . BuildingQueries . DELETE_FROM_DATABASE ( stone );
PlaceAssetMsg . sendPlaceAssetError ( player . getClientConnection (), 1 , "A Serious error has occurred. Please post details for to ensure transaction integrity" );
return false ;
}
WorldGrid . addObject ( stone , player );
//Add bane effect to TOL
targetCity . getTOL (). addEffectBit (( 1 << 16 ));
targetCity . getTOL (). updateEffects ();
2023-07-15 09:23:48 -04:00
2022-04-30 09:41:17 -04:00
Vector3fImmutable movePlayerOutsideStone = player . getLoc ();
movePlayerOutsideStone = movePlayerOutsideStone . setX ( movePlayerOutsideStone . x + 10 );
movePlayerOutsideStone = movePlayerOutsideStone . setZ ( movePlayerOutsideStone . z + 10 );
player . teleport ( movePlayerOutsideStone );
// Notify players
ChatSystemMsg chatMsg = new ChatSystemMsg ( null , "[Bane Channel] " + targetCity . getCityName () + " has been baned by " + baningGuild . getName () + ". Standoff phase has begun!" );
chatMsg . setMessageType ( 4 );
chatMsg . setChannel ( Enum . ChatChannelType . SYSTEM . getChannelID ());
DispatchMessage . dispatchMsgToAll ( chatMsg );
// Push this event to the DataWarehouse
BaneRecord baneRecord = BaneRecord . borrow ( bane , Enum . RecordEventType . PENDING );
DataWarehouse . pushToWarehouse ( baneRecord );
2024-12-28 05:09:51 -06:00
//add bane commander NPC
2024-12-28 05:18:24 -06:00
summonBaneCommander ( bane );
2024-12-31 14:37:16 -06:00
try {
//update map for all players online
for ( PlayerCharacter playerCharacter : SessionManager . getAllActivePlayerCharacters ()) {
CityDataMsg cityDataMsg = new CityDataMsg ( SessionManager . getSession ( playerCharacter ), false );
cityDataMsg . updateMines ( true );
cityDataMsg . updateCities ( true );
Dispatch dispatch = Dispatch . borrow ( playerCharacter , cityDataMsg );
DispatchMessage . dispatchMsgDispatch ( dispatch , Enum . DispatchChannel . SECONDARY );
}
} catch ( Exception e ){
}
2022-04-30 09:41:17 -04:00
return true ;
}
2024-12-28 05:18:24 -06:00
public static void summonBaneCommander ( Bane bane ){
2024-12-28 06:12:15 -06:00
Vector3fImmutable spawnLoc = Vector3fImmutable . getRandomPointOnCircle ( bane . getStone (). loc , 6 );
2024-12-28 05:28:27 -06:00
NPC baneCommander ;
2024-12-28 05:49:09 -06:00
int commanderuuid = DbManager . NPCQueries . BANE_COMMANDER_EXISTS ( bane . getStone (). getObjectUUID ());
2024-12-28 05:41:33 -06:00
2024-12-28 05:50:15 -06:00
if ( commanderuuid == 0 ) {
2024-12-28 05:18:24 -06:00
//add bane commander NPC
int contractID = 1502042 ;
2024-12-28 05:28:27 -06:00
baneCommander = NPC . createNPC ( "Bane Commander" , contractID , spawnLoc , bane . getCity (). getGuild (), ZoneManager . findSmallestZone ( bane . getStone (). loc ), ( short ) 70 , bane . getStone ());
2024-12-31 20:04:54 -06:00
try {
NPCManager . slotCharacterInBuilding ( baneCommander );
} catch ( Exception e ){
}
2024-12-30 16:29:16 -06:00
WorldGrid . addObject ( baneCommander , spawnLoc . x , spawnLoc . z );
WorldGrid . updateObject ( baneCommander );
2024-12-28 05:49:09 -06:00
}
else
{
baneCommander = NPC . getNPC ( commanderuuid );
2024-12-28 05:18:24 -06:00
}
2024-12-31 17:39:28 -06:00
//try {
// NPCManager.slotCharacterInBuilding(baneCommander);
//}catch (Exception e){
2024-12-31 17:34:51 -06:00
//swallow it
2024-12-31 17:39:28 -06:00
//}
2024-12-28 06:05:19 -06:00
baneCommander . runAfterLoad ();
2024-12-28 06:14:06 -06:00
//baneCommander.setLoc(spawnLoc);
2024-12-28 06:00:21 -06:00
InterestManager . setObjectDirty ( baneCommander );
2024-12-28 06:05:19 -06:00
baneCommander . updateLocation ();
2024-12-28 05:18:24 -06:00
}
2023-07-15 09:23:48 -04:00
public static Bane getBane ( int cityUUID ) {
Bane outBane ;
// Check cache first
outBane = banes . get ( cityUUID );
// Last resort attempt to load from database
if ( outBane == null )
outBane = DbManager . BaneQueries . LOAD_BANE ( cityUUID );
else
return outBane ;
// As we loaded from the db, store it in the internal cache
if ( outBane != null )
banes . put ( cityUUID , outBane );
return outBane ;
}
public static Bane getBaneByAttackerGuild ( Guild guild ) {
if ( guild == null || guild . isEmptyGuild ())
return null ;
ArrayList < Bane > baneList ;
baneList = new ArrayList <> ( banes . values ());
for ( Bane bane : baneList ) {
if ( bane . getOwner (). getGuild (). equals ( guild ))
return bane ;
}
return null ;
}
public static ArrayList < Bane > getBanesByNation ( Guild guild ) {
ArrayList < Bane > baneList ;
ArrayList < Bane > returnList ;
baneList = new ArrayList <> ( banes . values ());
returnList = new ArrayList <> ();
for ( Bane bane : baneList ) {
if ( bane . getOwner (). getGuild (). getNation (). equals ( guild ))
returnList . add ( bane );
}
return returnList ;
}
public static void addBane ( Bane bane ) {
Bane . banes . put ( bane . cityUUID , bane );
}
public static Bane makeBane ( PlayerCharacter owner , City city , Building stone ) {
Bane newBane ;
if ( DbManager . BaneQueries . CREATE_BANE ( city , owner , stone ) == false ) {
Logger . error ( "Error writing to database" );
return null ;
}
newBane = DbManager . BaneQueries . LOAD_BANE ( city . getObjectUUID ());
return newBane ;
}
//Call this to prematurely end a bane
2022-04-30 09:41:17 -04:00
public SiegePhase getSiegePhase () {
SiegePhase phase ;
if ( this . liveDate == null ) {
phase = SiegePhase . CHALLENGE ; //challenge
return phase ;
}
if ( DateTime . now (). isAfter ( this . liveDate )) {
2023-07-15 09:23:48 -04:00
phase = SiegePhase . WAR ; //war
2022-04-30 09:41:17 -04:00
return phase ;
}
// If code reaches this point we are in standoff mode.
2023-07-15 09:23:48 -04:00
phase = SiegePhase . STANDOFF ; //standoff
2022-04-30 09:41:17 -04:00
return phase ;
}
2023-07-15 09:23:48 -04:00
// Cache access
2022-04-30 09:41:17 -04:00
private void setDefaultTime () {
DateTime timeToSetDefault = new DateTime ( this . placementDate );
timeToSetDefault = timeToSetDefault . plusDays ( 1 );
DateTime currentTime = DateTime . now ();
DateTime defaultTime = new DateTime ( this . placementDate );
defaultTime = defaultTime . plusDays ( 2 );
defaultTime = defaultTime . hourOfDay (). setCopy ( 22 );
defaultTime = defaultTime . minuteOfHour (). setCopy ( 0 );
defaultTime = defaultTime . secondOfMinute (). setCopy ( 0 );
2024-12-28 07:57:51 -06:00
if ( currentTime . isAfter ( timeToSetDefault )){
DbManager . BaneQueries . SET_BANE_CAP_NEW ( 20 , this . getCityUUID ());
DbManager . BaneQueries . SET_BANE_TIME_NEW ( 9 , this . getCityUUID ());
DbManager . BaneQueries . SET_BANE_DAY_NEW ( 3 , this . getCityUUID ());
}
//this.setLiveDate(defaultTime);
2022-04-30 09:41:17 -04:00
else {
if ( this . defaultTimeJob != null )
this . defaultTimeJob . cancelJob ();
BaneDefaultTimeJob bdtj = new BaneDefaultTimeJob ( this );
JobScheduler . getInstance (). scheduleJob ( bdtj , timeToSetDefault . getMillis ());
this . defaultTimeJob = bdtj ;
}
}
2023-07-15 09:23:48 -04:00
//Returns a guild's bane
/*
* Getters
*/
public City getCity () {
return City . getCity ( this . cityUUID );
}
public PlayerCharacter getOwner () {
return ( PlayerCharacter ) DbManager . getObject ( Enum . GameObjectType . PlayerCharacter , ownerUUID );
}
public boolean remove () {
Building baneStone ;
baneStone = this . getStone ();
if ( baneStone == null ) {
Logger . debug ( "Removing bane without a stone." );
return false ;
}
// Reassert protection contracts
this . getCity (). protectionEnforced = true ;
// Remove visual effects on Bane and TOL.
this . getStone (). removeAllVisualEffects ();
this . getStone (). updateEffects ();
this . getCity (). getTOL (). removeAllVisualEffects ();
this . getCity (). getTOL (). updateEffects ();
// Remove bane from the database
if ( DbManager . BaneQueries . REMOVE_BANE ( this ) == false ) {
Logger . error ( "Database call failed for city UUID: " + this . getCity (). getObjectUUID ());
return false ;
}
// Remove bane from ingame cache
Bane . banes . remove ( cityUUID );
// Delete stone from database
if ( DbManager . BuildingQueries . DELETE_FROM_DATABASE ( baneStone ) == false ) {
Logger . error ( "Database error when deleting stone object" );
return false ;
}
2024-12-31 14:09:11 -06:00
//Remove bane commander NPC
if ( ! baneStone . getHirelings (). isEmpty ()) {
NPC npc = ( NPC ) baneStone . getHirelings (). keySet (). stream (). findFirst (). orElse ( null );
if ( npc != null ) {
DbManager . NPCQueries . DELETE_NPC ( npc );
DbManager . removeFromCache ( npc );
WorldGrid . RemoveWorldObject ( npc );
WorldGrid . removeObject ( npc );
}
}
2023-07-15 09:23:48 -04:00
// Remove object from simulation
baneStone . removeFromCache ();
WorldGrid . RemoveWorldObject ( baneStone );
WorldGrid . removeObject ( baneStone );
return true ;
}
public final DateTime getPlacementDate () {
return placementDate ;
}
public final boolean isAccepted () {
return ( this . getSiegePhase () != SiegePhase . CHALLENGE );
}
public final DateTime getLiveDate () {
return liveDate ;
}
2024-12-28 08:03:38 -06:00
public void setLiveDate_NEW ( DateTime baneTime ) {
2024-12-31 16:21:42 -06:00
2024-12-28 08:03:38 -06:00
}
2022-04-30 09:41:17 -04:00
public void setLiveDate ( DateTime baneTime ) {
if ( DbManager . BaneQueries . SET_BANE_TIME ( baneTime , this . getCity (). getObjectUUID ())) {
this . liveDate = new DateTime ( baneTime );
// Push event to warehouse
BaneRecord . updateLiveDate ( this , baneTime );
ChatManager . chatGuildInfo ( this . getOwner (). getGuild (), "The bane on " + this . getCity (). getGuild (). getName () + " has been set! Standoff phase has begun!" );
Guild attackerNation = this . getOwner (). getGuild (). getNation ();
if ( attackerNation != null )
for ( Guild subGuild : attackerNation . getSubGuildList ()) {
//Don't send the message twice.
if ( subGuild . equals ( attackerNation ))
continue ;
ChatManager . chatGuildInfo ( subGuild , "The bane on " + this . getCity (). getGuild (). getName () + " has been set! Standoff phase has begun!" );
}
ChatManager . chatGuildInfo ( this . getCity (). getGuild (), "The bane on " + this . getCity (). getGuild (). getName () + " has been set! Standoff phase has begun!" );
Guild defenderNation = this . getCity (). getGuild (). getNation ();
if ( defenderNation != null ) {
if ( defenderNation != this . getCity (). getGuild ())
ChatManager . chatGuildInfo ( defenderNation , "The bane on " + this . getCity (). getGuild (). getName () + " has been set! Standoff phase has begun!" );
for ( Guild subGuild : defenderNation . getSubGuildList ()) {
//Don't send the message twice.
if ( subGuild == this . getCity (). getGuild ())
continue ;
ChatManager . chatGuildInfo ( subGuild , "The bane on " + this . getCity (). getGuild (). getName () + " has been set! Standoff phase has begun!" );
}
}
if ( activateBaneJob != null )
this . activateBaneJob . cancelJob ();
ActivateBaneJob abtj = new ActivateBaneJob ( cityUUID );
JobScheduler . getInstance (). scheduleJob ( abtj , this . liveDate . getMillis ());
this . activateBaneJob = abtj ;
} else {
2023-07-15 09:23:48 -04:00
Logger . debug ( "error with city " + this . getCity (). getName ());
2022-04-30 09:41:17 -04:00
ChatManager . chatGuildInfo ( this . getOwner (). getGuild (), "A Serious error has occurred. Please post details for to ensure transaction integrity" );
ChatManager . chatGuildInfo ( this . getCity (). getGuild (), "A Serious error has occurred. Please post details for to ensure transaction integrity" );
}
}
public final void endBane ( SiegeResult siegeResult ) {
boolean baneRemoved ;
// No matter what the outcome of a bane, we re-asset
// protection contracts at this time. They don't quite
// matter if the city falls, as they are invalidated.
2023-07-15 09:23:48 -04:00
2022-04-30 09:41:17 -04:00
this . getCity (). protectionEnforced = true ;
2023-07-15 09:23:48 -04:00
2022-04-30 09:41:17 -04:00
switch ( siegeResult ) {
case DEFEND :
// Push event to warehouse
BaneRecord . updateResolution ( this , Enum . RecordEventType . DEFEND );
baneRemoved = remove ();
if ( baneRemoved ) {
// Update seieges withstood
2023-07-15 09:23:48 -04:00
2022-04-30 09:41:17 -04:00
this . getCity (). setSiegesWithstood ( this . getCity (). getSiegesWithstood () + 1 );
2023-07-15 09:23:48 -04:00
2022-04-30 09:41:17 -04:00
// Notify players
2023-07-15 09:23:48 -04:00
ChatSystemMsg msg = new ChatSystemMsg ( null , "[Bane Channel]" + this . getCity (). getGuild (). getName () + " has rallied against " + this . getOwner (). getGuild (). getName () + ". The siege on " + this . getCity (). getCityName () + " has been broken!" );
msg . setMessageType ( 4 );
msg . setChannel ( engine . Enum . ChatChannelType . SYSTEM . getChannelID ());
DispatchMessage . dispatchMsgToAll ( msg );
2022-04-30 09:41:17 -04:00
}
2023-07-15 09:23:48 -04:00
2022-04-30 09:41:17 -04:00
break ;
case CAPTURE :
// Push event to warehouse
BaneRecord . updateResolution ( this , Enum . RecordEventType . CAPTURE );
baneRemoved = this . remove ();
if ( baneRemoved ) {
2023-07-15 09:23:48 -04:00
ChatSystemMsg msg = new ChatSystemMsg ( null , "[Bane Channel]" + this . getOwner (). getGuild (). getName () + " have defeated " + this . getCity (). getGuild (). getName () + " and captured " + this . getCity (). getCityName () + '!' );
msg . setMessageType ( 4 );
msg . setChannel ( engine . Enum . ChatChannelType . SYSTEM . getChannelID ());
DispatchMessage . dispatchMsgToAll ( msg );
2022-04-30 09:41:17 -04:00
}
break ;
case DESTROY :
// Push event to warehouse
BaneRecord . updateResolution ( this , Enum . RecordEventType . DESTROY );
baneRemoved = this . remove ();
if ( baneRemoved ) {
2023-07-15 09:23:48 -04:00
ChatSystemMsg msg = new ChatSystemMsg ( null , "[Bane Channel]" + this . getOwner (). getGuild (). getName () + " have defeated " + this . getCity (). getGuild (). getName () + " and razed " + this . getCity (). getCityName () + '!' );
msg . setMessageType ( 4 );
msg . setChannel ( engine . Enum . ChatChannelType . SYSTEM . getChannelID ());
DispatchMessage . dispatchMsgToAll ( msg );
2022-04-30 09:41:17 -04:00
}
break ;
}
Zone cityZone = this . getCity (). getParent ();
if ( cityZone == null )
2023-07-15 09:23:48 -04:00
return ;
2022-04-30 09:41:17 -04:00
//UNPROTECT ALL SIEGE EQUIPMENT AFTER A BANE
2023-07-15 09:23:48 -04:00
for ( Building toUnprotect : cityZone . zoneBuildingSet ) {
if ( toUnprotect . getBlueprint () != null && toUnprotect . getBlueprint (). isSiegeEquip () && toUnprotect . assetIsProtected () == true )
toUnprotect . setProtectionState ( ProtectionState . NONE );
2022-04-30 09:41:17 -04:00
}
}
public boolean isErrant () {
boolean isErrant = true ;
if ( this . getOwner () == null )
return isErrant ;
2023-07-15 09:23:48 -04:00
2023-01-21 09:28:30 -05:00
if ( this . getOwner (). getGuild (). isEmptyGuild () == true )
2022-04-30 09:41:17 -04:00
return isErrant ;
2023-01-21 09:28:30 -05:00
if ( this . getOwner (). getGuild (). getNation (). isEmptyGuild () == true )
2022-04-30 09:41:17 -04:00
return isErrant ;
// Bane passes validation
isErrant = false ;
return isErrant ;
}
/**
* @return the stone
*/
public Building getStone () {
return BuildingManager . getBuilding ( this . stoneUUID );
}
/**
* @return the cityUUID
*/
public int getCityUUID () {
return cityUUID ;
}
2024-12-29 21:19:20 -06:00
public void applyZergBuffs (){
City city = this . getCity ();
if ( city == null )
return ;
2024-12-31 17:54:53 -06:00
city . onEnter ();
2024-12-29 21:19:20 -06:00
ArrayList < Integer > attackers = new ArrayList <> ();
ArrayList < Integer > defenders = new ArrayList <> ();
2024-12-31 17:54:53 -06:00
Guild attackNation = this . getOwner (). getGuild (). getNation ();
Guild defendNation = this . getCity (). getGuild (). getNation ();
2025-01-03 20:09:48 -06:00
HashSet < AbstractWorldObject > inSiegeRange = WorldGrid . getObjectsInRangePartial ( city . getTOL (). loc , 1750f , 1 );
for ( AbstractWorldObject obj : inSiegeRange ){
int uuid = obj . getObjectUUID ();
2024-12-29 21:19:20 -06:00
PlayerCharacter player = PlayerCharacter . getPlayerCharacter ( uuid );
if ( player == null )
continue ;
2024-12-31 17:54:53 -06:00
Guild playerNation = player . guild . getNation ();
2024-12-29 21:19:20 -06:00
//separate the players into categories
2024-12-31 17:54:53 -06:00
if ( playerNation . equals ( defendNation ))
2024-12-29 21:19:20 -06:00
defenders . add ( uuid );
2024-12-31 17:54:53 -06:00
else if ( playerNation . equals ( attackNation ))
2024-12-29 21:19:20 -06:00
attackers . add ( uuid );
else
2025-01-03 20:12:47 -06:00
MovementManager . translocate ( player , Vector3fImmutable . getRandomPointOnCircle ( ZoneManager . getZoneByUUID ( 656 ). getLoc (), 30f ), Regions . GetRegionForTeleport ( ZoneManager . getZoneByUUID ( 656 ). getLoc ()));
2024-12-31 18:23:03 -06:00
}
int attackerSize = 0 ;
int defenderSize = 0 ;
for ( int uuid : city . baneAttendees . keySet ()){
PlayerCharacter player = PlayerCharacter . getPlayerCharacter ( uuid );
if ( player == null )
continue ;
if ( player . guild . getNation (). equals ( defendNation ))
defenderSize += 1 ;
else if ( player . guild . getNation (). equals ( attackNation ))
attackerSize += 1 ;
2024-12-29 21:19:20 -06:00
}
//apply zerg mechanic for attackers
2024-12-31 18:23:03 -06:00
float attackerMultiplier = ZergManager . getCurrentMultiplier ( attackerSize , this . capSize );
float defenderMultiplier = ZergManager . getCurrentMultiplier ( defenderSize , this . capSize );
2024-12-29 21:19:20 -06:00
for ( int uuid : attackers ){
2025-01-03 20:41:11 -06:00
PlayerCharacter player = PlayerCharacter . getPlayerCharacter ( uuid );
if ( inSiegeRange . contains ( player )) //player is still physically here, needs updated multiplier
player . ZergMultiplier = attackerMultiplier ;
2025-01-03 20:59:35 -06:00
else
player . ZergMultiplier = 1 . 0f ;
2024-12-29 21:19:20 -06:00
}
for ( int uuid : defenders ){
2025-01-03 20:41:11 -06:00
PlayerCharacter player = PlayerCharacter . getPlayerCharacter ( uuid );
if ( inSiegeRange . contains ( player )) //player is still physically here, needs updated multiplier
player . ZergMultiplier = defenderMultiplier ;
2025-01-03 20:59:35 -06:00
else
player . ZergMultiplier = 1 . 0f ;
2024-12-29 21:19:20 -06:00
}
}
2022-04-30 09:41:17 -04:00
}