// opt/mapeditscripts
// fringe mapediting scripts

echo "\f0Extra map editing scripts:"

// list entity-sparklies with identical positions
echo "\fs\f2doublesparklies [enttype]\fr\t\tlist entity-sparklies with identical positions"
tempalias doublesparklies [
    if $editing [
        push eee $arg1
        if (! (strlen $eee)) [ eee = (listoptions ents) ]
        echo list entity sparklies with identical x, y and z coordinates "(" $eee ")"
        looplist $eee ot [
            looplist (enumentities $ot) oi [
                push oee (editentity $oi)
                push oex (at $oee 1)
                looplist $eee it [
                    looplist (enumentities $it) ii [
                        if (&& (< $ii $oi) (= $oex (at (editentity $ii) 1))) [
                            push iee (editentity $ii)
                            if (&& (= (at $iee 2) (at $oee 2)) (= (at $iee 3) (at $oee 3))) [
                                echo $ii : $iee --- $oi : $oee
                            ]
                            pop iee
                        ]
                    ]
                ]
                pop oee oex
            ]
        ]
        pop eee
    ][
        echo edit mode required
    ]
]

// list identical models on the same position
echo "\fs\f2doublemodels\fr\t\tlist identical models on the same position"
tempalias doublemodels [
    if $editing [
        push res 0
        echo "list doubled mapmodels (same position, model and elevation)"
        looplist (enumentities mapmodel) oi [
            push oee (editentity $oi)
            push oex (at $oee 1)
            looplist (enumentities mapmodel) ii [
                if (&& (< $ii $oi) (= $oex (at (editentity $ii) 1))) [
                    push iee (editentity $ii)
                    if (&& (= (at $iee 2) (at $oee 2)) (&& (strcmp (mapmodelslotname (at $iee 5)) (mapmodelslotname (at $oee 5))) (= (at $iee 6) (at $oee 6)))) [
                        echo $ii : $iee --- $oi : $oee
                        addtodoentity $oi (concat double model $ii : $iee --- $oi : $oee)
                        += res 1
                    ]
                    pop iee
                ]
            ]
            pop oee oex
        ]
        if $res [ showmenu "TODO entities" ]
        result (pop res)
    ][
        echo edit mode required
    ]
]

// get cube info of a certain cube
// getcubedata x y attr
// (loses current selection)
tempalias getcubedata [
    select $arg1 $arg2 1 1
    push res (concatword sw_ $arg3)
    selectionwalk [res = $$res]
    resetselections
    result (pop res)
]

// adjust mapmodel sparklie positions to a fixed offset over ground + mapmodel elevation + modelslot elevation
// mm_z slot z-offset
echo "\fs\f2mm_z slot z-offset\fr\tadjust mapmodel sparklie positions to a fixed offset over ground + mapmodel elevation + modelslot elevation"
tempalias mm_z [
    if $editing_sp [
        push es (editmapmodelslot $arg1)
        echo set z-coordinate of the entity sparklies of all mapmodels of slot # (escape $arg1) to floor + elevation + (at $es 2) + (escape $arg2)
        if (strlen $arg1) [
            looplist (enumentities mapmodel) i [
                push ee (editentity $i)
                if (= $arg1 (at $ee 5)) [
                    push nh (+ (getcubedata (at $ee 1) (at $ee 2) floor) (at $ee 6) $arg2 (at $es 2))
                    if (strlen $arg2) [editentity $i "" "" $nh]
                    echo $ee -> (pop nh) -> (editentity $i)
                ]
                pop ee
            ]
        ][
            echo usage: mm_z mmslotnumber heightoffset
        ]
        pop es
    ][
        echo offline edit mode required
    ]
]

