| 1391 | COMMAND(selectionwalk, "sss"); |
| 1392 | |
| 1393 | void transformclipentities() // transforms all clip entities to tag clips, if they are big enough (so, that no player could be above or below them) |
| 1394 | { // (hardcoded factor ENTSCALE10 for attr1 and ENTSCALE5 for attr2-4) |
| 1395 | EDITMP("transformclipentities"); |
| 1396 | int total = 0, thisrun, bonus = 5; |
| 1397 | do |
| 1398 | { |
| 1399 | thisrun = 0; |
| 1400 | loopv(ents) |
| 1401 | { |
| 1402 | entity &e = ents[i]; |
| 1403 | if((e.type == CLIP || e.type == PLCLIP) && e.attr2 / ENTSCALE5 && e.attr3 / ENTSCALE5 && e.attr4 / ENTSCALE5) |
| 1404 | { |
| 1405 | int allowedspace = e.type == CLIP ? 1 : 4; |
| 1406 | int clipmask = e.type == CLIP ? TAGCLIP : TAGPLCLIP; |
| 1407 | int i2 = e.attr2 / ENTSCALE5, i3 = e.attr3 / ENTSCALE5; // floor values |
| 1408 | int r2 = (e.attr2 % ENTSCALE5) > 0, r3 = (e.attr3 % ENTSCALE5) > 0; // fractions |
| 1409 | int x1i = e.x - i2, x2i = e.x + i2 - 1, y1i = e.y - i3, y2i = e.y + i3 - 1; // inner rectangle (fully covered cubes) |
| 1410 | int x1o = x1i - r2, x2o = x2i + r2, y1o = y1i - r3, y2o = y2i + r3; // outer rectangle (partially covered cubes) |
| 1411 | float z1 = S(e.x, e.y)->floor + float(e.attr1) / ENTSCALE10, z2 = z1 + float(e.attr4) / ENTSCALE5; |
| 1412 | bool bigenough = true, nodelete = false; |
| 1413 | for(int xx = x1o; xx <= x2o; xx++) for(int yy = y1o; yy <= y2o; yy++) // loop over outer rectangle to check, if a clip has the required height |
| 1414 | { |
| 1415 | if(OUTBORD(xx,yy) || SOLID(S(xx,yy))) continue; |
| 1416 | bool inner = xx >= x1i && xx <= x2i && yy >= y1i && yy <= y2i; // flag: xx|yy is inner rectangle |
| 1417 | sqr *s[4] = { S(xx, yy), S(xx + 1, yy), S(xx, yy + 1), S(xx + 1, yy + 1) }; |
| 1418 | int vdeltamax = 0; |
| 1419 | loopj(4) if(s[j]->vdelta > vdeltamax) vdeltamax = s[j]->vdelta; |
| 1420 | int floor = s[0]->floor - (s[0]->type == FHF ? (vdeltamax + 3) / 4 : 0), |
| 1421 | ceil = s[0]->ceil + (s[0]->type == CHF ? (vdeltamax + 3) / 4 : 0); |
| 1422 | bool alreadytagged = (s[0]->tag & (TAGCLIP | clipmask)) != 0; |
| 1423 | if((z1 - floor > allowedspace || ceil - z2 > allowedspace) && !alreadytagged) bigenough = false; |
| 1424 | if(!inner && !alreadytagged) nodelete = true; // fractional part of the clip would not be covered: entity can not be deleted |
| 1425 | } |
| 1426 | if(bigenough) |
| 1427 | { |
| 1428 | for(int xx = x1i; xx <= x2i; xx++) for(int yy = y1i; yy <= y2i; yy++) // only convert inner rectangle to tag clips |
| 1429 | { |
| 1430 | if(!OUTBORD(xx,yy) && !SOLID(S(xx,yy))) S(xx, yy)->tag |= clipmask; |
| 1431 | } |
| 1432 | if(!nodelete) |
| 1433 | { |
| 1434 | deleted_ents.add(e); |
| 1435 | e.type = NOTUSED; // only delete entity, if it is now fully covered in tag clips |
| 1436 | thisrun++; |
| 1437 | } |
| 1438 | } |
| 1439 | } |
| 1440 | } |
| 1441 | total += thisrun; |
| 1442 | } |
| 1443 | while(thisrun || bonus-- > 0); |
| 1444 | loopi(ssize) loopj(ssize) { sqr *s = S(i,j); if(s->tag & TAGCLIP) s->tag &= ~TAGPLCLIP; } |
| 1445 | conoutf("changed %d clip entities to tagged clip areas", total); |
| 1446 | if(total) unsavededits++; |
| 1447 | } |
| 1448 | |
| 1449 | COMMAND(transformclipentities, ""); |
| 1450 | |