Browse Source

Merge branch '1672-shields' into 'master'

Draft: Add a shield effect and make blood barrier give a shield

Closes #1894 and #1672

See merge request Isleward/isleward!579
merge-requests/579/merge
kckckc 1 year ago
parent
commit
2da2ea9a10
9 changed files with 213 additions and 66 deletions
  1. +3
    -5
      src/client/js/objects/objBase.js
  2. +1
    -1
      src/client/js/objects/objects.js
  3. +52
    -0
      src/server/clientComponents/effects/shield.js
  4. +100
    -48
      src/server/clientComponents/stats.js
  5. +8
    -8
      src/server/components/effects.js
  6. +4
    -0
      src/server/config/clientConfig.js
  7. +33
    -0
      src/server/config/effects/effectShield.js
  8. +6
    -2
      src/server/config/effects/effectTemplate.js
  9. +6
    -2
      src/server/mods/class-necromancer/spells/spellBloodBarrier.js

+ 3
- 5
src/client/js/objects/objBase.js View File

@@ -105,7 +105,7 @@ define([
});

if (stats)
stats.updateHpSprite();
stats.updateBars();
},

updateVisibility: function () {
@@ -138,10 +138,8 @@ define([
if (this.nameSprite)
this.nameSprite.visible = (visible && config.showNames);

if (!visible && this.stats && this.stats.hpSprite && this.stats.hpSprite.visible) {
this.stats.hpSprite.visible = false;
this.stats.hpSpriteInner.visible = false;
}
if (!visible && this.stats)
this.stats.updateBarVisibility(false);

this.components.forEach(c => {
if (c.setVisible)


+ 1
- 1
src/client/js/objects/objects.js View File

@@ -260,7 +260,7 @@ define([
obj.setSpritePosition();

if (obj.stats)
obj.stats.updateHpSprite();
obj.stats.updateBars();
}
},



+ 52
- 0
src/server/clientComponents/effects/shield.js View File

@@ -0,0 +1,52 @@
define([

], function (

) {
const shieldEffect = {
bar: null,
visible: true,

amount: 1,
maxAmount: 1,

init: function () {
if (this.obj.stats) {
this.bar = this.obj.stats.addBar({
color: 0x533399,
innerColor: 0xa24eff,
calcPercent: () => (this.amount / this.maxAmount),
isVisible: () => this.visible
});

this.obj.stats.updateBars();
}
},

extend: function (data) {
this.amount = data.amount;
this.maxAmount = data.maxAmount;

if (this.obj.stats)
this.obj.stats.updateBars();
},

destroy: function () {
if (this.bar && this.obj.stats)
this.obj.stats.removeBar(this.bar);
},

setVisible: function (visible) {
this.visible = visible;

if (this.obj.stats)
this.obj.stats.updateBars();
}
};

return {
templates: {
shield: shieldEffect
}
};
});

+ 100
- 48
src/server/clientComponents/stats.js View File

@@ -5,16 +5,15 @@ define([
events,
renderer
) {
const hpBarPadding = scaleMult;
const hpBarHeight = scaleMult;
const barPadding = scaleMult;
const barHeight = scaleMult;

return {
type: 'stats',

values: null,

hpSprite: null,
hpSpriteInner: null,
bars: [],

init: function (blueprint) {
if (this.obj.self)
@@ -25,66 +24,125 @@ define([

let obj = this.obj;

this.hpSprite = renderer.buildRectangle({
this.addBar({
color: 0x802343,
innerColor: 0xd43346,
calcPercent: () => (this.values.hp / this.values.hpMax),
isVisible: () => (this.values.hp < this.values.hpMax) && (!obj.sprite || obj.sprite.visible)
});

this.updateBars();
},

addBar: function (config) {
let obj = this.obj;

let { color, innerColor, calcPercent, isVisible } = config;

let sprite = renderer.buildRectangle({
layerName: 'effects',
x: obj.x * scale,
y: obj.y * scale,
w: 1,
h: 1,
color: 0x802343
color: color
});

this.hpSpriteInner = renderer.buildRectangle({
x: 0,
y: 0,
let spriteInner = renderer.buildRectangle({
layerName: 'effects',
x: obj.x,
y: obj.y,
w: 1,
h: 1,
layerName: 'effects',
color: 0xd43346
color: innerColor
});

let bar = {
sprite: sprite,
spriteInner: spriteInner,
calcPercent: calcPercent,
isVisible: isVisible
};
this.bars.push(bar);

return bar;
},

removeBar: function (bar) {
this.removeSprites(this.bars.find(b => b === bar));

this.bars.spliceFirstWhere(b => b === bar);
},

removeSprites: function (bar) {
renderer.destroyObject({
sprite: bar.sprite,
layerName: 'effects'
});

this.updateHpSprite();
renderer.destroyObject({
sprite: bar.spriteInner,
layerName: 'effects'
});
},

updateHpSprite: function () {
updateBars: function () {
const { obj: { x, y, dead, sprite } } = this;

if (dead)
return;
let barIndex = 0;

//By default, hp sprites are 10px higher than the owner object's sprite. Keeping in
// mind that bigger sprites always have their 'origin' in the bottom middle tile
const spriteHeight = sprite ? sprite.height : scale;
const spriteWidth = sprite ? sprite.width : scale;
this.bars.forEach(bar => {
const percent = bar.calcPercent();

const xOffset = -(spriteWidth - scale) / 2;
const yOffset = -(spriteHeight - scale) - (scaleMult * 2);
//By default, hp sprites are 10px higher than the owner object's sprite. Keeping in
// mind that bigger sprites always have their 'origin' in the bottom middle tile
const spriteHeight = sprite ? sprite.height : scale;
const spriteWidth = sprite ? sprite.width : scale;

const hpBarWidth = spriteWidth - (hpBarPadding * 2);
const xOffset = -(spriteWidth - scale) / 2;
const yOffset = -(spriteHeight - scale) - ((barIndex + 1) * scaleMult * 2);

const newX = (x * scale) + hpBarPadding + xOffset;
const newY = (y * scale) + yOffset;
const barWidth = spriteWidth - (barPadding * 2);

renderer.moveRectangle({
sprite: this.hpSprite,
x: newX,
y: newY,
w: hpBarWidth,
h: hpBarHeight
});
const newX = (x * scale) + barPadding + xOffset;
const newY = (y * scale) + yOffset;

renderer.moveRectangle({
sprite: bar.sprite,
x: newX,
y: newY,
w: barWidth,
h: barHeight
});

renderer.moveRectangle({
sprite: bar.spriteInner,
x: newX,
y: newY,
w: percent * barWidth,
h: barHeight
});

const isVisible = bar.isVisible ? bar.isVisible() : true;

renderer.moveRectangle({
sprite: this.hpSpriteInner,
x: newX,
y: newY,
w: (this.values.hp / this.values.hpMax) * hpBarWidth,
h: hpBarHeight
if (isVisible)
barIndex++;

bar.sprite.visible = isVisible;
bar.spriteInner.visible = isVisible;
});
},

const isVisible = (this.values.hp < this.values.hpMax) && (!sprite || sprite.visible);
updateBarVisibility: function (visible) {
this.bars.forEach(bar => {
const isVisible = (visible !== undefined) ? visible : bar.isVisible();

this.hpSprite.visible = isVisible;
this.hpSpriteInner.visible = isVisible;
bar.sprite.visible = isVisible;
bar.spriteInner.visible = isVisible;
});
},

extend: function (blueprint) {
@@ -101,18 +159,12 @@ define([
if (this.obj.has('serverId'))
events.emit('onGetPartyStats', this.obj.serverId, this.values);

this.updateHpSprite();
this.updateBars();
},

destroy: function () {
renderer.destroyObject({
sprite: this.hpSprite,
layerName: 'effects'
});

renderer.destroyObject({
sprite: this.hpSpriteInner,
layerName: 'effects'
this.bars.forEach(bar => {
this.removeSprites(bar);
});
}
};


+ 8
- 8
src/server/components/effects.js View File

@@ -152,7 +152,7 @@ module.exports = {
//If there is no existing effect or the effect is not stackable, make a new effect
if (!oldEffect || !oldEffect.shouldStack)
return this.buildEffect(options);
//If the effect is stackable and the new effect should stack, stack with the old effect
let shouldStack = oldEffect.shouldStack(options);
if (shouldStack && oldEffect.incrementStack) {
@@ -184,18 +184,18 @@ module.exports = {
buildEffect: function (options) {
let builtEffect = this.getTypeTemplate(options.type);

for (let p in options)
for (let p in options)
builtEffect[p] = options[p];
builtEffect.obj = this.obj;
builtEffect.id = this.nextId++;
builtEffect.silent = options.silent;

this.effects.push(builtEffect);

if (builtEffect.init)
builtEffect.init(options.source);

this.effects.push(builtEffect);

if (!options.silent)
this.obj.syncer.setArray(false, 'effects', 'addEffects', builtEffect.simplify());

@@ -204,7 +204,7 @@ module.exports = {
return builtEffect;
},

syncExtend: function (id, data) {
syncExtend: function (id, data, self) {
let effect = this.effects.find(e => e.id === id);
if (!effect)
return;
@@ -213,7 +213,7 @@ module.exports = {
if (effect.silent)
return;

this.obj.syncer.setArray(true, 'effects', 'extendEffects', {
this.obj.syncer.setArray(self, 'effects', 'extendEffects', {
id,
data
});
@@ -241,7 +241,7 @@ module.exports = {
this.destroyEffect(effect);

this.syncRemove(effect.id);
this.effects.spliceWhere(e => e.id === id);
},



+ 4
- 0
src/server/config/clientConfig.js View File

@@ -227,6 +227,10 @@ module.exports = {
extends: 'effects',
path: 'server/clientComponents/effects/auras.js'
});
config.clientComponents.push({
extends: 'effects',
path: 'server/clientComponents/effects/shield.js'
});

events.emit('onBeforeGetClientConfig', config);



+ 33
- 0
src/server/config/effects/effectShield.js View File

@@ -0,0 +1,33 @@
module.exports = {
type: 'shield',

amount: 0,
maxAmount: 0,

init: function () {
this.syncExtend({
amount: this.amount,
maxAmount: this.maxAmount
});
},

events: {
beforeTakeDamage: function (damage, source) {
if (this.amount > 0) {
let mitigatedAmount = Math.min(damage.amount, this.amount);

damage.amount -= mitigatedAmount;
this.amount -= mitigatedAmount;

//Sync new values to client
this.syncExtend({
amount: this.amount,
maxAmount: this.maxAmount
});
}

if (this.amount <= 0)
this.destroyed = true;
}
}
};

+ 6
- 2
src/server/config/effects/effectTemplate.js View File

@@ -1,7 +1,11 @@
module.exports = {
syncExtend: function (data) {
let effects = this.obj.effects;
effects.syncExtend(this.id, data);
effects.syncExtend(this.id, data, false);
},
syncExtendSelf: function (data) {
let effects = this.obj.effects;
effects.syncExtend(this.id, data, true);
},

isFirstOfType: function () {
@@ -34,5 +38,5 @@ module.exports = {
id: this.id,
type: this.type
};
}
}
};

+ 6
- 2
src/server/mods/class-necromancer/spells/spellBloodBarrier.js View File

@@ -39,8 +39,12 @@ module.exports = {
obj.stats.takeDamage(damage, 0, obj);

amount = amount * this.shieldMultiplier;
const heal = { amount };
target.stats.getHp(heal, obj);
target.effects.addEffect({
type: 'shield',
ttl: this.frenzyDuration,
amount: amount,
maxAmount: amount
});

//Only reset the first spell's cooldown if it's an auto attack and not a spell
const firstSpell = target.spellbook.spells[0];


Loading…
Cancel
Save