cleanup

cleanup

<template>
  <h1>{{content}}</h1>
</template>
<style scoped>
  h1 {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
    font-weight: 200;
    font-size: 100px;
    color: #414141;
  }
</style>
<script>
  exports = {
    props: ["content"]
  }
</script>


Manes Registry

Manes Registry

--
-- Copyright (C) 2017 DBot
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

PPM2.MIN_WEIGHT = 0.7
PPM2.MAX_WEIGHT = 1.5

PPM2.MIN_SCALE = 0.5
PPM2.MAX_SCALE = 1.3

PPM2.PONY_HEIGHT_MODIFIER = 0.64
PPM2.PONY_HEIGHT_MODIFIER_DUCK = 1.12
PPM2.PONY_HEIGHT_MODIFIER_DUCK_HULL = 1

PPM2.MIN_NECK = 0.6
PPM2.MAX_NECK = 1.4

PPM2.MIN_LEGS = 0.6
PPM2.MAX_LEGS = 1.75

PPM2.PONY_JUMP_MODIFIER = 1.4

PPM2.PLAYER_VOFFSET = 64 * PPM2.PONY_HEIGHT_MODIFIER
PPM2.PLAYER_VOFFSET_DUCK = 28 * PPM2.PONY_HEIGHT_MODIFIER_DUCK

PPM2.PLAYER_VIEW_OFFSET = Vector(0, 0, PPM2.PLAYER_VOFFSET)
PPM2.PLAYER_VIEW_OFFSET_DUCK = Vector(0, 0, PPM2.PLAYER_VOFFSET_DUCK)

PPM2.PLAYER_VIEW_OFFSET_ORIGINAL = Vector(0, 0, 64)
PPM2.PLAYER_VIEW_OFFSET_DUCK_ORIGINAL = Vector(0, 0, 28)

PPM2.MIN_TAIL_SIZE = 0.6
PPM2.MAX_TAIL_SIZE = 1.7 -- i luv big tails

PPM2.MIN_IRIS = 0.4
PPM2.MAX_IRIS = 1.3

PPM2.MIN_HOLE = 0.1
PPM2.MAX_HOLE = .95

PPM2.MIN_HOLE_SHIFT = -0.5
PPM2.MAX_HOLE_SHIFT = 0.5

PPM2.MIN_PUPIL_SIZE = 0.2
PPM2.MAX_PUPIL_SIZE = 1

PPM2.MIN_EYE_ROTATION = -180
PPM2.MAX_EYE_ROTATION = 180

PPM2.AvaliableTails = {
    'MAILCALL'
    'FLOOFEH'
    'ADVENTUROUS'
    'SHOWBOAT'
    'ASSERTIVE'
    'BOLD'
    'STUMPY'
    'SPEEDSTER'
    'EDGY'
    'RADICAL'
    'BOOKWORM'
    'BUMPKIN'
    'POOFEH'
    'CURLY'
    'NONE'
}

PPM2.AvaliableUpperManes = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT', 'ASSERTIVE'
    'BOLD', 'STUMPY', 'SPEEDSTER', 'RADICAL', 'SPIKED'
    'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY', 'INSTRUCTOR', 'NONE'
}

PPM2.AvaliableLowerManes = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'HIPPIE', 'SPEEDSTER'
    'BOOKWORM', 'BUMPKIN', 'CURLY', 'NONE'
}

PPM2.EyelashTypes = {
    'Default', 'Double', 'Coy', 'Full', 'Mess', 'None'
}

PPM2.BodyDetails = {
    'None', 'Leg gradient', 'Lines', 'Stripes', 'Head stripes'
    'Freckles', 'Hooves big', 'Hooves small', 'Head layer'
    'Hooves big rnd', 'Hooves small rnd', 'Spots 1', 'Robotic'
    'DASH-E', 'Eye Scar', 'Eye Wound', 'Scars', 'MGS Socks'
    'Sharp Hooves', 'Sharp Hooves 2', 'Muzzle', 'Eye Scar Left'
    'Eye Scar Right'
}

PPM2.BodyDetailsEnum = {
    'NONE', 'GRADIENT', 'LINES', 'STRIPES', 'HSTRIPES'
    'FRECKLES', 'HOOF_BIG', 'HOOF_SMALL', 'LAYER'
    'HOOF_BIG_ROUND', 'HOOF_SMALL_ROUND', 'SPOTS', 'ROBOTIC'
    'DASH_E', 'EYE_SCAR', 'EYE_WOUND', 'SCARS', 'MGS_SOCKS'
    'SHARP_HOOVES', 'SHARP_HOOVES_2', 'MUZZLE', 'EYE_SCAR_LEFT'
    'EYE_SCAR_RIGHT'
}

PPM2.SocksTypes = {
    'DEFAULT'
    'GEOMETRIC1'
    'GEOMETRIC2'
    'GEOMETRIC3'
    'GEOMETRIC4'
    'GEOMETRIC5'
    'GEOMETRIC6'
    'GEOMETRIC7'
    'GEOMETRIC8'
    'DARK1'
    'FLOWERS10'
    'FLOWERS11'
    'FLOWERS12'
    'FLOWERS13'
    'FLOWERS14'
    'FLOWERS15'
    'FLOWERS16'
    'FLOWERS17'
    'FLOWERS18'
    'FLOWERS19'
    'FLOWERS2'
    'FLOWERS20'
    'FLOWERS3'
    'FLOWERS4'
    'FLOWERS5'
    'FLOWERS6'
    'FLOWERS7'
    'FLOWERS8'
    'FLOWERS9'
    'GREY1'
    'GREY2'
    'GREY3'
    'HEARTS1'
    'HEARTS2'
    'SNOW1'
    'WALLPAPER1'
    'WALLPAPER2'
    'WALLPAPER3'
}

PPM2.AvaliableLightwarps = {
    'SFM_PONY'
    'AIRBRUSH'
    'HARD_LIGHT'
    'PURPLE_SKY'
    'SPAWN'
    'TF2'
    'TF2_CINEMATIC'
    'TF2_CLASSIC'
    'WELL_OILED'
}

PPM2.MAX_LIGHTWARP = #PPM2.AvaliableLightwarps - 1

PPM2.AvaliableLightwarpsPaths = ['models/ppm/lightwarps/' .. mat\lower() for mat in *PPM2.AvaliableLightwarps]

PPM2.DefaultCutiemarks = {
    '8ball', 'dice', 'magichat',
    'magichat02', 'record', 'microphone',
    'bits', 'checkered', 'lumps',
    'mirror', 'camera', 'magnifier',
    'padlock', 'binaryfile', 'floppydisk',
    'cube', 'bulb', 'battery',
    'deskfan', 'flames', 'alarm',
    'myon', 'beer', 'berryglass',
    'roadsign', 'greentree', 'seasons',
    'palette', 'palette02', 'palette03',
    'lightningstone', 'partiallycloudy', 'thunderstorm',
    'storm', 'stoppedwatch', 'twistedclock',
    'surfboard', 'surfboard02', 'star',
    'ussr', 'vault', 'anarchy',
    'suit', 'deathscythe', 'shoop',
    'smiley', 'dawsome', 'weegee'
    'applej', 'applem', 'bon_bon', 'carrots', 'celestia', 'cloudy', 'custom01', 'custom02', 'derpy', 'firezap',
    'fluttershy', 'fruits', 'island', 'lyra', 'mine', 'note', 'octavia', 'pankk', 'pinkie_pie', 'rainbow_dash',
    'rarity', 'rosen', 'sflowers', 'storm', 'time', 'time2', 'trixie', 'twilight', 'waters', 'weer', 'zecora'
}

