triClick — click a control by IDC. Returns true on success.
| 302 | } |
| 303 | |
| 304 | /// triClick <idc> — click a control by IDC. Returns true on success. |
| 305 | GameValue TriClick(const GameState* state, GameValuePar arg) |
| 306 | { |
| 307 | int idc = static_cast<int>(static_cast<GameScalarType>(arg)); |
| 308 | auto* display = GetActiveDisplayForSQF(); |
| 309 | if (!display) |
| 310 | { |
| 311 | LOG_ERROR(Core, "[tri] triClick: no active display"); |
| 312 | return GameValue(false); |
| 313 | } |
| 314 | // A transient channel/chat HUD can shadow a modal map child (e.g. the |
| 315 | // server get-ready dialog). If the topmost container doesn't own the |
| 316 | // control, resolve the stack entry that does. |
| 317 | if (!display->GetCtrl(idc)) |
| 318 | { |
| 319 | if (auto* owner = UIActiveDisplay::FindContainerWithIdc(GWorld, idc)) |
| 320 | display = owner; |
| 321 | } |
| 322 | IControl* ctrl = display->GetCtrl(idc); |
| 323 | if (!ctrl) |
| 324 | { |
| 325 | LOG_ERROR(Core, "[tri] triClick: IDC {} not found", idc); |
| 326 | return GameValue(false); |
| 327 | } |
| 328 | auto* control = dynamic_cast<Control*>(ctrl); |
| 329 | if (!control) |
| 330 | { |
| 331 | LOG_ERROR(Core, "[tri] triClick: IDC {} not a Control", idc); |
| 332 | return GameValue(false); |
| 333 | } |
| 334 | float cx = control->X() + control->W() * 0.5f; |
| 335 | float cy = control->Y() + control->H() * 0.5f; |
| 336 | LOG_INFO(Core, "[tri] triClick IDC={} at ({},{})", idc, cx, cy); |
| 337 | if (auto* host = FindHostForIdc(idc)) |
| 338 | { |
| 339 | host->OnLButtonDown(cx, cy); |
| 340 | host->OnLButtonUp(cx, cy); |
| 341 | } |
| 342 | else |
| 343 | { |
| 344 | control->OnLButtonDown(cx, cy); |
| 345 | control->OnLButtonUp(cx, cy); |
| 346 | } |
| 347 | return GameValue(true); |
| 348 | } |
| 349 | |
| 350 | // triClickAt [idc, u, v] — like triClick but presses at the local (u, v) point |
nothing calls this directly
no test coverage detected