Skip to content

Commit

Permalink
Consume ammunition when using arrow_volley
Browse files Browse the repository at this point in the history
  • Loading branch information
Socolin committed Mar 18, 2024
1 parent 23a5b6a commit b5a4994
Showing 1 changed file with 91 additions and 94 deletions.
185 changes: 91 additions & 94 deletions src/app/speciality/speciality-arrow-volley-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import {Injectable} from '@angular/core';
import {WeaponDamageRollUtil} from '../item/weapon-damage-roll-util.service';
import {CharacterAccessorService} from '../data-accessor/character-accessor.service';
import {selectCharacterActiveSkillValue} from '../data-accessor/selectors/character-active-skill-value-selector';
import {combineLatest, take} from 'rxjs';
import {firstValueFrom} from 'rxjs';
import {SystemDataDatabaseService} from '../system-data/system-data-database.service';
import {RollFactory} from '../shared/roll-factory';
import {IRoll} from '../shared/roll';
import {SkillRollUtil} from '../skill/skill-roll-util';
import {WeaponSelectorService} from '../item/weapon-selector.service';
import {selectCharacterEffects} from '../data-accessor/selectors/character-effects-selector';
import {ItemUpdaterService} from '../data-accessor/item-updater.service';

type ArrowResult = {
result: 'fail' | 'epicFail';
Expand Down Expand Up @@ -50,109 +51,105 @@ export class SpecialityArrowVolleyUtil {
protected readonly systemDataDatabaseService: SystemDataDatabaseService,
protected readonly rollFactory: RollFactory,
protected readonly skillRollUtil: SkillRollUtil,
protected readonly itemUpdaterService: ItemUpdaterService,
) {
}

async rollArrowVolley(characterId: string): Promise<ArrowVolleyResult | undefined> {
return new Promise(async resolve => {
let character$ = this.characterAccessorService.selectCharacter(characterId);
let weaponSelectionResult = await this.weaponSelectorService.selectWeapon(characterId, 'range')
if (!weaponSelectionResult) {
return undefined;
}

let weaponSelectionResult = await this.weaponSelectorService.selectWeapon(characterId, 'range')
if (!weaponSelectionResult) {
resolve(undefined);
return;
}
let weapon = weaponSelectionResult.selectedWeapon;
let ammunition = weaponSelectionResult.selectedAmmo;

let ammunitionElement: string | undefined;
let availableAmmunitionQuantity = 0;
if (ammunition) {
availableAmmunitionQuantity = ammunition.system.quantity;
ammunitionElement = ammunition.system.extraDamageEffect;
}

let weapon = weaponSelectionResult.selectedWeapon;
let ammunition = weaponSelectionResult.selectedAmmo;
let [weaponDamageRollFormula, weaponDamageWithAmmunitionRollFormula] = this.weaponDamageRollUtil.getWeaponDamageRoll('range', weapon, ammunition);

let character$ = this.characterAccessorService.selectCharacter(characterId);
let activeSkillValue = await firstValueFrom(character$.pipe(selectCharacterActiveSkillValue('combat', 'throw_shoot', this.systemDataDatabaseService)));
let characterEffects = await firstValueFrom(character$.pipe(selectCharacterEffects(this.systemDataDatabaseService)));
let arrows: ArrowResult[] = [];
let ammunitionUsed = 0;

for (let i = 0; i < 4; i++) {
let testRoll = await this.rollFactory.createRoll(`2d6`);
let rollResult = this.skillRollUtil.getRollResult(testRoll, activeSkillValue);
if (rollResult == 'epicFail') {
arrows.push({
testRoll: testRoll,
result: rollResult,
arrowNumber: i + 1
})
break;
}
if (rollResult == 'fail') {
arrows.push({
testRoll: testRoll,
result: rollResult,
arrowNumber: i + 1
})
continue;
}

let ammunitionElement: string | undefined;
let availableAmmunitionQuantity = 0;
if (ammunition) {
availableAmmunitionQuantity = ammunition.system.quantity;
ammunitionElement = ammunition.system.extraDamageEffect;
let weaponElement = weapon.system.element;
let arrowElement = weaponElement;
let damageRollFormula = weaponDamageRollFormula;
let isAmmunitionUsedForArrow = false;
if (ammunition && availableAmmunitionQuantity > ammunitionUsed) {
ammunitionUsed++;
isAmmunitionUsedForArrow = true;
arrowElement = ammunitionElement || weaponElement;
damageRollFormula = weaponDamageWithAmmunitionRollFormula;
}

let [weaponDamageRollFormula, weaponDamageWithAmmunitionRollFormula] = this.weaponDamageRollUtil.getWeaponDamageRoll('range', weapon, ammunition);

combineLatest([
character$.pipe(selectCharacterActiveSkillValue('combat', 'throw_shoot', this.systemDataDatabaseService)),
character$.pipe(selectCharacterEffects(this.systemDataDatabaseService))
]).pipe(take(1))
.subscribe(async ([activeSkillValue, characterEffects]) => {
let arrows: ArrowResult[] = [];
let ammunitionUsed = 0;

for (let i = 0; i < 4; i++) {
let testRoll = await this.rollFactory.createRoll(`2d6`);
let rollResult = this.skillRollUtil.getRollResult(testRoll, activeSkillValue);
if (rollResult == 'epicFail') {
arrows.push({
testRoll: testRoll,
result: rollResult,
arrowNumber: i + 1
})
break;
}
if (rollResult == 'fail') {
arrows.push({
testRoll: testRoll,
result: rollResult,
arrowNumber: i + 1
})
continue;
}

let weaponElement = weapon.system.element;
let arrowElement = weaponElement;
let damageRollFormula = weaponDamageRollFormula;
let isAmmunitionUsedForArrow = false;
if (ammunition && availableAmmunitionQuantity > ammunitionUsed) {
ammunitionUsed++;
isAmmunitionUsedForArrow = true;
arrowElement = ammunitionElement || weaponElement;
damageRollFormula = weaponDamageWithAmmunitionRollFormula;
}

let damageBonus = 0;
for (let characterEffect of characterEffects) {
for (let modifier of characterEffect.modifiers) {
if (modifier.stat === 'damage')
damageBonus += +modifier.value;
}
}

if (damageBonus) {
damageRollFormula += `+${damageBonus}`;
}

let damageRoll = await this.rollFactory.createRoll(damageRollFormula);
arrows.push({
testRoll: testRoll,
result: rollResult,
arrowNumber: i + 1,
damage: Math.ceil(Math.max(damageRoll.total, 1)),
element: arrowElement,
damageRollFormula: damageRollFormula,
damageRoll: damageRoll,
ammunition: isAmmunitionUsedForArrow
? {
name: ammunition!.name,
icon: ammunition!.img,
extraDamage: ammunition!.system.extraDamage
} : undefined
})
let damageBonus = 0;
for (let characterEffect of characterEffects) {
for (let modifier of characterEffect.modifiers) {
if (modifier.stat === 'damage')
damageBonus += +modifier.value;
}
resolve({
arrows: arrows,
skillSuccessValue: activeSkillValue.successValue,
weapon: {
name: weapon.name,
icon: weapon.img
}
})
});
});
}

if (damageBonus) {
damageRollFormula += `+${damageBonus}`;
}

let damageRoll = await this.rollFactory.createRoll(damageRollFormula);
arrows.push({
testRoll: testRoll,
result: rollResult,
arrowNumber: i + 1,
damage: Math.ceil(Math.max(damageRoll.total, 1)),
element: arrowElement,
damageRollFormula: damageRollFormula,
damageRoll: damageRoll,
ammunition: isAmmunitionUsedForArrow
? {
name: ammunition!.name,
icon: ammunition!.img,
extraDamage: ammunition!.system.extraDamage
} : undefined
})
}
if (ammunition && ammunitionUsed) {
await this.itemUpdaterService.changeQuantity(ammunition, -ammunitionUsed);
}
return {
arrows: arrows,
skillSuccessValue: activeSkillValue.successValue,
weapon: {
name: weapon.name,
icon: weapon.img
}
};
}

getAllRolls(result: ArrowVolleyResult): IRoll[] {
Expand Down

0 comments on commit b5a4994

Please sign in to comment.