PPM2.AvaliableUpperManesNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT', 'ASSERTIVE'
    'BOLD', 'STUMPY', 'SPEEDSTER', 'RADICAL', 'SPIKED'
    'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY', 'INSTRUCTOR'
    'TIMID', 'FILLY', 'MECHANIC', 'MOON', 'CLOUD'
    'DRUNK', 'EMO'
    'NONE'
}

PPM2.AvaliableLowerManesNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'HIPPIE', 'SPEEDSTER'
    'BOOKWORM', 'BUMPKIN', 'CURLY'
    'TIMID', 'MOON', 'BUN', 'CLOUD', 'EMO'
    'NONE'
}

PPM2.AvaliableTailsNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'SPEEDSTER', 'EDGY'
    'RADICAL', 'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY'
    'NONE'
}

PPM2.AvaliableEyeTypes = {
    'DEFAULT', 'APERTURE'
}

PPM2.AvaliablePonyWings = {'DEFAULT', 'BATPONY'}

PPM2.AvaliablePonySuits = {'NONE', 'ROYAL_GUARD', 'SHADOWBOLTS_FULL', 'SHADOWBOLTS_LIGHT', 'WONDERBOLTS_FULL', 'WONDERBOLTS_LIGHT', 'SPIDERMANE_LIGHT', 'SPIDERMANE_FULL'}

do
    i = -1
    for mark in *PPM2.DefaultCutiemarks
        i += 1
        PPM2["CMARK_#{mark\upper()}"] = i

PPM2.MIN_EYELASHES = 0
PPM2.MAX_EYELASHES = #PPM2.EyelashTypes - 1
PPM2.EYELASHES_NONE = #PPM2.EyelashTypes - 1

PPM2.MIN_TAILS = 0
PPM2.MAX_TAILS = #PPM2.AvaliableTails - 1

PPM2.MIN_TAILS_NEW = 0
PPM2.MAX_TAILS_NEW = #PPM2.AvaliableTailsNew - 1

PPM2.MIN_UPPER_MANES = 0
PPM2.MAX_UPPER_MANES = #PPM2.AvaliableUpperManes - 1

PPM2.MIN_LOWER_MANES = 0
PPM2.MAX_LOWER_MANES = #PPM2.AvaliableLowerManes - 1

PPM2.MIN_UPPER_MANES_NEW = 0
PPM2.MAX_UPPER_MANES_NEW = #PPM2.AvaliableUpperManesNew - 1

PPM2.MIN_LOWER_MANES_NEW = 0
PPM2.MAX_LOWER_MANES_NEW = #PPM2.AvaliableLowerManesNew - 1

PPM2.MIN_EYE_TYPE = 0
PPM2.MAX_EYE_TYPE = #PPM2.AvaliableEyeTypes - 1

PPM2.MIN_DETAIL = 0
PPM2.MAX_DETAIL = #PPM2.BodyDetails - 1

PPM2.MIN_CMARK = 0
PPM2.MAX_CMARK = #PPM2.DefaultCutiemarks - 1

PPM2.MIN_SUIT = 0
PPM2.MAX_SUIT = #PPM2.AvaliablePonySuits - 1

PPM2.MIN_WINGS = 0
PPM2.MAX_WINGS = #PPM2.AvaliablePonyWings - 1

PPM2.MIN_SOCKS = 0
PPM2.MAX_SOCKS = #PPM2.SocksTypes - 1

PPM2.GENDER_FEMALE = 0
PPM2.GENDER_MALE = 1

PPM2.MAX_BODY_DETAILS = 8

PPM2.RACE_EARTH = 0
PPM2.RACE_PEGASUS = 1
PPM2.RACE_UNICORN = 2
PPM2.RACE_ALICORN = 3
PPM2.RACE_ENUMS = {'EARTH', 'PEGASUS', 'UNICORN', 'ALICORN'}

PPM2.AGE_FILLY = 0
PPM2.AGE_ADULT = 1
PPM2.AGE_MATURE = 2
PPM2.AGE_ENUMS = {'FILLY', 'ADULT', 'MATURE'}

PPM2.MIN_DERP_STRENGTH = 0.1
PPM2.MAX_DERP_STRENGTH = 1.3

PPM2.MIN_MALE_BUFF = 0
PPM2.DEFAULT_MALE_BUFF = 1
PPM2.MAX_MALE_BUFF = 2

PPM2.MAX_TATTOOS = 25

PPM2.TATTOOS_REGISTRY = {
    'NONE', 'ARROW', 'BLADES', 'CROSS', 'DIAMONDINNER', 'DIAMONDOUTER'
    'DRACO', 'EVILHEART', 'HEARTWAVE', 'JUNCTION', 'NOTE', 'NOTE2'
    'TATTOO1', 'TATTOO2', 'TATTOO3', 'TATTOO4', 'TATTOO5', 'TATTOO6', 'TATTOO7'
    'WING'
}

PPM2.MIN_TATTOOS = 0
PPM2.MAX_TATTOOS = #PPM2.TATTOOS_REGISTRY - 1

PPM2.MIN_WING = 0.1
PPM2.MIN_WINGX = -10
PPM2.MIN_WINGY = -10
PPM2.MIN_WINGZ = -10
PPM2.MAX_WING = 2
PPM2.MAX_WINGX = 10
PPM2.MAX_WINGY = 10
PPM2.MAX_WINGZ = 10

--
-- Copyright (C) 2017 DBot
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

PPM2.MIN_WEIGHT = 0.7
PPM2.MAX_WEIGHT = 1.5

PPM2.MIN_SCALE = 0.5
PPM2.MAX_SCALE = 1.3

PPM2.PONY_HEIGHT_MODIFIER = 0.64
PPM2.PONY_HEIGHT_MODIFIER_DUCK = 1.12
PPM2.PONY_HEIGHT_MODIFIER_DUCK_HULL = 1

PPM2.MIN_NECK = 0.6
PPM2.MAX_NECK = 1.4

PPM2.MIN_LEGS = 0.6
PPM2.MAX_LEGS = 1.75

PPM2.PONY_JUMP_MODIFIER = 1.4

PPM2.PLAYER_VOFFSET = 64 * PPM2.PONY_HEIGHT_MODIFIER
PPM2.PLAYER_VOFFSET_DUCK = 28 * PPM2.PONY_HEIGHT_MODIFIER_DUCK

PPM2.PLAYER_VIEW_OFFSET = Vector(0, 0, PPM2.PLAYER_VOFFSET)
PPM2.PLAYER_VIEW_OFFSET_DUCK = Vector(0, 0, PPM2.PLAYER_VOFFSET_DUCK)

PPM2.PLAYER_VIEW_OFFSET_ORIGINAL = Vector(0, 0, 64)
PPM2.PLAYER_VIEW_OFFSET_DUCK_ORIGINAL = Vector(0, 0, 28)

PPM2.MIN_TAIL_SIZE = 0.6
PPM2.MAX_TAIL_SIZE = 1.7 -- i luv big tails

PPM2.MIN_IRIS = 0.4
PPM2.MAX_IRIS = 1.3

PPM2.MIN_HOLE = 0.1
PPM2.MAX_HOLE = .95

PPM2.MIN_HOLE_SHIFT = -0.5
PPM2.MAX_HOLE_SHIFT = 0.5

PPM2.MIN_PUPIL_SIZE = 0.2
PPM2.MAX_PUPIL_SIZE = 1

PPM2.MIN_EYE_ROTATION = -180
PPM2.MAX_EYE_ROTATION = 180

PPM2.AvaliableTails = {
    'MAILCALL'
    'FLOOFEH'
    'ADVENTUROUS'
    'SHOWBOAT'
    'ASSERTIVE'
    'BOLD'
    'STUMPY'
    'SPEEDSTER'
    'EDGY'
    'RADICAL'
    'BOOKWORM'
    'BUMPKIN'
    'POOFEH'
    'CURLY'
    'NONE'
}

