Merge pull request #104 from earthiverse/range-fix

Fix infinite range for `curse`, `cburst`, and `3shot`/`5shot`
This commit is contained in:
Kaan Soral
2024-02-21 16:05:32 +03:00
committed by GitHub
2 changed files with 56 additions and 52 deletions
+9
View File
@@ -221,6 +221,7 @@ skills={
"cooldown":60000, "cooldown":60000,
"target":"monster", "target":"monster",
"hostile":True, "hostile":True,
"use_range":True,
}, },
"tangle":{ "tangle":{
"type":"skill", "type":"skill",
@@ -232,6 +233,8 @@ skills={
"cooldown":60000, "cooldown":60000,
"target":True, "target":True,
"hostile":True, "hostile":True,
"use_range":True,
"range_multiplier":2,
}, },
"rspeed":{ "rspeed":{
"type":"skill", "type":"skill",
@@ -606,6 +609,9 @@ skills={
"cooldown":10000, "cooldown":10000,
"target":True, "target":True,
"hostile":True, "hostile":True,
"range_multiplier":3,
"range_bonus":20,
"use_range": True
}, },
"pcoat":{ "pcoat":{
"type":"skill", "type":"skill",
@@ -644,6 +650,7 @@ skills={
"warning":"Highly unbalanced skill, could get nerfed or modified", "warning":"Highly unbalanced skill, could get nerfed or modified",
"hostile":True, "hostile":True,
"projectile":"mentalburst", "projectile":"mentalburst",
"use_range":True,
}, },
"quickpunch":{ "quickpunch":{
"type":"skill", "type":"skill",
@@ -748,6 +755,7 @@ skills={
"pierces_immunity":True, "pierces_immunity":True,
"damage_type":"physical", "damage_type":"physical",
"procs":True, "procs":True,
"use_range":True,
}, },
"3shot":{ "3shot":{
"type":"skill", "type":"skill",
@@ -810,6 +818,7 @@ skills={
"name":"Curse", "name":"Curse",
"explanation":"Cursed opponents receive 20% more damage, deal 20% less damage and they slow down by 20.", "explanation":"Cursed opponents receive 20% more damage, deal 20% less damage and they slow down by 20.",
"mp":400, "mp":400,
"range":200,
"duration":5000, "duration":5000,
"cooldown":5000, "cooldown":5000,
"condition":"cursed", "condition":"cursed",
+47 -52
View File
@@ -2886,9 +2886,6 @@ function commence_attack(attacker, target, atype) {
} else if (atype == "cburst") { } else if (atype == "cburst") {
var mp_cutoff = attacker.next_mp; var mp_cutoff = attacker.next_mp;
var mp = attacker.next_mp; var mp = attacker.next_mp;
if (atype == "cburst") {
mp = mp_cutoff = attacker.next_mp;
}
if (attacker.mp < mp_cutoff) { if (attacker.mp < mp_cutoff) {
attacker.socket.emit("game_response", { response: "no_mp" }); attacker.socket.emit("game_response", { response: "no_mp" });
return { failed: true, reason: "no_mp", place: atype, id: target.id }; return { failed: true, reason: "no_mp", place: atype, id: target.id };
@@ -8259,7 +8256,8 @@ function init_io() {
} }
// Range check // Range check
if (target && (gSkill.range || gSkill.use_range)) { const isTargetTooFar = (target) => {
// Use the range of the skill, falling back to the player range if it isn't set
let range = gSkill.range || player.range; let range = gSkill.range || player.range;
if (gSkill.range_multiplier) { if (gSkill.range_multiplier) {
range *= gSkill.range_multiplier; range *= gSkill.range_multiplier;
@@ -8274,12 +8272,16 @@ function init_io() {
const dist = distance(player, target); const dist = distance(player, target);
if (dist > range + player.xrange) { if (dist > range + player.xrange) {
return fail_response("too_far", data.name, { dist: dist, id: target.id }); return true;
} }
if (dist > range) { if (dist > range) {
// xrange was used, reduce it by however much we used // xrange was used, reduce it by however much we used
player.xrange -= dist - range; player.xrange -= dist - range;
} }
return false;
};
if (target && isTargetTooFar(target)) {
return fail_response("too_far", data.name, { dist: dist, id: target.id });
} }
// Consume item check // Consume item check
@@ -8573,37 +8575,41 @@ function init_io() {
resend(target, "u+cid"); resend(target, "u+cid");
} }
} else if (data.name == "cburst") { } else if (data.name == "cburst") {
var hit = {}; var targeted = {};
var times = 0;
var attack = null; var attack = null;
var c_resolve = null; var c_resolve = null;
consume_mp(player, gSkill.mp); consume_mp(player, gSkill.mp);
player.first_burst = true; player.first_burst = true;
player.halt = true; player.halt = true;
if (is_array(data.targets)) { if (is_array(data.targets)) {
data.targets.forEach(function (t) { // Only look at the first 16 targets in the array if more are provided
// console.log(id); for (const t of data.targets.slice(0, 16)) {
var id = t[0]; const id = t[0];
var mp = max(0, parseInt(t[1]) || 0);
if (player.mp < 20 || times > 16 || !mp) { // Prevent attacking the same entity twice
return; if (targeted[id]) {
continue;
} }
times += 1; targeted[id] = true;
var target = instances[player.in].monsters[id];
const mp = max(0, parseInt(t[1]) || 0);
if (mp <= 0) {
continue;
}
let target = instances[player.in].monsters[id];
if (!target) { if (!target) {
target = instances[player.in].players[id]; target = instances[player.in].players[id];
} }
if (!target || is_invinc(target) || target.name == player.name) { if (!target || is_invinc(target) || target.name == player.name) {
return; continue;
} }
if (hit[id]) { if (isTargetTooFar(target)) {
return; continue;
} }
hit[id] = true;
player.next_mp = mp; player.next_mp = mp;
attack = commence_attack(player, target, "cburst"); attack = commence_attack(player, target, "cburst");
if (!attack || !attack.projectile) { if (!attack || !attack.projectile) {
return; continue;
} }
if (!c_resolve) { if (!c_resolve) {
c_resolve = attack; c_resolve = attack;
@@ -8613,14 +8619,12 @@ function init_io() {
c_resolve.pids.push(attack.pid); c_resolve.pids.push(attack.pid);
c_resolve.targets.push(attack.target); c_resolve.targets.push(attack.target);
} }
}); }
} }
player.halt = false; player.halt = false;
player.to_resend = "u+cid"; player.to_resend = "u+cid";
if (!c_resolve) { if (!c_resolve) {
if (attack) { reject = { failed: true, place: data.name, reason: "no_target" };
reject = attack;
}
disappearing_text(player.socket, player, "NO HITS"); disappearing_text(player.socket, player, "NO HITS");
} else { } else {
resolve = c_resolve; resolve = c_resolve;
@@ -8662,40 +8666,34 @@ function init_io() {
xy_emit(player, "ui", { type: data.name }); xy_emit(player, "ui", { type: data.name });
} else if (data.name == "3shot" || data.name == "5shot") { } else if (data.name == "3shot" || data.name == "5shot") {
player.halt = true; player.halt = true;
var times = 0; const targeted = {};
var hit = {}; let c_resolve = null;
var reftarget = null;
var targets = 3;
var attack = null;
var c_resolve = null;
if (data.name == "5shot") {
targets = 5;
}
//console.log(data.ids); //console.log(data.ids);
if (is_array(data.ids)) { if (is_array(data.ids)) {
data.ids.forEach(function (id) { // Only look at the first Xshot targets in the array if more are provided
if (times >= targets) { for (const id of data.ids.slice(0, data.name === "5shot" ? 5 : 3)) {
return; // Prevent attacking the same entity twice
if (targeted[id]) {
continue;
} }
times += 1; targeted[id] = true;
var target = instances[player.in].monsters[id];
target = instances[player.in].monsters[id];
if (!target) { if (!target) {
target = instances[player.in].players[id]; target = instances[player.in].players[id];
} }
if (!target || is_invinc(target) || target.name == player.name) { if (!target || is_invinc(target) || target.name == player.name) {
attack = { failed: true, place: data.name, reason: "no_target" }; continue;
return;
} }
if (hit[id]) { if (isTargetTooFar(target)) {
return; continue;
} }
hit[id] = true; const attack = commence_attack(player, target, data.name);
attack = commence_attack(player, target, data.name);
if (!attack || !attack.projectile) { if (!attack || !attack.projectile) {
return; continue;
} }
if (!c_resolve) { if (!c_resolve) {
reftarget = target;
c_resolve = attack; c_resolve = attack;
attack.pids = [attack.pid]; attack.pids = [attack.pid];
attack.targets = [attack.target]; attack.targets = [attack.target];
@@ -8703,16 +8701,13 @@ function init_io() {
c_resolve.pids.push(attack.pid); c_resolve.pids.push(attack.pid);
c_resolve.targets.push(attack.target); c_resolve.targets.push(attack.target);
} }
// if(times==1 && attack==null) times=40; }
});
} }
consume_mp(player, gSkill.mp, reftarget);
player.halt = false; player.halt = false;
player.to_resend = "u+cid"; player.to_resend = "u+cid";
consume_mp(player, gSkill.mp, target);
if (!c_resolve) { if (!c_resolve) {
if (attack) { reject = { failed: true, place: data.name, reason: "no_target" };
reject = attack;
}
disappearing_text(player.socket, player, "NO HITS"); disappearing_text(player.socket, player, "NO HITS");
} else { } else {
resolve = c_resolve; resolve = c_resolve;