Working implementation of sending exact damage for own pokemon

This isn't as elegant as I might like, but it does appear to work.
This commit is contained in:
Cathy J. Fitzpatrick 2013-04-09 01:36:12 -06:00
parent d297e1a283
commit cbfc3e5e16
10 changed files with 115 additions and 61 deletions

View File

@ -130,6 +130,13 @@ var BattlePokemon = (function() {
this.battle = side.battle;
if (typeof set === 'string') set = {name: set};
// "prebound" function for nicer syntax (avoids use of `bind`)
this.getHealth = (function(self) {
return function(side) {
return BattlePokemon.getHealth.call(self, side);
};
})(this);
this.set = set;
this.baseTemplate = this.battle.getTemplate(set.species || set.name);
@ -284,9 +291,10 @@ var BattlePokemon = (function() {
if (this.isActive) return fullname.substr(0,2) + positionList[this.position] + fullname.substr(2);
return fullname;
};
BattlePokemon.prototype.getDetails = function() {
if (this.illusion) return this.illusion.details + '|' + this.getHealth();
return this.details + '|' + this.getHealth();
// "static" function
BattlePokemon.getDetails = function(side) {
if (this.illusion) return this.illusion.details + '|' + this.getHealth(side);
return this.details + '|' + this.getHealth(side);
};
BattlePokemon.prototype.update = function(init) {
// reset for Light Metal etc
@ -921,19 +929,11 @@ var BattlePokemon = (function() {
this.update();
return true;
};
BattlePokemon.prototype.getHealth = function(realHp) {
if (!realHp) {
for (var i in this.battle.sides) {
if (this.battle.sides[i] === this.side) {
this.battle.sides[i].exactHealth.push(''+this.hp+'/'+this.maxhp+' '+this.status);
} else {
this.battle.sides[i].exactHealth.push('');
}
}
}
// "static" function
BattlePokemon.getHealth = function(side) {
if (!this.hp) return '0 fnt';
var hpstring;
if (realHp || this.battle.getFormat().debug) {
if ((this.side === side) || this.battle.getFormat().debug) {
hpstring = ''+this.hp+'/'+this.maxhp;
} else {
var ratio = this.hp / this.maxhp;
@ -991,9 +991,6 @@ var BattleSide = (function() {
this.active = [null];
this.sideConditions = {};
// stores exact health for use in the health queue
this.exactHealth = [];
this.id = (n?'p2':'p1');
switch (this.battle.gameType) {
@ -1024,16 +1021,14 @@ var BattleSide = (function() {
BattleSide.prototype.getData = function() {
var data = {
name: this.name,
pokemon: [],
exactHealth: this.exactHealth.join(',')
pokemon: []
};
this.exactHealth = [];
for (var i=0; i<this.pokemon.length; i++) {
var pokemon = this.pokemon[i];
data.pokemon.push({
ident: pokemon.fullname,
details: pokemon.details,
condition: pokemon.getHealth(true),
condition: pokemon.getHealth(pokemon.side),
active: (pokemon.position < pokemon.side.active.length),
moves: pokemon.moves.map(function(move) {
if (move === 'hiddenpower') {
@ -2016,7 +2011,7 @@ var Battle = (function() {
for (var m in pokemon.moveset) {
pokemon.moveset[m].used = false;
}
this.add('switch', side.active[pos], side.active[pos].getDetails());
this.add('switch', side.active[pos], BattlePokemon.getDetails.bind(side.active[pos]));
pokemon.update();
this.runEvent('SwitchIn', pokemon);
this.addQueue({pokemon: pokemon, choice: 'runSwitch'});
@ -2071,7 +2066,7 @@ var Battle = (function() {
for (var m in pokemon.moveset) {
pokemon.moveset[m].used = false;
}
this.add('drag', side.active[pos], side.active[pos].getDetails());
this.add('drag', side.active[pos], BattlePokemon.getDetails.bind(side.active[pos]));
pokemon.update();
this.runEvent('SwitchIn', pokemon);
this.addQueue({pokemon: pokemon, choice: 'runSwitch'});
@ -2206,7 +2201,7 @@ var Battle = (function() {
if (target.illusion && effect && effect.effectType === 'Move') {
this.debug('illusion cleared');
target.illusion = null;
this.add('replace', target, target.getDetails());
this.add('replace', target, BattlePokemon.getDetails.bind(target));
}
}
if (damage !== 0) damage = clampIntRange(damage, 1);
@ -2216,15 +2211,15 @@ var Battle = (function() {
if (name === 'tox') name = 'psn';
switch (effect.id) {
case 'partiallytrapped':
this.add('-damage', target, target.getHealth(), '[from] '+this.effectData.sourceEffect.fullname, '[partiallytrapped]');
this.add('-damage', target, target.getHealth, '[from] '+this.effectData.sourceEffect.fullname, '[partiallytrapped]');
break;
default:
if (effect.effectType === 'Move') {
this.add('-damage', target, target.getHealth());
this.add('-damage', target, target.getHealth);
} else if (source && source !== target) {
this.add('-damage', target, target.getHealth(), '[from] '+effect.fullname, '[of] '+source);
this.add('-damage', target, target.getHealth, '[from] '+effect.fullname, '[of] '+source);
} else {
this.add('-damage', target, target.getHealth(), '[from] '+name);
this.add('-damage', target, target.getHealth, '[from] '+name);
}
break;
}
@ -2258,10 +2253,10 @@ var Battle = (function() {
damage = target.damage(damage, source, effect);
switch (effect.id) {
case 'strugglerecoil':
this.add('-damage', target, target.getHealth(), '[from] recoil');
this.add('-damage', target, target.getHealth, '[from] recoil');
break;
default:
this.add('-damage', target, target.getHealth());
this.add('-damage', target, target.getHealth);
break;
}
if (target.fainted) this.faint(target);
@ -2285,20 +2280,20 @@ var Battle = (function() {
switch (effect.id) {
case 'leechseed':
case 'rest':
this.add('-heal', target, target.getHealth(), '[silent]');
this.add('-heal', target, target.getHealth, '[silent]');
break;
case 'drain':
this.add('-heal', target, target.getHealth(), '[from] drain', '[of] '+source);
this.add('-heal', target, target.getHealth, '[from] drain', '[of] '+source);
break;
case 'wish':
break;
default:
if (effect.effectType === 'Move') {
this.add('-heal', target, target.getHealth());
this.add('-heal', target, target.getHealth);
} else if (source && source !== target) {
this.add('-heal', target, target.getHealth(), '[from] '+effect.fullname, '[of] '+source);
this.add('-heal', target, target.getHealth, '[from] '+effect.fullname, '[of] '+source);
} else {
this.add('-heal', target, target.getHealth(), '[from] '+effect.fullname);
this.add('-heal', target, target.getHealth, '[from] '+effect.fullname);
}
break;
}
@ -3142,7 +3137,28 @@ var Battle = (function() {
return decisions;
};
Battle.prototype.add = function() {
this.log.push('|'+Array.prototype.slice.call(arguments).join('|'));
var parts = Array.prototype.slice.call(arguments);
var functions = parts.map(function(part) {
return typeof part === 'function';
});
if (functions.indexOf(true) < 0) {
this.log.push('|'+parts.join('|'));
} else {
this.log.push('|split');
var sides = this.sides.concat(null);
for (var i = 0; i < sides.length; ++i) {
var line = '';
for (var j = 0; j < parts.length; ++j) {
line += '|';
if (functions[j]) {
line += parts[j](sides[i]);
} else {
line += parts[j];
}
}
this.log.push(line);
}
}
};
Battle.prototype.addMove = function() {
this.lastMoveLine = this.log.length;

View File

@ -802,7 +802,7 @@ function parseCommandLocal(user, cmd, target, room, socket, message) {
case 'savereplay':
if (!room || !room.battle) return false;
var data = room.log.join("\n");
var data = room.getLog(2).join("\n");
var datahash = crypto.createHash('md5').update(data.replace(/[^(\x20-\x7F)]+/g,'')).digest('hex');
LoginServer.request('prepreplay', {

View File

@ -2517,7 +2517,7 @@ exports.BattleAbilities = {
onTryHit: function(target, source, move) {
if (target !== source && move.type === 'Electric') {
var d = target.heal(target.maxhp/4);
this.add('-heal',target,target.getHealth(),'[from] ability: Volt Absorb');
this.add('-heal',target,target.getHealth,'[from] ability: Volt Absorb');
return null;
}
},
@ -2532,7 +2532,7 @@ exports.BattleAbilities = {
onTryHit: function(target, source, move) {
if (target !== source && move.type === 'Water') {
var d = target.heal(target.maxhp/4);
this.add('-heal',target,target.getHealth(),'[from] ability: Water Absorb');
this.add('-heal',target,target.getHealth,'[from] ability: Water Absorb');
return null;
}
},

View File

@ -5131,7 +5131,7 @@ exports.BattleMovedex = {
var source = this.effectData.source;
var damage = target.heal(target.maxhp);
target.setStatus('');
this.add('-heal',target,target.getHealth(),'[from] move: Healing Wish');
this.add('-heal',target,target.getHealth,'[from] move: Healing Wish');
target.side.removeSideCondition('healingwish');
}
}
@ -6719,7 +6719,7 @@ exports.BattleMovedex = {
for (var m in target.moveset) {
target.moveset[m].pp = target.moveset[m].maxpp;
}
this.add('-heal',target,target.getHealth(),'[from] move: Lunar Dance');
this.add('-heal',target,target.getHealth,'[from] move: Lunar Dance');
target.side.removeSideCondition('lunardance');
}
}
@ -7968,7 +7968,7 @@ exports.BattleMovedex = {
var averagehp = Math.floor((target.hp + pokemon.hp) / 2) || 1;
target.sethp(averagehp);
pokemon.sethp(averagehp);
this.add('-sethp', target, target.getHealth(), pokemon, pokemon.getHealth(), '[from] move: Pain Split');
this.add('-sethp', target, target.getHealth, pokemon, pokemon.getHealth, '[from] move: Pain Split');
},
secondary: false,
target: "normal",
@ -13250,7 +13250,7 @@ exports.BattleMovedex = {
if (!target.fainted) {
var source = this.effectData.source;
var damage = this.heal(this.effectData.hp, target, target);
if (damage) this.add('-heal', target, target.getHealth(), '[from] move: Wish', '[wisher] '+source.name);
if (damage) this.add('-heal', target, target.getHealth, '[from] move: Wish', '[wisher] '+source.name);
}
}
},

View File

@ -385,7 +385,7 @@ exports.BattleScripts = {
this.debug('heal interrupted');
return false;
}
this.add('-heal', target, target.getHealth());
this.add('-heal', target, target.getHealth);
didSomething = true;
}
if (moveData.status) {

View File

@ -442,7 +442,7 @@ exports.BattleScripts = {
this.add('-fail', target);
return false;
}
this.add('-heal', target, target.getHealth());
this.add('-heal', target, target.getHealth);
didSomething = true;
}
if (moveData.status) {
@ -800,15 +800,15 @@ exports.BattleScripts = {
if (name === 'tox') name = 'psn';
switch (effect.id) {
case 'partiallytrapped':
this.add('-damage', target, target.getHealth(), '[from] '+this.effectData.sourceEffect.fullname, '[partiallytrapped]');
this.add('-damage', target, target.getHealth, '[from] '+this.effectData.sourceEffect.fullname, '[partiallytrapped]');
break;
default:
if (effect.effectType === 'Move') {
this.add('-damage', target, target.getHealth());
this.add('-damage', target, target.getHealth);
} else if (source && source !== target) {
this.add('-damage', target, target.getHealth(), '[from] '+effect.fullname, '[of] '+source);
this.add('-damage', target, target.getHealth, '[from] '+effect.fullname, '[of] '+source);
} else {
this.add('-damage', target, target.getHealth(), '[from] '+name);
this.add('-damage', target, target.getHealth, '[from] '+name);
}
break;
}

View File

@ -255,7 +255,7 @@ Oh, and one more thing: I didn't alter the descriptions much, if at all, on the
onImmunity: function(type, pokemon) {
if (type === 'Electric') {
var d = pokemon.heal(pokemon.maxhp/4);
this.add('-heal',pokemon,pokemon.getHealth(),'[from] ability: Volt Absorb');
this.add('-heal',pokemon,pokemon.getHealth,'[from] ability: Volt Absorb');
return null;
}
},

View File

@ -922,7 +922,7 @@ exports.BattleMovedex = {
if (!target.fainted) {
var source = this.effectData.source;
var damage = this.heal(target.maxhp/2, target, target);
if (damage) this.add('-heal', target, target.getHealth(), '[from] move: Wish', '[wisher] '+source.name);
if (damage) this.add('-heal', target, target.getHealth, '[from] move: Wish', '[wisher] '+source.name);
}
}
}

View File

@ -740,7 +740,7 @@ exports.BattleMovedex = {
if (!target.fainted) {
var source = this.effectData.source;
var damage = this.heal(target.maxhp/2, target, target);
if (damage) this.add('-heal', target, target.getHealth(), '[from] move: Wish', '[wisher] '+source.name);
if (damage) this.add('-heal', target, target.getHealth, '[from] move: Wish', '[wisher] '+source.name);
}
}
}

View File

@ -141,23 +141,61 @@ var BattleRoom = (function() {
this.active = false;
this.update();
};
// idx = 0, 1 : player log
// idx = 2 : spectator log
BattleRoom.prototype.getLog = function(idx) {
var log = [];
for (var i = 0; i < this.log.length; ++i) {
var line = this.log[i];
if (line === '|split') {
log.push(this.log[i + idx + 1]);
i += 3;
} else {
log.push(line);
}
}
return log;
};
BattleRoom.prototype.getLogForUser = function(user) {
var slot = this.battle.getSlot(user);
if (slot < 0) slot = 2;
return this.getLog(slot);
};
BattleRoom.prototype.update = function(excludeUser) {
if (this.log.length < this.lastUpdate) return;
var updates = this.log.slice(this.lastUpdate);
var update = {
since: this.lastUpdate,
updates: updates,
active: this.active
var logs = [[], [], []];
var updateLines = this.log.slice(this.lastUpdate);
for (var i = 0; i < updateLines.length;) {
var line = updateLines[i++];
if (line === '|split') {
logs[0].push(updateLines[i++]); // player 0
logs[1].push(updateLines[i++]); // player 1
logs[2].push(updateLines[i++]); // spectators
} else {
logs[0].push(line);
logs[1].push(line);
logs[2].push(line);
}
}
var roomid = this.id;
var updates = logs.map(function(log) {
return {
room: roomid,
since: this.lastUpdate,
updates: log,
active: this.active
};
});
this.lastUpdate = this.log.length;
update.room = this.id;
var hasUsers = false;
for (var i in this.users) {
var user = this.users[i];
hasUsers = true;
if (user === excludeUser) continue;
user.emit('update', update);
var slot = this.battle.getSlot(user);
if (slot < 0) slot = 2;
user.emit('update', updates[slot]);
}
// empty rooms time out after ten minutes
@ -434,7 +472,7 @@ var BattleRoom = (function() {
room: this.id,
roomType: 'battle',
version: BATTLE_ROOM_PROTOCOL_VERSION,
battlelog: this.log
battlelog: this.getLogForUser(user)
};
emit(socket, 'init', initdata);
if (this.battle.requests[user.userid]) {
@ -461,7 +499,7 @@ var BattleRoom = (function() {
room: this.id,
roomType: 'battle',
version: BATTLE_ROOM_PROTOCOL_VERSION,
battlelog: this.log
battlelog: this.getLogForUser(user)
};
user.emit('init', initdata);