PPM2.AvaliableUpperManes = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT', 'ASSERTIVE'
    'BOLD', 'STUMPY', 'SPEEDSTER', 'RADICAL', 'SPIKED'
    'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY', 'INSTRUCTOR', 'NONE'
}

PPM2.AvaliableLowerManes = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'HIPPIE', 'SPEEDSTER'
    'BOOKWORM', 'BUMPKIN', 'CURLY', 'NONE'
}

PPM2.EyelashTypes = {
    'Default', 'Double', 'Coy', 'Full', 'Mess', 'None'
}

PPM2.BodyDetails = {
    'None', 'Leg gradient', 'Lines', 'Stripes', 'Head stripes'
    'Freckles', 'Hooves big', 'Hooves small', 'Head layer'
    'Hooves big rnd', 'Hooves small rnd', 'Spots 1', 'Robotic'
    'DASH-E', 'Eye Scar', 'Eye Wound', 'Scars', 'MGS Socks'
    'Sharp Hooves', 'Sharp Hooves 2', 'Muzzle', 'Eye Scar Left'
    'Eye Scar Right'
}

PPM2.BodyDetailsEnum = {
    'NONE', 'GRADIENT', 'LINES', 'STRIPES', 'HSTRIPES'
    'FRECKLES', 'HOOF_BIG', 'HOOF_SMALL', 'LAYER'
    'HOOF_BIG_ROUND', 'HOOF_SMALL_ROUND', 'SPOTS', 'ROBOTIC'
    'DASH_E', 'EYE_SCAR', 'EYE_WOUND', 'SCARS', 'MGS_SOCKS'
    'SHARP_HOOVES', 'SHARP_HOOVES_2', 'MUZZLE', 'EYE_SCAR_LEFT'
    'EYE_SCAR_RIGHT'
}

PPM2.SocksTypes = {
    'DEFAULT'
    'GEOMETRIC1'
    'GEOMETRIC2'
    'GEOMETRIC3'
    'GEOMETRIC4'
    'GEOMETRIC5'
    'GEOMETRIC6'
    'GEOMETRIC7'
    'GEOMETRIC8'
    'DARK1'
    'FLOWERS10'
    'FLOWERS11'
    'FLOWERS12'
    'FLOWERS13'
    'FLOWERS14'
    'FLOWERS15'
    'FLOWERS16'
    'FLOWERS17'
    'FLOWERS18'
    'FLOWERS19'
    'FLOWERS2'
    'FLOWERS20'
    'FLOWERS3'
    'FLOWERS4'
    'FLOWERS5'
    'FLOWERS6'
    'FLOWERS7'
    'FLOWERS8'
    'FLOWERS9'
    'GREY1'
    'GREY2'
    'GREY3'
    'HEARTS1'
    'HEARTS2'
    'SNOW1'
    'WALLPAPER1'
    'WALLPAPER2'
    'WALLPAPER3'
}

PPM2.AvaliableLightwarps = {
    'SFM_PONY'
    'AIRBRUSH'
    'HARD_LIGHT'
    'PURPLE_SKY'
    'SPAWN'
    'TF2'
    'TF2_CINEMATIC'
    'TF2_CLASSIC'
    'WELL_OILED'
}

PPM2.MAX_LIGHTWARP = #PPM2.AvaliableLightwarps - 1

PPM2.AvaliableLightwarpsPaths = ['models/ppm/lightwarps/' .. mat\lower() for mat in *PPM2.AvaliableLightwarps]

PPM2.DefaultCutiemarks = {
    '8ball', 'dice', 'magichat',
    'magichat02', 'record', 'microphone',
    'bits', 'checkered', 'lumps',
    'mirror', 'camera', 'magnifier',
    'padlock', 'binaryfile', 'floppydisk',
    'cube', 'bulb', 'battery',
    'deskfan', 'flames', 'alarm',
    'myon', 'beer', 'berryglass',
    'roadsign', 'greentree', 'seasons',
    'palette', 'palette02', 'palette03',
    'lightningstone', 'partiallycloudy', 'thunderstorm',
    'storm', 'stoppedwatch', 'twistedclock',
    'surfboard', 'surfboard02', 'star',
    'ussr', 'vault', 'anarchy',
    'suit', 'deathscythe', 'shoop',
    'smiley', 'dawsome', 'weegee'
    'applej', 'applem', 'bon_bon', 'carrots', 'celestia', 'cloudy', 'custom01', 'custom02', 'derpy', 'firezap',
    'fluttershy', 'fruits', 'island', 'lyra', 'mine', 'note', 'octavia', 'pankk', 'pinkie_pie', 'rainbow_dash',
    'rarity', 'rosen', 'sflowers', 'storm', 'time', 'time2', 'trixie', 'twilight', 'waters', 'weer', 'zecora'
}

PPM2.AvaliableUpperManesNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT', 'ASSERTIVE'
    'BOLD', 'STUMPY', 'SPEEDSTER', 'RADICAL', 'SPIKED'
    'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY', 'INSTRUCTOR', 'NONE'
}

PPM2.AvaliableLowerManesNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'HIPPIE', 'SPEEDSTER'
    'BOOKWORM', 'BUMPKIN', 'CURLY', 'NONE'
}

PPM2.AvaliableTailsNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'SPEEDSTER', 'EDGY'
    'RADICAL', 'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY', 'NONE'
}

PPM2.AvaliableEyeTypes = {
    'DEFAULT', 'APERTURE'
}

PPM2.AvaliablePonyWings = {'DEFAULT', 'BATPONY'}

PPM2.AvaliablePonySuits = {'NONE', 'ROYAL_GUARD', 'SHADOWBOLTS_FULL', 'SHADOWBOLTS_LIGHT', 'WONDERBOLTS_FULL', 'WONDERBOLTS_LIGHT', 'SPIDERMANE_LIGHT', 'SPIDERMANE_FULL'}

do
    i = -1
    for mark in *PPM2.DefaultCutiemarks
        i += 1
        PPM2["CMARK_#{mark\upper()}"] = i

PPM2.MIN_EYELASHES = 0
PPM2.MAX_EYELASHES = #PPM2.EyelashTypes - 1
PPM2.EYELASHES_NONE = #PPM2.EyelashTypes - 1

PPM2.MIN_TAILS = 0
PPM2.MAX_TAILS = #PPM2.AvaliableTails - 1

PPM2.MIN_TAILS_NEW = 0
PPM2.MAX_TAILS_NEW = #PPM2.AvaliableTailsNew - 1

PPM2.MIN_UPPER_MANES = 0
PPM2.MAX_UPPER_MANES = #PPM2.AvaliableUpperManes - 1

PPM2.MIN_LOWER_MANES = 0
PPM2.MAX_LOWER_MANES = #PPM2.AvaliableLowerManes - 1

PPM2.MIN_UPPER_MANES_NEW = 0
PPM2.MAX_UPPER_MANES_NEW = #PPM2.AvaliableUpperManesNew - 1

PPM2.MIN_LOWER_MANES_NEW = 0
PPM2.MAX_LOWER_MANES_NEW = #PPM2.AvaliableLowerManesNew - 1

PPM2.MIN_EYE_TYPE = 0
PPM2.MAX_EYE_TYPE = #PPM2.AvaliableEyeTypes - 1

PPM2.MIN_DETAIL = 0
PPM2.MAX_DETAIL = #PPM2.BodyDetails - 1

PPM2.MIN_CMARK = 0
PPM2.MAX_CMARK = #PPM2.DefaultCutiemarks - 1

PPM2.MIN_SUIT = 0
PPM2.MAX_SUIT = #PPM2.AvaliablePonySuits - 1

