Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weapon - Ammo assigment #170

Merged
merged 3 commits into from
Apr 15, 2024
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
4 changes: 4 additions & 0 deletions src/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,7 @@
"DL.WealthLifestyle": "Lifestyle: ",
"DL.WealthTitle": "Wealth",
"DL.WeaponAdd": "Add weapon",
"DL.WeaponAmmoRequired": "Ammunition required",
"DL.WeaponAttack20": "Extra Damage 20+",
"DL.WeaponAttack20Text": "Attack Roll 20+",
"DL.WeaponAttackModifier": "Attack Modifier",
Expand All @@ -744,6 +745,9 @@
"DL.WeaponModifiers": "Modifiers",
"DL.WeaponName": "Weapon name",
"DL.WeaponProperties": "Properties",
"DL.WeaponResourceComsumption": "Resource consumption",
"DL.WeaponRunOutOfAmmo": "{weaponName} has run out of its ammunition.",
"DL.WeaponNoAmmo": "{weaponName} has no assigned ammunition.",
"DL.WeaponTitle": "Weapons",
"DL.WeaponWear": "Equip weapon",
"DL.With": "with"
Expand Down
34 changes: 30 additions & 4 deletions src/module/actor/actor.js
sasquach45932 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,27 @@ export class DemonlordActor extends Actor {
*/
async rollWeaponAttack(itemID, _options = {event: null}) {
const item = this.getEmbeddedDocument('Item', itemID)
let ammoItem

// Check if there is an ammo for weapon
if (item.system.consume.ammorequired) {
ammoItem = await this.ammo.find(x => x.id === item.system.consume.ammoitemid)
if (ammoItem) {
if (ammoItem.system.quantity === 0) {
return ui.notifications.warn(
game.i18n.format('DL.WeaponRunOutOfAmmo', {
weaponName: item.name,
}),
)
}
} else {
return ui.notifications.warn(
game.i18n.format('DL.WeaponNoAmmo', {
weaponName: item.name,
}),
)
}
}

// If no attribute to roll, roll without modifiers and boons
const attribute = item.system.action?.attack
Expand All @@ -427,11 +448,16 @@ export class DemonlordActor extends Actor {

// Check if actor is blocked by an affliction
if (!DLAfflictions.isActorBlocked(this, 'action', attribute))
launchRollDialog(game.i18n.localize('DL.DialogAttackRoll') + game.i18n.localize(item.name), async html =>
await this.rollAttack(item, html.find('[id="boonsbanes"]').val(), html.find('[id="modifier"]').val()),
)
launchRollDialog(game.i18n.localize('DL.DialogAttackRoll') + game.i18n.localize(item.name), async html => {
await this.rollAttack(item, html.find('[id="boonsbanes"]').val(), html.find('[id="modifier"]').val())
// Decrease ammo quantity
if (item.system.consume.ammorequired) {
await ammoItem.update({
'system.quantity': ammoItem.system.quantity - item.system.consume.amount,
})
}
})
}

/* -------------------------------------------- */

async rollAttribute(attribute, inputBoons, inputModifier) {
Expand Down
14 changes: 12 additions & 2 deletions src/module/data/item/WeaponDataModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ export default class WeaponDataModel extends foundry.abstract.DataModel {
wear: makeBoolField(true),
quantity: makeIntField(1),
availability: makeStringField(),
value: makeStringField()
value: makeStringField(),
consume: new foundry.data.fields.SchemaField({
ammorequired: makeBoolField(false),
amount: makeIntField(1),
ammoitemid: makeStringField()
}),
}
}
}
Expand All @@ -37,6 +42,11 @@ export function makeWeaponSchema() {
wear: makeBoolField(true),
quantity: makeIntField(1),
availability: makeStringField(),
value: makeStringField()
value: makeStringField(),
consume: new foundry.data.fields.SchemaField({
ammorequired: makeBoolField(false),
amount: makeIntField(1),
ammoitemid: makeStringField()
}),
})
}
10 changes: 9 additions & 1 deletion src/module/item/sheets/base-item-sheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export default class DLBaseItemSheet extends ItemSheet {
})
tippy('.dl-new-project-2.dropdown', {
content(reference) {
html = buildDropdownList(reference.attributes.name.value, reference.attributes.value.value)
html = buildDropdownList(reference.attributes.name.value, reference.attributes.value.value, data)
return html
},
allowHTML: true,
Expand All @@ -190,6 +190,14 @@ export default class DLBaseItemSheet extends ItemSheet {
inputs.focus(ev => ev.currentTarget.select())
}

// Weapon ammo required checkbox
html.find('.dl-ammorequired').click(async _ => {
await this.document.update({
'system.consume.ammorequired': !this.document.system.consume.ammorequired,
'system.consume.ammoitemid' : ''
})
})

// Item autoDestroy checkbox
html.find('.dl-autodestroy').click(async _ => {
await this.document.update({'system.autoDestroy': !this.document.system.autoDestroy})
Expand Down
79 changes: 66 additions & 13 deletions src/module/utils/handlebars-helpers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* global fromUuidSync */
import {capitalize, enrichHTMLUnrolled, i18n} from "./utils";
import {handlebarsBuildEditor} from "./editor";

Expand Down Expand Up @@ -50,7 +51,9 @@ export function registerHandlebarsHelpers() {
)
Handlebars.registerHelper('dlAvailabilityDropdown', (groupName, checkedKey) => _buildAvailabilityDropdownItem(groupName, checkedKey))
Handlebars.registerHelper('dlConsumableDropdown', (groupName, checkedKey) => _buildConsumableDropdownItem(groupName, checkedKey))
Handlebars.registerHelper('dlCheckCharacteristicsIsNull', (actorData) => _CheckCharacteristicsIsNull(actorData));
Handlebars.registerHelper('dlAmmoDropdown', (groupName, checkedKey, weapon) => _buildAmmoDropdownItem(groupName, checkedKey, weapon))
Handlebars.registerHelper('dlCheckItemOnActor', (data) => _CheckItemOnActor(data))
Handlebars.registerHelper('dlCheckCharacteristicsIsNull', (actorData) => _CheckCharacteristicsIsNull(actorData))
}

// ----------------------------------------------------
Expand All @@ -69,10 +72,9 @@ function _getAttributes(groupName) {
attributes = ['', 'C', 'U', 'R', 'E']
} else if (groupName === 'system.requirement.attribute') {
attributes = ['', 'strength', 'agility', 'intellect', 'will', 'perception']
}
else if (groupName === 'system.consumabletype') {
} else if (groupName === 'system.consumabletype') {
attributes = ['', 'D', 'F', 'P', 'V', 'T']
}
}
return attributes
}

Expand All @@ -98,11 +100,19 @@ function _buildRadioBoxes(groupName, checkedKey) {
// ----------------------------------------------------

function _CheckCharacteristicsIsNull(actorData) {
if (actorData === null) {
return true
} else {
return false
}
if (actorData === null) {
return true
} else {
return false
}
}

function _CheckItemOnActor(data) {
if (data.indexOf('Actor.') === -1) {
return false
} else {
return true
}
}

function _buildDropdownItem(groupName, checkedKey) {
Expand Down Expand Up @@ -174,14 +184,15 @@ function _buildDropdownItemWithValue(groupName, checkedKey, valueName, valueKey)
}


export function buildDropdownList(groupName, checkedKey) {
export function buildDropdownList(groupName, checkedKey, data) {
let labelPrefix = 'DL.Attribute'
let iconPrefix = 'dl-icon-'
let useIcon = true

if (groupName === 'path-type') return _buildPathTypeDropdownList(checkedKey)
if (groupName === 'level.attributeSelect') return _buildPathAttributeSelectDropdownList(checkedKey)
if (groupName.startsWith('level.attributeSelectTwoSet')) return _buildPathAttributeTwoSetDropdownList(groupName, checkedKey)
if (groupName === 'system.consume.ammoitemid') return _buildAmmoDropdownList (groupName, checkedKey, data)
if (groupName === 'system.hands') {labelPrefix = 'DL.WeaponHands'; useIcon = false}
if (groupName === 'system.consumabletype') {labelPrefix = 'DL.ConsumableType'; useIcon = false}
if (groupName === 'system.availability') {labelPrefix = 'DL.Availability', iconPrefix = 'dl-icon-availability-'}
Expand Down Expand Up @@ -336,6 +347,28 @@ function _buildPathAttributeTwoSetViewSelector(attributeName, isSelected, select
return new Handlebars.SafeString(html)
}

function _buildAmmoDropdownList(groupName, checkedKey, data) {
let attributes = [{ id: '', name: i18n('DL.None') }]
let html = `<div class="dl-new-project-2-dropdown">`
if (!data.document) return ''
let baseItemUuid = data.document.uuid
let actor = fromUuidSync(baseItemUuid.substr(0, baseItemUuid.search('.Item.')))
actor.items.forEach(item => {
if (item.type === 'ammo') attributes.push({ id: item._id, name: item.name })
})
for (let attribute of attributes) {
const value = attribute.id
const checked = value === checkedKey ? 'checked' : ''
const label = value ? attribute.name : i18n('DL.None')
html += `<div class="${checked}">
<input type="radio" name="${groupName}" value="${value}" ${checked}/>
<span>${label}</span>
</div>`
}
html += `</div>`
return new Handlebars.SafeString(html)
}

// ----------------------------------------------------

function _buildAvailabilityDropdownItem(groupName, checkedKey) {
Expand All @@ -358,11 +391,31 @@ function _buildConsumableDropdownItem(groupName, checkedKey) {
const attributes = ['', 'D', 'F', 'P', 'V', 'T']
for (let attribute of attributes) {
if (checkedKey != attribute) continue
const label = attribute === '' ? i18n("DL.ConsumableNone") : i18n(`DL.ConsumableType${attribute}`)
let html =
`<div class="dl-new-project-2 dropdown" name="${groupName}" value="${checkedKey}">
const label = attribute === '' ? i18n('DL.ConsumableNone') : i18n(`DL.ConsumableType${attribute}`)
let html = `<div class="dl-new-project-2 dropdown" name="${groupName}" value="${checkedKey}">
<span style="width: 120px; text-align: center; text-overflow: ellipsis">${label} </span>
</div>`
return new Handlebars.SafeString(html)
}
}

function _buildAmmoDropdownItem(groupName, checkedKey, weapon) {
let actorUuid = weapon.parent.uuid
let actor = fromUuidSync(actorUuid.substr(0, actorUuid.search('.Item.')))
let attributes = [{ id: '', name: '' }]

actor.items.forEach(item => {
if (item.type === 'ammo') attributes.push({ id: item._id, name: item.name })
})

if (!attributes.find(x => x.id === checkedKey)) checkedKey = ''

for (let attribute of attributes) {
if (checkedKey != attribute.id) continue
const label = attribute.id === '' ? i18n('DL.None') : attribute.name
let html = `<div class="dl-new-project-2 dropdown" name="${groupName}" value="${checkedKey}">
<span style="width: 200px; text-align: center; overflow: hidden; text-overflow: ellipsis;">${label} </span>
</div>`
return new Handlebars.SafeString(html)
}
}
25 changes: 25 additions & 0 deletions src/templates/item/item-weapon-sheet.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,31 @@
</div>
<hr>

<div class="dl-item-section-section margin">
<div>
<b>{{localize "DL.WeaponAmmoRequired"}}</b>
<div class="dl-custom-checkbox dl-ammorequired {{checked system.consume.ammorequired}}"> </div>
</div>
{{#if (dlCheckItemOnActor system.parent.uuid)}}
{{#if system.consume.ammorequired}}
<div>
<b>{{localize "DL.WeaponResourceComsumption"}}</b>
<div>
<div class="dl-new-project-2">
<i class="dl-icon-amount"></i>
<span class="sep"></span>
<span style="width: 64px; text-align: center; text-overflow: ellipsis">{{localize "DL.AmmoAmount"}}</span>
<span class="sep"></span>
<input type="number" name="system.consume.amount" value="{{system.consume.amount}}" placeholder="1"/>
</div>
{{dlAmmoDropdown "system.consume.ammoitemid" system.consume.ammoitemid system}}
</div>
</div>
{{/if}}
{{/if}}
</div>
<hr>

{{#if system.description}}
<div class="dl-item-section-description">
<div><b>{{localize "DL.TabsDescription"}}</b></div>
Expand Down
Loading