// adjust clipent sparklie positions to the middle of the clip
// clip_z
echo "\fs\f2clip_z\fr\t\t\tadjust clipent sparklie positions to the middle of the clip"
tempalias clip_z [
    if $editing_sp [
        echo set z-coordinate of the entity sparklies of all clip and plclip to the middle of the clips
        looplist (concat (enumentities clip) (enumentities plclip)) i [
            push ee (editentity $i)
            push nh (+ (getcubedata (at $ee 1) (at $ee 2) floor) (at $ee 4) (div (at $ee 7) 2))
            editentity $i "" "" $nh
            echo clip_z: $ee -> (pop nh) -> (editentity $i)
            pop ee
        ]
    ][
        echo offline edit mode required
    ]
]

// duplicate all clipped model slots with an unclipped version - then sort the slots
// (after running this, reducing the slot number of any clipped mapmodel by one will remove the clip)
// doubleclippedslots
echo "\fs\f2duplicateclippedslots\fr\t\tduplicate all clipped model slots with an unclipped version, then sort the slots"
tempalias duplicateclippedslots [
    if $editing_sp [
        echo double all clipped model slots with an unclipped version, then sort the slots
        loop i 256 [
            push info (editmapmodelslot $i)
            if (|| (at $info 0) (at $info 1)) [
                mapmodel 0 0 (at $info 2) (at $info 3) (at $info 4)
            ]
            pop info
        ]
        sortmapmodelslots
        echo "\f4When done, use duplicateclippedslots_cleanup."
    ][
        echo offline edit mode required
    ]
]

// clean up after using doubleclippedslots: sort&merge mapmodel slots, then delete all unused mapmodel slots
// doubleclippedslots_cleanup
echo "\fs\f2duplicateclippedslots_cleanup\fr\tremove all unnecessary mapmodel slots"
tempalias duplicateclippedslots_cleanup [
    if $editing_sp [
        sortmapmodelslots mergeused
        loop ii 256 [ push i (- 255 $ii) ; if (&& (strlen (mapmodelslotname $i)) (strcmp "" (mapmodelslotusage $i))) [deletemapmodelslot $i] ; pop i]
        echo all unnecessary mapmodel slots removed
    ][
        echo offline edit mode required
    ]
]

tempalias dryrun 0

// un-clip models that are fully in tagclipped areas
// uncliptagclippedmodels
echo "\fs\f2uncliptagclippedmodels\fr\tun-clip models that are fully in tagclipped areas"
tempalias uncliptagclippedmodels [
    if $editing_sp [
        push res 0
        looplist (enumentities mapmodel) i [
            push entinfo (editentity $i)
            push slotinfo (editmapmodelslot (at $entinfo 5))
            if (|| (at $slotinfo 0) (at $slotinfo 1)) [
                push radius (at $slotinfo 0)
                if (= $radius 0) [ radius = 1 ] // FIXME
                select (- (at $entinfo 1) $radius) (- (at $entinfo 2) $radius) (* $radius 2) (* $radius 2)
                push unclipped 0
                selectionwalk [ if (&& (! (&b 0x40 $sw_tag)) $sw_type) [ += unclipped 1 ] ]
                if (&& (! (at $slotinfo 0)) (< $unclipped 4)) [ unclipped = 0 ] // radius 0 is fine, if there is at least 1 tagclip
                if (! $unclipped) [
                    if $dryrun [
                        addtodoentity $i (concat $slotinfo can be unclipped by uncliptagclippedmodels)
                    ][
                        push uinfo (concat 0 0 (at $slotinfo 2) (at $slotinfo 3) (escape (at $slotinfo 4)))
                        loop j 256 [
                            if (strcmp (editmapmodelslot $j) $uinfo) [
                                addtodoentity $i (concatword "changed from mapmodel slot #" (at $entinfo 5) " to slot #" $j)
                                editentity $i "" "" "" "" $j
                                unclipped = -1
                                break
                            ]
                        ]
                        if (! $unclipped) [
                            editentity $i "" "" "" "" (mapmodel 0 0 (at $slotinfo 2) (at $slotinfo 3) (at $slotinfo 4))
                            addtodoentity $i (concatword "changed from mapmodel slot #" (at $entinfo 5) " to newly created slot #" (at (editentity $i) 5))
                        ]
                        pop uinfo
                    ]
                    += res 1
                ]
                pop unclipped radius
            ]
            pop entinfo slotinfo
        ]
        resetselections
        echo un-clipped $res mapmodel entities
        pop res
    ][
        echo offline edit mode required
    ]
]