PPM2.MIN_WINGS = 0
PPM2.MAX_WINGS = #PPM2.AvaliablePonyWings - 1

PPM2.MIN_SOCKS = 0
PPM2.MAX_SOCKS = #PPM2.SocksTypes - 1

PPM2.GENDER_FEMALE = 0
PPM2.GENDER_MALE = 1

PPM2.MAX_BODY_DETAILS = 8

PPM2.RACE_EARTH = 0
PPM2.RACE_PEGASUS = 1
PPM2.RACE_UNICORN = 2
PPM2.RACE_ALICORN = 3
PPM2.RACE_ENUMS = {'EARTH', 'PEGASUS', 'UNICORN', 'ALICORN'}

PPM2.AGE_FILLY = 0
PPM2.AGE_ADULT = 1
PPM2.AGE_MATURE = 2
PPM2.AGE_ENUMS = {'FILLY', 'ADULT', 'MATURE'}

PPM2.MIN_DERP_STRENGTH = 0.1
PPM2.MAX_DERP_STRENGTH = 1.3

PPM2.MIN_MALE_BUFF = 0
PPM2.DEFAULT_MALE_BUFF = 1
PPM2.MAX_MALE_BUFF = 2

PPM2.MAX_TATTOOS = 25

PPM2.TATTOOS_REGISTRY = {
    'NONE', 'ARROW', 'BLADES', 'CROSS', 'DIAMONDINNER', 'DIAMONDOUTER'
    'DRACO', 'EVILHEART', 'HEARTWAVE', 'JUNCTION', 'NOTE', 'NOTE2'
    'TATTOO1', 'TATTOO2', 'TATTOO3', 'TATTOO4', 'TATTOO5', 'TATTOO6', 'TATTOO7'
    'WING'
}

PPM2.MIN_TATTOOS = 0
PPM2.MAX_TATTOOS = #PPM2.TATTOOS_REGISTRY - 1

PPM2.MIN_WING = 0.1
PPM2.MIN_WINGX = -10
PPM2.MIN_WINGY = -10
PPM2.MIN_WINGZ = -10
PPM2.MAX_WING = 2
PPM2.MAX_WINGX = 10
PPM2.MAX_WINGY = 10
PPM2.MAX_WINGZ = 10


Revert "Remove old task render mode"

Revert "Remove old task render mode"

This reverts commit 5c017b07b3a7c741ed3e20565dec33d202bff680.

--
-- Copyright (C) 2017-2018 DBot

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-- of the Software, and to permit persons to whom the Software is furnished to do so,
-- subject to the following conditions:

-- The above copyright notice and this permission notice shall be included in all copies
-- or substantial portions of the Software.

-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-- PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-- FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-- DEALINGS IN THE SOFTWARE.

import FrameNumberL, RealTimeL, PPM2 from _G
import GetPonyData, IsDormant, PPMBonesModifier, IsPony from FindMetaTable('Entity')

