This commit is contained in:
Josh Larson
2025-01-18 15:21:02 -06:00
8 changed files with 162 additions and 14 deletions

View File

@@ -1,11 +1,10 @@
/***********************************************************************************
* Copyright (c) 2024 /// Project SWG /// www.projectswg.com *
* Copyright (c) 2025 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* ProjectSWG is an emulation project 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. *
* Our goal is to create one or more emulators which will provide servers for *
* players to continue playing a game similar to the one they used to play. *
* *
* This file is part of Holocore. *
* *
@@ -27,6 +26,7 @@
package com.projectswg.holocore.resources.support.global.commands.callbacks
import com.projectswg.common.network.packets.swg.zone.PlayMusicMessage
import com.projectswg.holocore.intents.gameplay.combat.BuffIntent
import com.projectswg.holocore.intents.gameplay.combat.LootItemIntent
import com.projectswg.holocore.intents.support.global.chat.SystemMessageIntent
import com.projectswg.holocore.intents.support.global.chat.SystemMessageIntent.Companion.broadcastPersonal
@@ -392,12 +392,16 @@ class TransferItemCallback : ICmdCallback {
}
private fun changeWeapon(actor: CreatureObject, target: SWGObject, equip: Boolean) {
val weaponHinderanceBuffName = "weaponHinderance" // CU permasnare buff. It doesn't reduce speed, but it prevents speed buffs from making the player run faster.
if (equip) {
// The equipped weapon must now be set to the target object
actor.equippedWeapon = target as WeaponObject
BuffIntent(weaponHinderanceBuffName, actor, actor, false).broadcast()
} else {
// The equipped weapon must now be set to the default weapon, which happens inside CreatureObject.setEquippedWeapon()
actor.equippedWeapon = null
BuffIntent(weaponHinderanceBuffName, actor, actor, true).broadcast()
}
}
}

View File

@@ -884,6 +884,12 @@ public class CreatureObject extends TangibleObject {
}
public void setMaxHealth(int maxHealth) {
int currentHealth = getHealth();
if (currentHealth > maxHealth) {
// Ensure it's not possible to have more health than the max health
setHealth(maxHealth);
}
creo6.setMaxHealth(maxHealth);
}

View File

@@ -270,7 +270,7 @@ class BuffService : Service() {
creature.setMovementPercent(0.0)
}
MovementLoader.MovementType.SNARE, MovementLoader.MovementType.PERMASNARE -> {
creature.setMovementPercent(strength)
creature.setMovementPercent(1.0 - strength)
}
MovementLoader.MovementType.BOOST, MovementLoader.MovementType.PERMABOOST -> {
creature.setMovementPercent(1.0 + strength)

View File

@@ -1,11 +1,10 @@
/***********************************************************************************
* Copyright (c) 2023 /// Project SWG /// www.projectswg.com *
* Copyright (c) 2025 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* ProjectSWG is an emulation project 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. *
* Our goal is to create one or more emulators which will provide servers for *
* players to continue playing a game similar to the one they used to play. *
* *
* This file is part of Holocore. *
* *
@@ -26,9 +25,10 @@
***********************************************************************************/
package com.projectswg.holocore.services.gameplay.player.experience.skills
import com.projectswg.holocore.services.gameplay.player.experience.skills.skillmod.HamSkillModService
import com.projectswg.holocore.services.gameplay.player.experience.skills.skillmod.SkillModService
import me.joshlarson.jlcommon.control.Manager
import me.joshlarson.jlcommon.control.ManagerStructure
@ManagerStructure(children = [SkillModService::class, SkillService::class])
@ManagerStructure(children = [HamSkillModService::class, SkillModService::class, SkillService::class])
class SkillManager : Manager()

View File

@@ -0,0 +1,57 @@
/***********************************************************************************
* Copyright (c) 2025 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is an emulation project for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create one or more emulators which will provide servers for *
* players to continue playing a game similar to the one they used to play. *
* *
* 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.player.experience.skills.skillmod
import com.projectswg.holocore.intents.gameplay.player.experience.SkillModIntent
import com.projectswg.holocore.resources.support.data.server_info.StandardLog
import me.joshlarson.jlcommon.control.IntentHandler
import me.joshlarson.jlcommon.control.Service
/**
* This service is responsible for modifying the health, action, and mind (HAM) of creatures based on skill mods.
* An example of a skill mod is a health mod that increases the health of a creature by a percentage (like healthPercent).
*/
class HamSkillModService : Service() {
@IntentHandler
private fun handleSkillModIntent(intent: SkillModIntent) {
val skillModName = intent.skillModName
val adjustModifier = intent.adjustModifier
when (skillModName) {
"healthPercent" -> handleHealthPercent(intent, adjustModifier)
}
}
private fun handleHealthPercent(intent: SkillModIntent, adjustModifier: Int) {
for (creature in intent.affectedCreatures) {
val originalMaxHealth = creature.maxHealth
val extraMaxHealth = ((adjustModifier / 100.0) * creature.maxHealth).toInt() // If healthPercent is 10, then mod is 1.1. A creature with 1000 health will then have 1100 health.
creature.maxHealth += extraMaxHealth
StandardLog.onPlayerTrace(this, creature, "max health increased by $adjustModifier%% $originalMaxHealth -> ${creature.maxHealth}") // %% is used to escape the % character
}
}
}

