From 4871a071d69552935bbe44cd3bed704960c788ee Mon Sep 17 00:00:00 2001 From: Light2 Date: Sun, 15 Jun 2014 02:26:49 +0200 Subject: [PATCH] Added city voting terminal radials and SUI windows, fixed lots of city bugs --- .../terminal/city_maintenance_terminal.py | 65 +++++++++------- .../radial/terminal/city_voting_terminal.py | 39 ++++++++-- src/services/playercities/PlayerCity.java | 78 ++++++++++++++++++- .../playercities/PlayerCityService.java | 58 ++++++++++++++ 4 files changed, 201 insertions(+), 39 deletions(-) diff --git a/scripts/radial/terminal/city_maintenance_terminal.py b/scripts/radial/terminal/city_maintenance_terminal.py index 70562682..6aee6a2b 100644 --- a/scripts/radial/terminal/city_maintenance_terminal.py +++ b/scripts/radial/terminal/city_maintenance_terminal.py @@ -5,6 +5,7 @@ from services.sui.SUIService import MessageBoxType from services.sui.SUIWindow import Trigger from java.util import Vector from java.lang import System +from java.lang import Long from java.util import Map from java.util import TreeMap import main.NGECore @@ -39,7 +40,6 @@ def createRadial(core, owner, target, radials): if city.getMayorID() != owner.getObjectID(): return - radials.add(RadialOptions(0, 216, 0, '@city/city:city_management')) #radials.add(RadialOptions(0, 227, 0, '@city/city:remove_trainers')) not needed for pswg radials.add(RadialOptions(3, 217, 0, '@city/city:city_name_new_t')) if city.isRegistered(): @@ -162,19 +162,19 @@ def handleManageMilitia(core, owner, target, option): if not playerCity: return menuItems = TreeMap() - menuItems.put(0, '@city/city:militia_new_t') + menuItems.put(Long(0), '@city/city:militia_new_t') for militiaId in playerCity.getMilitiaList(): militia = core.objectService.getObject(militiaId) if not militia: militia = core.objectService.getCreatureFromDB(militiaId) if militia: - menuItems.put(militiaId, militia.getCustomName()) + menuItems.put(Long(militiaId), militia.getCustomName()) returnList = Vector() returnList.add('List.lstList:SelectedRow') window = core.suiService.createListBox(1, '@city/city:militia_t', '@city/city:militia_d', menuItems, owner, None, 0) window.addHandler(0, '', Trigger.TRIGGER_OK, returnList, handleMilitiaListBox) - core.suiService.openSUIWindow(suiWindow) + core.suiService.openSUIWindow(window) return @@ -183,7 +183,7 @@ def handleMilitiaListBox(owner, window, eventType, returnList): playerCity = core.playerCityService.getPlayerCity(owner) if not playerCity: return - index = returnList.get(0) + index = int(returnList.get(0)) id = window.getObjectIdByIndex(index) if id == 0: handleAddMiltiaPrompt(core, owner) @@ -199,10 +199,11 @@ def handleAddMiltiaPrompt(core, owner): returnList = Vector() returnList.add('txtInput:LocalText') window.addHandler(0, '', Trigger.TRIGGER_OK, returnList, handleAddMiltia) - core.suiService.openSUIWindow(suiWindow) + core.suiService.openSUIWindow(window) return def handleAddMiltia(owner, window, eventType, returnList): + core = main.NGECore.getInstance() playerCity = core.playerCityService.getPlayerCity(owner) if not playerCity: return @@ -214,7 +215,7 @@ def handleAddMiltia(owner, window, eventType, returnList): if not playerCity.isCitizen(militiaId): owner.sendSystemMessage('@city/city:not_citizen', 0) return - if playerCity.isMilitiaMember(militiaId): + if playerCity.isMilitiaMember(militiaId) or militiaId == playerCity.getMayorID(): owner.sendSystemMessage('That player is already a member of the city militia.', 0) return militia = core.objectService.getObject(militiaId) @@ -239,9 +240,9 @@ def handleTreasuryReport(core, owner, target, option): if not playerCity: return menuItems = TreeMap() - menuItems.put(1, '@city/city:treasury ' + int(playerCity.getCityTreasury())) + menuItems.put(Long(1), '@city/city:treasury ' + str(playerCity.getCityTreasury())) window = core.suiService.createListBox(1, '@city/city:treasury_balance_t', '@city/city:treasury_balance_d', menuItems, owner, None, 0) - core.suiService.openSUIWindow(suiWindow) + core.suiService.openSUIWindow(window) return def handleStructureReport(core, owner, target, option): @@ -254,9 +255,9 @@ def handleStructureReport(core, owner, target, option): structure = core.objectService.getObject(structureId) if structure and structure.getAttachment('isCivicStructure') is not None and structure.getAttachment('isCivicStructure') == True: i += 1 - menuItems.put(i, structure.getLookAtText() + ' - Condition : ' + int((structure.getMaximumCondition() - structure.getConditionDamage()) / structure.getMaximumCondition() * 100) + '%') + menuItems.put(Long(i), structure.getLookAtText() + ' - Condition : ' + str((structure.getMaximumCondition() - structure.getConditionDamage()) / structure.getMaximumCondition() * 100) + '%') window = core.suiService.createListBox(1, '@city/city:structure_list_t', '@city/city:structure_list_d', menuItems, owner, None, 0) - core.suiService.openSUIWindow(suiWindow) + core.suiService.openSUIWindow(window) return @@ -308,7 +309,7 @@ def handleToggleZoning(core, owner, target, option): if not playerCity or playerCity.getMayorID() != owner.getObjectID(): return - playerCity.setZoningEnabled(!playerCity.isZoningEnabled()) + playerCity.setZoningEnabled(not playerCity.isZoningEnabled()) if playerCity.isZoningEnabled(): owner.sendSystemMessage('@city/city:zoning_enabled', 0) @@ -427,14 +428,15 @@ def handleSetIncomeTax(owner): return def handleSetIncomeTaxCallBack(owner, window, eventType, returnList): - if int(returnList.get(0))>2000 or int(returnList.get(0))<0: + tax = int(returnList.get(0)) + if tax > 2000 or tax < 0: owner.sendSystemMessage('Income tax value is out of range of accepteable values.', 0) handleSetIncomeTax(owner) return playerCity = main.NGECore.getInstance().playerCityService.getPlayerCity(owner) - playerCity.setIncomeTax(int(returnList.get(0))) - owner.sendSystemMessage('@city/city:set_income_tax', 0) + playerCity.setIncomeTax(tax) + owner.sendSystemMessage(OutOfBand.ProsePackage('@city/city:set_income_tax', tax), 0) return def handleSetSalesTax(owner): @@ -449,14 +451,15 @@ def handleSetSalesTax(owner): return def handleSetSalesTaxCallBack(owner, window, eventType, returnList): - if int(returnList.get(0))>20 or int(returnList.get(0))<0: + tax = int(returnList.get(0)) + if tax > 20 or tax < 0: owner.sendSystemMessage('Sales tax value is out of range of accepteable values.', 0) handleSetSalesTax(owner) return playerCity = main.NGECore.getInstance().playerCityService.getPlayerCity(owner) - playerCity.setIncomeTax(int(returnList.get(0))) - owner.sendSystemMessage('@city/city:set_sales_tax', 0) + playerCity.setIncomeTax(tax) + owner.sendSystemMessage(OutOfBand.ProsePackage('@city/city:set_sales_tax', tax), 0) return def handleSetPropertyTax(owner): @@ -471,14 +474,15 @@ def handleSetPropertyTax(owner): return def handleSetPropertyTaxCallBack(owner, window, eventType, returnList): - if int(returnList.get(0))>50 or int(returnList.get(0))<0: + tax = int(returnList.get(0)) + if tax > 50 or tax < 0: owner.sendSystemMessage('Property tax value is out of range of accepteable values.', 0) handleSetPropertyTax(owner) return playerCity = main.NGECore.getInstance().playerCityService.getPlayerCity(owner) - playerCity.setIncomeTax(int(returnList.get(0))) - owner.sendSystemMessage('@city/city:set_property_tax', 0) + playerCity.setIncomeTax(tax) + owner.sendSystemMessage(OutOfBand.ProsePackage('@city/city:set_property_tax', tax), 0) return def handleSetTravelTax(owner): @@ -497,14 +501,15 @@ def handleSetTravelTax(owner): return def handleSetTravelTaxCallBack(owner, window, eventType, returnList): - if int(returnList.get(0))>500 or int(returnList.get(0))<1: + tax = int(returnList.get(0)) + if tax > 500 or tax < 1: owner.sendSystemMessage('Travel tax value is out of range of accepteable values.', 0) handleSetIncomeTax(owner) return playerCity = main.NGECore.getInstance().playerCityService.getPlayerCity(owner) - playerCity.setTravelTax(int(returnList.get(0))) - owner.sendSystemMessage('@city/city:set_travel_fee', 0) + playerCity.setTravelTax(tax) + owner.sendSystemMessage(OutOfBand.ProsePackage('@city/city:set_travel_fee', tax), 0) return def handleSetGarageTax(owner): @@ -519,14 +524,15 @@ def handleSetGarageTax(owner): return def handleSetGarageTaxCallBack(owner, window, eventType, returnList): - if int(returnList.get(0))>500 or int(returnList.get(0))<1: + tax = int(returnList.get(0)) + if tax > 500 or tax < 1: owner.sendSystemMessage('Garage tax value is out of range of accepteable values.', 0) handleSetIncomeTax(owner) return - + playerCity = main.NGECore.getInstance().playerCityService.getPlayerCity(owner) - playerCity.setGarageTax(int(returnList.get(0))) - owner.sendSystemMessage('@city/city:set_garage_tax', 0) + playerCity.setGarageTax(tax) + owner.sendSystemMessage(OutOfBand.ProsePackage('@city/city:set_garage_tax', tax), 0) return def handleWithdrawal(core, owner, target, option): @@ -570,7 +576,6 @@ def handleCitizenList(core, owner, target, option): return def setCitizenListCallBack(owner, window, eventType, returnList): - idx = returnList.get(0) # todo add waypoint return @@ -952,5 +957,5 @@ def showSpecConfirmWindow(owner): def handleSpecConfirmCallback(owner, window, eventType, returnList): playerCity = main.NGECore.getInstance().playerCityService.getPlayerCity(owner) chosenSpec = owner.getAttachment('ChosenCitySpec') - playerCity.setSpecialisation(chosenSpec) + playerCity.setSpecialization(chosenSpec) return \ No newline at end of file diff --git a/scripts/radial/terminal/city_voting_terminal.py b/scripts/radial/terminal/city_voting_terminal.py index faa1fa61..be3f5772 100644 --- a/scripts/radial/terminal/city_voting_terminal.py +++ b/scripts/radial/terminal/city_voting_terminal.py @@ -2,6 +2,10 @@ from resources.common import RadialOptions from services.sui.SUIService import MessageBoxType from services.sui.SUIWindow import Trigger from java.util import Vector +from java.util import TreeMap +from java.util import Map +from java.lang import System +from java.lang import Long import sys def createRadial(core, owner, target, radials): @@ -27,25 +31,48 @@ def handleSelection(core, owner, target, option): if not city: return if option == 224 or option == 225: - handleViewStandings(core, owner) + core.playerCityService.handleViewStandings(owner, city) if option == 226: - handlePromptVote(core, owner) + core.playerCityService.handlePromptVote(owner, city) if option == 227 and city.isCandidate(owner.getObjectID()): handleUnregister(core, owner) if option == 227 and not city.isCandidate(owner.getObjectID()): handleRegister(core, owner) return - -def handleViewStandings(core, owner): - return - + def handlePromptVote(core, owner): return def handleUnregister(core, owner): + city = core.playerCityService.getCityObjectIsIn(owner) + if not city or not city.isCitizen(owner.getObjectID()): + return + if city.isElectionLocked(): + owner.sendSystemMessage('@city/city:registration_locked', 0) + return + if city.isCandidate(owner.getObjectID()): + city.getElectionList().remove(Long(owner.getObjectID())) + owner.sendSystemMessage('@city/city:unregistered_race', 0) + city.sendCandidateUnregisteredMail(owner) return def handleRegister(core, owner): + city = core.playerCityService.getCityObjectIsIn(owner) + if not city: + return + if not city.isCitizen(owner.getObjectID()): + owner.sendSystemMessage('@city/city:register_noncitizen', 0) + return + if city.isElectionLocked(): + owner.sendSystemMessage('@city/city:registration_locked', 0) + return + if owner.getAttachment('registerElectionCooldown') and owner.getAttachment('registerElectionCooldown') > System.currentTimeMillis(): + owner.sendSystemMessage('@city/city:register_timestamp', 0) + return + city.getElectionList().put(Long(owner.getObjectID()), 0) + owner.sendSystemMessage('@city/city:register_congrats', 0) + owner.setAttachment('registerElectionCooldown', System.currentTimeMillis() + 86400000) + city.sendCandidateRegisteredMail(owner) return \ No newline at end of file diff --git a/src/services/playercities/PlayerCity.java b/src/services/playercities/PlayerCity.java index a8a990c2..8d3f9f9e 100644 --- a/src/services/playercities/PlayerCity.java +++ b/src/services/playercities/PlayerCity.java @@ -114,6 +114,7 @@ public class PlayerCity implements Serializable { private boolean shuttlePort = false; private boolean registered = false; private boolean zoningEnabled = false; + private boolean electionLocked = false; // election is locked in third and final week private transient CollidableCircle area; private long cityNameChangeCooldown; private long cityTreasuryWithdrawalCooldown; @@ -129,6 +130,7 @@ public class PlayerCity implements Serializable { private Vector placedStructures = new Vector(); private Vector citizens = new Vector(); private Map electionList = new ConcurrentHashMap(); + private Map mayoralVotes = new ConcurrentHashMap(); // Key = voter id Value = candidate id private Vector cityBanList = new Vector(); private Vector militiaList = new Vector(); private Vector foundersList = new Vector(); @@ -242,9 +244,10 @@ public class PlayerCity implements Serializable { core.housingService.destroyStructure((BuildingObject) core.objectService.getObject(cityHallId)); return; } - - // TODO unregister city if rank < 3 - + if(newRank < 3 && isRegistered()) { + setRegistered(false); + core.mapService.removeLocation(core.terrainService.getPlanetByID(planetId), getCityCenterPosition().x, getCityCenterPosition().z, (byte) 17); + } setRank(newRank); demolishCivicStructuresOutsideRadius(); demolishHighRankStructures(); @@ -1263,5 +1266,74 @@ public class PlayerCity implements Serializable { return electionList.containsKey(candidateId); } + public void castVote(CreatureObject actor, CreatureObject candidate) { + if(mayoralVotes.get(actor.getObjectID()) == candidate.getObjectID()) + return; + if(mayoralVotes.containsKey(actor.getObjectID()) && electionList.containsKey(mayoralVotes.get(actor.getObjectID()))) + electionList.put(mayoralVotes.get(actor.getObjectID()), electionList.get(mayoralVotes.get(actor.getObjectID())) - 1); + mayoralVotes.put(actor.getObjectID(), candidate.getObjectID()); + electionList.put(candidate.getObjectID(), electionList.get(candidate.getObjectID()) + 1); + } + + public boolean isElectionLocked() { + return electionLocked; + } + + public void setElectionLocked(boolean electionLocked) { + this.electionLocked = electionLocked; + } + + public void sendCandidateRegisteredMail(CreatureObject candidate) { + Vector citizenList = getCitizens(); + NGECore core = NGECore.getInstance(); + for (long citizen : citizenList) { + if(citizen == candidate.getObjectID()) + continue; + CreatureObject citizenObject = core.objectService.getObject(citizen) == null ? core.objectService.getCreatureFromDB(citizen) : (CreatureObject) core.objectService.getObject(citizen); + if(citizenObject == null) + continue; + Mail actorMail = new Mail(); + actorMail.setMailId(NGECore.getInstance().chatService.generateMailId()); + actorMail.setRecieverId(citizen); + actorMail.setStatus(Mail.NEW); + actorMail.setTimeStamp((int) (new Date().getTime() / 1000)); + actorMail.setSubject("@city/city:registered_citizen_email_subject"); + actorMail.setSenderName("@city/city:new_city_from"); + actorMail.addProseAttachment(new ProsePackage("@city/city:rceb", "TO", candidate.getCustomName())); + + NGECore.getInstance().chatService.storePersistentMessage(actorMail); + if (citizenObject.getClient() != null) + NGECore.getInstance().chatService.sendPersistentMessageHeader(citizenObject.getClient(), actorMail); + + } + + } + + public void sendCandidateUnregisteredMail(CreatureObject candidate) { + Vector citizenList = getCitizens(); + NGECore core = NGECore.getInstance(); + for (long citizen : citizenList) { + if(citizen == candidate.getObjectID()) + continue; + CreatureObject citizenObject = core.objectService.getObject(citizen) == null ? core.objectService.getCreatureFromDB(citizen) : (CreatureObject) core.objectService.getObject(citizen); + if(citizenObject == null) + continue; + Mail actorMail = new Mail(); + actorMail.setMailId(NGECore.getInstance().chatService.generateMailId()); + actorMail.setRecieverId(citizen); + actorMail.setStatus(Mail.NEW); + actorMail.setTimeStamp((int) (new Date().getTime() / 1000)); + actorMail.setSubject("@city/city:unregistered_citizen_email_subject"); + actorMail.setSenderName("@city/city:new_city_from"); + actorMail.addProseAttachment(new ProsePackage("@city/city:unregistered_citizen_email_body", "TO", candidate.getCustomName())); + + NGECore.getInstance().chatService.storePersistentMessage(actorMail); + if (citizenObject.getClient() != null) + NGECore.getInstance().chatService.sendPersistentMessageHeader(citizenObject.getClient(), actorMail); + + } + + } + } diff --git a/src/services/playercities/PlayerCityService.java b/src/services/playercities/PlayerCityService.java index a9a981cc..b89faa24 100644 --- a/src/services/playercities/PlayerCityService.java +++ b/src/services/playercities/PlayerCityService.java @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.Date; import java.util.Map; import java.util.Random; +import java.util.TreeMap; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; @@ -39,6 +40,7 @@ import resources.objects.creature.CreatureObject; import resources.objects.tangible.TangibleObject; import services.chat.Mail; import services.sui.SUIService.InputBoxType; +import services.sui.SUIService.ListBoxType; import services.sui.SUIService.MessageBoxType; import services.sui.SUIWindow; import services.sui.SUIWindow.SUICallback; @@ -519,4 +521,60 @@ public class PlayerCityService implements INetworkDispatch { }); core.suiService.openSUIWindow(window); } + + public void handleViewStandings(CreatureObject actor, PlayerCity city) { + SUIWindow window = core.suiService.createListBox(ListBoxType.LIST_BOX_OK_CANCEL, "@city/city:mayoral_standings_t", "@city/city:mayoral_standings_d", new TreeMap(), actor, null, 0); + long mayorId = city.getMayorID(); + for(long candidateId : city.getElectionList().keySet()) { + CreatureObject candidate = core.objectService.getObject(candidateId) == null ? core.objectService.getCreatureFromDB(candidateId) : (CreatureObject) core.objectService.getObject(candidateId); + if(candidate == null) + continue; + if(candidateId == mayorId) + window.addListBoxMenuItem("Incumbent: " + candidate.getCustomName() + " -- Votes: " + String.valueOf(city.getElectionList().get(candidateId)), candidateId); + else + window.addListBoxMenuItem("Challenger: " + candidate.getCustomName() + " -- Votes: " + String.valueOf(city.getElectionList().get(candidateId)), candidateId); + } + core.suiService.openSUIWindow(window); + } + + public void handlePromptVote(CreatureObject actor, PlayerCity city) { + + if(!city.isCitizen(actor.getObjectID())) { + actor.sendSystemMessage("@city/city:vote_noncitizen", (byte) 0); + return; + } + + if(city.getElectionList().size() < 1) { + actor.sendSystemMessage("@city/city:no_candidates", (byte) 0); + return; + } + + SUIWindow window = core.suiService.createListBox(ListBoxType.LIST_BOX_OK_CANCEL, "@city/city:mayoral_vote_t", "@city/city:mayoral_vote_d", new TreeMap(), actor, null, 0); + long mayorId = city.getMayorID(); + for(long candidateId : city.getElectionList().keySet()) { + CreatureObject candidate = core.objectService.getObject(candidateId) == null ? core.objectService.getCreatureFromDB(candidateId) : (CreatureObject) core.objectService.getObject(candidateId); + if(candidate == null) + continue; + if(candidateId == mayorId) + window.addListBoxMenuItem(candidate.getCustomName() + " (Incumbent)", candidateId); + else + window.addListBoxMenuItem(candidate.getCustomName() + " (Challenger)", candidateId); + } + Vector returnList = new Vector(); + returnList.add("List.lstList:SelectedRow"); + window.addHandler(0, "", Trigger.TRIGGER_OK, returnList, (owner, eventType, inputList) -> { + + int index = Integer.parseInt(inputList.get(0)); + long candidateId = window.getObjectIdByIndex(index); + CreatureObject candidate = core.objectService.getObject(candidateId) == null ? core.objectService.getCreatureFromDB(candidateId) : (CreatureObject) core.objectService.getObject(candidateId); + if(candidate == null || !city.isCandidate(candidateId)) + return; + city.castVote(actor, candidate); + actor.sendSystemMessage(OutOfBand.ProsePackage("@city/city:vote_placed", "TO", candidate.getCustomName()), (byte) 0); + + }); + + } + + }