Skip to content

Commit

Permalink
Merge pull request #1212 from madsboddum/faction_points
Browse files Browse the repository at this point in the history
[Faction] Faction standing
  • Loading branch information
Josh-Larson committed Apr 4, 2023
2 parents f2980e1 + a20710e commit 20c701f
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/***********************************************************************************
* Copyright (c) 2019 /// Project SWG /// www.projectswg.com *
* Copyright (c) 2023 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
Expand Down Expand Up @@ -58,8 +58,8 @@ class FactionLoader : DataLoader() {
val isAggressive = set.getBoolean("isAggro")
val isPvP = set.getBoolean("isPvP")
val pvpFaction = processPvpFaction(set.getText("pvpFaction"))
private val enemies = processList(set.getText("enemies"))
private val allies = processList(set.getText("allies"))
val enemies = processList(set.getText("enemies"))
val allies = processList(set.getText("allies"))
val combatFactor = set.getInt("combatFactor").toInt()

fun isEnemy(faction: String) = enemies.contains(faction.lowercase(Locale.US))
Expand Down Expand Up @@ -94,7 +94,7 @@ class FactionLoader : DataLoader() {
private fun processList(listStr: String): List<String> {
if (listStr == "-" || listStr.isBlank())
return emptyList()
return listStr.lowercase(Locale.US).split(';')
return listStr.lowercase(Locale.US).split(';').map { it.trim() }
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/***********************************************************************************
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
* Copyright (c) 2023 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
Expand Down Expand Up @@ -30,7 +30,6 @@
import com.projectswg.common.data.CRC;
import com.projectswg.common.data.encodables.mongo.MongoData;
import com.projectswg.common.data.encodables.player.Mail;
import com.projectswg.common.data.location.Location;
import com.projectswg.common.network.NetBuffer;
import com.projectswg.common.network.packets.swg.zone.baselines.Baseline.BaselineType;
import com.projectswg.holocore.resources.support.global.network.BaselineBuilder;
Expand All @@ -48,6 +47,9 @@
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static java.lang.Math.max;
import static java.lang.Math.min;

public class PlayerObject extends IntangibleObject {

private static final ZoneId BORN_DATE_ZONE = ZoneId.of("America/New_York");
Expand All @@ -59,6 +61,7 @@ public class PlayerObject extends IntangibleObject {
private final PlayerObjectOwnerNP play9 = new PlayerObjectOwnerNP(this);
private final Set<String> joinedChannels = ConcurrentHashMap.newKeySet();
private final Map<Integer, Mail> mails = new ConcurrentHashMap<>();
private final Map<String, Integer> factionPoints = new ConcurrentHashMap<>();

private long startPlayTime = 0;
private long lastUpdatePlayTime = 0;
Expand All @@ -72,6 +75,23 @@ public PlayerObject(long objectId) {
super(objectId, BaselineType.PLAY);
super.setVolume(0);
}

public int adjustFactionPoints(String faction, int adjustment) {
int oldValue = factionPoints.getOrDefault(faction, 0);
int value = oldValue + adjustment;
int cappedValue = min(max(value, -5000), 5000);
int delta = cappedValue - oldValue;

if (delta != 0) {
factionPoints.put(faction, value);
}

return delta;
}

public Map<String, Integer> getFactionPoints() {
return new HashMap<>(factionPoints);
}

public String getAccount() {
return account;
Expand Down Expand Up @@ -669,6 +689,7 @@ public void saveMongo(MongoData data) {
data.putString("account", account);
data.putMap("mail", mails);
badges.saveMongo(data.getDocument("badges"));
data.putMap("factionPoints", factionPoints);
}

@Override
Expand All @@ -684,6 +705,7 @@ public void readMongo(MongoData data) {
account = data.getString("account", "");
mails.putAll(data.getMap("mail", Integer.class, Mail.class));
badges.readMongo(data.getDocument("badges"));
factionPoints.putAll(data.getMap("factionPoints", String.class, Integer.class));
}

}
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
/***********************************************************************************
* Copyright (c) 2023 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* --------------------------------------------------------------------------------*
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.holocore.services.gameplay.faction;

import com.projectswg.common.data.encodables.oob.ProsePackage;
Expand Down Expand Up @@ -37,7 +63,7 @@ public class FactionFlagService extends Service {

public FactionFlagService() {
statusChangers = new ConcurrentHashMap<>();
executor = new ScheduledThreadPool(1, "faction-service");
executor = new ScheduledThreadPool(1, "faction-flag-service");
pvpZones = new ConcurrentHashMap<>();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/***********************************************************************************
* Copyright (c) 2023 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* --------------------------------------------------------------------------------*
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http:></http:>//www.gnu.org/licenses/>. *
*/
package com.projectswg.holocore.services.gameplay.faction

import me.joshlarson.jlcommon.control.Manager
import me.joshlarson.jlcommon.control.ManagerStructure

