Browse Source

modding #1984: New object event: beforeIsSpellTarget

tags/v0.12.0
Shaun 1 year ago
parent
commit
cf237572db
2 changed files with 138 additions and 118 deletions
  1. +7
    -118
      src/server/components/spellbook.js
  2. +131
    -0
      src/server/components/spellbook/cast.js

+ 7
- 118
src/server/components/spellbook.js View File

@@ -1,13 +1,14 @@
let spellTemplate = require('../config/spells/spellTemplate');
let animations = require('../config/animations');
let playerSpells = require('../config/spells');
let playerSpellsConfig = require('../config/spellsConfig');
//Imports
const spellTemplate = require('../config/spells/spellTemplate');
const animations = require('../config/animations');
const playerSpells = require('../config/spells');
const playerSpellsConfig = require('../config/spellsConfig');

//Helpers
const rotationManager = require('./spellbook/rotationManager');
const cast = require('./spellbook/cast');

//Component

module.exports = {
type: 'spellbook',

@@ -338,119 +339,7 @@ module.exports = {
},

cast: function (action, isAuto) {
if (!action.has('spell')) {
const isCasting = this.isCasting();
this.stopCasting();

const consumeTick = isCasting;

return consumeTick;
}

let spell = this.spells.find(s => (s.id === action.spell));
if (!spell)
return false;

action.target = this.getTarget(spell, action);

//If a target has become nonSelectable, we need to stop attacks that are queued/auto
if (!action.target || action.target.nonSelectable)
return false;

action.auto = spell.auto;

let success = true;
if (spell.cd > 0) {
if (!isAuto) {
let type = (spell.auto) ? 'Weapon' : 'Spell';
this.sendAnnouncement(`${type} is on cooldown`);
}
success = false;
} else if (spell.manaCost > this.obj.stats.values.mana) {
if (!isAuto)
this.sendAnnouncement('Insufficient mana to cast spell');
success = false;
} else if (spell.has('range')) {
let distance = Math.max(Math.abs(action.target.x - this.obj.x), Math.abs(action.target.y - this.obj.y));
let range = spell.range;
if ((spell.useWeaponRange) && (this.obj.player)) {
let weapon = this.obj.inventory.findItem(this.obj.equipment.eq.oneHanded) || this.obj.inventory.findItem(this.obj.equipment.eq.twoHanded);
if (weapon)
range = weapon.range || 1;
}

if (distance > range) {
if (!isAuto)
this.sendAnnouncement('Target out of range');
success = false;
}
}

//LoS check
//Null means we don't have LoS and as such, we should move
if (spell.needLos && success) {
if (!this.physics.hasLos(~~this.obj.x, ~~this.obj.y, ~~action.target.x, ~~action.target.y)) {
if (!isAuto)
this.sendAnnouncement('Target not in line of sight');
action.auto = false;
success = null;
}
}

if (!success) {
this.queueAuto(action, spell);
return success;
} else if (!this.queueAuto(action, spell))
return false;

let castSuccess = {
success: true
};
this.obj.fireEvent('beforeCastSpell', castSuccess);
if (!castSuccess.success)
return false;

if (spell.manaReserve) {
let reserve = spell.manaReserve;

if (reserve.percentage) {
let reserveEvent = {
spell: spell.name,
reservePercent: reserve.percentage
};
this.obj.fireEvent('onBeforeReserveMana', reserveEvent);

if (!spell.active) {
if (1 - this.obj.stats.values.manaReservePercent < reserve.percentage) {
this.sendAnnouncement('Insufficient mana to cast spell');
return;
} this.obj.stats.addStat('manaReservePercent', reserveEvent.reservePercent);
} else
this.obj.stats.addStat('manaReservePercent', -reserveEvent.reservePercent);
}
}

if (spell.targetFurthest)
spell.target = this.obj.aggro.getFurthest();
else if (spell.targetRandom)
spell.target = this.obj.aggro.getRandom();

success = spell.castBase(action);
this.stopCasting(spell, true);

if (success) {
spell.consumeMana();
spell.setCd();
}

this.obj.fireEvent('afterCastSpell', {
castSuccess: success,
spell,
action
});

//Null means we didn't fail but are initiating casting
return (success === null || success === true);
return cast(this, action, isAuto);
},

getClosestRange: function (spellNum) {


+ 131
- 0
src/server/components/spellbook/cast.js View File

@@ -0,0 +1,131 @@
/* eslint-disable-next-line max-lines-per-function */
const cast = (cpnSpellbook, action, isAuto) => {
const { obj, physics, spells } = cpnSpellbook;

//Stop casting
if (!action.has('spell')) {
const wasCasting = cpnSpellbook.isCasting();
cpnSpellbook.stopCasting();

//Consume a tick if we were casting
return wasCasting;
}

const spell = spells.find(s => (s.id === action.spell));
if (!spell)
return false;

action.target = cpnSpellbook.getTarget(spell, action);
action.auto = spell.auto;

//If a target has become nonSelectable, we need to stop attacks that are queued/auto
if (!action.target || action.target.nonSelectable)
return false;

let success = true;
if (spell.cd > 0) {
if (!isAuto) {
const type = (spell.auto) ? 'Weapon' : 'Spell';
cpnSpellbook.sendAnnouncement(`${type} is on cooldown`);
}
success = false;
} else if (spell.manaCost > obj.stats.values.mana) {
if (!isAuto)
cpnSpellbook.sendAnnouncement('Insufficient mana to cast spell');
success = false;
} else if (spell.has('range')) {
const distance = Math.max(Math.abs(action.target.x - obj.x), Math.abs(action.target.y - obj.y));
let range = spell.range;
if ((spell.useWeaponRange) && (obj.player)) {
const weapon = obj.inventory.findItem(obj.equipment.eq.oneHanded) || obj.inventory.findItem(obj.equipment.eq.twoHanded);
if (weapon)
range = weapon.range || 1;
}

if (distance > range) {
if (!isAuto)
cpnSpellbook.sendAnnouncement('Target out of range');
success = false;
}
}

//LoS check
//Null means we don't have LoS and as such, we should move
if (spell.needLos && success) {
if (!physics.hasLos(~~obj.x, ~~obj.y, ~~action.target.x, ~~action.target.y)) {
if (!isAuto)
cpnSpellbook.sendAnnouncement('Target not in line of sight');
action.auto = false;
success = null;
}
}

if (!success) {
cpnSpellbook.queueAuto(action, spell);
return success;
} else if (!cpnSpellbook.queueAuto(action, spell))
return false;

const eventBeforeCastSpell = {
success: true,
action
};
obj.fireEvent('beforeCastSpell', eventBeforeCastSpell);
if (!eventBeforeCastSpell.success)
return false;

if (spell.manaReserve) {
const reserve = spell.manaReserve;

if (reserve.percentage) {
const reserveEvent = {
spell: spell.name,
reservePercent: reserve.percentage
};
obj.fireEvent('onBeforeReserveMana', reserveEvent);

if (!spell.active) {
if (1 - obj.stats.values.manaReservePercent < reserve.percentage) {
cpnSpellbook.sendAnnouncement('Insufficient mana to cast spell');
return;
} obj.stats.addStat('manaReservePercent', reserveEvent.reservePercent);
} else
obj.stats.addStat('manaReservePercent', -reserveEvent.reservePercent);
}
}

if (spell.targetFurthest)
spell.target = obj.aggro.getFurthest();
else if (spell.targetRandom)
spell.target = obj.aggro.getRandom();

if (!!eventBeforeCastSpell.action.target?.effects) {
const eventBeforeIsSpellTarget = {
source: obj,
spell,
target: eventBeforeCastSpell.action.target
};
eventBeforeIsSpellTarget.target.fireEvent('beforeIsSpellTarget', eventBeforeIsSpellTarget);
eventBeforeCastSpell.action.target = eventBeforeIsSpellTarget.target;
}

success = spell.castBase(eventBeforeCastSpell.action);
cpnSpellbook.stopCasting(spell, true);

if (success) {
spell.consumeMana();
spell.setCd();
}

obj.fireEvent('afterCastSpell', {
castSuccess: success,
spell,
action: eventBeforeCastSpell.action
});

//Null means we didn't fail but are initiating casting
return (success === null || success === true);
};

module.exports = cast;

Loading…
Cancel
Save