diff --git a/src/main/java/com/projectswg/holocore/services/gameplay/combat/cloning/CloningService.kt b/src/main/java/com/projectswg/holocore/services/gameplay/combat/cloning/CloningService.kt index 947457567..afe025daf 100644 --- a/src/main/java/com/projectswg/holocore/services/gameplay/combat/cloning/CloningService.kt +++ b/src/main/java/com/projectswg/holocore/services/gameplay/combat/cloning/CloningService.kt @@ -239,7 +239,8 @@ class CloningService : Service() { corpse.posture = Posture.UPRIGHT corpse.setTurnScale(1.0) corpse.setMovementPercent(1.0) - corpse.health = corpse.maxHealth + applyCloneWounds(corpse) + corpse.health = corpse.maxHealth - corpse.healthWounds corpse.sendObservers(PlayClientEffectObjectMessage("clienteffect/player_clone_compile.cef", "", corpse.objectId, "")) corpse.sendSelf(PlayMusicMessage(0, "sound/item_repairobj.snd", 1, false)) if (corpse.pvpFaction != PvpFaction.NEUTRAL) { @@ -247,6 +248,12 @@ class CloningService : Service() { } } + // Pre-designating a facility isn't supported yet, so every clone is away from the players clone data and costs the full wounds + private fun applyCloneWounds(corpse: CreatureObject) { + val woundCeiling = (corpse.maxHealth * MAX_WOUND_PERCENTAGE).toInt() + corpse.healthWounds = (corpse.healthWounds + CLONE_WOUNDS).coerceAtMost(woundCeiling) + } + /** * Picks the closest cloning facility and clones `cloneRequestor` * there. If an error occurs upon attempting to clone, it will pick the next @@ -318,6 +325,8 @@ class CloningService : Service() { companion object { private const val CLONE_TIMER: Long = 30 // Amount of minutes before a player is forced to clone + private const val CLONE_WOUNDS = 100 // Health wounds received when cloning away from your clone data + private const val MAX_WOUND_PERCENTAGE = 0.7 // Wounds can never take more than this share of unmodified maximum health private val defaultCloner: BuildingObject? get() { val defaultCloner = BuildingLookup.getBuildingByTag("tat_moseisley_cloning1") diff --git a/src/test/java/com/projectswg/holocore/services/gameplay/combat/CloningTest.kt b/src/test/java/com/projectswg/holocore/services/gameplay/combat/CloningTest.kt index 1db4b7333..623c3adec 100644 --- a/src/test/java/com/projectswg/holocore/services/gameplay/combat/CloningTest.kt +++ b/src/test/java/com/projectswg/holocore/services/gameplay/combat/CloningTest.kt @@ -31,6 +31,7 @@ import com.projectswg.holocore.services.gameplay.combat.cloning.CloningService import com.projectswg.holocore.services.gameplay.combat.duel.DuelService import com.projectswg.holocore.services.support.objects.ObjectStorageService import com.projectswg.holocore.test.runners.AcceptanceTest +import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertDoesNotThrow @@ -61,4 +62,24 @@ class CloningTest : AcceptanceTest() { assertDoesNotThrow { character2.waitForObjectMove() } } + + @Test + fun `cloning applies health wounds`() { + val user = generateUser(AccessLevel.DEV) + val character1 = HeadlessSWGClient.createZonedInCharacter(user.username, user.password, "charone") + val character2 = HeadlessSWGClient.createZonedInCharacter(user.username, user.password, "chartwo") + character1.duel(character2.player.creatureObject) + character2.duel(character1.player.creatureObject) + character1.adminKill(character2.player.creatureObject) + character1.deathblow(character2.player.creatureObject) + + val suiWindow = character2.waitForCloneActivation() + suiWindow.select(0) + suiWindow.clickOk() + character2.waitForObjectMove() + + val clone = character2.player.creatureObject + assertEquals(100, clone.healthWounds) + assertEquals(clone.maxHealth - clone.healthWounds, clone.health) + } } \ No newline at end of file