? Show All Error writing cache file
R
replace with picker()/at() of _/Sqimitive? 
R
rep.walkImpassable(cr, function (o) { 
B, R
for mapMove this currently plays one tick earlier (two ticks at the beginning before DOM.Map starts animating the movement, then each tick at N-1 when Map is animating N, then completion one tick earlier while Map is still playing animation); either mapMove ticks should be adjusted (e.g. transitionFace with tick of N, subsequent coords change at N+1, then transitionFace before next move at N+1, coords at N+2, etc.) or DOM.Map should play them differently 
R
297 corresponds to the inner area of Hchat-room__msgs; it's hardcoded for now because messages may be incoming before final node dimensions are known. The general intention is to create a max-width: 100%; max-height: 10em restriction while maintaining aspect ratio (something that these combined with explicit width; height; can't do). 
R
copy/paste of Sqimitive.Ordered.staticProps.indexFor(); could use toString() + replace() but that won't work when minified due to name mangling 
#ll R
Change "_.log && _.log(...)" paradigm to "_.L# && _.log(...)" where L# is a bunch of properties on _ (alike to _.debug) that toggle logging of specific channels (e.g. Map loading). This will also remove the need for oldLog() - log() will be always available. 
R
Previous rule was that Map doesn't change between first init and last render so it's possible to set up hooks in attach and iterate in render (like Bits.ObjectList does), but this is no longer correct and such old code (chiefly in DOM.Bits) should be updated. `#Module can produce "sub-modules". Each module is owned by a `#ModuleContainer (such as `#Context or `#Screen), not the module that has produced it. Children (`'nest()) of `#Module can be only other `#Module-s, not unrelated classes (such as `@DOM.Slider`@) - these must be stored in `#Module's properties, possibly in a separate `@Common.Sqimitive`@ collection. Submodules are automatically removed when `'this is removed and are removed from `'this when removed from `#ModuleContainer. However, their `'el can be attached to any point in DOM (by default it appends to `#Module's `'el). This is how submodules are usually created: 
R
var cls = calc 
R
classic: false, // XXX move to Screen? 
R
// XXX XXX maybe add a databank property and move there 
R
4 duplicates with _moveOpt() 
R
shroud logic is H3-specific; refactor it to a subclass or, more likely, to a dynamic mixin since DOM.Map is nested by environment 
R
duplicates with H3.Rules 
R
Take Z into account on small maps only. On over/underworld switching, relying on Z causes much bigger amount of nodes to be updated, making the switch very slow. 
R
2 _controlCreature: function () { 
R
duplicates with _updateAttackable; XXX slow 
R
// XXX duplicates with _updateAttackable; XXX slow 
R
8 _castSpell: function (enemies, allCost, done) { 
R
duplicates with H3.Rules.RPC 
R
may be merged with fireball's calculations 
R
may be merged with fireball's calculations 
R
_refreshHero: function (hero) { 
R
_controlTown: function (town) { 
R
_controlHero: function (hero) { 
R
This ensures combined garrisons of hero and town don't have duplicate creature IDs. It doesn't reorder creatures in any particular way so for example if hero and town had 1*C1 then town will have 0*C1, hero - 2*C1, or if only town had two slots, each 1*C1 then it will have one slot 2*C1. Reordering must be done later, once the returned async completes. 
R
Note: heroTotal, [2] is old (current) aiValue's of hero's garrison, not the value it will have after combining (this value is total, [0]). 
R
//> maxCost `- from `'spot (the town), not `'hero, measured over any terrain and thus only an estimate 
R
Doesn't check reachability. 
R
25 replace with ShipState? 
#ddd R
props.width = props.width || 1 // databank defaults; XXX why do we need them? just put 1 into databank (also check other similar places) 
R
set to 1 explicitly 
R
this calculator thing remains from pre-rewrite of Calc.Effect where Calc was much less flexible in terms of listen and update; it's likely that members of _calcs and calcs of attackTargets can be merged or have their options optimized (e.g. might not need to listen on WS server) 
R
if (this.combat.tc) { // XXX duplicates in H3.Rules.RPC 
R
it's probably more flexible and less hardcoded to define max audible distance in AClass on the per-object basis (rationale: big loud objects are heard from afar); add a new field to map.byPassable (or create a new index) telling which sounds (or objects) are heard on a given spot, and at what volume; this will allow very far-heard objects and Audio won't need to traverse the map on every update to determine them 
R
duplicates with H3.Rules 
R
duplicates with H3.Rules.RPC 
R
duplicates with H3.DOM.UI 
R
4 add helper methods to quickly build MessageBox'es with frequently used layouts (e.g. OK/Cancel) 
R
6 uniformize all format functions to create boxes with captions (like SpellImage), not only images 
R
duplicates with `{Checks`} 
R
_cast: function (book, spell) { 
R
duplicates with CreatureInfo's 
R
clicked: function () { 
R
SpellAffectorList's logic must be extracted into a H3.Rules calculator and used here 
R
this is walking the entire view.path on tick 0 but more correct is to walk one step at a time at the specific tick to allow other consumers of combatMove update precisely in sync with the creature move animation; there are no such consumers currently (except mapCountImage but it's hidden until last tick) 
R
partially duplicates with _playTransitionCreatureOverlay() 
R
partially duplicates with _playTransitionCreatureOverlay 
R
Duplicates with cast_missileEvery(). 
R
'=_updateCursor': function (sup) { 
R
attach: function () { 
R
audio may technically change so must update hooks when it happens 
R
use H3.DOM.Audio 
R
duplicates with _uploadSaved() 
R
// May be improved in the future (XXX). 
R
defining strings in code isn't ideal but quest_choices messages can't be part of effects since they often need custom MessageBox set up 
R, I
review all places where classic is accessed and add listening to change_classic (possibly after/together with #clsi
R
refactor upgraded creature forms into a Rules Calculator 
R
center: true, // XXX use _opt.center on all other H3 windows and remove left/top from CSS? 
R
Very lazy update. 
R
this old code was supposed to notify us when hero becomes or ceases to be garrisoned/visiting but it's flaky because hero can enter/leave town without moving on ADVMAP; we now have visiting/garrisoned properties for hero AObject-s so should instead hook ochange_p_VIS/GAR 
R
we currently have a variety of tracing log methods: here, AI, Calculator, etc. try to unify them; also see ll 
R
refactor and move generic methods to `#RPC, extract and move logic to H3.Rules 
R
should pathFindFor() adjust returned path to subtract actionableSpot? just like it automatically adds it. 
R
do_hireHero: function (args) { 
R
hardcoded building ID, need to make an Effect target 
R
In SoD all types of taverns and towns are on solid ground so vehicle will be always horse. However, we allow water-based taverns in custom maps. This is still assuming only water terrain needs ship and others need horse because there's no terrain type -> vehicle index. We could figure that by iterating over all vehicle types and querying hero_walkTerrain Effect target but doesn't sound good either. 
R
do_heroLevelSkill: function (args) { 
R
do_heroArtifactSwap: function (args) { 
R
Very similar to _disembark(). 
R
see if this conundrum can be eased by using the new "^" event prefix in Sqimitive 
R
logically, this should be moved to: Combat.State = Common.Sqimitive.extend('HeroWO.H3.Combat.State', { _update: function () { this.batch(null, function () { <here> }) this way, changes done after batch() ends but before _update's override handler is reached will be noticed 
R
this and all other combat-related methods do not need to be part of RPC, they are not using anything except _opt.context plus do_combat can be called for player different from H3 RPC's player; make a separate class This assumes AObject-s of all parties are frozen with $pending. 
R
duplicates with tacticsNext 
R
calc is removed but expandModifier() is semi-static so can use it like that 
R
this partially matches Effect::fromShort() and it only supports some modifier formats (which our spells currently evaluate to); need to implement generic priority calculation like in PHP 
R
First aid should be reworked: add a new creature-only spell "heal" (similar to dispel <-> dispel helpful) and add it to FAT's creature_spells. This way there will be no stat interference (currently what affects damageMin/Max also affects FAT's efficiency) and no checks for creature type (like one below) or team will be needed (can use spellImmune), plus other spell targets will be possible to use (like making healing global using spellGlobal). This is not done now because creature spells are not implemented yet. 
#ang R
var angle = Math.atan2(target.get('y') - attacker.get('y'), target.get('x') - target.get('y') % 2 / 2 - attacker.get('x') + attacker.get('y') % 2 / 2) * (180 / Math.PI) 
R
var angle = Math.atan2(cell.y - attacker[1], cell.x - cell.y % 2 / 2 - attacker[0] - attacker[1] % 2 / 2) * (180 / Math.PI) 
R
var angle = Math.atan2(curTarget.get('y') - attacker.get('y'), curTarget.get('x') - curTarget.get('y') % 2 / 2 - attacker.get('x') + attacker.get('y') % 2 / 2) * (180 / Math.PI) 
#rrl R, I
as it stands now, msg[0] cannot be localized because it joins many targets together: "The ... do ... damage. [Target1 perish] [Target2 perish] ..." 
R, I
SoD has different messages for ripple-type spells: - The Death spell does %d damage \n to all living creatures. - The %s spell does %d damage \n to all undead creatures. - The Armageddon does %d damage. We're using the same message for ripple- and arrow-type spells since HeroWO has a complex system of deciding which creature is hit (livind, undead, etc.), and we also explain how many targets perished. 
R
//= targets array`, Set 
R
_startCombat: function (combat) { 
R
review H3.*.js Bits and Calcs to check if owner changes are correctly listened to 
R
_applyModifier: function (o, operation, params) { 
R
consider reworking ..._message into general purpose handlers with some kind of selectors/filters without a hardcoded mode number 
R
var HeroItemCollection = Effects.Collection.extend({ 
R
// SoD doesn't allow picking hero for CPU. XXX Duplicates with WebSocket.Server.Client. 
R
duplicates with H3.DOM.Bits 
R
combine with existing effect instead of always adding new (as in other places) 
#h3t R
cls = _.sample(this.objectsID['hero_' + cls]) 
R
cls = _.sample(this.rules.objectsID['hero_' + cls]) 
R
_.each(['texture', 'animation'], function (prop) { 
R
var cls = _.sample(self.objectsID['artifact_' + art[1]]) 
R
var cls = self.objectsID['resource_' + type] 
R
var cls = _.sample(self.objectsID['monster_' + creature]) 
R
var cls = _.sample(self.objectsID['town_' + town]) 
R
var cls = _.sample(self.objectsID['hero_' + hero]) 
R
duplicates with `{Checks`} 
R
_grantExperience: function (hero, delta) { 
R
implement merging with previously set Effect as in _initializeTownSpells() 
R
duplicates with h3m2herowo.php 
R
duplicates with Effects.Collection 
R
to avoid conflicts there likely needs to be a central hook on all AObject fields affecting appearance, such as on subclass, that will update texture/animation; this is not implemented currently, as only the town fort/less factor affects object appearance in SoD 
R
duplicates with _initializePlayers() 
R
The fact that we are modifying entries when evaluating is against HeroWO's general rule that all data should stored already prepared. Ideally, entries should be marked right when they are added (possibly using a new Effects property); this would need updating of all places where bonus_effects are produced (or at least some generic mechanism on both PHP and JS sides). For now, the entry detection mechanism is an implementation detail that might change. 
R
need to implement generic priority calculation like in PHP 
#mk R
refactor other methods to uniform "makeXXX" 
R
move to make...() factory on cx 
R
state: 'created', // XXX replace with just 'loading' bool 
R
Code is no longer used. 
R
here and in other files: anyAtCoords doesn't check for bounds but very often need to check both in-bounds and "any object"; need to either add another method that checks for both or make any... check bounds 
R
replace neutral checks that look like so: !p.get('player') with a new prop/method check: p.isNeutral 
IC, R
32 is the cost of moving over cobblestone road, i.e. the fastest terrain (see databank-effects.php); https://forum.herowo.net/t/27 
R
duplicates with CombatLog in databank.php but there's no way to transfer this schema given MapBuilder doesn't create any combats 
R
since these are mutually exclusive, combine into one option with 'r'/'s'/null (or numeric consts) values? 
R
Refactor: improve code quality • client/RPC.js 
R
more correct would be to have some kind of "mini-server" where clients could be attached, ot a list of all created syncs; current implementation works for visual clients (a client per Screen) but not for special clients (like Replay); "mini-server" might also allow cleaner rewrite of H3.Rules' "mini-server" (initializeSinglePlayer()), possibly merging some single/multi-player code 
R
This works for bySpot because every change (i.e. assignment of value different from old) causes ochange on bySpot. However, it is fragile with byTarget and depends on implementation details of Effects' BatchIndexUpdater: if $ifX is set while $ifY is not, and $ifY is being set while $ifX is unset - such Effect is still part of byTarget but as of now the updater does remove + add so we still receive ochange. If the updater becomes more intelligent, we would skip change in this switch without receiving ochange in byTarget and doing _fire_changes(). 
R
0 check existing code and extract HTML <chunks> (usually fed to el.html()) into templates 
R
// unused values (if they're known). However, some modules wrongly access H3-specific constants as map.constants so that needs to be fixed first (XXX). 
R
fix this and other similar consts to count from 1? 
R
make float short modifier use two's complement (will allow zero const) Float-fix note: even though PHP and JSON have distinct types for representing integer and float values, JavaScript does not (Number.isInteger(1.0) === true). To work around this, if a float has 0 fraction then it's increased by 0.0001 - this is too little to have any affect on final values but enough to recognize it as float. Note: in PHP, do not use round()/floor()/etc. to specify short integer modifier (`'delta) because they take float and return float. Use `[(integer)`] instead: 
R
$subclass turned out to be a "union in itself" property, i.e. multiple type-dependent properties combined into one slot under the same name. It may be worth breaking it into different properties, each with a proper name (like "heroID" for prison or "animationGroup" for terrain). 
R
replace mirrorX/mirrorY with $mirror array, $compact'ed like $passable: [true, false] = '10'; $mirror[0] is x, [1] is y, or with a bitfield 
#arbp R
`> hero non-layered 1D sub-store `- `'X is ArtifactSlot->$id; when >= `'$id of `'backpack, means the artifact is not equipped (XXX this usage prevents modifications from adding new artifactSlotsID as they'd be considered part of backpack); may have gaps 
R
throw new Error('Extending ' + prop + ' is currently disallowed.') 
R
change to a recurring target similarly to creature_strikes and combatCasts 
R
do we need it, given Lich's attach is implemented using shootingCloud/creature_shootingCloud? 
R
do we need it, given it doesn't have (XXX) any special effects other than damage? 
R
use 'terrain' rather than 'other' for non-interactive objects like Kelp 
I, R
// Archers to Sharpshooters, etc. (XXX also merge with creature_upgradeCan?) 
R
//> ownable_shroud int `- number of tiles around owned non-hero/town objects (e.g. mine); XXX merge with *_shroud? 
R
localize $name 
R
DefPreview 1.0.0 stores groups sequentially while 1.2.1 properly indexes them, resulting in gaps (that we skip over here). For 1.2.1, we could skip reading H3L but hopefully we'll move from DefPreview to some console tool in a future rather than fixing this. 
#hhsi R
Databank's Spell->$id is declared as different from SPTRAITS.TXT index. However, we don't have means to map the two other than by idName which for some spells is different from makeIdentifier(). But not only that, we don't have access to SPTRAITS.TXT and can't look up spell name (or other info, e.g. $description). All we have is SoD's spell ID. Leaving fixing this for later since as of now Spell->$id-s of "userland" spells do match. 
R
$spells = [['hero_spells', $this->o_append($hero->spells), 'ifObject' => true, 'stack' => $this->const('effect.stack.classStats')]]; 
R
'spells' => $details->spells, 
R
$this->effect(['town_spells', $this->o_append($details->existingSpells), 'ifObject' => $obj->id, 'source' => $this->const('effect.source.initialize')]); 
R
$this->effect(['town_spellChance', $this->o_clamp00, 'ifSpell' => $spell, 'ifObject' => $obj->id, 'source' => $this->const('effect.source.initialize')]); 
R
$this->effect(['hero_spells', $this->o_append($details->spells), 'ifObject' => $obj->id, 'source' => $this->const('effect.source.initialize'), 'stack' => [array_search('classStats', H3Effect::stack), 1]]); 
R
if (isset($details->spell)) { 
R
$artifact = $this->spells->atCoords($details->spell, 0, 0, 'scroll'); 
#clc R
$copyProps = [ 
R
'type', 'texture', 'animation', 'duration', 'width', 'height', 'miniMap', 'passableType', 'passable', 'actionable', 'actionableFromTop']) 
R
'type', 'texture', 'animation', 'duration', 'width', 'height', 'miniMap', 'passableType', 'passable', 'actionable', 'actionableFromTop']) 
R
'type', 'texture', 'animation', 'duration', 'width', 'height', 'miniMap', 'passableType', 'passable', 'actionable', 'actionableFromTop']) 
R
var props = ['type', 'duration', 'width', 'height', 'miniMap', 'passableType', 'passable', 'actionable', 'actionableFromTop'] 
R
_.each(['type', 'texture', 'animation', 'duration', 'width', 'height', 'miniMap', 'passableType', 'passable', 'actionable', 'actionableFromTop'], function (prop) { 
R
'type', 'texture', 'animation', 'duration', 'width', 'height', 'miniMap', 'passableType', 'passable', 'actionable', 'actionableFromTop']) 
R
This should be generally addressed by parsing RoE's and AB's OBJECTS.TXT and creating a compatibility list rather than hardcoding an array here. 
#dor R
// If changing this calculation, update addMapMargin() and copies of this in JS (XXX). 
R
res.displayOrder = 1 << 26 | spot[1] + opt.height - 1 << 18 | 3 << 16 | spot[0] << 2 
R
displayOrder: 1 << 26 | spot[1] + hero.get('height') - 1 << 18 | 3 << 16 | spot[0] << 2, 
R
displayOrder: 1 << 26 | state.get('y') - act[1] + boat.height - 1 << 18 | 3 << 16 | (state.get('x') - act[0]) << 2, 
R
displayOrder: 1 << 26 | from[1] - act[1] + boat.height - 1 << 18 | 3 << 16 | (from[0] - act[0]) << 2, 
R
displayOrder: 1 << 26 | dest[1] + actor.get('height') - 1 << 18 | 3 << 16 | dest[0] << 2, 
R
this.map.objects.setAtCoords(hero, 0, 0, 0, 'displayOrder', 1 << 26 | this._bonusSpot[1] + this.map.objects.atCoords(hero, 0, 0, 'height', 0) - 1 << 18 | 3 << 16 | this._bonusSpot[0] << 2) 
R
duplicates with JS code Determines hero level by the number of experience points. 
R
duplicates with `{Checks`} 
#fish R
margin-left: calc(-274px + 40em); /* XXX fishy calculation */ 
R
all this shifting smells real peccant */ 
R
more peccant shifting, yay */