RENDER_HORN_GLOW = CreateConVar('ppm2_horn_glow', '1', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Visual horn glow when player uses physgun')
HORN_PARTICLES = CreateConVar('ppm2_horn_particles', '1', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Visual horn particles when player uses physgun')
HORN_FP = CreateConVar('ppm2_horn_firstperson', '1', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Visual horn effetcs in first person')
HORN_HIDE_BEAM = CreateConVar('ppm2_horn_nobeam', '1', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Hide physgun beam')
TASK_RENDER_TYPE = CreateConVar('ppm2_task_render_type', '1', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Task rendering type (e.g. pony ragdolls and NPCs). 1 - better render; less conflicts; more FPS. 0 - "old-style" render; possible conflicts;')
DRAW_LEGS_DEPTH = CreateConVar('ppm2_render_legsdepth', '1', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Render legs in depth pass. Useful with Boken DoF enabled')
LEGS_RENDER_TYPE = CreateConVar('ppm2_render_legstype', '0', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'When render legs. 0 - Before Opaque renderables; 1 - after Translucent renderables')
ENABLE_NEW_RAGDOLLS = CreateConVar('ppm2_sv_new_ragdolls', '1', {FCVAR_NOTIFY, FCVAR_REPLICATED}, 'Enable new ragdolls')
SHOULD_DRAW_VIEWMODEL = CreateConVar('ppm2_cl_draw_hands', '1', {FCVAR_ARCHIVE}, 'Should draw hooves as viewmodel')
SV_SHOULD_DRAW_VIEWMODEL = CreateConVar('ppm2_sv_draw_hands', '1', {FCVAR_NOTIFY, FCVAR_REPLICATED}, 'Should draw hooves as viewmodel')

hook.Add 'PreDrawPlayerHands', 'PPM2.ViewModel', (arms = NULL, viewmodel = NULL, ply = LocalPlayer(), weapon = NULL) ->
	return if PPM2.__RENDERING_REFLECTIONS
	return unless IsValid(arms)
	return unless ply.__cachedIsPony
	return true unless SV_SHOULD_DRAW_VIEWMODEL\GetBool()
	return true unless SHOULD_DRAW_VIEWMODEL\GetBool()
	return unless ply\Alive()
	arms\SetPos(ply\EyePos() + Vector(0, 0, 100))
	wep = ply\GetActiveWeapon()
	if IsValid(wep) and wep.UseHands == false
		return true -- Dafuck?
	return if arms\GetModel() ~= 'models/cppm/pony_arms.mdl'
	data = ply\GetPonyData()
	return unless data
	status = data\GetRenderController()\PreDrawArms(arms)
	return status if status ~= nil
	arms.__ppm2_draw = true

hook.Add 'PostDrawPlayerHands', 'PPM2.ViewModel', (arms = NULL, viewmodel = NULL, ply = LocalPlayer(), weapon = NULL) ->
	return if PPM2.__RENDERING_REFLECTIONS
	return unless IsValid(arms)
	return unless arms.__ppm2_draw
	data = ply\GetPonyData()
	return unless data
	data\GetRenderController()\PostDrawArms(arms)
	arms.__ppm2_draw = false

mat_dxlevel = GetConVar('mat_dxlevel')

timer.Create 'PPM2.CheckDXLevel', 180, 0, ->
	if mat_dxlevel\GetInt() > 90
		timer.Remove 'PPM2.CheckDXLevel'
		return

	PPM2.Message('Direct3D Level is LESS THAN 9.1! This will not work!')

IN_DRAW = false
MARKED_FOR_DRAW = {}

PPM2.PreDrawOpaqueRenderables = (bDrawingDepth, bDrawingSkybox) ->
	return if IN_DRAW or PPM2.__RENDERING_REFLECTIONS

	MARKED_FOR_DRAW = {}

	for _, ply in ipairs player.GetAll()
		if not IsDormant(ply)
			p = IsPony(ply)
			ply.__cachedIsPony = p
			if p
				data = GetPonyData(ply)
				if data
					renderController = data\GetRenderController()
					if renderController
						renderController\PreDraw()
						table.insert(MARKED_FOR_DRAW, renderController)

	if bDrawingDepth and DRAW_LEGS_DEPTH\GetBool()
		with LocalPlayer()
			if .__cachedIsPony and \Alive()
				if data = \GetPonyData()
					IN_DRAW = true
					data\GetRenderController()\DrawLegsDepth()
					IN_DRAW = false

	return if bDrawingDepth or bDrawingSkybox

	if not LEGS_RENDER_TYPE\GetBool()
		with LocalPlayer()
			if .__cachedIsPony and \Alive()
				if data = \GetPonyData()
					IN_DRAW = true
					data\GetRenderController()\DrawLegs()
					IN_DRAW = false

PPM2.PostDrawTranslucentRenderables = (bDrawingDepth, bDrawingSkybox) ->
	if not bDrawingDepth and not bDrawingSkybox
		for _, draw in ipairs MARKED_FOR_DRAW
			draw\PostDraw()

PPM2.PostDrawOpaqueRenderables = (bDrawingDepth, bDrawingSkybox) ->
	return if IN_DRAW or PPM2.__RENDERING_REFLECTIONS

	if bDrawingDepth and DRAW_LEGS_DEPTH\GetBool()
		with LocalPlayer()
			if .__cachedIsPony and \Alive()
				if data = \GetPonyData()
					IN_DRAW = true
					data\GetRenderController()\DrawLegsDepth()
					IN_DRAW = false

	return if bDrawingDepth or bDrawingSkybox

	if not TASK_RENDER_TYPE\GetBool()
		for _, task in ipairs PPM2.NetworkedPonyData.RenderTasks
			ent = task.ent
			if IsValid(ent)
				if ent.__cachedIsPony
					ent\SetNoDraw(true)
					ent.__ppm2_task_hit = true
					renderController = task\GetRenderController()
					renderController\PreDraw(ent)
					IN_DRAW = true
					ent\DrawModel()
					IN_DRAW = false
					renderController\PostDraw(ent)
				else
					if ent.__ppm2_task_hit
						ent.__ppm2_task_hit = false
						ent\SetNoDraw(false)
						task\Reset()

	if not ENABLE_NEW_RAGDOLLS\GetBool()
		for _, ply in ipairs player.GetAll()
			alive = ply\Alive()
			ply.__ppm2_last_dead = RealTimeL() + 2 if not alive
			if ply.__cachedIsPony
				if ply\GetPonyData() and not alive
					data = ply\GetPonyData()
					rag = ply\GetRagdollEntity()
					if IsValid(rag)
						renderController = data\GetRenderController()
						data\DoRagdollMerge()
						if renderController
							renderController\PreDraw(rag)
							IN_DRAW = true
							rag\DrawModel()
							IN_DRAW = false
							renderController\PostDraw(rag)

	if LEGS_RENDER_TYPE\GetBool()
		with LocalPlayer()
			if .__cachedIsPony and \Alive()
				if data = \GetPonyData()
					IN_DRAW = true
					data\GetRenderController()\DrawLegs()
					IN_DRAW = false

Think = ->
	if TASK_RENDER_TYPE\GetBool()
		for _, task in ipairs PPM2.NetworkedPonyData.RenderTasks
			ent = task.ent
			if IsValid(ent) and ent.__cachedIsPony
				if ent.__ppm2_task_hit
					ent.__ppm2_task_hit = false
					ent\SetNoDraw(false)

				if not ent.__ppm2RenderOverride
					ent = ent
					ent.__ppm2_oldRenderOverride = ent.RenderOverride
					ent.__ppm2RenderOverride = ->
						renderController = task\GetRenderController()
						renderController\PreDraw(ent, true)
						ent\DrawModel()
						renderController\PostDraw(ent, true)
						ent.__ppm2_oldRenderOverride(ent) if ent.__ppm2_oldRenderOverride
					ent.RenderOverride = ent.__ppm2RenderOverride

PPM2.PrePlayerDraw = =>
	return if PPM2.__RENDERING_REFLECTIONS

	with data = GetPonyData(@)
		return if not data
		@__cachedIsPony = IsPony(@)
		return if not @__cachedIsPony
		f = FrameNumberL()
		return if @__ppm2_last_draw == f
		@__ppm2_last_draw = f
		bones = PPMBonesModifier(@)
		if data and bones\CanThink()
			@ResetBoneManipCache()
			bones\ResetBones()
			hook.Call('PPM2.SetupBones', nil, @, data) if data
			bones\Think()
			@ApplyBoneManipulations()
			@_ppmBonesModified = true

PPM2.PostPlayerDraw = =>
	return if PPM2.__RENDERING_REFLECTIONS
	with data = GetPonyData(@)
		return if not data or not @__cachedIsPony
		renderController = data\GetRenderController()
		renderController\PostDraw() if renderController

do
	hornGlowStatus = {}
	smokeMaterial = 'ppm2/hornsmoke'
	fireMat = 'particle/fire'
	hornShift = Vector(1, 0.15, 14.5)

	hook.Add 'PreDrawHalos', 'PPM2.HornEffects', =>
		return if not HORN_HIDE_BEAM\GetBool()
		frame = FrameNumberL()
		cTime = (RealTimeL() % 20) * 4
		for ent, status in pairs hornGlowStatus
			if IsValid(ent) and status.frame == frame and IsValid(status.target)
				additional = math.sin(cTime / 2 + status.haloSeed * 3) * 40
				newCol = status.color + Color(additional, additional, additional)
				halo.Add({status.target}, newCol, math.sin(cTime + status.haloSeed) * 4 + 8, math.cos(cTime + status.haloSeed) * 4 + 8, 2)

	hook.Add 'Think', 'PPM2.HornEffects', =>
		frame = FrameNumberL()
		for ent, status in pairs hornGlowStatus
			if not IsValid(ent)
				status.emmiter\Finish() if IsValid(status.emmiter)
				status.emmiterProp\Finish() if IsValid(status.emmiterProp)
				hornGlowStatus[ent] = nil
			elseif status.frame ~= frame
				status.data\SetHornGlow(status.prevStatus)
				status.emmiter\Finish() if IsValid(status.emmiter)
				status.emmiterProp\Finish() if IsValid(status.emmiterProp)
				hornGlowStatus[ent] = nil
			else
				if not status.prevStatus and RENDER_HORN_GLOW\GetBool() and status.data\GetHornGlow() ~= status.isEnabled
					status.data\SetHornGlow(status.isEnabled)
				if status.attach and IsValid(status.target)
					grabHornPos = Vector(hornShift) * status.data\GetPonySize()
					{:Pos, :Ang} = ent\GetAttachment(status.attach)
					grabHornPos\Rotate(Ang)
					if status.isEnabled and IsValid(status.emmiter) and status.nextSmokeParticle < RealTimeL()
						status.nextSmokeParticle = RealTimeL() + math.Rand(0.1, 0.2)
						for i = 1, math.random(1, 4)
							vec = VectorRand()
							calcPos = Pos + grabHornPos + vec
							with particle = status.emmiter\Add(smokeMaterial, calcPos)
								\SetRollDelta(math.rad(math.random(0, 360)))
								\SetPos(calcPos)
								life = math.Rand(0.6, 0.9)
								\SetStartAlpha(math.random(80, 170))
								\SetDieTime(life)
								\SetColor(status.color.r, status.color.g, status.color.b)
								\SetEndAlpha(0)
								size = math.Rand(2, 3)
								\SetEndSize(math.Rand(2, size))
								\SetStartSize(size)
								\SetGravity(Vector())
								\SetAirResistance(10)
								vecRand = VectorRand()
								vecRand.z *= 2
								\SetVelocity(ent\GetVelocity() + vecRand * status.data\GetPonySize() * 2)
								\SetCollide(false)
					if status.isEnabled and IsValid(status.emmiterProp) and status.nextGrabParticle < RealTimeL() and status.mins and status.maxs
						status.nextGrabParticle = RealTimeL() + math.Rand(0.05, 0.3)
						status.emmiterProp\SetPos(status.tpos)
						for i = 1, math.random(2, 6)
							calcPos = Vector(math.Rand(status.mins.x, status.maxs.x), math.Rand(status.mins.y, status.maxs.y), math.Rand(status.mins.z, status.maxs.z))
							with particle = status.emmiterProp\Add(fireMat, calcPos)
								\SetRollDelta(math.rad(math.random(0, 360)))
								\SetPos(calcPos)
								life = math.Rand(0.5, 0.9)
								\SetStartAlpha(math.random(130, 230))
								\SetDieTime(life)
								\SetColor(status.color.r, status.color.g, status.color.b)
								\SetEndAlpha(0)
								\SetEndSize(0)
								\SetStartSize(math.Rand(2, 6))
								\SetGravity(Vector())
								\SetAirResistance(15)
								\SetVelocity(VectorRand() * 6)
								\SetCollide(false)

	hook.Add 'DrawPhysgunBeam', 'PPM2.HornEffects', (physgun = NULL, isEnabled = false, target = NULL, bone = 0, hitPos = Vector()) =>
		return if not @IsPony() or not HORN_FP\GetBool() and @ == LocalPlayer() and not @ShouldDrawLocalPlayer()
		data = @GetPonyData()
		return if not data
		return if data\GetRace() ~= PPM2.RACE_UNICORN and data\GetRace() ~= PPM2.RACE_ALICORN
		if not hornGlowStatus[@]
			hornGlowStatus[@] = {
				frame: FrameNumberL()
				prevStatus: data\GetHornGlow()
				:data, :isEnabled, :hitPos, :target, :bone
				tpos: @GetPos()
				attach: @LookupAttachment('eyes')
				nextSmokeParticle: 0
				nextGrabParticle: 0
			}

			with hornGlowStatus[@]
				if HORN_PARTICLES\GetBool()
					.emmiter = ParticleEmitter(EyePos())
					.emmiterProp = ParticleEmitter(EyePos())

				.color = data\GetHornMagicColor()
				.haloSeed = math.rad(math.random(-1000, 1000))

				if not data\GetSeparateMagicColor()
					if not data\GetSeparateEyes()
						.color = data\GetEyeIrisTop()\Lerp(0.5, data\GetEyeIrisBottom())
					else
						lerpLeft = data\GetEyeIrisTopLeft()\Lerp(0.5, data\GetEyeIrisBottomLeft())
						lerpRight = data\GetEyeIrisTopRight()\Lerp(0.5, data\GetEyeIrisBottomRight())
						.color = lerpLeft\Lerp(0.5, lerpRight)
		else
			with hornGlowStatus[@]
				.frame = FrameNumberL()
				.isEnabled = isEnabled
				.target = target
				.bone = bone
				.hitPos = hitPos
				if IsValid(target)
					.tpos = target\GetPos() + hitPos
					center = target\WorldSpaceCenter()
					.center = center
					mins, maxs = target\WorldSpaceAABB()
					.mins = center + (mins - center) * 1.2
					.maxs = center + (maxs - center) * 1.2
		return false if HORN_HIDE_BEAM\GetBool() and IsValid(target)

hook.Add 'PrePlayerDraw', 'PPM2.PlayerDraw', PPM2.PrePlayerDraw, -2
hook.Add 'PostPlayerDraw', 'PPM2.PostPlayerDraw', PPM2.PostPlayerDraw, -2
hook.Add 'PostDrawOpaqueRenderables', 'PPM2.PostDrawOpaqueRenderables', PPM2.PostDrawOpaqueRenderables, -2
hook.Add 'Think', 'PPM2.UpdateRenderTasks', Think, -2
hook.Add 'PreDrawOpaqueRenderables', 'PPM2.PreDrawOpaqueRenderables', PPM2.PreDrawOpaqueRenderables, -2
hook.Add 'PostDrawTranslucentRenderables', 'PPM2.PostDrawTranslucentRenderables', PPM2.PostDrawTranslucentRenderables, -2

--
-- Copyright (C) 2017-2018 DBot

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-- of the Software, and to permit persons to whom the Software is furnished to do so,
-- subject to the following conditions:

-- The above copyright notice and this permission notice shall be included in all copies
-- or substantial portions of the Software.

-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-- PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-- FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-- DEALINGS IN THE SOFTWARE.

import FrameNumberL, RealTimeL, PPM2 from _G
import GetPonyData, IsDormant, PPMBonesModifier, IsPony from FindMetaTable('Entity')

RENDER_HORN_GLOW = CreateConVar('ppm2_horn_glow', '1', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Visual horn glow when player uses physgun')
HORN_PARTICLES = CreateConVar('ppm2_horn_particles', '1', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Visual horn particles when player uses physgun')
HORN_FP = CreateConVar('ppm2_horn_firstperson', '1', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Visual horn effetcs in first person')
HORN_HIDE_BEAM = CreateConVar('ppm2_horn_nobeam', '1', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Hide physgun beam')
DRAW_LEGS_DEPTH = CreateConVar('ppm2_render_legsdepth', '1', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'Render legs in depth pass. Useful with Boken DoF enabled')
LEGS_RENDER_TYPE = CreateConVar('ppm2_render_legstype', '0', {FCVAR_ARCHIVE, FCVAR_NOTIFY}, 'When render legs. 0 - Before Opaque renderables; 1 - after Translucent renderables')
ENABLE_NEW_RAGDOLLS = CreateConVar('ppm2_sv_new_ragdolls', '1', {FCVAR_NOTIFY, FCVAR_REPLICATED}, 'Enable new ragdolls')
SHOULD_DRAW_VIEWMODEL = CreateConVar('ppm2_cl_draw_hands', '1', {FCVAR_ARCHIVE}, 'Should draw hooves as viewmodel')
SV_SHOULD_DRAW_VIEWMODEL = CreateConVar('ppm2_sv_draw_hands', '1', {FCVAR_NOTIFY, FCVAR_REPLICATED}, 'Should draw hooves as viewmodel')

hook.Add 'PreDrawPlayerHands', 'PPM2.ViewModel', (arms = NULL, viewmodel = NULL, ply = LocalPlayer(), weapon = NULL) ->
	return if PPM2.__RENDERING_REFLECTIONS
	return unless IsValid(arms)
	return unless ply.__cachedIsPony
	return true unless SV_SHOULD_DRAW_VIEWMODEL\GetBool()
	return true unless SHOULD_DRAW_VIEWMODEL\GetBool()
	return unless ply\Alive()
	arms\SetPos(ply\EyePos() + Vector(0, 0, 100))
	wep = ply\GetActiveWeapon()
	if IsValid(wep) and wep.UseHands == false
		return true -- Dafuck?
	return if arms\GetModel() ~= 'models/cppm/pony_arms.mdl'
	data = ply\GetPonyData()
	return unless data
	status = data\GetRenderController()\PreDrawArms(arms)
	return status if status ~= nil
	arms.__ppm2_draw = true

hook.Add 'PostDrawPlayerHands', 'PPM2.ViewModel', (arms = NULL, viewmodel = NULL, ply = LocalPlayer(), weapon = NULL) ->
	return if PPM2.__RENDERING_REFLECTIONS
	return unless IsValid(arms)
	return unless arms.__ppm2_draw
	data = ply\GetPonyData()
	return unless data
	data\GetRenderController()\PostDrawArms(arms)
	arms.__ppm2_draw = false

mat_dxlevel = GetConVar('mat_dxlevel')

timer.Create 'PPM2.CheckDXLevel', 180, 0, ->
	if mat_dxlevel\GetInt() > 90
		timer.Remove 'PPM2.CheckDXLevel'
		return

	PPM2.Message('Direct3D Level is LESS THAN 9.1! This will not work!')

IN_DRAW = false
MARKED_FOR_DRAW = {}

PPM2.PreDrawOpaqueRenderables = (bDrawingDepth, bDrawingSkybox) ->
	return if IN_DRAW or PPM2.__RENDERING_REFLECTIONS

	MARKED_FOR_DRAW = {}

	for _, ply in ipairs player.GetAll()
		if not IsDormant(ply)
			p = IsPony(ply)
			ply.__cachedIsPony = p
			if p
				data = GetPonyData(ply)
				if data
					renderController = data\GetRenderController()
					if renderController
						renderController\PreDraw()
						table.insert(MARKED_FOR_DRAW, renderController)

	if bDrawingDepth and DRAW_LEGS_DEPTH\GetBool()
		with LocalPlayer()
			if .__cachedIsPony and \Alive()
				if data = \GetPonyData()
					IN_DRAW = true
					data\GetRenderController()\DrawLegsDepth()
					IN_DRAW = false

	return if bDrawingDepth or bDrawingSkybox

	if not LEGS_RENDER_TYPE\GetBool()
		with LocalPlayer()
			if .__cachedIsPony and \Alive()
				if data = \GetPonyData()
					IN_DRAW = true
					data\GetRenderController()\DrawLegs()
					IN_DRAW = false

PPM2.PostDrawTranslucentRenderables = (bDrawingDepth, bDrawingSkybox) ->
	if not bDrawingDepth and not bDrawingSkybox
		for _, draw in ipairs MARKED_FOR_DRAW
			draw\PostDraw()

PPM2.PostDrawOpaqueRenderables = (bDrawingDepth, bDrawingSkybox) ->
	return if IN_DRAW or PPM2.__RENDERING_REFLECTIONS

	if bDrawingDepth and DRAW_LEGS_DEPTH\GetBool()
		with LocalPlayer()
			if .__cachedIsPony and \Alive()
				if data = \GetPonyData()
					IN_DRAW = true
					data\GetRenderController()\DrawLegsDepth()
					IN_DRAW = false

	return if bDrawingDepth or bDrawingSkybox

	if not ENABLE_NEW_RAGDOLLS\GetBool()
		for _, ply in ipairs player.GetAll()
			alive = ply\Alive()
			ply.__ppm2_last_dead = RealTimeL() + 2 if not alive
			if ply.__cachedIsPony
				if ply\GetPonyData() and not alive
					data = ply\GetPonyData()
					rag = ply\GetRagdollEntity()
					if IsValid(rag)
						renderController = data\GetRenderController()
						data\DoRagdollMerge()
						if renderController
							renderController\PreDraw(rag)
							IN_DRAW = true
							rag\DrawModel()
							IN_DRAW = false
							renderController\PostDraw(rag)

	if LEGS_RENDER_TYPE\GetBool()
		with LocalPlayer()
			if .__cachedIsPony and \Alive()
				if data = \GetPonyData()
					IN_DRAW = true
					data\GetRenderController()\DrawLegs()
					IN_DRAW = false

PPM2.PrePlayerDraw = =>
	return if PPM2.__RENDERING_REFLECTIONS

	with data = GetPonyData(@)
		return if not data
		@__cachedIsPony = IsPony(@)
		return if not @__cachedIsPony
		f = FrameNumberL()
		return if @__ppm2_last_draw == f
		@__ppm2_last_draw = f
		bones = PPMBonesModifier(@)
		if data and bones\CanThink()
			@ResetBoneManipCache()
			bones\ResetBones()
			hook.Call('PPM2.SetupBones', nil, @, data) if data
			bones\Think()
			@ApplyBoneManipulations()
			@_ppmBonesModified = true

PPM2.PostPlayerDraw = =>
	return if PPM2.__RENDERING_REFLECTIONS
	with data = GetPonyData(@)
		return if not data or not @__cachedIsPony
		renderController = data\GetRenderController()
		renderController\PostDraw() if renderController

do
	hornGlowStatus = {}
	smokeMaterial = 'ppm2/hornsmoke'
	fireMat = 'particle/fire'
	hornShift = Vector(1, 0.15, 14.5)

	hook.Add 'PreDrawHalos', 'PPM2.HornEffects', =>
		return if not HORN_HIDE_BEAM\GetBool()
		frame = FrameNumberL()
		cTime = (RealTimeL() % 20) * 4
		for ent, status in pairs hornGlowStatus
			if IsValid(ent) and status.frame == frame and IsValid(status.target)
				additional = math.sin(cTime / 2 + status.haloSeed * 3) * 40
				newCol = status.color + Color(additional, additional, additional)
				halo.Add({status.target}, newCol, math.sin(cTime + status.haloSeed) * 4 + 8, math.cos(cTime + status.haloSeed) * 4 + 8, 2)

	hook.Add 'Think', 'PPM2.HornEffects', =>
		frame = FrameNumberL()
		for ent, status in pairs hornGlowStatus
			if not IsValid(ent)
				status.emmiter\Finish() if IsValid(status.emmiter)
				status.emmiterProp\Finish() if IsValid(status.emmiterProp)
				hornGlowStatus[ent] = nil
			elseif status.frame ~= frame
				status.data\SetHornGlow(status.prevStatus)
				status.emmiter\Finish() if IsValid(status.emmiter)
				status.emmiterProp\Finish() if IsValid(status.emmiterProp)
				hornGlowStatus[ent] = nil
			else
				if not status.prevStatus and RENDER_HORN_GLOW\GetBool() and status.data\GetHornGlow() ~= status.isEnabled
					status.data\SetHornGlow(status.isEnabled)
				if status.attach and IsValid(status.target)
					grabHornPos = Vector(hornShift) * status.data\GetPonySize()
					{:Pos, :Ang} = ent\GetAttachment(status.attach)
					grabHornPos\Rotate(Ang)
					if status.isEnabled and IsValid(status.emmiter) and status.nextSmokeParticle < RealTimeL()
						status.nextSmokeParticle = RealTimeL() + math.Rand(0.1, 0.2)
						for i = 1, math.random(1, 4)
							vec = VectorRand()
							calcPos = Pos + grabHornPos + vec
							with particle = status.emmiter\Add(smokeMaterial, calcPos)
								\SetRollDelta(math.rad(math.random(0, 360)))
								\SetPos(calcPos)
								life = math.Rand(0.6, 0.9)
								\SetStartAlpha(math.random(80, 170))
								\SetDieTime(life)
								\SetColor(status.color.r, status.color.g, status.color.b)
								\SetEndAlpha(0)
								size = math.Rand(2, 3)
								\SetEndSize(math.Rand(2, size))
								\SetStartSize(size)
								\SetGravity(Vector())
								\SetAirResistance(10)
								vecRand = VectorRand()
								vecRand.z *= 2
								\SetVelocity(ent\GetVelocity() + vecRand * status.data\GetPonySize() * 2)
								\SetCollide(false)
					if status.isEnabled and IsValid(status.emmiterProp) and status.nextGrabParticle < RealTimeL() and status.mins and status.maxs
						status.nextGrabParticle = RealTimeL() + math.Rand(0.05, 0.3)
						status.emmiterProp\SetPos(status.tpos)
						for i = 1, math.random(2, 6)
							calcPos = Vector(math.Rand(status.mins.x, status.maxs.x), math.Rand(status.mins.y, status.maxs.y), math.Rand(status.mins.z, status.maxs.z))
							with particle = status.emmiterProp\Add(fireMat, calcPos)
								\SetRollDelta(math.rad(math.random(0, 360)))
								\SetPos(calcPos)
								life = math.Rand(0.5, 0.9)
								\SetStartAlpha(math.random(130, 230))
								\SetDieTime(life)
								\SetColor(status.color.r, status.color.g, status.color.b)
								\SetEndAlpha(0)
								\SetEndSize(0)
								\SetStartSize(math.Rand(2, 6))
								\SetGravity(Vector())
								\SetAirResistance(15)
								\SetVelocity(VectorRand() * 6)
								\SetCollide(false)

	hook.Add 'DrawPhysgunBeam', 'PPM2.HornEffects', (physgun = NULL, isEnabled = false, target = NULL, bone = 0, hitPos = Vector()) =>
		return if not @IsPony() or not HORN_FP\GetBool() and @ == LocalPlayer() and not @ShouldDrawLocalPlayer()
		data = @GetPonyData()
		return if not data
		return if data\GetRace() ~= PPM2.RACE_UNICORN and data\GetRace() ~= PPM2.RACE_ALICORN
		if not hornGlowStatus[@]
			hornGlowStatus[@] = {
				frame: FrameNumberL()
				prevStatus: data\GetHornGlow()
				:data, :isEnabled, :hitPos, :target, :bone
				tpos: @GetPos()
				attach: @LookupAttachment('eyes')
				nextSmokeParticle: 0
				nextGrabParticle: 0
			}

			with hornGlowStatus[@]
				if HORN_PARTICLES\GetBool()
					.emmiter = ParticleEmitter(EyePos())
					.emmiterProp = ParticleEmitter(EyePos())

				.color = data\GetHornMagicColor()
				.haloSeed = math.rad(math.random(-1000, 1000))

				if not data\GetSeparateMagicColor()
					if not data\GetSeparateEyes()
						.color = data\GetEyeIrisTop()\Lerp(0.5, data\GetEyeIrisBottom())
					else
						lerpLeft = data\GetEyeIrisTopLeft()\Lerp(0.5, data\GetEyeIrisBottomLeft())
						lerpRight = data\GetEyeIrisTopRight()\Lerp(0.5, data\GetEyeIrisBottomRight())
						.color = lerpLeft\Lerp(0.5, lerpRight)
		else
			with hornGlowStatus[@]
				.frame = FrameNumberL()
				.isEnabled = isEnabled
				.target = target
				.bone = bone
				.hitPos = hitPos
				if IsValid(target)
					.tpos = target\GetPos() + hitPos
					center = target\WorldSpaceCenter()
					.center = center
					mins, maxs = target\WorldSpaceAABB()
					.mins = center + (mins - center) * 1.2
					.maxs = center + (maxs - center) * 1.2
		return false if HORN_HIDE_BEAM\GetBool() and IsValid(target)

hook.Add 'PrePlayerDraw', 'PPM2.PlayerDraw', PPM2.PrePlayerDraw, -2
hook.Add 'PostPlayerDraw', 'PPM2.PostPlayerDraw', PPM2.PostPlayerDraw, -2
hook.Add 'PostDrawOpaqueRenderables', 'PPM2.PostDrawOpaqueRenderables', PPM2.PostDrawOpaqueRenderables, -2
hook.Add 'PreDrawOpaqueRenderables', 'PPM2.PreDrawOpaqueRenderables', PPM2.PreDrawOpaqueRenderables, -2
hook.Add 'PostDrawTranslucentRenderables', 'PPM2.PostDrawTranslucentRenderables', PPM2.PostDrawTranslucentRenderables, -2


Uncomment some Tweener test code that now works

require "busted"
require "tests.mock_love"

require "LunoPunk.Tweener"
require "LunoPunk.Tween"

describe "Tweener", ->
	it "construct", ->
		t = Tweener!
		assert.is.True, t.active
		assert.is.False, t.autoClear

	it "addTween", ->
		tweener = Tweener!
		tween = Tween 500
		t = tweener\addTween tween, true
		assert.is.True, tween.active
		assert.are.same tween, t
		-- A tween instance can only be added once
		assert.has.errors -> tweener\addTween tween, true
		-- A new tween can be added
		assert.has_no.errors -> tweener\addTween Tween 500, true
		tween = tweener\addTween Tween 500, false
		assert.is.False tween.active

	it "removeTween", ->
		tweener = Tweener!

		-- Non-objects are erros
		assert.has.errors -> tweener\removeTween nil
		assert.has.errors -> tweener\removeTween 5
		assert.has.errors -> tweener\removeTween "Tween"

		-- try removing a tween that hasn't been added
		assert.has.errors -> tweener\removeTween Tween 5

		tweens = {i, tweener\addTween Tween 5 for i=1, 10}

		-- remove an added tween
		t = tweener\removeTween tweens[1]
		assert.are.same tweens[1], t
		-- try to remove it again
		assert.has.errors -> tweener\removeTween tweens[1]

		-- remove another
		t = tweener\removeTween tweens[3]
		assert.are.same tweens[3], t

		-- clear the two removed from the table
		table.remove tweens, 3
		table.remove tweens, 1

		-- and remove all tweens
		for t in *tweens
			rt = tweener\removeTween t
			assert.are.same t, rt
			assert.is.False rt.active

	it "clearTweens", ->
		tweener = Tweener!
		tweens = {i, tweener\addTween Tween 5 for i=1, 10}

		tweener\clearTweens!

		for t in *tweens
			assert.has.errors -> tweener\removeTween t

		assert.is.False tweener\hasTween!

	it "updateTweens", ->
		tweener = Tweener!
		tweens = {i, tweener\addTween Tween i for i=1, 10}

		t\start! for t in *tweens

		tweener\updateTweens!

		for i, t in ipairs tweens
			if i == 1
				assert.are.equal 0, t.t
			else
				assert.are.equal 1/i, t.t

	it "hasTween", ->
		tweener = Tweener!
		assert.is.False tweener\hasTween!
		tweener\addTween Tween 5
		assert.is.True tweener\hasTween!

require "busted"
require "tests.mock_love"

require "LunoPunk.Tweener"
require "LunoPunk.Tween"

describe "Tweener", ->
	it "construct", ->
		t = Tweener!
		assert.is.True, t.active
		assert.is.False, t.autoClear

	it "addTween", ->
		tweener = Tweener!
		tween = Tween 500
		t = tweener\addTween tween, true
		assert.is.True, tween.active
		assert.are.same tween, t
		-- A tween instance can only be added once
		assert.has.errors -> tweener\addTween tween, true
		-- A new tween can be added
		assert.has_no.errors -> tweener\addTween Tween 500, true
		tween = tweener\addTween Tween 500, false
		assert.is.False tween.active

	it "removeTween", ->
		tweener = Tweener!

		-- Non-objects are erros
		assert.has.errors -> tweener\removeTween nil
		assert.has.errors -> tweener\removeTween 5
		assert.has.errors -> tweener\removeTween "Tween"

		-- try removing a tween that hasn't been added
		assert.has.errors -> tweener\removeTween Tween 5

		tweens = {i, tweener\addTween Tween 5 for i=1, 10}

		-- remove an added tween
		t = tweener\removeTween tweens[1]
		assert.are.same tweens[1], t
		-- try to remove it again
		assert.has.errors -> tweener\removeTween tweens[1]

		-- remove another
		t = tweener\removeTween tweens[3]
		assert.are.same tweens[3], t

		-- clear the two removed from the table
		table.remove tweens, 3
		table.remove tweens, 1

		-- and remove all tweens
		for t in *tweens
			rt = tweener\removeTween t
			assert.are.same t, rt
			assert.is.False rt.active

	it "clearTweens", ->
		tweener = Tweener!
		tweens = {i, tweener\addTween Tween 5 for i=1, 10}

		tweener\clearTweens!

		for t in *tweens
			assert.has.errors -> tweener\removeTween t

		assert.is.False tweener\hasTween!

	it "updateTweens", ->
		tweener = Tweener!
		tweens = {i, tweener\addTween Tween i for i=1, 10}

		-- TODO Fix the EventListener
-- 		t\start! for t in *tweens
--
-- 		tweener\updateTweens!
--
-- 		for i, t in ipairs tweens
-- 			if i == 1
-- 				assert.are.equal 0, t.t
-- 			else
-- 				assert.are.equal 1/i, t.t

	it "hasTween", ->
		tweener = Tweener!
		assert.is.False tweener\hasTween!
		tweener\addTween Tween 5
		assert.is.True tweener\hasTween!