Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions serverdata/creation/attribute_limits.sdb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
male_template female_template min_health max_health min_strength max_strength min_constitution max_constitution min_action max_action min_quickness max_quickness min_stamina max_stamina min_mind max_mind min_focus max_focus min_willpower max_willpower total

bothan_male bothan_female 900 900 0 0 850 850 1000 1000 0 0 1200 1200 1000 1000 0 0 950 950 5900
human_male human_female 1000 1000 0 0 1000 1000 1000 1000 0 0 1000 1000 1000 1000 0 0 1000 1000 6000
moncal_male moncal_female 900 900 0 0 850 850 1000 1000 0 0 950 950 1000 1000 0 0 1200 1200 5900
rodian_male rodian_female 900 900 0 0 850 850 1000 1000 0 0 1300 1300 1000 1000 0 0 850 850 5900
trandoshan_male trandoshan_female 1150 1150 0 0 1500 1500 1000 1000 0 0 850 850 1000 1000 0 0 900 900 6400
twilek_male twilek_female 900 900 0 0 1050 1050 1000 1000 0 0 1100 1100 1000 1000 0 0 900 900 5950
wookiee_male wookiee_female 1250 1250 0 0 1300 1300 1000 1000 0 0 950 950 1000 1000 0 0 1000 1000 6500
zabrak_male zabrak_female 1100 1100 0 0 900 900 1000 1000 0 0 1000 1000 1000 1000 0 0 1100 1100 6100
sullustan_male sullustan_female 1050 1050 0 0 900 900 1000 1000 0 0 1050 1050 1000 1000 0 0 1100 1100 6100
ithorian_male ithorian_female 1300 1300 0 0 1200 1200 1000 1000 0 0 900 900 1000 1000 0 0 950 950 6350
9 changes: 9 additions & 0 deletions serverdata/creation/profession_mods.sdb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
profession health strength constitution action quickness stamina mind focus willpower

crafting_artisan 1000 0 1000 1000 0 1000 1000 0 1000
combat_brawler 1000 0 1000 1000 0 1000 1000 0 1000
social_entertainer 1000 0 1000 1000 0 1000 1000 0 1000
combat_marksman 1000 0 1000 1000 0 1000 1000 0 1000
science_medic 1000 0 1000 1000 0 1000 1000 0 1000
outdoors_scout 1000 0 1000 1000 0 1000 1000 0 1000
jedi 1000 0 1000 1000 0 1000 1000 0 1000
12 changes: 12 additions & 0 deletions serverdata/creation/racial_mods.sdb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
male_template female_template health strength constitution action quickness stamina mind focus willpower

