(cx,cy,click)
| 8475 | } |
| 8476 | /* ================================================================= picking */ |
| 8477 | function pick(cx,cy,click){ |
| 8478 | if(!W)return; |
| 8479 | /* Whether a bird is on offer is decided on HOVER, every move, and the reticle |
| 8480 | is the offer being made. Never re-decided on the click itself. */ |
| 8481 | if(!click) setHover(POV.bird?null:birdAt(cx,cy)); |
| 8482 | const p=groundAt(cx,cy,0); |
| 8483 | let hit=null; |
| 8484 | if(p&&OPEN&&W.own){ |
| 8485 | const o=W.own.get(hexKey(...hexAt(p.x,p.z))); |
| 8486 | hit=o===undefined?null:W.districts[o]; |
| 8487 | }else if(p&&!OPEN){ |
| 8488 | /* At world scale an island is a disc, and the nearest one you are standing |
| 8489 | inside is the one you mean. */ |
| 8490 | for(const q of W.quarters){ |
| 8491 | if(q.shown<=0)continue; |
| 8492 | if(Math.hypot(p.x-q.x,p.z-q.z)<=spec(Math.max(1,q.level)).radius+3){ hit=q; break; } |
| 8493 | } |
| 8494 | } |
| 8495 | if(hit!==hovered){ hovered=hit; paintBorders(); } |
| 8496 | /* Only ground a click does something with. An unread realm does not open, and |
| 8497 | inside one, only a district with something standing on it has a feed. Never |
| 8498 | while riding: the pointer is a flight stick then, not a cursor. */ |
| 8499 | stageEl.classList.toggle('pick', |
| 8500 | !POV.bird&&!!hit&&(OPEN?!!hit.built:hit.shown>0)); |
| 8501 | if(click){ |
| 8502 | /* Only the bird the reticle is already on. Re-testing the cursor here |
| 8503 | instead would let a bird that happened to fly under the pointer between |
| 8504 | press and release swallow a click aimed at a realm — which is exactly the |
| 8505 | failure this is built to make impossible. */ |
| 8506 | const bird=POV.aim; |
| 8507 | POV.aim=null; |
| 8508 | if(bird&&bird[0].parent){ possess(bird[0],bird[1]); return; } |
| 8509 | if(!OPEN) { if(hit) enterRealm(hit); } |
| 8510 | else{ |
| 8511 | /* Inside a realm the first click on a town OPENS it: the plot lights and |
| 8512 | the panel beside it reads out what was upvoted there, which is the |
| 8513 | thing somebody clicking a district is asking for. The slap is what a |
| 8514 | second click on the town already open does, so the toy is still one |
| 8515 | click away and never lands on top of the answer. */ |
| 8516 | if(hit&&hit.built&&hit.i===selected) slap(hit,clock.getElapsedTime()); |
| 8517 | select(hit?hit.i:null); |
| 8518 | } |
| 8519 | } |
| 8520 | } |
| 8521 | /* Selection lights the district's plot border and syncs the sidebar. It used |
| 8522 | to do considerably more: the selected district was REBUILT — torn down and |
| 8523 | raised again — so that it could skip the merge and keep every one of its |
no test coverage detected