Skip to content

Commit

Permalink
feat(actor and actor sheet): transfer all data functions from sheet t…
Browse files Browse the repository at this point in the history
…o actor and refactor the order

now the data are calculated before or after the effects, the actor is used for data transformation
and the actor sheet is used for data organization and integration with interface.
  • Loading branch information
SouOWendel committed Mar 12, 2024
1 parent 7d6a05b commit 33ab28a
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 183 deletions.
221 changes: 170 additions & 51 deletions module/documents/actor.mjs
Expand Up @@ -18,82 +18,197 @@ export class OrdemActor extends Actor {
// Data modifications in this step occur before processing embedded
// documents or derived data.
const actorData = this;
const systemData = actorData.system;

this._prepareBaseDataAgent(actorData);
if (actorData.type == 'agent') {
this._migrateData(systemData);
this._prepareBaseDataAgent(systemData);
this._prepareDataStatus(systemData);
}
}

/**
* @override
* Augment the basic actor data with additional dynamic data. Typically,
* you'll want to handle most of your calculated/derived data in this step.
* Data calculated in this step should generally not exist in template.json
* (such as ability modifiers rather than ability scores) and should be
* available both inside and outside of character sheets (such as if an actor
* is queried and has a roll executed directly from it).
*/
prepareDerivedData() {
const actorData = this;
const systemData = actorData.system;
const flags = actorData.flags.ordemparanormal || {};

// Make separate methods for each Actor type (character, npc, etc.) to keep
// things organized.
if (actorData.type == 'agent') {
this._prepareDefense(systemData);
this._prepareSkills(systemData);
this._prepareActorSpaces(actorData);
}
}

