(cx,cy,click)
| 8706 | } |
| 8707 | /* ================================================================= picking */ |
| 8708 | function pick(cx,cy,click){ |
| 8709 | if(!W)return; |
| 8710 | /* Whether a bird is on offer is decided on HOVER, every move, and the reticle |
| 8711 | is the offer being made. Never re-decided on the click itself. */ |
| 8712 | if(!click) setHover(POV.bird?null:birdAt(cx,cy)); |
| 8713 | const p=groundAt(cx,cy,0); |
| 8714 | let hit=null; |
| 8715 | if(p&&OPEN&&W.own){ |
| 8716 | const o=W.own.get(hexKey(...hexAt(p.x,p.z))); |
| 8717 | hit=o===undefined?null:W.districts[o]; |
| 8718 | }else if(p&&!OPEN){ |
| 8719 | /* At world scale an island is a disc, and the nearest one you are standing |
| 8720 | inside is the one you mean. */ |
| 8721 | for(const q of W.quarters){ |
| 8722 | if(q.shown<=0)continue; |
| 8723 | if(Math.hypot(p.x-q.x,p.z-q.z)<=spec(Math.max(1,q.level)).radius+3){ hit=q; break; } |
| 8724 | } |
| 8725 | } |
| 8726 | if(hit!==hovered){ hovered=hit; paintBorders(); } |
| 8727 | /* Only ground a click does something with. An unread realm does not open, and |
| 8728 | inside one, only a district with something standing on it has a feed. Never |
| 8729 | while riding: the pointer is a flight stick then, not a cursor. */ |
| 8730 | stageEl.classList.toggle('pick', |
| 8731 | !POV.bird&&!!hit&&(OPEN?!!hit.built:hit.shown>0)); |
| 8732 | if(click){ |
| 8733 | /* Only the bird the reticle is already on. Re-testing the cursor here |
| 8734 | instead would let a bird that happened to fly under the pointer between |
| 8735 | press and release swallow a click aimed at a realm — which is exactly the |
| 8736 | failure this is built to make impossible. */ |
| 8737 | const bird=POV.aim; |
| 8738 | POV.aim=null; |
| 8739 | if(bird&&bird[0].parent){ possess(bird[0],bird[1]); return; } |
| 8740 | if(!OPEN) { if(hit) enterRealm(hit); } |
| 8741 | else{ |
| 8742 | /* Inside a realm the first click on a town OPENS it: the plot lights and |
| 8743 | the panel beside it reads out what was upvoted there, which is the |
| 8744 | thing somebody clicking a district is asking for. The slap is what a |
| 8745 | second click on the town already open does, so the toy is still one |
| 8746 | click away and never lands on top of the answer. */ |
| 8747 | if(hit&&hit.built&&hit.i===selected) slap(hit,clock.getElapsedTime()); |
| 8748 | select(hit?hit.i:null); |
| 8749 | } |
| 8750 | } |
| 8751 | } |
| 8752 | /* Selection lights the district's plot border and syncs the sidebar. It used |
| 8753 | to do considerably more: the selected district was REBUILT — torn down and |
| 8754 | raised again — so that it could skip the merge and keep every one of its |
no test coverage detected