(cx,cy,click)
| 8463 | } |
| 8464 | /* ================================================================= picking */ |
| 8465 | function pick(cx,cy,click){ |
| 8466 | if(!W)return; |
| 8467 | /* Whether a bird is on offer is decided on HOVER, every move, and the reticle |
| 8468 | is the offer being made. Never re-decided on the click itself. */ |
| 8469 | if(!click) setHover(POV.bird?null:birdAt(cx,cy)); |
| 8470 | const p=groundAt(cx,cy,0); |
| 8471 | let hit=null; |
| 8472 | if(p&&OPEN&&W.own){ |
| 8473 | const o=W.own.get(hexKey(...hexAt(p.x,p.z))); |
| 8474 | hit=o===undefined?null:W.districts[o]; |
| 8475 | }else if(p&&!OPEN){ |
| 8476 | /* At world scale an island is a disc, and the nearest one you are standing |
| 8477 | inside is the one you mean. */ |
| 8478 | for(const q of W.quarters){ |
| 8479 | if(q.shown<=0)continue; |
| 8480 | if(Math.hypot(p.x-q.x,p.z-q.z)<=spec(Math.max(1,q.level)).radius+3){ hit=q; break; } |
| 8481 | } |
| 8482 | } |
| 8483 | /* No hover card at either scale. Nothing follows the cursor now: `hovered` is |
| 8484 | still tracked, but the only thing it does is light the plot border under the |
| 8485 | pointer. The affordance the card used to carry — "click to walk in" — is |
| 8486 | already stated in the hint bar, permanently, where it does not have to |
| 8487 | appear over the world to be read. */ |
| 8488 | if(hit!==hovered){ hovered=hit; paintBorders(); } |
| 8489 | if(click){ |
| 8490 | /* Only the bird the reticle is already on. Re-testing the cursor here |
| 8491 | instead would let a bird that happened to fly under the pointer between |
| 8492 | press and release swallow a click aimed at a realm — which is exactly the |
| 8493 | failure this is built to make impossible. */ |
| 8494 | const bird=POV.aim; |
| 8495 | POV.aim=null; |
| 8496 | if(bird&&bird[0].parent){ possess(bird[0],bird[1]); return; } |
| 8497 | if(!OPEN) { if(hit) enterRealm(hit); } |
| 8498 | else{ |
| 8499 | /* Inside a realm a click on a town is a SLAP, full stop. It used to have |
| 8500 | to earn it by selecting first, which meant the one gesture people |
| 8501 | actually try on a town did nothing the first time. Selection still |
| 8502 | happens — it lights the plot border and syncs the sidebar — but it |
| 8503 | moves nothing, so the two never fight over the same click. */ |
| 8504 | if(hit&&hit.built) slap(hit,clock.getElapsedTime()); |
| 8505 | select(hit?hit.i:null); |
| 8506 | } |
| 8507 | } |
| 8508 | } |
| 8509 | /* Selection lights the district's plot border and syncs the sidebar. It used |
| 8510 | to do considerably more: the selected district was REBUILT — torn down and |
| 8511 | raised again — so that it could skip the merge and keep every one of its |
no test coverage detected