@ManagerStructure(children = [FactionFlagService::class, FactionPointService::class])
class FactionManager : Manager()
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/***********************************************************************************
* Copyright (c) 2023 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* --------------------------------------------------------------------------------*
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.holocore.services.gameplay.faction

import com.projectswg.common.data.encodables.oob.ProsePackage
import com.projectswg.common.data.encodables.oob.StringId
import com.projectswg.holocore.intents.gameplay.combat.CreatureKilledIntent
import com.projectswg.holocore.intents.support.global.chat.SystemMessageIntent
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject
import com.projectswg.holocore.resources.support.objects.swg.player.PlayerObject
import me.joshlarson.jlcommon.control.IntentHandler
import me.joshlarson.jlcommon.control.Service
import me.joshlarson.jlcommon.utilities.ThreadUtilities
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import kotlin.math.abs

class FactionPointService : Service() {

private val executor = Executors.newSingleThreadExecutor(ThreadUtilities.newThreadFactory("faction-point-service-%d"))
private val youHaveBeenAwardedPoints = StringId("base_player", "prose_award_faction")
private val maxCapReached = StringId("base_player", "prose_max_faction")
private val youHaveLostPoints = StringId("base_player", "prose_lose_faction")
private val minCapReached = StringId("base_player", "prose_min_faction")

override fun stop(): Boolean {
executor.awaitTermination(1, TimeUnit.SECONDS)
return super.stop()
}

@IntentHandler
private fun handleCreatureKilled(creatureKilledIntent: CreatureKilledIntent) {
val corpse = creatureKilledIntent.corpse
val corpseFaction = corpse.faction ?: return
val allies = corpseFaction.allies
val enemies = corpseFaction.enemies
val corpseFactionName = corpseFaction.name

involvedPlayers(corpse).forEach { involvedPlayer ->
executor.execute {
decreaseFactionPoints(corpseFactionName, involvedPlayer)
allies.forEach { allyFactionName -> decreaseFactionPoints(allyFactionName, involvedPlayer) }
enemies.forEach { enemyFactionName -> increaseFactionPoints(enemyFactionName, involvedPlayer) }
}
}
}

private fun involvedPlayers(corpse: CreatureObject) = corpse.hateMap.keys.filter { it.isPlayer }.map { it.playerObject }

private fun increaseFactionPoints(factionName: String, involvedPlayer: PlayerObject) {
adjustFactionPoints(
factionName = factionName,
involvedPlayer = involvedPlayer,
adjustment = 15,
changeMessage = youHaveBeenAwardedPoints,
capMessage = maxCapReached
)
}

private fun decreaseFactionPoints(factionName: String, involvedPlayer: PlayerObject) {
adjustFactionPoints(
factionName = factionName,
involvedPlayer = involvedPlayer,
adjustment = -22,
changeMessage = youHaveLostPoints,
capMessage = minCapReached
)
}

private fun adjustFactionPoints(factionName: String, involvedPlayer: PlayerObject, adjustment: Int, changeMessage: StringId, capMessage: StringId) {
val owner = involvedPlayer.owner ?: return
val delta = involvedPlayer.adjustFactionPoints(factionName, adjustment)

if (delta != 0) {
val prosePackage = ProsePackage(changeMessage, "DI", abs(delta), "TO", "@faction/faction_names:$factionName")
SystemMessageIntent.broadcastPersonal(owner, prosePackage)
} else {
val prosePackage = ProsePackage(capMessage, "TO", "@faction/faction_names:$factionName")
SystemMessageIntent.broadcastPersonal(owner, prosePackage)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/***********************************************************************************
* Copyright (c) 2022 /// Project SWG /// www.projectswg.com *
* Copyright (c) 2023 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
Expand Down Expand Up @@ -28,24 +28,46 @@
package com.projectswg.holocore.services.gameplay.player.character

import com.projectswg.common.network.packets.swg.zone.CharacterSheetResponseMessage
import com.projectswg.common.network.packets.swg.zone.FactionResponseMessage
import com.projectswg.holocore.intents.support.global.command.ExecuteCommandIntent
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject
import com.projectswg.holocore.resources.support.objects.swg.player.PlayerObject
import me.joshlarson.jlcommon.control.IntentHandler
import me.joshlarson.jlcommon.control.Service

class PlayerCharacterSheetService : Service() {

@IntentHandler
private fun handleExecuteCommandIntent(eci: ExecuteCommandIntent) {
if (eci.command.cppCallback != "requestCharacterSheetInfo")
return

if (eci.command.cppCallback != "requestCharacterSheetInfo") return

val creature = eci.source
val player = creature.playerObject ?: return
creature.sendSelf(CharacterSheetResponseMessage(
lotsUsed=player.lotsAvailable - player.lotsUsed,
factionCrc=creature.pvpFaction.crc,
factionStatus=creature.pvpStatus.value
))
sendCharacterSheetResponseMessage(creature, player)
sendFactionResponseMessage(player, creature)
}

private fun sendCharacterSheetResponseMessage(creature: CreatureObject, player: PlayerObject) {
creature.sendSelf(
CharacterSheetResponseMessage(
lotsUsed = player.lotsAvailable - player.lotsUsed, factionCrc = creature.pvpFaction.crc, factionStatus = creature.pvpStatus.value
)
)
}


private fun sendFactionResponseMessage(player: PlayerObject, creature: CreatureObject) {
val factionPoints = player.factionPoints
val factionNameList = factionPoints.keys.toList()
val factionPointList = factionNameList.map { factionPoints.getOrDefault(it, 0) }.map { it.toFloat() }
creature.sendSelf(
FactionResponseMessage(
factionRank = "recruit", // From datatables/faction/rank.iff, should be dynamic once we implement faction ranks
rebelPoints = factionPoints.getOrDefault("rebel", 0),
imperialPoints = factionPoints.getOrDefault("imperial", 0),
factionNames = factionNameList,
factionPoints = factionPointList
)
)
}

}
Loading

0 comments on commit 20c701f

Please sign in to comment.