View File

@@ -25,9 +25,15 @@
***********************************************************************************/
package com.projectswg.holocore.headless
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject
import java.util.concurrent.TimeUnit
fun ZonedInCharacter.sendSelfBuffCommand(buffCommand: String) {
sendCommand(buffCommand)
player.waitForNextObjectDelta(player.creatureObject.objectId, 4, 4, 1, TimeUnit.SECONDS) ?: throw IllegalStateException("Failed to receive buff object delta for player")
}
player.waitForNextObjectDelta(player.creatureObject.objectId, 6, 19, 1, TimeUnit.SECONDS) ?: throw IllegalStateException("Failed to receive buff object delta for player")
}
fun ZonedInCharacter.sendTargetBuffCommand(buffCommand: String, target: CreatureObject) {
sendCommand(buffCommand, target)
player.waitForNextObjectDelta(target.objectId, 6, 19, 1, TimeUnit.SECONDS) ?: throw IllegalStateException("Failed to receive buff object delta for player")
}

View File

@@ -0,0 +1,73 @@
/***********************************************************************************
* Copyright (c) 2025 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is an emulation project for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create one or more emulators which will provide servers for *
* players to continue playing a game similar to the one they used to play. *
* *
* 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.combat
import com.projectswg.holocore.headless.*
import com.projectswg.holocore.resources.support.global.player.AccessLevel
import com.projectswg.holocore.test.runners.AcceptanceTest
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
class NutrientInjectionTest : AcceptanceTest() {
@Test
fun buffSelf() {
val zonedInCharacter1 = createMasterMedic()
zonedInCharacter1.waitForHealthChange() // Wait for health update for becoming a master medic
val char1OriginalMaxHealth = zonedInCharacter1.player.creatureObject.maxHealth
zonedInCharacter1.sendSelfBuffCommand("nutrientInjection")
val char1NewMaxHealth = zonedInCharacter1.player.creatureObject.maxHealth
assertTrue(char1NewMaxHealth > char1OriginalMaxHealth)
}
@Test
fun buffFriendlyTarget() {
val zonedInCharacter1 = createMasterMedic()
val zonedInCharacter2 = createZonedInCharacter("Chartwo")
val char2OriginalMaxHealth = zonedInCharacter2.player.creatureObject.maxHealth
zonedInCharacter1.waitUntilAwareOf(zonedInCharacter2.player.creatureObject)
zonedInCharacter1.sendTargetBuffCommand("nutrientInjection", zonedInCharacter2.player.creatureObject)
val char2NewMaxHealth = zonedInCharacter2.player.creatureObject.maxHealth
assertTrue(char2NewMaxHealth > char2OriginalMaxHealth)
}
private fun createMasterMedic(): ZonedInCharacter {
val zonedInCharacter1 = createZonedInCharacter("Charone")
zonedInCharacter1.adminGrantSkill("science_medic_master")
return zonedInCharacter1
}
private fun createZonedInCharacter(characterName: String): ZonedInCharacter {
val user = generateUser(accessLevel = AccessLevel.DEV)
return HeadlessSWGClient.createZonedInCharacter(user.username, user.password, characterName)
}
}

View File

@@ -49,6 +49,7 @@ import com.projectswg.holocore.services.gameplay.player.badge.BadgeManager
import com.projectswg.holocore.services.gameplay.player.character.TippingService
import com.projectswg.holocore.services.gameplay.player.experience.ExperiencePointService
import com.projectswg.holocore.services.gameplay.player.experience.skills.SkillService
import com.projectswg.holocore.services.gameplay.player.experience.skills.skillmod.HamSkillModService
import com.projectswg.holocore.services.gameplay.player.group.GroupService
import com.projectswg.holocore.services.support.global.chat.ChatManager
import com.projectswg.holocore.services.support.global.commands.CommandExecutionService
@@ -114,6 +115,7 @@ abstract class AcceptanceTest : TestRunnerSynchronousIntents() {
registerService(BuffService())
registerService(DuelService())
registerService(FactionFlagService())
registerService(HamSkillModService())
}
@AfterEach