alclient
Version:
A node client for interacting with Adventure Land - The Code MMORPG. This package extends the functionality of 'alclient' by managing a mongo database.
230 lines • 7.29 kB
JavaScript
import { Tools } from "./Tools.js";
import { Constants } from "./Constants.js";
import { TradeItem } from "./TradeItem.js";
export class Player {
G;
afk;
id;
ctype;
abs;
angle;
armor = 0;
apiercing = 0;
attack;
avoidance = 0;
cid;
crit = 0;
critdamage = 0;
damage_type;
evasion = 0;
frequency;
going_x;
going_y;
heal;
level = 1;
move_num;
moving;
name;
party;
reflection = 0;
resistance = 0;
rpiercing = 0;
target;
team;
x;
y;
s = {};
c = {};
cx;
focus;
hp;
max_hp;
max_mp;
mp;
npc;
owner;
pdps;
q = {};
range;
rip;
skin;
slots;
speed;
stand;
tp;
// Soft Properties
in;
map;
width = Constants.CHARACTER_WIDTH;
height = Constants.CHARACTER_HEIGHT;
constructor(data, map, instance, g) {
this.G = g;
// Set soft properties
this.map = map;
this.in = instance;
if (!data.npc)
this.damage_type = this.G.classes[data.ctype].damage_type;
// Set everything else
this.updateData(data);
}
updateData(data) {
if (this.id !== undefined && this.id !== data.id)
throw new Error("The entity's ID does not match");
// Set everything
for (const key in data)
this[key] = data[key];
}
calculateDamageRange(defender, skill = "attack") {
const gSkill = this.G.skills[skill];
// If the entity is immune, most skills won't do damage
if (defender.immune && skill !== "attack" && !gSkill?.pierces_immunity)
return [0, 0];
if (defender["1hp"] || skill == "taunt")
return this.crit ? [1, 2] : [1, 1];
let baseDamage = this.attack;
if (skill == "heal")
baseDamage = this.heal;
if (!gSkill)
console.debug(`calculateDamageRange DEBUG: '${skill}' isn't a skill!?`);
if (gSkill?.damage)
baseDamage = gSkill.damage;
// NOTE: I asked Wizard to add something to G.conditions.cursed and .marked so we don't need these hardcoded.
if (defender.s.cursed)
baseDamage *= 1.2;
if (defender.s.marked)
baseDamage *= 1.1;
const damage_type = gSkill[skill]?.damage_type ?? this.damage_type;
let additionalApiercing = 0;
if (gSkill?.apiercing)
additionalApiercing = gSkill.apiercing;
// NOTE: currently no skills with rpiercing
// let additionalRpiercing = 0
// if (gSkill?.rpiercing) additionalRpiercing = gSkill.rpiercing
if (damage_type == "physical")
baseDamage *= Tools.damage_multiplier(defender.armor - this.apiercing - additionalApiercing);
else if (damage_type == "magical")
baseDamage *= Tools.damage_multiplier(defender.resistance - this.rpiercing /** - additionalRpiercing */);
if (gSkill?.damage_multiplier)
baseDamage *= gSkill.damage_multiplier;
let lowerLimit = baseDamage * 0.9;
let upperLimit = baseDamage * 1.1;
if (this.crit) {
if (this.crit >= 100) {
lowerLimit *= 2 + this.critdamage / 100;
}
upperLimit *= 2 + this.critdamage / 100;
}
// NOTE: This information is from @Wizard on Discord on May 1st, 2020
// https://discord.com/channels/238332476743745536/243707345887166465/705722706250694737
if (skill == "cleave") {
lowerLimit *= 0.1;
upperLimit *= 0.9;
}
return [lowerLimit, upperLimit];
}
/**
* Returns the items that the player is selling in their trade slots.
*
* @see getWantedItems for items the player is buying
*/
getItemsForSale() {
const slots = new Map();
for (const s in this.slots) {
const slot = s;
const item = this.slots[slot];
if (!item)
continue; // Nothing in the slot
if (!item.rid)
continue; // Not a trade item
if (item.b)
continue; // They are buying, not selling
slots.set(slot, new TradeItem(item, this.G));
}
return slots;
}
/**
* Returns the items that the player is purchasing in their trade slots
*
* @see getItemsForSale for items the player is selling
*/
getWantedItems() {
const slots = new Map();
for (const s in this.slots) {
const slot = s;
const item = this.slots[slot];
if (!item)
continue; // Nothing in the slot
if (!item.rid)
continue; // Not a trade item
if (!item.b)
continue; // They are selling, not buying
slots.set(slot, new TradeItem(item, this.G));
}
return slots;
}
/**
* Returns true if the player is attacking us, or one of our party members
* @param player The player whose party to check if they are attacking
*/
isAttackingPartyMember(player) {
// Check if the entity is targeting anything
if (this.target == undefined)
return false;
// Check if the entity is attacking us
// NOTE: I don't want to get in to the semantics if we are actually in a party, I'm assuming if we aren't in a party, we're a party of "1".
if (this.isAttackingUs(player))
return true;
// Check if the entity is targeting a party member
if (player?.partyData?.list?.includes(this.target))
return true;
return false;
}
/**
* Returns true if they are attacking us specifically, false otherwise
* @param player The player to check if they are attacking
*/
isAttackingUs(player) {
return this.target == player.id;
}
/**
* If the player is disabled, they cannot move or attack
* @returns If the player is disabled
*/
isDisabled() {
return this.rip || (this.s.stunned || this.s.fingered || this.s.deepfreezed || this.s.sleeping) !== undefined;
}
/**
* Returns true if the player is "friendly", for example, if it's one of our characters, in our party, or in our friends list.
* @param character Our character (e.g.: bot.character)
*/
isFriendly(bot) {
// Check if it's an NPC
if (this.npc)
return true;
// Check if it's us
if (bot.id == this.id)
return true;
// Check if we're the owner
if (this.owner && bot.owner == this.owner)
return true;
// Check if we're in the same party
if (this.party && bot.party == this.party)
return true;
// Check if we're on the same team
if (this.team && bot.team == this.team)
return true;
// TODO: Check if they're in our friends list
// They're not friendly >:(
return false;
}
/**
* Returns true if this player is an NPC.
*
* @return {*} {boolean}
* @memberof Player
*/
isNPC() {
return this.npc !== undefined;
}
}
//# sourceMappingURL=Player.js.map