bothan_male bothan_female -100 0 -150 0 0 200 0 0 -50
human_male human_female 0 0 0 0 0 0 0 0 0
moncal_male moncal_female -100 0 -150 0 0 -50 0 0 200
rodian_male rodian_female -100 0 -150 0 0 300 0 0 -150
trandoshan_male trandoshan_female 150 0 500 0 0 -150 0 0 -100
twilek_male twilek_female -100 0 50 0 0 100 0 0 -100
wookiee_male wookiee_female 250 0 300 0 0 -50 0 0 0
zabrak_male zabrak_female 100 0 -100 0 0 0 0 0 100
sullustan_male sullustan_female 50 0 -100 0 0 50 0 0 100
ithorian_male ithorian_female 300 0 200 0 0 -100 0 0 -50
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/***********************************************************************************
* Copyright (c) 2026 /// 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.resources.support.data.server_info.loader

import com.projectswg.common.data.encodables.tangible.Race
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet
import java.io.File
import java.io.IOException

class CreationAttributeLimitsLoader internal constructor() : DataLoader() {
private val limitsByRace: MutableMap<Race, AttributeLimits> = HashMap()

fun getLimits(race: Race): AttributeLimits? = limitsByRace[race]

@Throws(IOException::class)
override fun load() {
SdbLoader.load(File("serverdata/creation/attribute_limits.sdb")).use { set ->
while (set.next()) {
val limits = AttributeLimits(set)
limitsByRace[Race.getRace(set.getText("male_template"))] = limits
limitsByRace[Race.getRace(set.getText("female_template"))] = limits
}
}
}

class AttributeLimits(set: SdbResultSet) {
val minHealth: Int = set.getInt("min_health").toInt()
val maxHealth: Int = set.getInt("max_health").toInt()
val minConstitution: Int = set.getInt("min_constitution").toInt()
val maxConstitution: Int = set.getInt("max_constitution").toInt()
val minAction: Int = set.getInt("min_action").toInt()
val maxAction: Int = set.getInt("max_action").toInt()
val minStamina: Int = set.getInt("min_stamina").toInt()
val maxStamina: Int = set.getInt("max_stamina").toInt()
val minMind: Int = set.getInt("min_mind").toInt()
val maxMind: Int = set.getInt("max_mind").toInt()
val minWillpower: Int = set.getInt("min_willpower").toInt()
val maxWillpower: Int = set.getInt("max_willpower").toInt()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/***********************************************************************************
* Copyright (c) 2026 /// 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.resources.support.data.server_info.loader

import com.projectswg.holocore.resources.support.data.server_info.SdbLoader
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet
import java.io.File
import java.io.IOException

class CreationProfessionModsLoader internal constructor() : DataLoader() {
private val modsByProfession: MutableMap<String, ProfessionMods> = HashMap()

fun getMods(profession: String): ProfessionMods? = modsByProfession[profession]

@Throws(IOException::class)
override fun load() {
SdbLoader.load(File("serverdata/creation/profession_mods.sdb")).use { set ->
while (set.next()) {
val mods = ProfessionMods(set)
modsByProfession[mods.profession] = mods
}
}
}

class ProfessionMods(set: SdbResultSet) {
val profession: String = set.getText("profession")
val health: Int = set.getInt("health").toInt()
val constitution: Int = set.getInt("constitution").toInt()
val action: Int = set.getInt("action").toInt()
val stamina: Int = set.getInt("stamina").toInt()
val mind: Int = set.getInt("mind").toInt()
val willpower: Int = set.getInt("willpower").toInt()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/***********************************************************************************
* Copyright (c) 2026 /// 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.resources.support.data.server_info.loader

import com.projectswg.common.data.encodables.tangible.Race
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet
import java.io.File
import java.io.IOException

class CreationRacialModsLoader internal constructor() : DataLoader() {
private val modsByRace: MutableMap<Race, RacialMods> = HashMap()

fun getMods(race: Race): RacialMods? = modsByRace[race]

@Throws(IOException::class)
override fun load() {
SdbLoader.load(File("serverdata/creation/racial_mods.sdb")).use { set ->
while (set.next()) {
val mods = RacialMods(set)
modsByRace[Race.getRace(set.getText("male_template"))] = mods
modsByRace[Race.getRace(set.getText("female_template"))] = mods
}
}
}

class RacialMods(set: SdbResultSet) {
val health: Int = set.getInt("health").toInt()
val constitution: Int = set.getInt("constitution").toInt()
val action: Int = set.getInt("action").toInt()
val stamina: Int = set.getInt("stamina").toInt()
val mind: Int = set.getInt("mind").toInt()
val willpower: Int = set.getInt("willpower").toInt()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ abstract class DataLoader {
fun playerLevels(): PlayerLevelLoader = ServerData.playerLevels
fun playerRoles(): PlayerRoleLoader = ServerData.playerRoles
fun playerStartClothing(): StartClothingLoader = ServerData.playerStartClothing
fun creationAttributeLimits(): CreationAttributeLimitsLoader = ServerData.creationAttributeLimits
fun creationProfessionMods(): CreationProfessionModsLoader = ServerData.creationProfessionMods
fun creationRacialMods(): CreationRacialModsLoader = ServerData.creationRacialMods
fun buildouts(): BuildoutLoader = buildouts(listOf())
fun buildouts(events: Collection<String>): BuildoutLoader = BuildoutLoader.load(events)
fun buildingCells(): BuildingCellLoader = ServerData.buildingCells
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ object ServerData {
val playerLevels by SoftDataLoaderDelegate(::PlayerLevelLoader)
val playerRoles by SoftDataLoaderDelegate(::PlayerRoleLoader)
val playerStartClothing by SoftDataLoaderDelegate(::StartClothingLoader)
val creationAttributeLimits by SoftDataLoaderDelegate(::CreationAttributeLimitsLoader)
val creationProfessionMods by SoftDataLoaderDelegate(::CreationProfessionModsLoader)
val creationRacialMods by SoftDataLoaderDelegate(::CreationRacialModsLoader)
val staticItems by SoftDataLoaderDelegate(::StaticItemLoader)
val performances by SoftDataLoaderDelegate(::PerformanceLoader)
val combatXpMultipliers by SoftDataLoaderDelegate(::CombatXpMultiplierLoader)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ import com.projectswg.common.data.swgfile.ClientFactory
import com.projectswg.common.network.packets.swg.login.creation.ClientCreateCharacter
import com.projectswg.holocore.intents.gameplay.player.experience.GrantSkillIntent
import com.projectswg.holocore.intents.support.objects.ObjectCreatedIntent
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader.Companion.creationAttributeLimits
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader.Companion.creationProfessionMods
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader.Companion.creationRacialMods
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader.Companion.playerStartClothing
import com.projectswg.holocore.resources.support.data.server_info.loader.TerrainZoneInsertionLoader.ZoneInsertion
import com.projectswg.holocore.resources.support.global.player.AccessLevel
Expand All @@ -55,6 +58,7 @@ class CharacterCreation(private val player: Player, private val create: ClientCr
val creatureObj = createCreature(race.filename, info)
val playerObj = createPlayer(creatureObj)

setCreationAttributes(creatureObj, race)
setCreatureObjectValues(creatureObj, race)
setPlayerObjectValues(playerObj, race)
createHair(creatureObj, create.hair, create.hairCustomization)
Expand Down Expand Up @@ -158,6 +162,39 @@ class CharacterCreation(private val player: Player, private val create: ClientCr
createItem(creatureObj.inventory, "object/tangible/instrument/shared_slitherhorn.iff")
}

private fun setCreationAttributes(creatureObj: CreatureObject, race: Race) {
val professionMods = creationProfessionMods().getMods(create.clothes) ?: return
val racialMods = creationRacialMods().getMods(race) ?: return
val limits = creationAttributeLimits().getLimits(race) ?: return

val health = (professionMods.health + racialMods.health).coerceIn(limits.minHealth, limits.maxHealth)
val constitution = (professionMods.constitution + racialMods.constitution).coerceIn(limits.minConstitution, limits.maxConstitution)
val action = (professionMods.action + racialMods.action).coerceIn(limits.minAction, limits.maxAction)
val stamina = (professionMods.stamina + racialMods.stamina).coerceIn(limits.minStamina, limits.maxStamina)
val mind = (professionMods.mind + racialMods.mind).coerceIn(limits.minMind, limits.maxMind)
val willpower = (professionMods.willpower + racialMods.willpower).coerceIn(limits.minWillpower, limits.maxWillpower)

creatureObj.setBaseHealth(health)
creatureObj.maxHealth = health
creatureObj.health = health
creatureObj.setBaseAction(action)
creatureObj.maxAction = action
creatureObj.action = action
creatureObj.setBaseMind(mind)
creatureObj.maxMind = mind
creatureObj.mind = mind

creatureObj.setBaseConstitution(constitution)
creatureObj.maxConstitution = constitution
creatureObj.constitution = constitution
creatureObj.setBaseStamina(stamina)
creatureObj.maxStamina = stamina
creatureObj.stamina = stamina
creatureObj.setBaseWillpower(willpower)
creatureObj.maxWillpower = willpower
creatureObj.willpower = willpower
}

private fun createDefaultWeapon(creatureObj: CreatureObject): WeaponObject {
val defWeapon = createDefaultWeapon()
defWeapon.moveToContainer(creatureObj)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,10 @@ public void setMaxAction(int maxAction) {
creo6.setMaxAction(maxAction);
}

public void setBaseMind(int baseMind) {
baseAttributes.setMind(baseMind);
}

public void setMind(int mind) {
creo6.setMind(mind);
}
Expand All @@ -933,6 +937,78 @@ public void setMaxMind(int maxMind) {
creo6.setMaxMind(maxMind);
}

public int getConstitution() {
return creo6.getConstitution();
}

public int getBaseConstitution() {
return baseAttributes.getHealthRegen();
}

public void setBaseConstitution(int baseConstitution) {
baseAttributes.setHealthRegen(baseConstitution);
}

public void setConstitution(int constitution) {
creo6.setConstitution(constitution);
}

public int getMaxConstitution() {
return creo6.getMaxConstitution();
}

public void setMaxConstitution(int maxConstitution) {
creo6.setMaxConstitution(maxConstitution);
}

public int getStamina() {
return creo6.getStamina();
}

public int getBaseStamina() {
return baseAttributes.getActionRegen();
}

public void setBaseStamina(int baseStamina) {
baseAttributes.setActionRegen(baseStamina);
}

public void setStamina(int stamina) {
creo6.setStamina(stamina);
}

public int getMaxStamina() {
return creo6.getMaxStamina();
}

public void setMaxStamina(int maxStamina) {
creo6.setMaxStamina(maxStamina);
}

public int getWillpower() {
return creo6.getWillpower();
}

public int getBaseWillpower() {
return baseAttributes.getMindRegen();
}

public void setBaseWillpower(int baseWillpower) {
baseAttributes.setMindRegen(baseWillpower);
}

public void setWillpower(int willpower) {
creo6.setWillpower(willpower);
}

public int getMaxWillpower() {
return creo6.getMaxWillpower();
}

public void setMaxWillpower(int maxWillpower) {
creo6.setMaxWillpower(maxWillpower);
}

private void initBaseAttributes() {
baseAttributes.setHealth(1000);
baseAttributes.setAction(100);
Expand Down
Loading
Loading