// un-clip models that are fully clipped by a clip entity
// unclipentclippedmodels
echo "\fs\f2unclipentclippedmodels\fr\tun-clip models that are fully clipped by a clip entity"
tempalias unclipentclippedmodels [
    if $editing_sp [
        push res 0
        looplist (enumentities mapmodel) i [
            push entinfo (editentity $i)
            push slotinfo (editmapmodelslot (at $entinfo 5))
            if (|| (at $slotinfo 0) (at $slotinfo 1)) [
                push radius (at $slotinfo 0) // model clip radius
                push bot (+f (getcubedata (at $entinfo 1) (at $entinfo 2) floor) (at $entinfo 6) (at $slotinfo 2))  // model clip bottom, float
                push h (at $slotinfo 1) // model clip height
                looplist (enumentities clip) ci [
                    push clipinfo (editentity $ci)
                    if (&& (! (at $clipinfo 10)) (at $clipinfo 7)) [ // skip non-zero shapes
                        push cibot (+f (getcubedata (at $clipinfo 1) (at $clipinfo 2) floor) (at $clipinfo 4))  // clip bottom, float
                        push cih (at $clipinfo 7) // clip height, float
                        push clipped (&& (<=f $cibot $bot) (>= (+f $cibot $cih) (+f $bot $h))) // check height range
                        *= clipped (&& (<= (- (at $clipinfo 1) (at $clipinfo 5)) (- (at $entinfo 1) $radius)) (>= (+ (at $clipinfo 1) (at $clipinfo 5)) (+ (at $entinfo 1) $radius))) // check x range
                        *= clipped (&& (<= (- (at $clipinfo 2) (at $clipinfo 6)) (- (at $entinfo 2) $radius)) (>= (+ (at $clipinfo 2) (at $clipinfo 6)) (+ (at $entinfo 2) $radius))) // check y range
                        if $clipped [
                            if $dryrun [
                                addtodoentity $i (concat $slotinfo can be unclipped by unclipentclippedmodels)
                            ][
                                push uinfo (concat 0 0 (at $slotinfo 2) (at $slotinfo 3) (escape (at $slotinfo 4)))
                                loop j 256 [
                                    if (strcmp (editmapmodelslot $j) $uinfo) [
                                        addtodoentity $i (concatword "changed from mapmodel slot #" (at $entinfo 5) " to slot #" $j)
                                        editentity $i "" "" "" "" $j
                                        clipped = 0
                                        break
                                    ]
                                ]
                                if $clipped [
                                    editentity $i "" "" "" "" (mapmodel 0 0 (at $slotinfo 2) (at $slotinfo 3) (at $slotinfo 4))
                                    addtodoentity $i (concatword "changed from mapmodel slot #" (at $entinfo 5) " to newly created slot #" (at (editentity $i) 5))
                                ]
                                pop uinfo
                            ]
                            += res 1
                            h = 0 // exit clipent loop
                        ]
                        pop clipped cih cibot
                    ]
                    pop clipinfo
                    if (! $h) break
                ]
                pop h bot radius
            ]
            pop entinfo slotinfo
        ]
        resetselections
        echo un-clipped $res mapmodel entities
        pop res
    ][
        echo offline edit mode required
    ]
]

// find middle cube in selection
// selectmiddle
echo "\fs\f2selectmiddle\fr\tfind middle cube in selection"
tempalias selectmiddle [
    if $editing [
        push res resetselections
        selectionwalk [] [
            looplist $sw_cursel [x y xs ys] [
                res = (concat $res ";" addselection (+ $x (div $xs 2)) (+ $y (div $ys 2)) 1 1)
            ]
        ]
        echo reduced (listlen (selx)) selections to the middle cube
        res
        pop res
    ][
        echo edit mode required
    ]
]

