Melee fight
This commit is contained in:
@@ -325,6 +325,25 @@ export class CrucibleActor extends Actor {
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollArmor( rollData) {
|
||||
let armor = this.getEquippedArmor()
|
||||
if (armor) {
|
||||
|
||||
}
|
||||
return { armor: "none"}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async incDecHP( formula ) {
|
||||
let dmgRoll = new Roll(formula).roll( {async: false})
|
||||
await CrucibleUtility.showDiceSoNice(dmgRoll, game.settings.get("core", "rollMode"))
|
||||
let hp = duplicate(this.data.data.secondary.hp)
|
||||
hp.value = Number(hp.value) + Number(dmgRoll.total)
|
||||
this.update( {'data.secondary.hp': hp })
|
||||
return Number(dmgRoll.total)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getAbility(abilKey) {
|
||||
return this.data.data.abilities[abilKey];
|
||||
@@ -590,20 +609,71 @@ export class CrucibleActor extends Actor {
|
||||
let rollData = this.getCommonRollData()
|
||||
rollData.mode = "shield"
|
||||
rollData.shield = shield
|
||||
rollData.useshield = true
|
||||
rollData.img = shield.img
|
||||
this.startRoll(rollData)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
rollArmorDie() {
|
||||
async rollArmorDie(rollData = undefined) {
|
||||
let armor = this.getEquippedArmor()
|
||||
if (armor) {
|
||||
armor = duplicate(armor)
|
||||
let reduce = 0
|
||||
let multiply = 1
|
||||
let disadvantage = false
|
||||
let advantage = false
|
||||
let messages = ["Armor applied"]
|
||||
|
||||
if (rollData) {
|
||||
if (CrucibleUtility.isArmorLight(armor) && CrucibleUtility.isWeaponPenetrating(rollData.attackRollData.weapon) ) {
|
||||
return { armorIgnored: true, nbSuccess: 0, messages: ["Armor ignored : Penetrating weapons ignore Light Armors."] }
|
||||
}
|
||||
if (CrucibleUtility.isWeaponPenetrating(rollData.attackRollData.weapon) ) {
|
||||
messages.push("Armor reduced by 1 (Penetrating weapon)")
|
||||
reduce = 1
|
||||
}
|
||||
if (CrucibleUtility.isWeaponLight(rollData.attackRollData.weapon) ) {
|
||||
messages.push("Armor with advantage (Light weapon)")
|
||||
advantage = true
|
||||
}
|
||||
if (CrucibleUtility.isWeaponHeavy(rollData.attackRollData.weapon) ) {
|
||||
messages.push("Armor with disadvantage (Heavy weapon)")
|
||||
disadvantage = true
|
||||
}
|
||||
if (CrucibleUtility.isWeaponHack(rollData.attackRollData.weapon) ) {
|
||||
messages.push("Armor reduced by 1 (Hack weapon)")
|
||||
reduce = 1
|
||||
}
|
||||
if (CrucibleUtility.isWeaponUndamaging(rollData.attackRollData.weapon) ) {
|
||||
messages.push("Armor multiplied by 2 (Undamaging weapon)")
|
||||
multiply = 2
|
||||
}
|
||||
}
|
||||
let diceColor = armor.data.absorprionroll
|
||||
let rollTable = CrucibleUtility.getRollTableFromDiceColor( diceColor)
|
||||
|
||||
let armorResult = await CrucibleUtility.getRollTableFromDiceColor( diceColor, false )
|
||||
let armorValue = (Number(armorResult.data.text) - reduce) * multiply
|
||||
if ( advantage || disadvantage) {
|
||||
let armorResult2 = await CrucibleUtility.getRollTableFromDiceColor( diceColor, false )
|
||||
let armorValue2 = (Number(armorResult2.data.text) - reduce) * multiply
|
||||
if ( advantage) {
|
||||
armorValue = (armorValue2 > armorValue) ? armorValue2 : armorValue
|
||||
messages.push(`Armor advantage - Roll 1 = ${armorValue} - Roll 2 = ${armorValue2}`)
|
||||
}
|
||||
if ( disadvantage) {
|
||||
armorValue = (armorValue2 < armorValue) ? armorValue2 : armorValue
|
||||
messages.push(`Armor disadvantage - Roll 1 = ${armorValue} - Roll 2 = ${armorValue2}`)
|
||||
}
|
||||
}
|
||||
armorResult.armorValue = armorValue
|
||||
if ( !rollData) {
|
||||
ChatMessage.create( { content: "Armor result : " + armorValue } )
|
||||
}
|
||||
messages.push( "Armor result : " + armorValue)
|
||||
return { armorIgnored: false, nbSuccess: armorValue, messages: messages }
|
||||
}
|
||||
return { armorIgnored: true, nbSuccess: 0, messages: ["No armor equipped."] }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
@@ -68,7 +68,7 @@ export class CrucibleRollDialog extends Dialog {
|
||||
this.rollData.rollAdvantage = event.currentTarget.value
|
||||
})
|
||||
html.find('#useshield').change((event) => {
|
||||
this.rollData.useShield = event.currentTarget.checked
|
||||
this.rollData.useshield = event.currentTarget.checked
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ export class CrucibleUtility {
|
||||
/* -------------------------------------------- */
|
||||
static async init() {
|
||||
Hooks.on('renderChatLog', (log, html, data) => CrucibleUtility.chatListeners(html));
|
||||
Hooks.on("dropCanvasData", (canvas, data) => {
|
||||
/*Hooks.on("dropCanvasData", (canvas, data) => {
|
||||
CrucibleUtility.dropItemOnToken(canvas, data)
|
||||
});
|
||||
});*/
|
||||
|
||||
this.rollDataStore = {}
|
||||
this.defenderStore = {}
|
||||
@@ -51,7 +51,12 @@ export class CrucibleUtility {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------- */
|
||||
static upperFirst(text) {
|
||||
if (typeof text !== 'string') return text
|
||||
return text.charAt(0).toUpperCase() + text.slice(1)
|
||||
}
|
||||
|
||||
/*-------------------------------------------- */
|
||||
static getSkills() {
|
||||
return duplicate(this.skills)
|
||||
@@ -90,18 +95,87 @@ export class CrucibleUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async getRollTableFromDiceColor(diceColor) {
|
||||
static isArmorLight(armor) {
|
||||
if (armor && (armor.data.armortype.includes("light") || armor.data.armortype.includes("clothes"))) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isWeaponPenetrating(weapon) {
|
||||
if (weapon && weapon.data.qualities.toLowerCase().includes("penetrating")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isWeaponLight(weapon) {
|
||||
if (weapon && weapon.data.qualities.toLowerCase().includes("light")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isWeaponHeavy(weapon) {
|
||||
if (weapon && weapon.data.qualities.toLowerCase().includes("heavy")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isWeaponHack(weapon) {
|
||||
if (weapon && weapon.data.qualities.toLowerCase().includes("hack")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isWeaponUndamaging(weapon) {
|
||||
if (weapon && weapon.data.qualities.toLowerCase().includes("undamaging")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isWeaponDangerous(weapon) {
|
||||
if (weapon && weapon.data.qualities.toLowerCase().includes("dangerous")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isWeaponDeadly(weapon) {
|
||||
if (weapon && weapon.data.qualities.toLowerCase().includes("deadly")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async getRollTableFromDiceColor(diceColor, displayChat = true) {
|
||||
let rollTableName = __color2RollTable[diceColor]
|
||||
if (rollTableName) {
|
||||
const pack = game.packs.get("fvtt-crucible-rpg.rolltables")
|
||||
const index = await pack.getIndex()
|
||||
const entry = index.find(e => e.name === rollTableName)
|
||||
let table = await pack.getDocument(entry._id)
|
||||
const draw = await table.draw({ displayChat: true, rollMode: "gmroll" })
|
||||
const draw = await table.draw({ displayChat: displayChat, rollMode: "gmroll" })
|
||||
return draw.results.length > 0 ? draw.results[0] : undefined
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async getCritical(level, weapon) {
|
||||
const pack = game.packs.get("fvtt-crucible-rpg.rolltables")
|
||||
|
||||
let tableName = "Crit " + level + " (" + this.upperFirst(weapon.data.damage) + ")"
|
||||
const index = await pack.getIndex()
|
||||
const entry = index.find(e => e.name === tableName)
|
||||
let table = await pack.getDocument(entry._id)
|
||||
const draw = await table.draw({ displayChat: false, rollMode: "gmroll" })
|
||||
return draw.results.length > 0 ? draw.results[0] : undefined
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async chatListeners(html) {
|
||||
|
||||
@@ -110,12 +184,12 @@ export class CrucibleUtility {
|
||||
})
|
||||
html.on("click", '.roll-defense-melee', event => {
|
||||
let rollId = $(event.currentTarget).data("roll-id")
|
||||
let rollData = CrucibleUtility.getRollData( rollId )
|
||||
let rollData = CrucibleUtility.getRollData(rollId)
|
||||
rollData.defenseWeaponId = $(event.currentTarget).data("defense-weapon-id")
|
||||
let actor = game.canvas.tokens.get(rollData.defenderTokenId).actor
|
||||
if (actor && (game.user.isGM || actor.isOwner) ) {
|
||||
actor.rollDefenseMelee(rollData )
|
||||
}
|
||||
let actor = game.canvas.tokens.get(rollData.defenderTokenId).actor
|
||||
if (actor && (game.user.isGM || actor.isOwner)) {
|
||||
actor.rollDefenseMelee(rollData)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -197,12 +271,12 @@ export class CrucibleUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getTarget() {
|
||||
if (game.user.targets && game.user.targets.size == 1) {
|
||||
if (game.user.targets) {
|
||||
for (let target of game.user.targets) {
|
||||
return target;
|
||||
return target
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
return undefined
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -245,15 +319,102 @@ export class CrucibleUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getSuccessResult(sum){
|
||||
ui.notifications.warn("Not implemented up to now !")
|
||||
static getSuccessResult(rollData) {
|
||||
if (rollData.sumSuccess <= -3) {
|
||||
return { result: "miss", fumble: true, attackerHPLoss: "2d3", hpLossType: "melee" }
|
||||
}
|
||||
if (rollData.sumSuccess == -2) {
|
||||
return { result: "miss", dangerous_fumble: true, attackerHPLoss: "1d3", hpLossType: "melee" }
|
||||
}
|
||||
if (rollData.sumSuccess == -1) {
|
||||
return { result: "miss" }
|
||||
}
|
||||
if (rollData.sumSuccess == 0) {
|
||||
if (rollData.attackRollData.weapon.data.isranged) {
|
||||
return { result: "target_space", aoe: true }
|
||||
} else {
|
||||
return { result: "clash", hack_vs_shields: true }
|
||||
}
|
||||
}
|
||||
if (rollData.sumSuccess == 1) {
|
||||
return { result: "hit", defenderDamage: "1", entangle: true, knockback: true }
|
||||
}
|
||||
if (rollData.sumSuccess == 2) {
|
||||
return { result: "hit", defenderDamage: "2", critical_1: true, entangle: true, knockback: true, penetrating_impale: true, hack_armors: true }
|
||||
}
|
||||
if (rollData.sumSuccess >= 3) {
|
||||
return { result: "hit", defenderDamage: "3", critical_2: true, entangle: true, knockback: true, penetrating_impale: true, hack_armors: true }
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async processAttackDefense( rollData) {
|
||||
if ( rollData.attackRollData) {
|
||||
static async getFumble(weapon) {
|
||||
const pack = game.packs.get("fvtt-crucible-rpg.rolltables")
|
||||
const index = await pack.getIndex()
|
||||
let entry
|
||||
|
||||
if (weapon.isranged) {
|
||||
entry = index.find(e => e.name === "Fumble! (ranged)")
|
||||
}
|
||||
if (!weapon.isranged) {
|
||||
entry = index.find(e => e.name === "Fumble! (melee)")
|
||||
}
|
||||
let table = await pack.getDocument(entry._id)
|
||||
const draw = await table.draw({ displayChat: false, rollMode: "gmroll" })
|
||||
return draw.results.length > 0 ? draw.results[0] : undefined
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async processSuccessResult(rollData) {
|
||||
if (game.user.isGM) { // Only GM process this
|
||||
let result = rollData.successDetails
|
||||
let attacker = game.actors.get(rollData.actorId)
|
||||
let defender = game.canvas.tokens.get(rollData.attackRollData.defenderTokenId).actor
|
||||
|
||||
if (attacker && result.attackerHPLoss) {
|
||||
result.attackerHPLossValue = await attacker.incDecHP("-" + result.attackerHPLoss)
|
||||
}
|
||||
if (attacker && defender && result.defenderDamage) {
|
||||
let dmgDice = (rollData.attackRollData.weapon.data.isranged) ? "d6" : "d8"
|
||||
result.damageWeaponFormula = result.defenderDamage + dmgDice
|
||||
result.defenderHPLossValue = await defender.incDecHP("-" + result.damageWeaponFormula)
|
||||
}
|
||||
if (result.fumble || (result.dangerous_fumble && CrucibleUtility.isWeaponDangerous(rollData.attackRollData.weapon))) {
|
||||
result.fumbleDetails = await this.getFumble(rollData.weapon)
|
||||
}
|
||||
if (result.critical_1 || result.critical_2) {
|
||||
let isDeadly = CrucibleUtility.isWeaponDeadly(rollData.attackRollData.weapon)
|
||||
result.critical = await this.getCritical((result.critical_1) ? "I" : "II", rollData.attackRollData.weapon )
|
||||
result.criticalText = result.critical.data.text
|
||||
}
|
||||
this.createChatWithRollMode(rollData.alias, {
|
||||
content: await renderTemplate(`systems/fvtt-crucible-rpg/templates/chat-attack-defense-result.html`, rollData)
|
||||
})
|
||||
console.log("Results processed", rollData)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async processAttackDefense(rollData) {
|
||||
if (rollData.attackRollData) {
|
||||
//console.log("Defender token, ", rollData, rollData.defenderTokenId)
|
||||
let defender = game.canvas.tokens.get(rollData.attackRollData.defenderTokenId).actor
|
||||
let sumSuccess = rollData.attackRollData.nbSuccess - rollData.nbSuccess
|
||||
this.getSuccessResult(sumSuccess)
|
||||
if (sumSuccess > 0) {
|
||||
let armorResult = await defender.rollArmorDie(rollData)
|
||||
rollData.armorResult = armorResult
|
||||
sumSuccess += rollData.armorResult.nbSuccess
|
||||
if (sumSuccess < 0) { // Never below 0
|
||||
sumSuccess = 0
|
||||
}
|
||||
}
|
||||
rollData.sumSuccess = sumSuccess
|
||||
rollData.successDetails = this.getSuccessResult(rollData)
|
||||
if (game.user.isGM) {
|
||||
this.processSuccessResult(rollData)
|
||||
} else {
|
||||
game.socket.emit("system.fvtt-crucible-rpg", { msg: "msg_gm_process_attack_defense", data: rollData });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,6 +424,9 @@ export class CrucibleUtility {
|
||||
if (msg.name == "msg_update_roll") {
|
||||
this.updateRollData(msg.data)
|
||||
}
|
||||
if (msg.name == "msg_gm_process_attack_defense") {
|
||||
this.processSuccessResult(msg.data)
|
||||
}
|
||||
if (msg.name == "msg_gm_item_drop" && game.user.isGM) {
|
||||
let actor = game.actors.get(msg.data.actorId)
|
||||
let item
|
||||
@@ -412,7 +576,7 @@ export class CrucibleUtility {
|
||||
}
|
||||
|
||||
// shield => 14
|
||||
if (rollData.useShield && rollData.shield) {
|
||||
if (rollData.useshield && rollData.shield) {
|
||||
diceFormula += "+ 1" + String(rollData.shield.data.shielddie) + "cs>=5"
|
||||
} else {
|
||||
diceFormula += " + 0d6cs>=5"
|
||||
@@ -429,8 +593,9 @@ export class CrucibleUtility {
|
||||
rollData.roll = myRoll
|
||||
rollData.nbSuccess = myRoll.total
|
||||
if (rollData.rollAdvantage != "none") {
|
||||
|
||||
|
||||
rollData.rollOrder = 1
|
||||
rollData.rollType = (rollData.rollAdvantage == "roll-advantage") ? "Advantage": "Disadvantage"
|
||||
this.createChatWithRollMode(rollData.alias, {
|
||||
content: await renderTemplate(`systems/fvtt-crucible-rpg/templates/chat-generic-result.html`, rollData)
|
||||
})
|
||||
@@ -457,6 +622,7 @@ export class CrucibleUtility {
|
||||
}
|
||||
rollData.rollOrder = 3
|
||||
}
|
||||
rollData.nbSuccess = Math.max(0, rollData.nbSuccess)
|
||||
|
||||
rollData.isFirstRollAdvantage = false
|
||||
// Manage exp
|
||||
@@ -522,7 +688,7 @@ export class CrucibleUtility {
|
||||
chatGM.whisper = this.getUsers(user => user.isGM);
|
||||
chatGM.content = "Blinde message of " + game.user.name + "<br>" + chatOptions.content;
|
||||
console.log("blindMessageToGM", chatGM);
|
||||
game.socket.emit("system.fvtt-crucible-rgp", { msg: "msg_gm_chat_message", data: chatGM });
|
||||
game.socket.emit("system.fvtt-crucible-rpg", { msg: "msg_gm_chat_message", data: chatGM });
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user