/**
*
*
* @param {*} system
*/
async _prepareBaseDataAgent(actorData) {
_prepareDataStatus(system) {
const VIG = system.attributes.vit.value;
const PRE = system.attributes.pre.value;
const NEX = system.NEX.value;
const calcNEX = NEX < 99 ? Math.floor(NEX / 5) : 20;
const nexAdjust = calcNEX - 1;
const nexIf = calcNEX > 1;
system.PE.perRound = calcNEX;
if (system.class == 'fighter') {
system.PV.max = 20 + VIG + (nexIf && nexAdjust * (4 + VIG));
system.PE.max = 2 + PRE + (nexIf && nexAdjust * (2 + PRE));
system.SAN.max = 12 + (nexIf && nexAdjust * 3);
} else if (system.class == 'specialist') {
system.PV.max = 16 + VIG + (nexIf && nexAdjust * (3 + VIG));
system.PE.max = 3 + PRE + (nexIf && nexAdjust * (3 + PRE));
system.SAN.max = 16 + (nexIf && nexAdjust * 4);
} else if (system.class == 'occultist') {
system.PV.max = 12 + VIG + (nexIf && nexAdjust * (2 + VIG));
system.PE.max = 4 + PRE + (nexIf && nexAdjust * (4 + PRE));
system.SAN.max = 20 + (nexIf && nexAdjust * 5);
} else {
system.PV.max = system.PV.max || 0;
system.PE.max = system.PE.max || 0;
system.SAN.max = system.SAN.max || 0;
}
}

// System access
const system = actorData.system;
/**
*
* @param {*} system
*/
_prepareDefense(system) {
const REFLEXES = system.skills.reflexes;
const AGI = system.attributes.dex.value;
system.defense.value += AGI;
return (system.defense.dodge =
system.defense.value + REFLEXES.value + (REFLEXES.mod || 0));
}

if (actorData.type !== 'agent') return;

// TODO: Update portuguese class name for english class name (6.3.1)
if (system?.class == 'Combatente') await Actor.updateDocuments([{_id: actorData.actor._id, system: {class: 'fighter'}} ]);
if (system?.class == 'Especialista') await Actor.updateDocuments([{_id: actorData.actor._id, system: {class: 'specialist'}} ]);
if (system?.class == 'Ocultista') await Actor.updateDocuments([{_id: actorData.actor._id, system: {class: 'occultist'}} ]);
/**
*
* @param {*} system
*/
_prepareSkills(system) {
/**
* Faz um loop das perícias e depois faz algumas verificações para definir a formula de rolagem,
* depois disso, salva o valor nas informações
* */
for (const [keySkill, skillsName] of Object.entries(system.skills)) {
// Definindo constantes para acesso simplificado.
const overLoad = skillsName.conditions.load;
const needTraining = skillsName.conditions.trained;

// Calculate the modifier using d20 rules.
if (skillsName.degree.label == 'trained') skillsName.value = 5;
else if (skillsName.degree.label == 'veteran') skillsName.value = 10;
else if (skillsName.degree.label == 'expert') skillsName.value = 15;
else skillsName.value = 0;

// Formando o nome com base nas condições de carga e treino da perícia.
skillsName.label =
game.i18n.localize(CONFIG.ordemparanormal.skills[keySkill]) +
(overLoad ? '+' : needTraining ? '*' : '') ?? k;

// FORMULA DE ROLAGEM: Criando o que vem antes e depois do D20 das perícias.
const beforeD20Formula = skillsName.attr[1] ? skillsName.attr[1] : 2;

const afterD20Formula =
(skillsName.attr[1] != 0 ? 'kh' : 'kl') +
(skillsName.value != 0 ? '+' + skillsName.value : '') +
(skillsName.mod ? '+' + skillsName.mod : '');

skillsName.formula = beforeD20Formula + 'd20' + afterD20Formula;
}
}

/**
*
*/
async _prepareBaseDataAgent(system) {
// Loop through ability scores, and add their modifiers to our sheet output.
for (const [keySkill, skillsName] of Object.entries(system.skills)) {

/**
* Faz um loop de todos os atributos, depois disso, se o atributo
* necessário para a perícia for o mesmo que a mesma perícia em que o loop
* esta no momento, este valor é atualizado para ser utilizado nas rolagens.
*/
for (const [keyAttr, attribute] of Object.entries(system.attributes)) {
// console.log('keyAttr is ' + keyAttr);
// console.log('skillsName.attr[0] is ' + skillsName.attr[0]);
if (skillsName.attr[0] == keyAttr) {
// console.log('attribute.value ' + attribute.value + ' data.skills[keySkill].attr[1] ' + data.skills[keySkill].attr[1]);
system.skills[keySkill].attr[1] = attribute.value;
}
}
}
}

/**
* @override
* Augment the basic actor data with additional dynamic data. Typically,
* you'll want to handle most of your calculated/derived data in this step.
* Data calculated in this step should generally not exist in template.json
* (such as ability modifiers rather than ability scores) and should be
* available both inside and outside of character sheets (such as if an actor
* is queried and has a roll executed directly from it).
* Prepare and calcule the spaces of actors
*
* @param {Object} actorData The actor to prepare.
*
* @return {undefined}
*/
prepareDerivedData() {
const actorData = this;
_prepareActorSpaces(ActorData) {
const system = ActorData.system;
const spaces = (system.spaces ??= {});
const FOR = system.attributes.str.value || 0;
spaces.over, (spaces.pctMax = 0);

// eslint-disable-next-line no-unused-vars
const flags = actorData.flags.ordemparanormal || {};
// Get the total weight from items
const physicalItems = ['armament', 'generalEquipment', 'protection'];
const weight = ActorData.items.reduce((weight, i) => {
if (!physicalItems.includes(i.type)) return weight;
const q = i.system.quantity || 0;
const w = i.system.weight || 0;
return weight + q * w;
}, 0);

// Make separate methods for each Actor type (character, npc, etc.) to keep
// things organized.
this._prepareAgentData(actorData);
}
// Populate the final values
spaces.value = weight.toNearest(0.1);
spaces.max = FOR !== 0 ? FOR * 5 : 2;

/**
* Preparação dos dados específicos do tipo Agente
*/
_prepareAgentData(actorData) {
if (actorData.type !== 'agent') return;
// Plus bonus
spaces.value += spaces.bonus.value;
spaces.max += spaces.bonus.max;

// Loop through ability scores, and add their modifiers to our sheet output.
for (const [keySkill, skillsName] of Object.entries(actorData.system.skills)) {
// Calculate the modifier using d20 rules.
// if (skillsName.mod) skillsName.mod = 0;
if (skillsName.degree.label == 'trained') skillsName.value = 5;
else if (skillsName.degree.label == 'veteran') skillsName.value = 10;
else if (skillsName.degree.label == 'expert') skillsName.value = 15;
else skillsName.value = 0;
spaces.pct = Math.clamped((spaces.value * 100) / spaces.max, 0, 100);

// console.log(JSON.stringify(skillsName.degree) + skillsName.value);
// Apply the debuffs
if (spaces.value > spaces.max) {
spaces.over = spaces.value - spaces.max;
system.desloc.value += -3;
system.defense.value += -5;
spaces.pctMax = Math.clamped((spaces.over * 100) / spaces.max, 0, 100);
}
if (spaces.value > spaces.max * 2)
ui.notifications.warn(game.i18n.localize('WARN.overWeight'));
}

/**
*
*/
async _migrateData(system) {
// TODO: Update portuguese class name for english class name (6.3.1)
if (system?.class == 'Combatente')
await Actor.updateDocuments([
{ _id: actorData.actor._id, system: { class: 'fighter' } },
]);
if (system?.class == 'Especialista')
await Actor.updateDocuments([
{ _id: actorData.actor._id, system: { class: 'specialist' } },
]);
if (system?.class == 'Ocultista')
await Actor.updateDocuments([
{ _id: actorData.actor._id, system: { class: 'occultist' } },
]);
}

/**
Expand All @@ -115,8 +230,6 @@ export class OrdemActor extends Actor {
if (this.system.type !== 'agent') return;
let skillUpper;

console.log(system);

// Copy the skills scores to the top level, so that rolls can use
// formulas like `@iniciativa.value + 4`.
// TODO: criar acesso rapido de variavel para outras linguagens
Expand All @@ -125,21 +238,27 @@ export class OrdemActor extends Actor {
system[k] = foundry.utils.deepClone(v);

skillUpper = k.charAt(0).toUpperCase() + k.slice(1);
system[game.i18n.localize('ordemparanormal.skill' + skillUpper).toLowerCase()] = foundry.utils.deepClone(v);
system[
game.i18n.localize('ordemparanormal.skill' + skillUpper).toLowerCase()
] = foundry.utils.deepClone(v);
}
}

// Copy the attributes to the top level, so that rolls can use
// formulas like `@dex.value`.
if(system.attributes) {
if (system.attributes) {
for (const [k, v] of Object.entries(system.attributes)) {
system[k] = foundry.utils.deepClone(v);
}
}

if(system.attributes && system.skills) {
system.rollInitiative = ((system.attributes.dex.value == 0) ? 2 : system.attributes.dex.value) + 'd20' +
((system.attributes.dex.value == 0) ? 'kl' : 'kh') + '+' + system.skills.initiative.value;
if (system.attributes && system.skills) {
system.rollInitiative =
(system.attributes.dex.value == 0 ? 2 : system.attributes.dex.value) +
'd20' +
(system.attributes.dex.value == 0 ? 'kl' : 'kh') +
'+' +
system.skills.initiative.value;
}

// Add level for easier access, or fall back to 0.
Expand Down

0 comments on commit 33ab28a

Please sign in to comment.