diff --git a/CHANGELOG.md b/CHANGELOG.md
index fcecd17..46a5e2a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,14 @@
## Recent updates
+### 2024-09-11
+
+- Added: Herbalist, Miner, Nurse general skill implementation.
+- Updating special rolls form the main character sheet to be in line with new look.
+- Added warning to players not targeting monsters before rolling an attack.
+
+### 2024-09-10
+
- Finished updating new Player Shield Block code.
- Shields and Shieldsman skills automated into new Player Shield Block code.
- Updated general skill rolls to use new output format. Further updates may be needed to streamline the code more.
diff --git a/gs.mjs b/gs.mjs
index 1d1b058..2c9fc0a 100644
--- a/gs.mjs
+++ b/gs.mjs
@@ -191,11 +191,11 @@ async function weaponMacroHotbarDrop(data, slot){
}
};`;
if(item.type === 'weapon'){
- command += `actor.sheet._newPlayerAttack(mockEvent);`;
+ command += `actor.sheet._playerAttack(mockEvent);`;
}else if(item.type === 'armor')
- command += `actor.sheet._newPlayerDodge(mockEvent);`;
+ command += `actor.sheet._playerDodge(mockEvent);`;
else if(item.type === 'shield')
- command += `actor.sheet._newPlayerBlock(mockEvent);`;
+ command += `actor.sheet._playerBlock(mockEvent);`;
else
console.log(`GS Hotbar Drop Error | The current item you have dropped into the hot bar is not configured yet.`);
diff --git a/lang/en.json b/lang/en.json
index ba9fe5a..56104df 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -246,7 +246,19 @@
"piec": "Pieces",
"heal": "Heal",
"aTrack": "Attrition Track",
- "dc": "DC"
+ "dc": "DC",
+ "strFoc": "Strength Focus",
+ "strRef": "Strength Reflex",
+ "strEnd": "Strength Endurance",
+ "psyFoc": "Pysche Focus",
+ "psyRef": "Pysche Reflex",
+ "psyEnd": "Pysche Endurance",
+ "tecFoc": "Technique Focus",
+ "tecRef": "Technique Reflex",
+ "tecEnd": "Technique Endurance",
+ "intFoc": "Intelligence Focus",
+ "intRef": "Intelligence Reflex",
+ "intEnd": "Intelligence Endurance"
},
"monster": {
"type": "Type",
@@ -396,6 +408,7 @@
}
},
"dialog": {
+ "random": "Random",
"rolling": "Rolling",
"cancel": "Cancel",
"dice": "Dice",
@@ -407,6 +420,8 @@
"suffered": "Damage Suffered",
"outOfRange": "You are out of range for the attack.",
"curvedShotLabel": "Curved Short",
+ "skillCheck": "Skill Check",
+ "firstTargetMonster": "You must target a monster before rolling a Hit Check. Right-click and toggle target state or hover mouse over token and click 'T'.",
"dodge": {
"value": "Dodge Value",
"roll": "Dodge Roll",
@@ -611,6 +626,14 @@
"header": "Will you use the following skill: ",
"primary": "Yes",
"secondary": "No"
+ },
+ "herbalist":{
+ "title": " Skill Choices",
+ "header": "Choose a Main Roll",
+ "body": "Choose to roll either an Observe, Sixth Sense, or General Knowledge check which will include this skill level bonus: ",
+ "button1": "Observe",
+ "button2": "Sixth Sense",
+ "button3": "General Knowledge"
}
}
}
diff --git a/module/sheets/GSActorSheet.mjs b/module/sheets/GSActorSheet.mjs
index 07fdc43..e36c707 100644
--- a/module/sheets/GSActorSheet.mjs
+++ b/module/sheets/GSActorSheet.mjs
@@ -131,15 +131,29 @@ export default class GSActorSheet extends ActorSheet{
async _playerAttack(event){
event.preventDefault();
+ const targets = Array.from(game.user.targets);
+ const targetToken = targets[0].document.actor.getActiveTokens()[0];
+
+ // Return early if target isn't selected and warn player
+ if(!targetToken){
+ ui.notifications.warm(game.i18n.localize('gs.dialog.firstTargetMonster'));
+ return;
+ }
+
const actor = this.actor;
const actorToken = game.actors.get(actor._id).getActiveTokens()[0];
const defaultDice = '2d6';
- const skills = actor.items.filter(i => i.type === 'skill');
+ const skills = this._getFromItemsList('skill');
const itemInfo = this._pullItemInfo(event, actor);
- const targets = Array.from(game.user.targets);
- const targetToken = targets[0].document.actor.getActiveTokens()[0];
let chatMessage = this._setMessageHeader(actor, itemInfo, 'toHit');
+ // Checking if range is vallid before rolling attacks, else return early
+ const rangeValid = this._checkWeaponRange(actorToken, targetToken, itemInfo);
+ if(!rangeValid){
+ ui.notifications.warn(game.i18n.localize('gs.dialog.outOfRange'));
+ return;
+ }
+
// Checking for Curved Shot skill if weapon is a bow and skill present to update various factors
if(itemInfo.system.type.split(" / ")[0] === 'Bow' && skills.some(s => s.name === 'Curved Shot')){
const cSPromptResponse = await this._promptMiscModChoice('curvedShot');
@@ -147,87 +161,80 @@ export default class GSActorSheet extends ActorSheet{
this._curvedShotCheck(itemInfo, skills);
}
- // Checking if range is vallid before rolling attacks
- const rangeValid = this._checkWeaponRange(actorToken, targetToken, itemInfo);
+ // Setting base hit check dice to chat window
+ chatMessage += this._addToFlavorMessage('diceInfo', game.i18n.localize('gs.dialog.dice'), defaultDice);
- if(rangeValid){
- // Setting base hit check dice to chat window
- chatMessage += this._addToFlavorMessage('diceInfo', game.i18n.localize('gs.dialog.dice'), defaultDice);
-
- // Pulling Weapon To Hit Info
- let weaponHitMod = itemInfo.system.hitMod;
- if(skills.some(s => s.name === 'Gorilla Tactics')){
- const gorTact = skills.find(s => s.name === 'Gorilla Tactics');
- const gTactVal = this._updateWeaponHitMod(gorTact);
- weaponHitMod = weaponHitMod - gTactVal;
- chatMessage += this._addToFlavorMessage('armorDodgeScore', gorTact.name, gTactVal);
- }
- chatMessage += this._addToFlavorMessage('gearModifier', game.i18n.localize('gs.dialog.gearMod'), weaponHitMod);
-
- // Pulling Class Bonus
- let {classBonus, message, stat} = this._getClassLevelBonus2('weapon', itemInfo, chatMessage);
- chatMessage = message;
-
- // Checking for skill hit check bonus
- let {skillBonus, skillMessage} = await this._getHitSkillModifier(skills, itemInfo);
- chatMessage += skillMessage;
-
- // Get random modifiers from Prompt
- let randomMods = await this._promptRandomModifiers();
- if(randomMods) chatMessage += this._addToFlavorMessage('miscScore', game.i18n.localize('gs.dialog.miscMod'), randomMods);
-
- // Setting Roll Message
- let rollString = this._setRollMessage(defaultDice, weaponHitMod, stat, classBonus, skillBonus, randomMods);
-
- // Rolling Dice
- let {roll, diceResults, rollTotal} = await this._rollDice(rollString);
-
- // Checking for Effectiveness Score buffs
- let {tempAmount, eSMessage} = this._checkEffectivenessSkills(skills, itemInfo);
- rollTotal += tempAmount;
- chatMessage += eSMessage;
-
- // Setting up Effectivess Score view
- chatMessage += this._addToFlavorMessage('diceInfo', game.i18n.localize('gs.gear.spells.efs'), rollTotal);
- let extraDamage = this._getExtraDamage(rollTotal) || 0;
- if(extraDamage)
- chatMessage += this._addToFlavorMessage('diceInfo', game.i18n.localize('gs.dialog.bonusDmg'), extraDamage);
-
- // Checking for Crit Success/Failure
- const sliceSkill = skills.find(s => s.name === 'Slice Attack') || 0;
- const critStatus = this._checkForCriticals(diceResults, sliceSkill);
- if(critStatus != undefined || critStatus != null)
- chatMessage += `${critStatus[1]}`;
-
- // Getting target information
- try{
- chatMessage += this._setMonsterTargetInfo(targets, itemInfo, extraDamage);
- }catch(err){
- ui.notifications.warn("You must select a target first before attacking.", err);
- console.error('... setting monster target', err);
- return false;
- }
+ // Pulling Weapon To Hit Info
+ let weaponHitMod = itemInfo.system.hitMod;
+ if(skills.some(s => s.name === 'Gorilla Tactics')){
+ const gorTact = skills.find(s => s.name === 'Gorilla Tactics');
+ const gTactVal = this._updateWeaponHitMod(gorTact);
+ weaponHitMod = weaponHitMod - gTactVal;
+ chatMessage += this._addToFlavorMessage('armorDodgeScore', gorTact.name, gTactVal);
+ }
+ chatMessage += this._addToFlavorMessage('gearModifier', game.i18n.localize('gs.dialog.gearMod'), weaponHitMod);
- // Ending of chat message box before roll evaluation
- chatMessage += this._setMessageEnder();
+ // Pulling Class Bonus
+ let {classBonus, message, stat} = this._getClassLevelBonus2('weapon', itemInfo, chatMessage);
+ chatMessage = message;
- // Sending dice rolls to chat window
- await roll.toMessage({
- speaker: { actor: actor },
- flavor: chatMessage,
- user: game.user.id
- // content: Change dice rolls and other items here if needed
- });
- }else{
- ui.notifications.warn(game.i18n.localize('gs.dialog.outOfRange'));
+ // Checking for skill hit check bonus
+ let {skillBonus, skillMessage} = await this._getHitSkillModifier(skills, itemInfo);
+ chatMessage += skillMessage;
+
+ // Get random modifiers from Prompt
+ let randomMods = await this._promptRandomModifiers();
+ if(randomMods) chatMessage += this._addToFlavorMessage('miscScore', game.i18n.localize('gs.dialog.miscMod'), randomMods);
+
+ // Setting Roll Message
+ let rollString = this._setRollMessage(defaultDice, weaponHitMod, stat, classBonus, skillBonus, randomMods);
+
+ // Rolling Dice
+ let {roll, diceResults, rollTotal} = await this._rollDice(rollString);
+
+ // Checking for Effectiveness Score buffs
+ let {tempAmount, eSMessage} = this._checkEffectivenessSkills(skills, itemInfo);
+ rollTotal += tempAmount;
+ chatMessage += eSMessage;
+
+ // Setting up Effectivess Score view
+ chatMessage += this._addToFlavorMessage('diceInfo', game.i18n.localize('gs.gear.spells.efs'), rollTotal);
+ let extraDamage = this._getExtraDamage(rollTotal) || 0;
+ if(extraDamage)
+ chatMessage += this._addToFlavorMessage('diceInfo', game.i18n.localize('gs.dialog.bonusDmg'), extraDamage);
+
+ // Checking for Crit Success/Failure
+ const sliceSkill = skills.find(s => s.name === 'Slice Attack') || 0;
+ const critStatus = this._checkForCriticals(diceResults, sliceSkill);
+ if(critStatus != undefined || critStatus != null)
+ chatMessage += `${critStatus[1]}`;
+
+ // Getting target information
+ try{
+ chatMessage += this._setMonsterTargetInfo(targets, itemInfo, extraDamage);
+ }catch(err){
+ ui.notifications.warn("You must select a target first before attacking.", err);
+ console.error('... setting monster target', err);
+ return false;
}
+
+ // Ending of chat message box before roll evaluation
+ chatMessage += this._setMessageEnder();
+
+ // Sending dice rolls to chat window
+ await roll.toMessage({
+ speaker: { actor: actor },
+ flavor: chatMessage,
+ user: game.user.id
+ // content: Change dice rolls and other items here if needed
+ });
}
async _playerDodge(event){
event.preventDefault();
const actor = this.actor;
const defaultDice = '2d6';
- const skills = actor.items.filter(i => i.type === 'skill');
+ const skills = this._getFromItemsList('skill');
const itemInfo = this._pullItemInfo(event, actor);
// Setting Message Header for dodge roll
@@ -277,7 +284,7 @@ export default class GSActorSheet extends ActorSheet{
event.preventDefault();
const actor = this.actor;
const defaultDice = '2d6';
- const skills = actor.items.filter(i => i.type === 'skill');
+ const skills = this._getFromItemsList('skill');
const itemInfo = this._pullItemInfo(event, actor);
// Setting Message Header for dodge roll
@@ -747,7 +754,7 @@ export default class GSActorSheet extends ActorSheet{
}
async _genRollsToWindow(promptChoices){
- // promptChoices = [labelText 0, abilityScore 1, classLevelBonus 2, modifiers 3, className 4, skillBonus 5, skillInfo 6];
+ // promptChoices = [labelText 0, abilityScore 1, classLevelBonus 2, modifiers 3, className 4, skillBonus 5, skill 6];
const defaultDice = '2d6';
// Adding header information
@@ -791,6 +798,14 @@ export default class GSActorSheet extends ActorSheet{
});
}
+ /**
+ * Returns a JSON object from the items field with the given type
+ * @param {string} typeName The type of item you want returned: "weapon", "armor", "shield", "item", "spell", "skill", "race", "martialtechniques"
+ * @returns JSON object of the given type
+ */
+ _getFromItemsList(typeName){
+ return this.actor.items.filter(i => i.type === typeName);
+ }
//~~~~~~~~~~~~~~~~~~~~~~~~~ OLD CODE BELOW ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -806,24 +821,36 @@ export default class GSActorSheet extends ActorSheet{
const skill = this.actor.items.get(skillId);
const skipCheck = ['Draconic Heritage', 'Beloved of the Fae', 'Darkvision', 'Faith: Supreme God', 'Faith: Earth Mother',
'Faith: Trade God', 'Faith: God of Knowledge', 'Faith: Valkyrie', 'Faith: Ancestral Dragon'];
+ const supplementGenSkills = ['Herbalist', 'Miner'];
+ // If Gen skills to be skipped are found, return and stop from rolling dice
if(skipCheck.includes(skill.name)) return;
if(skill.name.toLowerCase() === 'long-distance movement')
- this._specialRolls(event, 'longDistance', 'Long-Distance Movement');
+ this._specialRolls('longDistance', 'Long-Distance Movement');
else if(skill.name.toLowerCase() === 'general knowledge')
- this._specialRolls(event, 'generalKnow', 'General Knowledge');
+ this._specialRolls('generalKnow', 'General Knowledge');
else if(skill.name.toLowerCase() === 'cool and collected'){
const resistType = await this._promptMiscModChoice('coolAndCollected');
- this._specialRolls(event, resistType === "int" ? "intRes" : "psyRes", "default");
+ this._specialRolls(resistType === "int" ? "intRes" : "psyRes", "default");
+ }else if(supplementGenSkills.includes(skill.name)){
+ let promptChoices = await this._promptMiscModChoice(skill.name);
+ if(promptChoices === 'Observe')
+ this._specialRolls('observe', 'Observe', skill);
+ else if(promptChoices === 'Sixth Sense')
+ this._specialRolls('sixthSense', 'Sixth Sense', skill);
+ else if(promptChoices === 'General Knowledge')
+ this._specialRolls('generalKnow', 'General Knowledge', skill);
}else{
let promptChoices = await this._promptMiscModChoice(skill.name);
if(promptChoices){
let skillBonus = this._getSkillBonus(skill.name);
- skillBonus = skillBonus === 3 ? 4 : skillBonus;
+ if(skill.name === 'Sacrament of Forgiveness')
+ skillBonus -= 1;
+ else
+ skillBonus = skillBonus === 3 ? 4 : skillBonus;
promptChoices[5] = skillBonus;
promptChoices[6] = skill;
- console.log('... checking promptChoices', promptChoices);
this._genRollsToWindow(promptChoices);
}else{
ui.notifications.warn(`${game.i18n.localize('gs.dialog.genSkills.cancelled')}`);
@@ -881,7 +908,7 @@ export default class GSActorSheet extends ActorSheet{
* @returns The value (level) of the given skill
*/
_getSkillBonus(skillName){
- const skills = this.actor.items.filter(i => i.type === 'skill');
+ const skills = this._getFromItemsList('skill');
let skillValue = 0;
skills.forEach(s => {
if(s.name.toLowerCase() === skillName.toLowerCase()){
@@ -1051,7 +1078,7 @@ export default class GSActorSheet extends ActorSheet{
// Checking actor type to get skills
if(actorType === "character"){
- skills = this.actor.items.filter(item => item.type === 'skill');
+ skills = this._getFromItemsList('skill');
// Updating the Critical Success/Failure rate based on the given skill
const setSuccessFailValues = (skillValue) => {
@@ -1165,7 +1192,7 @@ export default class GSActorSheet extends ActorSheet{
}
// Checking skills for Piercing Attack skill and weapon
- const skills = this.actor.items.filter(item => item.type === 'skill');
+ const skills = this._getFromItemsList('skill');
// Getting Weapon ID to check for Piercing trait
let eventID;
if(event)
@@ -1428,7 +1455,7 @@ export default class GSActorSheet extends ActorSheet{
classBonus = bonus;
if(classBonus > 0) localizedMessage += this._addToFlavorMessage("levelScore", className, classBonus);
- skills = this.actor.items.filter(item => item.type === 'skill');
+ skills = this._getFromItemsList('skill');
if(modSelector === '.power'){
const {dice, mod} = this._parseDiceNotation(diceNotation);
diceToRoll = dice;
@@ -1467,8 +1494,8 @@ export default class GSActorSheet extends ActorSheet{
}else if(modSelector === '.spellDif'){
const spellID = container.dataset.id;
const spell = this.actor.items.get(spellID);
- const skills = this.actor.items.filter(item => item.type === 'skill');
- const items = this.actor.items.filter(item => item.type === 'item');
+ const skills = this._getFromItemsList('skill');
+ const items = this._getFromItemsList('item');
// Checking if a Shaman spell and has Shaman's Bag or Beloved of the Fae skill
if(spell.system.schoolChoice === "Spirit Arts"){
let belovedSkill = this.actor.items.find(i => i.name === "Beloved of the Fae");
@@ -1720,7 +1747,7 @@ export default class GSActorSheet extends ActorSheet{
* @returns Updated modifier and localized message
*/
_calculateDodgeModifier(modifier, skills, localizedMessage){
- const armor = this.actor.items.filter(item => item.type === 'armor');
+ const armor = this._getFromItemsList('armor');
const strEnd = this.actor.system.abilities.calc.se;
const {monk, scout, fighter} = this.actor.system.levels.classes;
@@ -1732,8 +1759,8 @@ export default class GSActorSheet extends ActorSheet{
// Helper function to return bonus Parry values on gear
const checkGear = (skill) => {
- const shield = this.actor.items.filter(item => item.type === 'shield');
- const weapons = this.actor.items.filter(item => item.type === 'weapon');
+ const shield = this._getFromItemsList('shield');
+ const weapons = this._getFromItemsList('weapon');
let highestParry = 0, highestWeapon = 0;
shield.forEach(item => {
@@ -2023,7 +2050,7 @@ export default class GSActorSheet extends ActorSheet{
const halfLifeForce = Math.round(systemData.lifeForce.double / 2);
healThisAmount(systemData.lifeForce.wounds - halfLifeForce);
}else if(healType === 'healing'){
- const skills = this.actor.items.filter(item => item.type === 'skill');
+ const skills = this._getFromItemsList('skill');
let skillMod = 0;
for(const skill of skills){
@@ -2043,6 +2070,7 @@ export default class GSActorSheet extends ActorSheet{
* @param {*} event The click event
*/
async _actorRolls(event){
+ event.preventDefault();
const cssClassType = event.currentTarget.classList;
const classType = cssClassType[1];
@@ -2077,7 +2105,7 @@ export default class GSActorSheet extends ActorSheet{
this._toggleCombatState(event, this.actor);
// this._rollInitiative(event);
} else if (specialRolls.includes(classType)) {
- this._specialRolls(event, classType, classType.charAt(0).toUpperCase() + classType.slice(1).replace(/([A-Z])/g, ' $1').trim());
+ this._specialRolls(classType, classType.charAt(0).toUpperCase() + classType.slice(1).replace(/([A-Z])/g, ' $1').trim());
} else if (fateButtons.includes(classType)){
this._fateAdjustment(event, classType);
} else if (resting.includes(classType)) {
@@ -2187,8 +2215,10 @@ export default class GSActorSheet extends ActorSheet{
'Cooking', 'Craftsmanship', 'Criminal Knowledge', 'Etiquette', 'Labor', 'Leadership', 'Meditate', 'Negotiate: Persuade', 'Negotiate: Tempt',
'Negotiate: Intimidate', 'No Preconceptions', 'Perform: Sing', 'Perform: Play', 'Perform: Dance', 'Perform: Street Perform', 'Perform: Act',
'Production: Farming', 'Production: Fishing', 'Production: Logging', 'Production: Mining', 'Research', 'Riding', 'Survivalism ', 'Theology',
- 'Worship', 'Cartography'];
+ 'Worship', 'Cartography', 'Nurse', 'Sacrament of Forgiveness'];
const specialRolls = ['moveRes', 'strRes', 'psyRes', 'intRes', 'strength', 'stealth', 'acrobatics', 'monsterKnow'];
+ const supplementGenSkills = ['Herbalist', 'Miner'];
+ const thirdButtonNames = ['stealth', 'acrobatics', 'Herbalist', 'Miner'];
const addModifiersSection = () => {
return `
${game.i18n.localize("gs.dialog.mods.addInfo")}
@@ -2308,7 +2338,7 @@ export default class GSActorSheet extends ActorSheet{
};
break;
case 'returnSpell':
- const spells = this.actor.items.filter(item => item.type === 'spell');
+ const spells = this._getFromItemsList('spell');
const header1 = game.i18n.localize(`gs.dialog.spellMaint.header`);
promptTitle = game.i18n.localize(`gs.dialog.spellMaint.title`);
dialogContent = `${header1}
`;
@@ -2355,6 +2385,7 @@ export default class GSActorSheet extends ActorSheet{
resolve(0);
}
};
+ break;
default:
break;
}
@@ -2424,6 +2455,8 @@ export default class GSActorSheet extends ActorSheet{
"Theology": { first: 'i', second: 'none', class: 'priest/dragon' },
"Worship": { first: 'p', second: 'none', class: 'priest/dragon' },
"Cartography": { first: 'i', second: 'none', class: 'scout' },
+ "Nurse": { first: 'i', second: 'none', class: 'none' },
+ "Sacrament of Forgiveness": { first: 'i', second: 'none', class: 'priest/dragon' },
};
let header = game.i18n.localize(`gs.dialog.genSkills.header`) + promptType;
dialogContent = `${header}
`;
@@ -2508,7 +2541,6 @@ export default class GSActorSheet extends ActorSheet{
else if(primaryAbility === 'p')
settingItems('psy', primaryAbility, secondaryAbility);
- console.log('... checking classNames', classNames);
classNames = classNames.includes("/") ? classNames.split("/") : classNames;
let tempName = '';
for(let x = 0; x < classNames.length; x++){
@@ -2533,11 +2565,33 @@ export default class GSActorSheet extends ActorSheet{
label: game.i18n.localize('gs.dialog.cancel'),
callback: () => resolve(0)
};
+ }else if(supplementGenSkills.includes(promptType)){
+ promptTitle = promptType + game.i18n.localize('gs.dialog.herbalist.title');
+ dialogContent = `${game.i18n.localize('gs.dialog.herbalist.header')}
+ ${game.i18n.localize('gs.dialog.herbalist.body')}${promptType}
`;
+ button1 = {
+ label: game.i18n.localize('gs.dialog.herbalist.button1'),
+ callback: () => {
+ resolve(game.i18n.localize('gs.dialog.herbalist.button1'));
+ }
+ };
+ button2 = {
+ label: game.i18n.localize('gs.dialog.herbalist.button2'),
+ callback: () => {
+ resolve(game.i18n.localize('gs.dialog.herbalist.button2'));
+ }
+ };
+ button3 = {
+ label: game.i18n.localize('gs.dialog.herbalist.button3'),
+ callback: () => {
+ resolve(game.i18n.localize('gs.dialog.herbalist.button3'));
+ }
+ };
}
if(promptType != 'returnSpell')
buttons = { button1: button1, buttonTwo: button2 };
- if(promptType === 'stealth' || promptType === 'acrobatics')
+ if(thirdButtonNames.includes(promptType))
buttons.button3 = button3;
new Dialog({
@@ -2644,7 +2698,7 @@ export default class GSActorSheet extends ActorSheet{
await roll.toMessage({
speaker: ChatMessage.getSpeaker({actor: this.actor}),
- flavor: `${game.i18n.localize("gs.dialog.rolling")} ${flavorMessage} ${status[1]}`,
+ flavor: `${flavorMessage} ${status[1]}`,
});
} catch (error) {
console.error("Error evaluating roll:", error);
@@ -2656,8 +2710,8 @@ export default class GSActorSheet extends ActorSheet{
* @param {string} rollType The type of roll being made
* @returns Highest class level associated with the roll, if any
*/
- _specialRollsClassBonus(rollType, dialogMessage){
- let classBonus = 0, selectedClass = "";
+ _specialRollsClassBonus(rollType){
+ let classBonus = 0, selectedClass = "", dialogMessage = '';
switch(rollType){
case 'luck': case 'swim': case 'strRes': case 'longDistance': case 'tacMove': return {classBonus, dialogMessage};
case 'psyRes': case 'intRes':
@@ -2666,10 +2720,10 @@ export default class GSActorSheet extends ActorSheet{
console.log('>>> AdvLevel & Dragon Level', advLevel, dragonLevel);
if(advLevel >= dragonLevel){
classBonus = parseInt(advLevel, 10);
- dialogMessage += `${game.i18n.localize('gs.actor.character.lvl')}: ${classBonus}
`;
+ dialogMessage += this._addToFlavorMessage('levelScore', game.i18n.localize('gs.actor.character.lvl'), classBonus);
}else{
classBonus = parseInt(dragonLevel, 10);
- dialogMessage += `${game.i18n.localize('gs.actor.character.dPri')}: ${classBonus}
`;
+ dialogMessage += this._addToFlavorMessage('levelScore', game.i18n.localize('gs.actor.character.dPri'), classBonus);
}
return {classBonus, dialogMessage};
}
@@ -2712,7 +2766,7 @@ export default class GSActorSheet extends ActorSheet{
console.error(`GS _specialRollsClassBonus || Unknown roll type: ${rollType}`);
}
- dialogMessage += `${game.i18n.localize(selectedClass)}: ${classBonus}
`;
+ dialogMessage += this._addToFlavorMessage('levelScore', game.i18n.localize(selectedClass), classBonus);
return {classBonus, dialogMessage};
}
@@ -2737,14 +2791,14 @@ export default class GSActorSheet extends ActorSheet{
/**
* Sorts the special roll from the character sheet side bar and helps get all associated bonuses for this roll check
- * @param {*} event The event of the click
* @param {string} rollType The type of roll being made, must be lowercase
* @param {string} skillName The skill associated with the roll for any applicable bonus
+ * @param {JSON} extraSkill This is an extra skill modifier, currently only used with the herbalist skill, otherwise leave blank
*/
- async _specialRolls(event, rollType, skillName){
- event.preventDefault();
- let abilityScore = 0, dice = '2d6', classBonus = 0, maintainedSpell, spellTypeMaintained;
- let dialogMessage = game.i18n.localize(`gs.dialog.actorSheet.sidebar.buttons.${rollType}`);
+ async _specialRolls(rollType, skillName, extraSkill = null){
+ let abilityScore = 0, dice = '2d6', classBonus = 0, maintainedSpell, spellTypeMaintained, abilityName = '';
+ const fakeSkill = { name: skillName };
+ let chatMessage = this._setMessageHeader(this.actor, fakeSkill, game.i18n.localize('gs.dialog.skillCheck'));
const intelligenceFocusChecks = ['generalKnow', 'magicalKnow', 'observe', 'tacMove'];
const intelligenceReflexChecks = ['sixthSense'];
const intelligenceEduranceChecks = [];
@@ -2756,9 +2810,22 @@ export default class GSActorSheet extends ActorSheet{
const techniqueFocusChecks = ['firstAid', 'handiwork', 'swim', 'climbF', 'jump'];
const adventurerLevel = ['swim', 'strRes', 'longDistance', 'tacMove'];
const specialPrompts = ['moveRes', 'strRes', 'psyRes', 'intRes', 'strength', 'stealth', 'monsterKnow', 'acrobatics'];
+ const abilityMapping = {
+ ir: intelligenceReflexChecks, if: intelligenceFocusChecks, ie: intelligenceEduranceChecks,
+ tf: techniqueFocusChecks, pr: psycheReflexChecks, pe: pyscheEnduranceChecks,
+ sr: strengthReflexChecks, se: strengthEnduranceChecks, sf: strengthFocusChecks
+ };
+ const abilityNames = {
+ ir: game.i18n.localize('gs.actor.character.intRef'), if: game.i18n.localize('gs.actor.character.intFoc'), ie: game.i18n.localize('gs.actor.character.intEnd'),
+ tf: game.i18n.localize('gs.actor.character.tecFoc'), pr: game.i18n.localize('gs.actor.character.psyRef'), pe: game.i18n.localize('gs.actor.character.psyEnd'),
+ sr: game.i18n.localize('gs.actor.character.strRef'), se: game.i18n.localize('gs.actor.character.strEnd'), sf: game.i18n.localize('gs.actor.character.strFoc')
+ }
+
+ // Sending standard dice to chat message
+ chatMessage += this._addToFlavorMessage('diceInfo', game.i18n.localize('gs.dialog.dice'), dice);
if(rollType === 'spellMaint'){
- maintainedSpell = await this._promptMiscModChoice('returnSpell', dialogMessage);
+ maintainedSpell = await this._promptMiscModChoice('returnSpell', chatMessage);
const maintainedSpellSchool = maintainedSpell.system.schoolChoice.toLowerCase();
spellTypeMaintained = maintainedSpell.system.styleChoice.toLowerCase();
maintainedSpellSchool === 'words of true power' ? (intelligenceEduranceChecks.push('spellMaintI'), rollType = "spellMaintI")
@@ -2767,35 +2834,36 @@ export default class GSActorSheet extends ActorSheet{
: (pyscheEnduranceChecks.push('spellMaintPs'), rollType="spellMaintPs");
}
- const abilityMapping = {
- ir: intelligenceReflexChecks, if: intelligenceFocusChecks, ie: intelligenceEduranceChecks,
- tf: techniqueFocusChecks, pr: psycheReflexChecks, pe: pyscheEnduranceChecks,
- sr: strengthReflexChecks, se: strengthEnduranceChecks, sf: strengthFocusChecks
- };
+ // Checking if RollType is found in ability mapping and subsequently getting ability name from key
for (const [key, checks] of Object.entries(abilityMapping)){
if(checks.includes(rollType)){
abilityScore = this._findTheCalcAbilityScore(key);
+ abilityName = abilityNames[key];
break;
}
}
+
+ // Updating ability score to that of the Special Prompts array
if(specialPrompts.includes(rollType)){
- abilityScore = await this._promptMiscModChoice(rollType, dialogMessage);
+ abilityScore = await this._promptMiscModChoice(rollType);
+ abilityName = skillName;
}
- dialogMessage += `${game.i18n.localize('gs.actor.character.abil')}: ${abilityScore}
`;
- console.log(">> from genskill to specail roll", event, rollType, skillName);
+ // Adding ability scores to chat message
+ chatMessage += this._addToFlavorMessage('abilScore', abilityName, abilityScore);
+
// Getting class bonus or adventurer level in certain cases.
- const {classBonus: cBonus, dialogMessage: dMessage} = this._specialRollsClassBonus(rollType, dialogMessage);
+ const {classBonus: cBonus, dialogMessage: dMessage} = this._specialRollsClassBonus(rollType, chatMessage);
classBonus += cBonus;
- dialogMessage = dMessage;
+ chatMessage += dMessage;
if(adventurerLevel.includes(rollType)){
- classBonus = this._getAdventurerLevel(dialogMessage);
+ classBonus = this._getAdventurerLevel(chatMessage);
if(classBonus > 0)
- dialogMessage += `${game.i18n.localize('gs.actor.common.leve')}: ${classBonus}
`;
+ chatMessage += this._addToFlavorMessage('levelScore', game.i18n.localize('gs.actor.common.leve'), classBonus);
}
// Getting misc modifiers such as circumstance bonuses or terrain disadvantages and etc.
- const rollMod = await this._promptMiscModChoice("rollMod", dialogMessage);
+ const rollMod = await this._promptMiscModChoice("rollMod", game.i18n.localize('gs.dialog.random'));
// Updating skillName when special roll != skill name
switch(rollType){
@@ -2831,6 +2899,7 @@ export default class GSActorSheet extends ActorSheet{
// Getting skill bonus
let skillBonus = this._getSkillBonus(skillName);
+
// Correcting skill bonuses here as needed
if(rollType === 'provoke' || (rollType === 'tacMove' && skillBonus != 0)) skillBonus -= 1;
else if(rollType === 'moveObs') skillBonus += 1;
@@ -2838,15 +2907,29 @@ export default class GSActorSheet extends ActorSheet{
else if(rollType === 'generalKnow' || rollType === 'longDistance')
skillBonus = skillBonus === 3 ? 4 : skillBonus;
+ // Helper function for the next section
+ const addExtraSkillInfo = (extraSkill) => {
+ let skillValue = extraSkill.system.value < 3 ? extraSkill.system.value : 4
+ chatMessage += this._addToFlavorMessage('skillScore', extraSkill.name, skillValue);
+ skillBonus += skillValue;
+ }
+
if(skillBonus > 0)
- dialogMessage += `${game.i18n.localize('gs.actor.character.skills')}: ${skillBonus}
`;
+ chatMessage += this._addToFlavorMessage('skillScore', skillName, skillBonus);
+ if((rollType === 'observe' || rollType === 'sixthSense' || rollType === 'generalKnow') && extraSkill)
+ addExtraSkillInfo(extraSkill);
+ if(rollType === 'firstAid'){
+ const skills = this._getFromItemsList('skill');
+ const nurseSkill = skills.find(s => s.name === "Nurse") || 0;
+ if(nurseSkill)
+ addExtraSkillInfo(nurseSkill);
+ }
if(rollMod > 0)
- dialogMessage += `${game.i18n.localize('gs.dialog.mods.mod')}: ${rollMod}
`;
+ chatMessage += this._addToFlavorMessage('rollScore', game.i18n.localize('gs.dialog.mods.mod'), rollMod);
- //console.log("=== Checking", dice, abilityScore, classBonus, skillBonus, rollMod);
const rollMessage = this._setRollMessage(dice, abilityScore, classBonus, skillBonus, rollMod);
- this._sendRollMessage(rollMessage, dialogMessage, maintainedSpell ? maintainedSpell : "");
+ this._sendRollMessage(rollMessage, chatMessage, maintainedSpell ? maintainedSpell : "");
}
// Pushing all items from embedded documents into top level objects for ease of use
diff --git a/packs/armor/000474.log b/packs/armor/000476.log
similarity index 100%
rename from packs/armor/000474.log
rename to packs/armor/000476.log
diff --git a/packs/armor/CURRENT b/packs/armor/CURRENT
index 104ad81..b79af71 100644
--- a/packs/armor/CURRENT
+++ b/packs/armor/CURRENT
@@ -1 +1 @@
-MANIFEST-000473
+MANIFEST-000475
diff --git a/packs/armor/LOG b/packs/armor/LOG
index aeb0c8f..f41c078 100644
--- a/packs/armor/LOG
+++ b/packs/armor/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.655 c48 Recovering log #472
-2024/09/10-11:28:26.658 c48 Delete type=0 #472
-2024/09/10-11:28:26.658 c48 Delete type=3 #471
+2024/09/11-11:37:16.651 2994 Recovering log #474
+2024/09/11-11:37:16.653 2994 Delete type=0 #474
+2024/09/11-11:37:16.653 2994 Delete type=3 #473
diff --git a/packs/armor/LOG.old b/packs/armor/LOG.old
index 101d955..aeb0c8f 100644
--- a/packs/armor/LOG.old
+++ b/packs/armor/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.187 4814 Delete type=3 #1
+2024/09/10-11:28:26.655 c48 Recovering log #472
+2024/09/10-11:28:26.658 c48 Delete type=0 #472
+2024/09/10-11:28:26.658 c48 Delete type=3 #471
diff --git a/packs/armor/MANIFEST-000473 b/packs/armor/MANIFEST-000475
similarity index 51%
rename from packs/armor/MANIFEST-000473
rename to packs/armor/MANIFEST-000475
index 4ac2280..1b69e2f 100644
Binary files a/packs/armor/MANIFEST-000473 and b/packs/armor/MANIFEST-000475 differ
diff --git a/packs/spells/000481.log b/packs/items/000481.log
similarity index 100%
rename from packs/spells/000481.log
rename to packs/items/000481.log
diff --git a/packs/items/CURRENT b/packs/items/CURRENT
index 511a4db..a2f5062 100644
--- a/packs/items/CURRENT
+++ b/packs/items/CURRENT
@@ -1 +1 @@
-MANIFEST-000478
+MANIFEST-000480
diff --git a/packs/items/LOG b/packs/items/LOG
index c0f3eb8..7bc1066 100644
--- a/packs/items/LOG
+++ b/packs/items/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.610 d7c Recovering log #477
-2024/09/10-11:28:26.612 d7c Delete type=0 #477
-2024/09/10-11:28:26.613 d7c Delete type=3 #476
+2024/09/11-11:37:16.608 4604 Recovering log #479
+2024/09/11-11:37:16.610 4604 Delete type=0 #479
+2024/09/11-11:37:16.611 4604 Delete type=3 #478
diff --git a/packs/items/LOG.old b/packs/items/LOG.old
index fce1186..c0f3eb8 100644
--- a/packs/items/LOG.old
+++ b/packs/items/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.119 1c88 Delete type=3 #1
+2024/09/10-11:28:26.610 d7c Recovering log #477
+2024/09/10-11:28:26.612 d7c Delete type=0 #477
+2024/09/10-11:28:26.613 d7c Delete type=3 #476
diff --git a/packs/items/MANIFEST-000478 b/packs/items/MANIFEST-000480
similarity index 50%
rename from packs/items/MANIFEST-000478
rename to packs/items/MANIFEST-000480
index 5ffce02..ee9cd2f 100644
Binary files a/packs/items/MANIFEST-000478 and b/packs/items/MANIFEST-000480 differ
diff --git a/packs/items/000479.log b/packs/martialtechniques/000093.log
similarity index 100%
rename from packs/items/000479.log
rename to packs/martialtechniques/000093.log
diff --git a/packs/martialtechniques/CURRENT b/packs/martialtechniques/CURRENT
index 2f2c868..5b83d76 100644
--- a/packs/martialtechniques/CURRENT
+++ b/packs/martialtechniques/CURRENT
@@ -1 +1 @@
-MANIFEST-000090
+MANIFEST-000092
diff --git a/packs/martialtechniques/LOG b/packs/martialtechniques/LOG
index dbc7769..949706e 100644
--- a/packs/martialtechniques/LOG
+++ b/packs/martialtechniques/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.696 c64 Recovering log #89
-2024/09/10-11:28:26.698 c64 Delete type=0 #89
-2024/09/10-11:28:26.699 c64 Delete type=3 #88
+2024/09/11-11:37:16.692 f60 Recovering log #91
+2024/09/11-11:37:16.694 f60 Delete type=0 #91
+2024/09/11-11:37:16.695 f60 Delete type=3 #90
diff --git a/packs/martialtechniques/LOG.old b/packs/martialtechniques/LOG.old
index e5849ca..dbc7769 100644
--- a/packs/martialtechniques/LOG.old
+++ b/packs/martialtechniques/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.257 1c88 Delete type=3 #1
+2024/09/10-11:28:26.696 c64 Recovering log #89
+2024/09/10-11:28:26.698 c64 Delete type=0 #89
+2024/09/10-11:28:26.699 c64 Delete type=3 #88
diff --git a/packs/martialtechniques/MANIFEST-000090 b/packs/martialtechniques/MANIFEST-000092
similarity index 52%
rename from packs/martialtechniques/MANIFEST-000090
rename to packs/martialtechniques/MANIFEST-000092
index cba9753..9ec17b4 100644
Binary files a/packs/martialtechniques/MANIFEST-000090 and b/packs/martialtechniques/MANIFEST-000092 differ
diff --git a/packs/martialtechniques/000091.log b/packs/monsters/000491.log
similarity index 100%
rename from packs/martialtechniques/000091.log
rename to packs/monsters/000491.log
diff --git a/packs/monsters/CURRENT b/packs/monsters/CURRENT
index 527a905..3b626ee 100644
--- a/packs/monsters/CURRENT
+++ b/packs/monsters/CURRENT
@@ -1 +1 @@
-MANIFEST-000488
+MANIFEST-000490
diff --git a/packs/monsters/LOG b/packs/monsters/LOG
index 8ef19d5..09a0bb4 100644
--- a/packs/monsters/LOG
+++ b/packs/monsters/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.628 c64 Recovering log #487
-2024/09/10-11:28:26.630 c64 Delete type=0 #487
-2024/09/10-11:28:26.631 c64 Delete type=3 #486
+2024/09/11-11:37:16.624 f60 Recovering log #489
+2024/09/11-11:37:16.627 f60 Delete type=0 #489
+2024/09/11-11:37:16.628 f60 Delete type=3 #488
diff --git a/packs/monsters/LOG.old b/packs/monsters/LOG.old
index bebbeac..8ef19d5 100644
--- a/packs/monsters/LOG.old
+++ b/packs/monsters/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.150 4814 Delete type=3 #1
+2024/09/10-11:28:26.628 c64 Recovering log #487
+2024/09/10-11:28:26.630 c64 Delete type=0 #487
+2024/09/10-11:28:26.631 c64 Delete type=3 #486
diff --git a/packs/monsters/MANIFEST-000488 b/packs/monsters/MANIFEST-000490
similarity index 50%
rename from packs/monsters/MANIFEST-000488
rename to packs/monsters/MANIFEST-000490
index 776c082..180367d 100644
Binary files a/packs/monsters/MANIFEST-000488 and b/packs/monsters/MANIFEST-000490 differ
diff --git a/packs/monsters/000489.log b/packs/mounts/000080.log
similarity index 100%
rename from packs/monsters/000489.log
rename to packs/mounts/000080.log
diff --git a/packs/mounts/CURRENT b/packs/mounts/CURRENT
index c7a124b..dad8bc0 100644
--- a/packs/mounts/CURRENT
+++ b/packs/mounts/CURRENT
@@ -1 +1 @@
-MANIFEST-000077
+MANIFEST-000079
diff --git a/packs/mounts/LOG b/packs/mounts/LOG
index 64eb313..1e6233f 100644
--- a/packs/mounts/LOG
+++ b/packs/mounts/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.638 30b4 Recovering log #76
-2024/09/10-11:28:26.641 30b4 Delete type=0 #76
-2024/09/10-11:28:26.641 30b4 Delete type=3 #75
+2024/09/11-11:37:16.635 3ce4 Recovering log #78
+2024/09/11-11:37:16.637 3ce4 Delete type=0 #78
+2024/09/11-11:37:16.638 3ce4 Delete type=3 #77
diff --git a/packs/mounts/LOG.old b/packs/mounts/LOG.old
index 81258e0..64eb313 100644
--- a/packs/mounts/LOG.old
+++ b/packs/mounts/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.166 44e0 Delete type=3 #1
+2024/09/10-11:28:26.638 30b4 Recovering log #76
+2024/09/10-11:28:26.641 30b4 Delete type=0 #76
+2024/09/10-11:28:26.641 30b4 Delete type=3 #75
diff --git a/packs/mounts/MANIFEST-000077 b/packs/mounts/MANIFEST-000079
similarity index 55%
rename from packs/mounts/MANIFEST-000077
rename to packs/mounts/MANIFEST-000079
index 5575901..f0ed5ef 100644
Binary files a/packs/mounts/MANIFEST-000077 and b/packs/mounts/MANIFEST-000079 differ
diff --git a/packs/mounts/000078.log b/packs/races/000465.log
similarity index 100%
rename from packs/mounts/000078.log
rename to packs/races/000465.log
diff --git a/packs/races/CURRENT b/packs/races/CURRENT
index dd4dce9..22a6199 100644
--- a/packs/races/CURRENT
+++ b/packs/races/CURRENT
@@ -1 +1 @@
-MANIFEST-000462
+MANIFEST-000464
diff --git a/packs/races/LOG b/packs/races/LOG
index 6fcaa1e..73991b7 100644
--- a/packs/races/LOG
+++ b/packs/races/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.679 d7c Recovering log #461
-2024/09/10-11:28:26.681 d7c Delete type=0 #461
-2024/09/10-11:28:26.682 d7c Delete type=3 #460
+2024/09/11-11:37:16.675 4604 Recovering log #463
+2024/09/11-11:37:16.677 4604 Delete type=0 #463
+2024/09/11-11:37:16.677 4604 Delete type=3 #462
diff --git a/packs/races/LOG.old b/packs/races/LOG.old
index 218aae9..6fcaa1e 100644
--- a/packs/races/LOG.old
+++ b/packs/races/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.227 4814 Delete type=3 #1
+2024/09/10-11:28:26.679 d7c Recovering log #461
+2024/09/10-11:28:26.681 d7c Delete type=0 #461
+2024/09/10-11:28:26.682 d7c Delete type=3 #460
diff --git a/packs/races/MANIFEST-000462 b/packs/races/MANIFEST-000464
similarity index 51%
rename from packs/races/MANIFEST-000462
rename to packs/races/MANIFEST-000464
index 5760f37..074db85 100644
Binary files a/packs/races/MANIFEST-000462 and b/packs/races/MANIFEST-000464 differ
diff --git a/packs/races/000463.log b/packs/rollTables/000239.log
similarity index 100%
rename from packs/races/000463.log
rename to packs/rollTables/000239.log
diff --git a/packs/rollTables/CURRENT b/packs/rollTables/CURRENT
index 470e565..4846f49 100644
--- a/packs/rollTables/CURRENT
+++ b/packs/rollTables/CURRENT
@@ -1 +1 @@
-MANIFEST-000236
+MANIFEST-000238
diff --git a/packs/rollTables/LOG b/packs/rollTables/LOG
index dfe9d3f..aad73bf 100644
--- a/packs/rollTables/LOG
+++ b/packs/rollTables/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.603 30b4 Recovering log #235
-2024/09/10-11:28:26.605 30b4 Delete type=0 #235
-2024/09/10-11:28:26.606 30b4 Delete type=3 #234
+2024/09/11-11:37:16.599 3ce4 Recovering log #237
+2024/09/11-11:37:16.602 3ce4 Delete type=0 #237
+2024/09/11-11:37:16.602 3ce4 Delete type=3 #236
diff --git a/packs/rollTables/LOG.old b/packs/rollTables/LOG.old
index 3d0c4a4..dfe9d3f 100644
--- a/packs/rollTables/LOG.old
+++ b/packs/rollTables/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.103 4814 Delete type=3 #1
+2024/09/10-11:28:26.603 30b4 Recovering log #235
+2024/09/10-11:28:26.605 30b4 Delete type=0 #235
+2024/09/10-11:28:26.606 30b4 Delete type=3 #234
diff --git a/packs/rollTables/MANIFEST-000236 b/packs/rollTables/MANIFEST-000238
similarity index 85%
rename from packs/rollTables/MANIFEST-000236
rename to packs/rollTables/MANIFEST-000238
index 1fc0d96..b22aa98 100644
Binary files a/packs/rollTables/MANIFEST-000236 and b/packs/rollTables/MANIFEST-000238 differ
diff --git a/packs/rollTables/000237.log b/packs/rules/000403.log
similarity index 100%
rename from packs/rollTables/000237.log
rename to packs/rules/000403.log
diff --git a/packs/rules/CURRENT b/packs/rules/CURRENT
index 9e7a9e4..dfb5e64 100644
--- a/packs/rules/CURRENT
+++ b/packs/rules/CURRENT
@@ -1 +1 @@
-MANIFEST-000400
+MANIFEST-000402
diff --git a/packs/rules/LOG b/packs/rules/LOG
index f2e9083..a83d754 100644
--- a/packs/rules/LOG
+++ b/packs/rules/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.686 c48 Recovering log #399
-2024/09/10-11:28:26.689 c48 Delete type=0 #399
-2024/09/10-11:28:26.689 c48 Delete type=3 #398
+2024/09/11-11:37:16.683 2994 Recovering log #401
+2024/09/11-11:37:16.686 2994 Delete type=0 #401
+2024/09/11-11:37:16.686 2994 Delete type=3 #400
diff --git a/packs/rules/LOG.old b/packs/rules/LOG.old
index ce9590c..f2e9083 100644
--- a/packs/rules/LOG.old
+++ b/packs/rules/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.237 44e0 Delete type=3 #1
+2024/09/10-11:28:26.686 c48 Recovering log #399
+2024/09/10-11:28:26.689 c48 Delete type=0 #399
+2024/09/10-11:28:26.689 c48 Delete type=3 #398
diff --git a/packs/rules/MANIFEST-000400 b/packs/rules/MANIFEST-000402
similarity index 84%
rename from packs/rules/MANIFEST-000400
rename to packs/rules/MANIFEST-000402
index 1dbe9e5..ef14a5a 100644
Binary files a/packs/rules/MANIFEST-000400 and b/packs/rules/MANIFEST-000402 differ
diff --git a/packs/rules/000401.log b/packs/shields/000471.log
similarity index 100%
rename from packs/rules/000401.log
rename to packs/shields/000471.log
diff --git a/packs/shields/CURRENT b/packs/shields/CURRENT
index f11dd62..65eef60 100644
--- a/packs/shields/CURRENT
+++ b/packs/shields/CURRENT
@@ -1 +1 @@
-MANIFEST-000468
+MANIFEST-000470
diff --git a/packs/shields/LOG b/packs/shields/LOG
index 2abe2fc..e391444 100644
--- a/packs/shields/LOG
+++ b/packs/shields/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.672 30b4 Recovering log #467
-2024/09/10-11:28:26.675 30b4 Delete type=0 #467
-2024/09/10-11:28:26.675 30b4 Delete type=3 #466
+2024/09/11-11:37:16.667 3ce4 Recovering log #469
+2024/09/11-11:37:16.669 3ce4 Delete type=0 #469
+2024/09/11-11:37:16.669 3ce4 Delete type=3 #468
diff --git a/packs/shields/LOG.old b/packs/shields/LOG.old
index d8b6560..2abe2fc 100644
--- a/packs/shields/LOG.old
+++ b/packs/shields/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.217 1c88 Delete type=3 #1
+2024/09/10-11:28:26.672 30b4 Recovering log #467
+2024/09/10-11:28:26.675 30b4 Delete type=0 #467
+2024/09/10-11:28:26.675 30b4 Delete type=3 #466
diff --git a/packs/shields/MANIFEST-000468 b/packs/shields/MANIFEST-000470
similarity index 51%
rename from packs/shields/MANIFEST-000468
rename to packs/shields/MANIFEST-000470
index 71f1894..9264d8a 100644
Binary files a/packs/shields/MANIFEST-000468 and b/packs/shields/MANIFEST-000470 differ
diff --git a/packs/shields/000469.log b/packs/skills/000486.log
similarity index 100%
rename from packs/shields/000469.log
rename to packs/skills/000486.log
diff --git a/packs/skills/CURRENT b/packs/skills/CURRENT
index b3a90ab..03b905b 100644
--- a/packs/skills/CURRENT
+++ b/packs/skills/CURRENT
@@ -1 +1 @@
-MANIFEST-000483
+MANIFEST-000485
diff --git a/packs/skills/LOG b/packs/skills/LOG
index 68f3d04..7e7f8be 100644
--- a/packs/skills/LOG
+++ b/packs/skills/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.647 d7c Recovering log #482
-2024/09/10-11:28:26.649 d7c Delete type=0 #482
-2024/09/10-11:28:26.649 d7c Delete type=3 #481
+2024/09/11-11:37:16.643 4604 Recovering log #484
+2024/09/11-11:37:16.645 4604 Delete type=0 #484
+2024/09/11-11:37:16.645 4604 Delete type=3 #483
diff --git a/packs/skills/LOG.old b/packs/skills/LOG.old
index 18d7929..68f3d04 100644
--- a/packs/skills/LOG.old
+++ b/packs/skills/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.177 1c88 Delete type=3 #1
+2024/09/10-11:28:26.647 d7c Recovering log #482
+2024/09/10-11:28:26.649 d7c Delete type=0 #482
+2024/09/10-11:28:26.649 d7c Delete type=3 #481
diff --git a/packs/skills/MANIFEST-000483 b/packs/skills/MANIFEST-000485
similarity index 50%
rename from packs/skills/MANIFEST-000483
rename to packs/skills/MANIFEST-000485
index 4d88d92..e19d9e0 100644
Binary files a/packs/skills/MANIFEST-000483 and b/packs/skills/MANIFEST-000485 differ
diff --git a/packs/skills/000484.log b/packs/spells/000483.log
similarity index 100%
rename from packs/skills/000484.log
rename to packs/spells/000483.log
diff --git a/packs/spells/CURRENT b/packs/spells/CURRENT
index a2f5062..182ad0e 100644
--- a/packs/spells/CURRENT
+++ b/packs/spells/CURRENT
@@ -1 +1 @@
-MANIFEST-000480
+MANIFEST-000482
diff --git a/packs/spells/LOG b/packs/spells/LOG
index 81f18d2..5a575a4 100644
--- a/packs/spells/LOG
+++ b/packs/spells/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.618 c48 Recovering log #479
-2024/09/10-11:28:26.620 c48 Delete type=0 #479
-2024/09/10-11:28:26.620 c48 Delete type=3 #478
+2024/09/11-11:37:16.616 2994 Recovering log #481
+2024/09/11-11:37:16.618 2994 Delete type=0 #481
+2024/09/11-11:37:16.618 2994 Delete type=3 #480
diff --git a/packs/spells/LOG.old b/packs/spells/LOG.old
index 3e4ebef..81f18d2 100644
--- a/packs/spells/LOG.old
+++ b/packs/spells/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.133 44e0 Delete type=3 #1
+2024/09/10-11:28:26.618 c48 Recovering log #479
+2024/09/10-11:28:26.620 c48 Delete type=0 #479
+2024/09/10-11:28:26.620 c48 Delete type=3 #478
diff --git a/packs/spells/MANIFEST-000480 b/packs/spells/MANIFEST-000482
similarity index 50%
rename from packs/spells/MANIFEST-000480
rename to packs/spells/MANIFEST-000482
index 4b32a77..8f15006 100644
Binary files a/packs/spells/MANIFEST-000480 and b/packs/spells/MANIFEST-000482 differ
diff --git a/packs/weapons/000489.log b/packs/weapons/000491.log
similarity index 100%
rename from packs/weapons/000489.log
rename to packs/weapons/000491.log
diff --git a/packs/weapons/CURRENT b/packs/weapons/CURRENT
index 527a905..3b626ee 100644
--- a/packs/weapons/CURRENT
+++ b/packs/weapons/CURRENT
@@ -1 +1 @@
-MANIFEST-000488
+MANIFEST-000490
diff --git a/packs/weapons/LOG b/packs/weapons/LOG
index 8c39312..092118a 100644
--- a/packs/weapons/LOG
+++ b/packs/weapons/LOG
@@ -1,3 +1,3 @@
-2024/09/10-11:28:26.663 c64 Recovering log #487
-2024/09/10-11:28:26.666 c64 Delete type=0 #487
-2024/09/10-11:28:26.666 c64 Delete type=3 #486
+2024/09/11-11:37:16.658 f60 Recovering log #489
+2024/09/11-11:37:16.661 f60 Delete type=0 #489
+2024/09/11-11:37:16.662 f60 Delete type=3 #488
diff --git a/packs/weapons/LOG.old b/packs/weapons/LOG.old
index 5a7a51f..8c39312 100644
--- a/packs/weapons/LOG.old
+++ b/packs/weapons/LOG.old
@@ -1 +1,3 @@
-2024/09/09-08:51:25.200 44e0 Delete type=3 #1
+2024/09/10-11:28:26.663 c64 Recovering log #487
+2024/09/10-11:28:26.666 c64 Delete type=0 #487
+2024/09/10-11:28:26.666 c64 Delete type=3 #486
diff --git a/packs/weapons/MANIFEST-000488 b/packs/weapons/MANIFEST-000490
similarity index 50%
rename from packs/weapons/MANIFEST-000488
rename to packs/weapons/MANIFEST-000490
index 1821eea..4be5534 100644
Binary files a/packs/weapons/MANIFEST-000488 and b/packs/weapons/MANIFEST-000490 differ