From e4ec1e19dbd9d7422e1b1a14742cb85e6465c297 Mon Sep 17 00:00:00 2001 From: Gimzie Date: Tue, 16 Jan 2024 12:05:07 -0600 Subject: [PATCH] Add various sprite images & add controller / liquid movement indication (#88) * Add walking Whomp & adjust MovIndicatorRenderer for clarity * Add movement indicators for liquids * Add Vertical Lift - Totem and fix Red Coin/Gold Ring * Fix Resizable & Fixed-Side Platform rendering * Add preference to adjust liquid indicator rendering order * Add purple Bowser Flame and Big Bowser Battle Lift * Add Big Icy Spiked Ball & hidden Fire Snake * Add back & forth movement controller visualization * Fix movement indicator cull bounds & separator misplacement --- coinkiller_data/icons/render_controllers.png | Bin 0 -> 8144 bytes coinkiller_data/spritedata.xml | 1899 +++++++++++------ .../sprites/big_icy_spiked_ball.png | Bin 0 -> 7752 bytes coinkiller_data/sprites/bowser_flame.png | Bin 3070 -> 14872 bytes ...bowser_flame.png => bowser_flame_blue.png} | Bin .../sprites/bowser_flame_purple.png | Bin 0 -> 2093 bytes coinkiller_data/sprites/bowser_lift/l.png | Bin 0 -> 3256 bytes coinkiller_data/sprites/bowser_lift/m.png | Bin 0 -> 2662 bytes coinkiller_data/sprites/bowser_lift/s.png | Bin 0 -> 2545 bytes coinkiller_data/sprites/fire_snake_hidden.png | Bin 0 -> 613 bytes coinkiller_data/sprites/lava_top.png | Bin 2868 -> 10498 bytes coinkiller_data/sprites/poison_top.png | Bin 3170 -> 11115 bytes coinkiller_data/sprites/totem_lift/l.png | Bin 0 -> 894 bytes coinkiller_data/sprites/totem_lift/m.png | Bin 0 -> 708 bytes coinkiller_data/sprites/totem_lift/r.png | Bin 0 -> 981 bytes coinkiller_data/sprites/whomp_big_walk.png | Bin 0 -> 12198 bytes coinkiller_data/sprites/whomp_walk.png | Bin 0 -> 5018 bytes leveleditor/leveleditorwindow.cpp | 9 + leveleditor/leveleditorwindow.h | 2 + leveleditor/leveleditorwindow.ui | 27 +- leveleditor/levelview.cpp | 109 +- leveleditor/levelview.h | 2 + leveleditor/settingsdialog.cpp | 12 + leveleditor/settingsdialog.h | 2 + leveleditor/settingsdialog.ui | 49 +- leveleditor/zoneeditorwidget.cpp | 4 + objectrenderer.cpp | 727 +++++-- objectrenderer.h | 53 +- objects.cpp | 204 +- settingsmanager.cpp | 8 + settingsmanager.h | 4 + 31 files changed, 2130 insertions(+), 981 deletions(-) create mode 100644 coinkiller_data/icons/render_controllers.png create mode 100644 coinkiller_data/sprites/big_icy_spiked_ball.png rename coinkiller_data/sprites/{dry_bowser_flame.png => bowser_flame_blue.png} (100%) create mode 100644 coinkiller_data/sprites/bowser_flame_purple.png create mode 100644 coinkiller_data/sprites/bowser_lift/l.png create mode 100644 coinkiller_data/sprites/bowser_lift/m.png create mode 100644 coinkiller_data/sprites/bowser_lift/s.png create mode 100644 coinkiller_data/sprites/fire_snake_hidden.png create mode 100644 coinkiller_data/sprites/totem_lift/l.png create mode 100644 coinkiller_data/sprites/totem_lift/m.png create mode 100644 coinkiller_data/sprites/totem_lift/r.png create mode 100644 coinkiller_data/sprites/whomp_big_walk.png create mode 100644 coinkiller_data/sprites/whomp_walk.png diff --git a/coinkiller_data/icons/render_controllers.png b/coinkiller_data/icons/render_controllers.png new file mode 100644 index 0000000000000000000000000000000000000000..6c90cc7d37cf68c4d1813bfc29a555e03d244b57 GIT binary patch literal 8144 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 literal 0 HcmV?d00001 diff --git a/coinkiller_data/spritedata.xml b/coinkiller_data/spritedata.xml index ed72d28c..5b1dd987 100644 --- a/coinkiller_data/spritedata.xml +++ b/coinkiller_data/spritedata.xml @@ -2,7 +2,7 @@ - + Lock All Camera Movement @@ -12,25 +12,25 @@ Unlocks Camera Movement - Move To Target Node + Repeat Camera Movement Maintain Existing Locks Lock Backwards X-Axis Movement - + + - - - + + - + - - Strongest (7 Blocks) - Strong (6 Blocks) - Weak (5 Blocks) - Weakest (4 Blocks) - Large Bubbles (4 Blocks) + + 7 Tiles + 6 Tiles + 5 Tiles + 4 Tiles + 4 Tiles (Line of Bubbles) Pipe Up @@ -40,9 +40,9 @@ - - 10 blocks - 5 blocks + + 10 Tiles + 5 Tiles @@ -86,6 +86,13 @@ + + + Fire Flower + Gold Flower Card + Gold Flower Card (No 1-Up) + Super Leaf + One Two @@ -105,11 +112,16 @@ Red Coin Ring Coins Moon Coin + ScCourse 0x0010 (Crash) + BsRoot? 0x0000 (smoke) - - Walks - Still + + + Left + Right + Towards Player + @@ -133,8 +145,9 @@ - - + + + No Movement Up - Normal Up - Fast @@ -155,12 +168,12 @@ - - + - + + No Movement Up - Normal @@ -182,12 +195,13 @@ - + - + + No Movement Up - Normal @@ -209,8 +223,14 @@ - + + + + Normal + Transparent + Very Transparent + @@ -219,7 +239,7 @@ - + @@ -231,6 +251,7 @@ Slow Medium Fast + Static Clockwise @@ -246,31 +267,27 @@ - - + + All Tiles Alternating Alternating type 2 - - Red Block - Brick Block - Coin - Stone Block - Wood Block - Same as 4? - Blue Block - Mini Mario Passageway (Right) - Up-facing Vertical Blue Pipe - Top Left - Broken Vertical Blue Pipe - Top Right - Horizontal Mini Pipe Center - Left-facing/Right-facing [which?] Horizontal Green Pipe - Bottom Left + + Red Block (ID 27) + Brick Block (ID 20) + Coin (ID 15) + Stone Block (ID 24) + Wood Block (ID 23) + Wood Block (ID 23) + Blue Block (ID 19) Destroy Create + @@ -322,6 +339,7 @@ Walk right Walk left + None On vine @@ -390,6 +408,7 @@ + Fire Flower and Star Gold Flower and Super Leaf @@ -397,21 +416,39 @@ Super Star Fire Flower and Gold Flower + + - + + Up + Down + Left + Right + + Normal Jump When Spawned Shot From Cannon Frozen - + + + + Up-Right + Up-Left + Down-Right + Down-Left + Higher Up-Right + Higher Up-Left + + @@ -474,13 +511,13 @@ - 12 Blocks Horizontal - 6 Vertical - 10 Blocks Horizontal - 8 Vertical - 18 Blocks Horizontal - 6 Vertical - 18 Blocks Horizontal - 7 Vertical (Fast) - 9 Blocks Horizontal - 7 Vertical (Fast) - 6 Blocks Horizontal - 9 Vertical - 16 Blocks Horizontal - 9 Vertical + 12 Tiles Horizontal - 6 Vertical + 10 Tiles Horizontal - 8 Vertical + 18 Tiles Horizontal - 6 Vertical + 18 Tiles Horizontal - 7 Vertical (Fast) + 9 Tiles Horizontal - 7 Vertical (Fast) + 6 Tiles Horizontal - 9 Vertical + 16 Tiles Horizontal - 9 Vertical Up (Permanent) Nothing? Up (Permanent and Fast) @@ -488,6 +525,7 @@ Static and Facing Drection Static and Facing Drection Up (Permanent) + No @@ -508,20 +546,42 @@ + + Right + Left + Up + Down + + + Right + Left + Up + Down + - + + Right + Left + Up + Down + - + + Right + Left + Up + Down + @@ -650,6 +710,11 @@ + + + Spawn + Despawn + Slowest @@ -678,12 +743,34 @@ - - + Counterclockwise Clockwise - + + Auto Start + Event Triggered (One Swing) + Event Triggered + + + + No Arc + 22.5 + 45 + 67.5 + 90 (Clockwise) + 112.5 (Clockwise) + 135 (Clockwise) + 157.5 (Clockwise) + 180 (Clockwise) + 202.5 (Clockwise) + 225 (Clockwise) + 247.5 (Clockwise) + 270 + 292.5,14 + 337.5 + + None 22.5 45 @@ -697,7 +784,8 @@ 225 247.5 270 - 292.5,14 + 292.5 + 315 337.5 @@ -767,11 +855,8 @@ Event Triggered - Rotates Back When Deactivated (Slowest) - - None - Screen Shake For Direction Change - Coin Sound - + + Slowest Slower @@ -788,7 +873,7 @@ - + Normal Smoke Effect @@ -801,7 +886,7 @@ - + Normal Moves Down Floats in Place @@ -811,13 +896,15 @@ 45 degree Down 80 degree Down + - + + Small Height / Medium Width Small Height / Small Width @@ -829,20 +916,24 @@ Down Left Right + Up-Right (Bone Lift) None Sparkes With Smoke Sparkles + + Left Right + @@ -855,8 +946,6 @@ - - @@ -869,14 +958,35 @@ + + Normal + Coin Starts Upside Down + Coin Faces Screen (Broken) + Coin Faces Controller + + - - Normal/Falling + + Normal Paracoin 1 Paracoin 2 - - + + Stationary + Falling + Falling (Medium) + Falling (Fast) + Falling (Fastest) + Gravity Affected + + + Above Layer 1 + Above Layer 2 + Further Above Layer 1 + + + + @@ -885,9 +995,27 @@ Coin Faces Screen Coin Faces Controller - + - + + Normal + Paracoin 1 (Broken) + Paracoin 2 (Broken) + + + Stationary + Falling + Falling (Medium) + Falling (Fast) + Falling (Fastest) + Gravity Affected + + + Above Layer 1 + Above Layer 2 + Further Above Layer 1 + + @@ -897,10 +1025,13 @@ Medium Slow - - No Offset - Launch delayed - Spawn launched + + Synced + Not Synced + Start Launched (Not Synced) + Delayed Start (Synced) + Delayed Start (Not Synced) + Delayed Start (Start Launched) 16 Tiles @@ -919,10 +1050,13 @@ Medium Slow - - No Offset - Launch delayed - Spawn launched + + Synced + Not Synced + Start Launched (Not Synced) + Delayed Start (Synced) + Delayed Start (Not Synced) + Delayed Start (Start Launched) 16 Tiles @@ -936,6 +1070,7 @@ + 30 degrees right 30 degrees left @@ -949,14 +1084,13 @@ - + Short Medium Long Spawn once - Goomba Bob-omb @@ -968,7 +1102,7 @@ Left Right - + @@ -986,19 +1120,19 @@ - - + + Normal - ??? - Automaticaly Fall + Wide Detection Range? [Broken] + Automatically Fall - - + + Normal - ??? + Wide Detection Range? [Broken] Automatically Fall @@ -1008,7 +1142,7 @@ Counterclockwise Clockwise - + One Bar Two Bars Three Bars @@ -1090,9 +1224,10 @@ + - + Right @@ -1104,7 +1239,7 @@ - + Target Event Enables After Delay Target Event Disables After Delay @@ -1113,8 +1248,9 @@ Activate On Triggering Event Disabled - Single Use + Single Use Only While Start Event Is Active + Only While Status is Satisfied Enables Event @@ -1123,6 +1259,12 @@ + + All Players Contribute to Requirements + Only Mario Contributes + Only Luigi Contributes + Both Players Must Contribute (Movement-only) + @@ -1134,7 +1276,7 @@ Fire Mini Super Leaf - Unknown 6 + Small Mega Mario Star @@ -1194,9 +1336,6 @@ - - - @@ -1206,6 +1345,10 @@ + + Spawn + Despawn + Slowest Slower @@ -1223,13 +1366,13 @@ - + Already Climbing Falls - + Right Swings Down Left Swings Down @@ -1243,7 +1386,7 @@ - Normal + Normal From Pipe Facing Up - 45° Right From Pipe Facing Right - 45° Up From Pipe Facing Right @@ -1259,59 +1402,59 @@ - Default (9 Blocks) - 2 Blocks - 3 Blocks - 4 Blocks - 5 Blocks - 6 Blocks - 7 Blocks - 8 Blocks - 9 Blocks - 10 Blocks - 11 Blocks - 12 Blocks - 13 Blocks - 14 Blocks - 15 Blocks - 16 Blocks + Default (9 Tiles) + 2 Tiles + 3 Tiles + 4 Tiles + 5 Tiles + 6 Tiles + 7 Tiles + 8 Tiles + 9 Tiles + 10 Tiles + 11 Tiles + 12 Tiles + 13 Tiles + 14 Tiles + 15 Tiles + 16 Tiles - Default (7 Blocks) - 2 Blocks - 3 Blocks - 4 Blocks - 5 Blocks - 6 Blocks - 7 Blocks - 8 Blocks - 9 Blocks - 10 Blocks - 11 Blocks - 12 Blocks - 13 Blocks - 14 Blocks - 15 Blocks - 16 Blocks + Default (7 Tiles) + 2 Tiles + 3 Tiles + 4 Tiles + 5 Tiles + 6 Tiles + 7 Tiles + 8 Tiles + 9 Tiles + 10 Tiles + 11 Tiles + 12 Tiles + 13 Tiles + 14 Tiles + 15 Tiles + 16 Tiles Default (Unlimited) - 2 Blocks - 3 Blocks - 4 Blocks - 5 Blocks - 6 Blocks - 7 Blocks - 8 Blocks - 9 Blocks - 10 Blocks - 11 Blocks - 12 Blocks - 13 Blocks - 14 Blocks - 15 Blocks - 16 Blocks + 2 Tiles + 3 Tiles + 4 Tiles + 5 Tiles + 6 Tiles + 7 Tiles + 8 Tiles + 9 Tiles + 10 Tiles + 11 Tiles + 12 Tiles + 13 Tiles + 14 Tiles + 15 Tiles + 16 Tiles Towards Player @@ -1336,59 +1479,59 @@ - Default (9 Blocks) - 2 Blocks - 3 Blocks - 4 Blocks - 5 Blocks - 6 Blocks - 7 Blocks - 8 Blocks - 9 Blocks - 10 Blocks - 11 Blocks - 12 Blocks - 13 Blocks - 14 Blocks - 15 Blocks - 16 Blocks + Default (9 Tiles) + 2 Tiles + 3 Tiles + 4 Tiles + 5 Tiles + 6 Tiles + 7 Tiles + 8 Tiles + 9 Tiles + 10 Tiles + 11 Tiles + 12 Tiles + 13 Tiles + 14 Tiles + 15 Tiles + 16 Tiles - Default (7 Blocks) - 2 Blocks - 3 Blocks - 4 Blocks - 5 Blocks - 6 Blocks - 7 Blocks - 8 Blocks - 9 Blocks - 10 Blocks - 11 Blocks - 12 Blocks - 13 Blocks - 14 Blocks - 15 Blocks - 16 Blocks + Default (7 Tiles) + 2 Tiles + 3 Tiles + 4 Tiles + 5 Tiles + 6 Tiles + 7 Tiles + 8 Tiles + 9 Tiles + 10 Tiles + 11 Tiles + 12 Tiles + 13 Tiles + 14 Tiles + 15 Tiles + 16 Tiles Default (Unlimited) - 2 Blocks - 3 Blocks - 4 Blocks - 5 Blocks - 6 Blocks - 7 Blocks - 8 Blocks - 9 Blocks - 10 Blocks - 11 Blocks - 12 Blocks - 13 Blocks - 14 Blocks - 15 Blocks - 16 Blocks + 2 Tiles + 3 Tiles + 4 Tiles + 5 Tiles + 6 Tiles + 7 Tiles + 8 Tiles + 9 Tiles + 10 Tiles + 11 Tiles + 12 Tiles + 13 Tiles + 14 Tiles + 15 Tiles + 16 Tiles Towards Player @@ -1408,10 +1551,11 @@ Normal Start Upside Down - Gimbal Rotation + Face The Screen + Nothing @@ -1452,7 +1596,7 @@ - + Normal Fly In From Background @@ -1465,26 +1609,38 @@ - + Fly In From Background Fly In From Right + Above Other Sprites Below Other Sprites - - + + + + Moves when Touched Already Moving Moves when Touched Already Moving - + + Forwards + Backwards + + + Falls Off + Go Back + Stops + + @@ -1516,19 +1672,19 @@ - + - + - + Unlimited 3 Rocks 5 Rocks - + @@ -1537,14 +1693,14 @@ - + Normal Upside Down Shifted Up A Tile - + - + Chase Chase & Explode @@ -1560,6 +1716,8 @@ + + @@ -1575,7 +1733,7 @@ - + Show Hide @@ -1600,7 +1758,7 @@ - + Show Hide @@ -1627,7 +1785,7 @@ - + Colored Stem Gray Stem @@ -1639,7 +1797,7 @@ - + Colored Stem @@ -1652,7 +1810,7 @@ - + @@ -1691,9 +1849,13 @@ Dry Bowser - - + + + + Left + Right + @@ -1701,9 +1863,9 @@ - + - + @@ -1713,36 +1875,68 @@ + + Above layer 1 Tiles Below Layer 1 Tiles - + Normal Spin (Death Animation) From Pipe - + Normal Blue - + Up Down Left Right + Right (facing left) + Spawn normally + Down (Falling very fast) + Up (Ascending very fast) + Up (Ascending very fast) + Down (Falling very fast) + Left (Flies across the screen) + Left (Flies across the screen) - + + Above layer 1 Tiles Below Layer 1 Tiles - + + + Normal + Spin (Death Animation) + From Pipe + + + + + Up + Down + Left + Right + Right (facing left) + Spawn normally + Down (Falling very fast) + Up (Ascending very fast) + Up (Ascending very fast) + Down (Falling very fast) + Left (Flies across the screen) + Left (Flies across the screen) + @@ -1781,7 +1975,7 @@ - + @@ -1792,7 +1986,7 @@ - + @@ -1826,9 +2020,10 @@ Faster Fastest - + + - + @@ -1836,7 +2031,7 @@ Big - + Right Left @@ -1860,30 +2055,30 @@ - + - - Up/Down - Up/Down Right (speed 0) - Up/Down Right (speed 1) - Up/Down Right (speed 2) - Up/Down Right (speed 3) - Up/Down Right (speed 4) - Up/Down Right (speed 5) - Up/Down Right (speed 6) - Up/Down Right (speed 7) - Up/Down Right (speed 8) - Up/Down Right (speed 9) - Up/Down Right (speed 10) - Up/Down Right (speed 11) - Up/Down Right (speed 12) - Up/Down Right (speed 13) - Up/Down + + Normal (Default) + Diagonal (speed 0) + Diagonal (speed 1) + Diagonal (speed 2) + Diagonal (speed 3) + Diagonal (speed 4) + Diagonal (speed 5) + Diagonal (speed 6) + Diagonal (speed 7) + Diagonal (speed 8) + Diagonal (speed 9) + Diagonal (speed 10) + Diagonal (speed 11) + Diagonal (speed 12) + Diagonal (speed 13) + Normal - - + + - + @@ -1893,6 +2088,7 @@ + @@ -1900,7 +2096,7 @@ - + Moves when Touched (Default) Already Moving Moves when Touched @@ -1909,7 +2105,7 @@ Forwards Backwards - + Falls Changes Direction Stops @@ -1918,6 +2114,7 @@ Appear While on Lift Only + Appear and Rotate Lift While on Lift Only Shown based on Start Behavior @@ -1934,9 +2131,10 @@ Left + - + @@ -1957,7 +2155,6 @@ - Camera Stays Above Camera Stays Below @@ -1968,13 +2165,12 @@ Limit in Co-op Play Unknown Value 3 - + - Camera Stays Above Camera Stays Below @@ -1985,21 +2181,31 @@ Limit in Co-op Play Unknown Value 3 - + - + - + Face Player Right Left + + Normal (Default) + Lowest + Low + Medium + Normal + High + Higher + Highest + Normal On Ceiling @@ -2027,6 +2233,7 @@ Limit Until Both Players Cross Unknown Value 3 + @@ -2042,6 +2249,7 @@ Limit Until Both Players Cross Unknown Value 3 + @@ -2080,6 +2288,7 @@ Green Red + @@ -2087,7 +2296,12 @@ Left Up Down + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + @@ -2139,12 +2353,13 @@ - + + - - + + @@ -2156,24 +2371,35 @@ - - + + - + + + + Towards Player + Right + Right (Facing Screen) + Fall Normally Fly Upwards Then Fall + + Right + Left + + Above layer 1 Tiles @@ -2199,11 +2425,11 @@ Green Red - + - + @@ -2227,15 +2453,15 @@ - + - - - Down - Up + + + Up + Down - + None Top @@ -2246,7 +2472,7 @@ Left/Right - + Slow Medium @@ -2257,51 +2483,54 @@ - + - + - + Stops - Goes Backwards + Repeat Movement Falls down - Stops - Goes Backwards - Falls down + Stops (Linear) + Repeat Movement (Linear) + Falls down (Linear) - + - + - + Already moving Disabled By Event Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down - - + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + None Top Bottom @@ -2310,11 +2539,16 @@ Right Left/Right - - - - - + + Normal + Unload if far from start of zone + Unload when loaded + + + + + + Slow Medium Fast @@ -2324,45 +2558,53 @@ - + - + Already moving Disabled By Event Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down - - + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + None Top Bottom - Top and Bottom + Top/Bottom Left Right - Left and Right + Left/Right - - - - - + + Normal + Unload if far from start of zone + Unload when loaded + + + + + + Slow Medium Fast @@ -2372,45 +2614,53 @@ - + - + Already moving Disabled By Event Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down - - + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + None Top Bottom - Top and Bottom + Top/Bottom Left Right - Left and Right + Left/Right - - - - - + + Normal + Unload if far from start of zone + Unload when loaded + + + + + + Slow Medium Fast @@ -2420,87 +2670,109 @@ - + - + Already moving Disabled By Event Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down - - + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + None Top Bottom - Top and Bottom + Top/Bottom Left Right - Left and Right + Left/Right + + + Normal + Unload if far from start of zone + Unload when loaded + + + + + + + Slow + Medium + Fast + Very Fast + Fastest (Glitchy) - - - - - - + - + Already moving Disabled By Event Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down - - + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + None Top Bottom - Top and Bottom + Top/Bottom Left Right - Left and Right + Left/Right - - - - - + + Normal + Unload if far from start of zone + Unload when loaded + + + + + + Slow Medium Fast @@ -2565,9 +2837,12 @@ Towards Player Away From Player - - - + + + One + Two + + Always Spawn If Gold Ring Isn't Active If Gold Ring Is Active @@ -2581,14 +2856,23 @@ - - - - + + One + Two + Three + + + + + Normal + Slower + Faster + All At Once + - + @@ -2596,9 +2880,22 @@ Blue Coin + Slowest + 4 + 3 + 9 Slow + 6 + 7 + 8 Medium Fast + Static + Static + Static + Same as 9 + Same as 9 + Same as 9 Clockwise @@ -2620,31 +2917,39 @@ Right + + Left + Right + Ignores Patrol Range + - - - - + + + + - - + + Camera Stays Above Camera Stays Below - - - + + Left + Right + + Normal Start Upside Down - Gimbal Rotation + Face The Screen + Nothing Coin @@ -2683,17 +2988,17 @@ Fire Flower Gold Flower Card - Gold Flower + Gold Flower Card Always Super Leaf - + - + - + Left @@ -2706,7 +3011,7 @@ Fast Super Fast - + Normal Stationary Pass Through Walls @@ -2714,7 +3019,7 @@ - + Left @@ -2727,7 +3032,7 @@ Fast Super Fast - + Normal Stationary Pass Through Walls @@ -2798,8 +3103,8 @@ - - + + 3 4 @@ -2819,7 +3124,7 @@ - + @@ -2845,12 +3150,13 @@ Right Left + - + Normal Faster @@ -2880,14 +3186,18 @@ Stops Jumps Right Falls Down - Changes Direction - Warps to First Node + Falls (All at once) 4 + Warp to First Node + + + Once Stepped On + Already Moving + Once Stepped On (All Players) - - + Normal @@ -2918,14 +3228,19 @@ Stops Jumps Right Falls Down - Changes Direction + Falls (All at once) 4 Warp to First Node - + + Once Stepped On + Already Moving + Once Stepped On (All Players) + + @@ -2950,6 +3265,7 @@ + One @@ -2968,7 +3284,16 @@ - + + 0 Frames + 20 Frames + 40 Frames + 60 Frames + 80 Frames + 100 Frames + 120 Frames + 140 Frames + @@ -2987,7 +3312,16 @@ - + + 0 Frames + 20 Frames + 40 Frames + 60 Frames + 80 Frames + 100 Frames + 120 Frames + 140 Frames + Activates Event @@ -3005,7 +3339,16 @@ - + + 0 Frames + 20 Frames + 40 Frames + 60 Frames + 80 Frames + 100 Frames + 120 Frames + 140 Frames + @@ -3024,7 +3367,16 @@ - + + 0 Frames + 20 Frames + 40 Frames + 60 Frames + 80 Frames + 100 Frames + 120 Frames + 140 Frames + Activates Event @@ -3084,7 +3436,7 @@ - + @@ -3134,8 +3486,11 @@ Already Falling - - + + + + + Left Right @@ -3148,9 +3503,9 @@ Fast Super Fast - + - + Normal Stationary Pass Through Walls @@ -3158,7 +3513,8 @@ - + + Left Right @@ -3171,9 +3527,9 @@ Fast Super Fast - + - + Normal Stationary Pass Through Walls @@ -3181,8 +3537,9 @@ - - + + + Left Right @@ -3198,7 +3555,7 @@ - + Normal Stationary Pass Through Walls @@ -3229,7 +3586,7 @@ Normal Only Spawn When Above Snakeblock - + Normal Stationary Pass Through Walls @@ -3261,7 +3618,7 @@ Normal Only Spawn When Above Snakeblock - + Normal Stationary Pass Through Walls @@ -3270,7 +3627,7 @@ - + @@ -3320,7 +3677,7 @@ - + Appear After Stopping Always Visible @@ -3330,8 +3687,7 @@ Right Side With Offset Left Side - - + @@ -3353,6 +3709,12 @@ Down + + Normal + Keeps Moving + Doesn't Go Back + + Slow @@ -3362,25 +3724,28 @@ Fastest (Glitchy) - - - Above layer 1 Tiles + + + Above Layer 1 Tiles Below Layer 1 Tiles + - - - Above layer 1 Tiles + + + Above Layer 1 Tiles Below Layer 1 Tiles + - + + Super Mushroom Super Mushroom @@ -3417,6 +3782,7 @@ From Pipe Thrown + @@ -3437,8 +3803,15 @@ - - + + + + + + Up + Down + + @@ -3448,30 +3821,34 @@ Right - + Normal Flame No Flame - Purple Flame (Broken) - Blue Flame (Broken) + Purple Flame + Purple Flame (Broken) - + - - + + + One Two - - + + + Start Height + Sway Down Distance + Start Height + Head Long Middle Piece @@ -3491,6 +3868,7 @@ Gimbal Rotation + Stone Rotation Pivot @@ -3525,53 +3903,74 @@ Mushroom/Coin - + - + Already moving Disabled By Event Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down - - - - - + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + + None + Top + Bottom + Top/Bottom + Left + Right + Left/Right + + + Normal + Unload if far from start of zone + Unload when loaded + + + + + + Slow Medium Fast Very Fast Fastest (Glitchy) - - + + Normal Tall and Skinny - - + + - + + + + Left Right @@ -3584,9 +3983,9 @@ Fast Super Fast - + - + Normal Stationary Pass Through Walls @@ -3594,7 +3993,8 @@ - + + Left Right @@ -3607,9 +4007,9 @@ Fast Super Fast - + - + Normal Stationary Pass Through Walls @@ -3628,12 +4028,12 @@ - + One Two - + Flies Away Flies side to side Flies in place @@ -3688,7 +4088,12 @@ - + + + Towards Player + Left + Right + @@ -3697,35 +4102,38 @@ 10 Mario Seconds (Blue) - + - + - + Already moving Disabled By Event Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down - - + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + None Top Bottom @@ -3734,10 +4142,16 @@ Right Left/Right - - - - + + Normal + Unload if far from start of zone + Unload when loaded + + + + + + Slow Medium Fast @@ -3747,42 +4161,51 @@ - + - - Already moving + + Already Moving Disabled By Event + Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + Normal + Unload if far from start of zone + Unload when loaded + - - + + Slow Medium Fast Very Fast Fastest (Glitchy) - - + + @@ -3795,31 +4218,51 @@ - + - - - - + + + + + Already Moving + Move when Touched + Move when Touched (All Players) + + + Forwards + Backwards + + Falls Off Go Back - Stop + Stops + - - - - - Fall Off + + + + + Already Moving + Move when Touched + Move when Touched (All Players) + + + Forwards + Backwards + + + Falls Off Go Back - Stop + Stops + @@ -3827,16 +4270,20 @@ - + - + + Already Moving + Move when Touched + Move when Touched (All Players) + - + No Switching Fall When Hit Start on Bottom @@ -3860,7 +4307,7 @@ - + @@ -3868,11 +4315,15 @@ Not Visible - - + + + Random + Pattern + + One Two @@ -3895,6 +4346,7 @@ + One @@ -3912,10 +4364,10 @@ - + - - + + One Platform Two Platforms @@ -3923,7 +4375,7 @@ - + @@ -3938,81 +4390,133 @@ Blue Flame (Broken) - - - - Does Nothing + + + + Already Moving + Disabled By Event Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down - - - + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + + None + Top + Bottom + Top/Bottom + Left + Right + Left/Right + + + Normal + Unload if far from start of zone + Unload when loaded + + + + + + Slow Medium Fast Very Fast Fastest (Glitchy) - - + + - - - - Does Nothing + + + + Already moving + Disabled By Event Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down - - - + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + + None + Top + Bottom + Top/Bottom + Left + Right + Left/Right + + + Normal + Unload if far from start of zone + Unload when loaded + + + + + + Slow Medium Fast Very Fast Fastest (Glitchy) - - + + - + - - + + + Normal / Slow + Lower / Medium + Lowest / Fast + No Delay / Slower + + + Small + Medium + Long + @@ -4022,52 +4526,73 @@ Left Right - - + + 10 100 - - - - Does Nothing + + + + Already moving + Disabled By Event Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down - - - + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + + None + Top + Bottom + Top/Bottom + Left + Right + Left/Right + + + Normal + Unload if far from start of zone + Unload when loaded + + + + + + Slow Medium Fast Very Fast Fastest (Glitchy) - - 2 Tiles - 4 Tiles + + 2x11 Tiles + 4x9 Tiles - + @@ -4080,42 +4605,63 @@ - - - - Does Nothing + + + + Already moving + Disabled By Event Enabled By Event - + Right Left Up Down - Right - Left - Up - Down - Right - Left - Up - Down - Right - Left - Up - Down - - - + Right (Above Layer 1) + Left (Above Layer 1) + Up (Above Layer 1) + Down (Above Layer 1) + Right (Delayed) + Left (Delayed) + Up (Delayed) + Down (Delayed) + Right (Delayed and Above Layer 1) + Left (Delayed and Above Layer 1) + Up (Delayed and Above Layer 1) + Down (Delayed and Above Layer 1) + + + + + + None + Top + Bottom + Top/Bottom + Left + Right + Left/Right + + + Normal + Unload if far from start of zone + Unload when loaded + + + + + + Slow Medium Fast Very Fast Fastest(Glitchy) - - 3 Blocks Tall - 2 Blocks Tall - 4 Blocks Tall + + 2 Tiles + 3 Tiles + 4 Tiles @@ -4123,7 +4669,7 @@ - + Moves when Touched (Default) Already Moving Moves when Touched @@ -4132,14 +4678,17 @@ Forwards Backwards - + Falls Changes Direction Stops Disappears - + + Always + When On Lift Only + @@ -4166,8 +4715,12 @@ - + + + Spawn + Despawn + Slowest Slower @@ -4182,6 +4735,8 @@ - + + + diff --git a/coinkiller_data/sprites/big_icy_spiked_ball.png b/coinkiller_data/sprites/big_icy_spiked_ball.png new file mode 100644 index 0000000000000000000000000000000000000000..9c919ff54e8813faa002cf7d2d0ebcfa6466872b GIT binary patch literal 7752 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 M07*qoM6N<$f`}5!3jhEB diff --git a/coinkiller_data/sprites/dry_bowser_flame.png b/coinkiller_data/sprites/bowser_flame_blue.png similarity index 100% rename from coinkiller_data/sprites/dry_bowser_flame.png rename to coinkiller_data/sprites/bowser_flame_blue.png diff --git a/coinkiller_data/sprites/bowser_flame_purple.png b/coinkiller_data/sprites/bowser_flame_purple.png new file mode 100644 index 0000000000000000000000000000000000000000..f16dd8706c3b18cd64066e45158d2152687678ee GIT binary patch literal 2093 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 U22bd=6#xJL07*qoM6N<$f)E1qSpWb4 literal 0 HcmV?d00001 diff --git a/coinkiller_data/sprites/bowser_lift/s.png b/coinkiller_data/sprites/bowser_lift/s.png new file mode 100644 index 0000000000000000000000000000000000000000..0bf2dcb972e94377c79bbbdac90da41dd34257ec GIT binary patch literal 2545 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 Hu0mjfy7H&- literal 0 HcmV?d00001 diff --git a/coinkiller_data/sprites/fire_snake_hidden.png b/coinkiller_data/sprites/fire_snake_hidden.png new file mode 100644 index 0000000000000000000000000000000000000000..b11ba70993c728cab2f8c84c621279c00d023355 GIT binary patch literal 613 zcmV-r0-F7aP)wy@5)5pv&%dzO?F$>DN=9{2!dW2VQhH9X9he)hyK=lTq!M z>tq@q{pS3>mGke6r#&+=N;Svg8r%QM+D)A|hfQuw+s-e#u?Oyb<@?s37GflJ5y@ZZ zjxG6Sqvwm*BJ0Z1VL$AFyZ;&Qz4BDn2W?Y1rLub3o#TI-&0pzmwS~Awe#Z43xOd6z zcFEV-0TU1oGW6Jwp-d>_W0T1dl`w|D+OS(Y@bk9W`hC~RFa1$%^n-^+O@%GlXiYHf zW*8xEQ~%wyWW!?TvKAycS65HFbKr!LY8?mr6`aEgs+i~bUw$bcF&&YGh(4udlRK2GWH;b&X@VQ$N zo5dK}%7wvJIbpd4Ej%u~X1m7qBECkbQUAxx4h$prB)!b-QZy^Yr-hAnzfo3*ON5^_ z5|#(>d%p@=pUJBeMS>N&k2G7ah2sy6et7mBMTo(It2^F000000NkvXXu0mjfbE_nD literal 0 HcmV?d00001 diff --git a/coinkiller_data/sprites/lava_top.png b/coinkiller_data/sprites/lava_top.png index 72fc437a9d9081f1b370c22843860bf3bfd3ca13..8faa7b335795c29caf4843ac454028cbfc8f5ba2 100644 GIT binary patch literal 10498 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 literal 3170 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 IM6N<$f?4$(5&!@I diff --git a/coinkiller_data/sprites/totem_lift/l.png b/coinkiller_data/sprites/totem_lift/l.png new file mode 100644 index 0000000000000000000000000000000000000000..e33ad98b66f603c491a32dab13fd2e2627ee8706 GIT binary patch literal 894 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 literal 0 HcmV?d00001 diff --git a/leveleditor/leveleditorwindow.cpp b/leveleditor/leveleditorwindow.cpp index 29e77e77..849d1270 100644 --- a/leveleditor/leveleditorwindow.cpp +++ b/leveleditor/leveleditorwindow.cpp @@ -75,6 +75,7 @@ LevelEditorWindow::LevelEditorWindow(LevelManager* lvlMgr, int initialArea) : ui->actionGrid->setIcon(QIcon(basePath + "grid.png")); ui->actionCheckerboard->setIcon(QIcon(basePath + "checkerboard.png")); ui->actionRenderLiquids->setIcon(QIcon(basePath + "render_liquids.png")); + ui->actionRenderControllers->setIcon(QIcon(basePath + "render_controllers.png")); ui->actionRenderCameraLimits->setIcon(QIcon(basePath + "render_camera_limits.png")); ui->actionAddArea->setIcon(QIcon(basePath + "add.png")); ui->actionDeleteCurrentArea->setIcon(QIcon(basePath + "remove.png")); @@ -166,6 +167,7 @@ LevelEditorWindow::LevelEditorWindow(LevelManager* lvlMgr, int initialArea) : ui->actionGrid->setChecked(settings->get("grid", false).toBool()); ui->actionCheckerboard->setChecked(settings->get("checkerboard", false).toBool()); ui->actionRenderLiquids->setChecked(settings->get("renderLiquids", true).toBool()); + ui->actionRenderControllers->setChecked(settings->get("renderControllers", true).toBool()); ui->actionRenderCameraLimits->setChecked(settings->get("renderCameraLimits", true).toBool()); loadSettings(); @@ -485,6 +487,12 @@ void LevelEditorWindow::on_actionRenderLiquids_toggled(bool toggle) settings->set("renderLiquids", toggle); } +void LevelEditorWindow::on_actionRenderControllers_toggled(bool toggle) +{ + levelView->toggleRenderControllers(toggle); + settings->set("renderControllers", toggle); +} + void LevelEditorWindow::on_actionRenderCameraLimits_toggled(bool toggle) { levelView->toggleRenderCameraLimits(toggle); @@ -743,6 +751,7 @@ void LevelEditorWindow::loadArea(int id, bool closeLevel, bool init) levelView->toggleGrid(ui->actionGrid->isChecked()); levelView->toggleCheckerboard(ui->actionCheckerboard->isChecked()); levelView->toggleRenderLiquids(ui->actionRenderLiquids->isChecked()); + levelView->toggleRenderControllers(ui->actionRenderControllers->isChecked()); levelView->toggleRenderCameraLimits(ui->actionRenderCameraLimits->isChecked()); #ifdef USE_KDE_BLUR diff --git a/leveleditor/leveleditorwindow.h b/leveleditor/leveleditorwindow.h index 6c0da87e..24d81ace 100644 --- a/leveleditor/leveleditorwindow.h +++ b/leveleditor/leveleditorwindow.h @@ -98,6 +98,8 @@ private slots: void on_actionRenderLiquids_toggled(bool arg1); + void on_actionRenderControllers_toggled(bool arg1); + void on_actionRenderCameraLimits_toggled(bool arg1); void on_actionPaste_triggered(); diff --git a/leveleditor/leveleditorwindow.ui b/leveleditor/leveleditorwindow.ui index 5728d5f4..8febba71 100644 --- a/leveleditor/leveleditorwindow.ui +++ b/leveleditor/leveleditorwindow.ui @@ -6,8 +6,8 @@ 0 0 - 1280 - 700 + 1237 + 529 @@ -46,8 +46,8 @@ 0 0 - 1278 - 624 + 1235 + 448 @@ -60,8 +60,8 @@ 0 0 - 1280 - 21 + 1237 + 23 @@ -161,6 +161,7 @@ + @@ -561,6 +562,20 @@ Ctrl+Shift+A + + + true + + + Render Controller Indicators + + + Render Controller Indicators + + + QAction::TextHeuristicRole + + diff --git a/leveleditor/levelview.cpp b/leveleditor/levelview.cpp index 23f1bc07..dbe50cf5 100644 --- a/leveleditor/levelview.cpp +++ b/leveleditor/levelview.cpp @@ -15,13 +15,15 @@ with CoinKiller. If not, see http://www.gnu.org/licenses/. */ +#include "is.h" #include "leveleditorwindow.h" #include "levelview.h" #include "unitsconvert.h" #include "objectrenderer.h" -#include "is.h" +#include "settingsmanager.h" #include +#include #include #include #include @@ -29,8 +31,8 @@ #include #include #include -#include #include +#include LevelView::LevelView(QWidget *parent, Level *level, QUndoStack *undoStack) : @@ -44,8 +46,9 @@ LevelView::LevelView(QWidget *parent, Level *level, QUndoStack *undoStack) : zoom = 1; grid = false; checkerboard = false; - renderLiquids = false; - renderCameraLimits = false; + renderLiquids = true; + renderControllers = true; + renderCameraLimits = true; render2DTile = true; render3DOverlay = true; @@ -135,6 +138,32 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti painter.setOpacity(1); } + // Render Translucent Liquid Indicators (if set to appear under tiles) + if (renderLiquids && editManager->spriteInteractionEnabled() && !SettingsManager::getInstance()->getLERenderTransparentLiquidAboveTiles()) + { + for (int i = 0; i < level->zones.size(); i++) + { + const Zone* zone = level->zones.at(i); + + QRect zonerect(zone->getx(), zone->gety(), zone->getwidth(), zone->getheight()); + + if (!drawrect.intersects(zonerect)) + continue; + + foreach (Sprite* s, level->sprites) + { + if (s->getid() != 12 && s->getid() != 13 && s->getid() != 15) + continue; + + if (zonerect.contains(s->getx(), s->gety(), false)) + { + LiquidRenderer liquidRend(s, zone); + liquidRend.renderTranslucent(&painter, &drawrect); + } + } + } + } + // Render Tiles for (int l = 1; l >= 0; l--) { @@ -172,6 +201,7 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti // Render Locations if (editManager->locationInteractionEnabled()) { + painter.save(); for (int i = 0; i < level->locations.size(); i++) { const Location* loc = level->locations.at(i); @@ -191,8 +221,10 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti painter.setPen(QColor(255,255,255)); painter.drawText(locrect.adjusted(5,5,0,0), locText); } + painter.restore(); } + // Render anything that falls under "sprites" if (editManager->spriteInteractionEnabled()) { // Render Liquids @@ -215,6 +247,8 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti if (zonerect.contains(s->getx(), s->gety(), false)) { LiquidRenderer liquidRend(s, zone); + if (SettingsManager::getInstance()->getLERenderTransparentLiquidAboveTiles()) + liquidRend.renderTranslucent(&painter, &drawrect); liquidRend.render(&painter, &drawrect); } } @@ -319,6 +353,71 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti } } + // Render Movement Controller - Back & Forth Indicators + static const QSet supportsMovBackForth{28, 60, 101, 204, 293}; + for (int i = 0; renderControllers && i < level->zones.size(); i++) + { + const Zone* zone = level->zones.at(i); + QRect zonerect(zone->getx() - 80, zone->gety() - 80, zone->getwidth() + 160, zone->getheight() + 160); + + if (!drawrect.intersects(zonerect)) + continue; + + foreach (Sprite* s, level->sprites) + { + if (!zonerect.contains(s->getx(), s->gety(), false)) + continue; + + if (!supportsMovBackForth.contains(s->getid())) + continue; + + int distance; + int direction = -1; + + // Find the correct associated Back & Forth movement controller & note its data + foreach (Sprite* m, level->sprites) + { + if (!zonerect.contains(m->getx(), m->gety(), false)) + continue; + + if (m->getid() != 166 || m->getNybbleData(20, 21) != s->getNybbleData(20, 21)) + continue; + + distance = m->getNybble(14) * 20; + direction = m->getNybble(7) % 4; + break; + } + + if (direction == -1 || distance == 0) + continue; + + // Render a movement indicator for the sprite + QColor color = QColor(244, 250, 255); + int x = s->getx() + s->getOffsetX(); + int y = s->gety() + s->getOffsetY(); + + MovIndicatorRenderer *indicator; + switch (direction) + { + case 0: // Right + indicator = new MovIndicatorRenderer(x + s->getwidth(), y + s->getheight()/2, x + s->getwidth() + distance, y + s->getheight()/2, 2, 6, false, false, color); + break; + case 1: // Left + indicator = new MovIndicatorRenderer(x, y + s->getheight()/2, x - distance, y + s->getheight()/2, 2, 6, false, false, color); + break; + case 2: // Up + indicator = new MovIndicatorRenderer(x + s->getwidth()/2, y, x + s->getwidth()/2, y - distance, 2, 6, false, true, color); + break; + default: // Down + indicator = new MovIndicatorRenderer(x + s->getwidth()/2, y + s->getheight(), x + s->getwidth()/2, y + s->getheight() + distance, 2, 6, false, true, color); + break; + } + + indicator->render(&painter); + delete indicator; + } + } + // Render Sprites for (int i = 0; i < level->sprites.size(); i++) { @@ -575,7 +674,7 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti painter.drawText(zonerect.adjusted(adjustX,adjustY,100,20), zoneText); } - // Render Edition Mode Stuff + // Render Stuff if (selections) editManager->render(&painter); diff --git a/leveleditor/levelview.h b/leveleditor/levelview.h index 983e822d..19cf3549 100644 --- a/leveleditor/levelview.h +++ b/leveleditor/levelview.h @@ -39,6 +39,7 @@ class LevelView : public QWidget void toggleGrid(bool toggle) { grid = toggle; update(); } void toggleCheckerboard(bool toggle) { checkerboard = toggle; update(); } void toggleRenderLiquids(bool toggle) { renderLiquids = toggle; update(); } + void toggleRenderControllers(bool toggle) { renderControllers = toggle; update(); } void toggleRenderCameraLimits(bool toggle) { renderCameraLimits = toggle; update(); } void toggle3DOverlay(bool toggle) { render3DOverlay = toggle; update(); } void toggle2DTile(bool toggle) { render2DTile = toggle; update(); } @@ -96,6 +97,7 @@ public slots: bool grid; bool checkerboard; bool renderLiquids; + bool renderControllers; bool renderCameraLimits; bool render2DTile; bool render3DOverlay; diff --git a/leveleditor/settingsdialog.cpp b/leveleditor/settingsdialog.cpp index 90d41399..57525121 100644 --- a/leveleditor/settingsdialog.cpp +++ b/leveleditor/settingsdialog.cpp @@ -12,6 +12,7 @@ SettingsDialog::SettingsDialog(QWidget *parent) : connect(ui->backgroundColorPickerButton, &QPushButton::clicked, this, &SettingsDialog::changeBackgroundColor); connect(ui->undoLimitSpinBox, &QSpinBox::valueChanged, this, &SettingsDialog::changeUndoLimit); + connect(ui->renderTransparentLiquidAboveTilesComboBox, &QComboBox::currentIndexChanged, this, &SettingsDialog::changeRenderTransparentLiquidAboveTiles); connect(ui->selectOnPlacedCheckBox, &QCheckBox::clicked, this, &SettingsDialog::changeSelectOnPlaced); connect(ui->showStatusBarCheckBox, &QCheckBox::clicked, this, &SettingsDialog::changeShowStatusbar); connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &SettingsDialog::handleButtonClicked); @@ -28,6 +29,9 @@ void SettingsDialog::loadSettings() { undoLimit = SettingsManager::getInstance()->getLEUndoLimit(); ui->undoLimitSpinBox->setValue(static_cast(undoLimit)); + renderTransparentLiquidAboveTiles = SettingsManager::getInstance()->getLERenderTransparentLiquidAboveTiles(); + ui->renderTransparentLiquidAboveTilesComboBox->setCurrentIndex(renderTransparentLiquidAboveTiles); + selectOnPlaced = SettingsManager::getInstance()->getLESelectOnPlace(); ui->selectOnPlacedCheckBox->setChecked(selectOnPlaced); @@ -42,6 +46,9 @@ void SettingsDialog::restoreDefaults() { undoLimit = SettingsManager::LE_UNDO_LIMIT_DEFAULT; ui->undoLimitSpinBox->setValue(static_cast(undoLimit)); + renderTransparentLiquidAboveTiles = SettingsManager::LE_RENDER_TRANSPARENT_LIQUID_ABOVE_TILES_DEFAULT; + ui->renderTransparentLiquidAboveTilesComboBox->setCurrentIndex(renderTransparentLiquidAboveTiles); + selectOnPlaced = SettingsManager::LE_SELECT_ON_PLACE_DEFAULT; ui->selectOnPlacedCheckBox->setChecked(selectOnPlaced); @@ -52,6 +59,7 @@ void SettingsDialog::restoreDefaults() { void SettingsDialog::applyChanges() { SettingsManager::getInstance()->setLEWindowColor(backgroundColor); SettingsManager::getInstance()->setLEUndoLimit(undoLimit); + SettingsManager::getInstance()->setLERenderTransparentLiquidAboveTiles(renderTransparentLiquidAboveTiles); SettingsManager::getInstance()->setLESelectOnPlace(selectOnPlaced); SettingsManager::getInstance()->setLEShowStatusbar(showStatusbar); @@ -92,6 +100,10 @@ void SettingsDialog::changeUndoLimit() { undoLimit = ui->undoLimitSpinBox->value(); } +void SettingsDialog::changeRenderTransparentLiquidAboveTiles() { + renderTransparentLiquidAboveTiles = ui->renderTransparentLiquidAboveTilesComboBox->currentIndex(); +} + void SettingsDialog::changeSelectOnPlaced() { selectOnPlaced = ui->selectOnPlacedCheckBox->isChecked(); } diff --git a/leveleditor/settingsdialog.h b/leveleditor/settingsdialog.h index 6d87ce1e..d67d9bb4 100644 --- a/leveleditor/settingsdialog.h +++ b/leveleditor/settingsdialog.h @@ -21,6 +21,7 @@ class SettingsDialog : public QDialog { private slots: void changeBackgroundColor(); void changeUndoLimit(); + void changeRenderTransparentLiquidAboveTiles(); void changeSelectOnPlaced(); void changeShowStatusbar(); void handleButtonClicked(QAbstractButton *button); @@ -36,6 +37,7 @@ private slots: QColor backgroundColor; quint32 undoLimit; + bool renderTransparentLiquidAboveTiles; bool selectOnPlaced; bool showStatusbar; }; diff --git a/leveleditor/settingsdialog.ui b/leveleditor/settingsdialog.ui index c2a89c2f..aacb77f2 100644 --- a/leveleditor/settingsdialog.ui +++ b/leveleditor/settingsdialog.ui @@ -98,10 +98,57 @@ background-color: rgb(119, 136, 153); + + + + + + + + + Liquid Movement Indicator Position: + + + + + + + Chooses whether to render the transparent indicator for liquids above or below tiles. + + + false + + + false + + + 10 + + + + Below Tiles + + + + + Above Tiles + + + + + + + + + + Qt::Horizontal + + + - Show Statusbar + Show status bar diff --git a/leveleditor/zoneeditorwidget.cpp b/leveleditor/zoneeditorwidget.cpp index 4a730b2a..376b2e21 100644 --- a/leveleditor/zoneeditorwidget.cpp +++ b/leveleditor/zoneeditorwidget.cpp @@ -266,7 +266,11 @@ void ZoneEditorWidget::updateInfo() multiplayerTracking->setCurrentText(multiplayerTrackings.value(editZone->getMultiplayerTracking())); progPathId->setValue(editZone->getProgPathId()); unk1->setValue(editZone->getUnk1()); + boundingId->setDisabled(true); + boundingId->setStyleSheet("color: gray"); boundingId->setValue(editZone->getBoundingId()); + backgroundId->setDisabled(true); + backgroundId->setStyleSheet("color: gray"); backgroundId->setValue(editZone->getBackgroundId()); handleChanges = true; diff --git a/objectrenderer.cpp b/objectrenderer.cpp index 9bf962e0..6b0846dc 100644 --- a/objectrenderer.cpp +++ b/objectrenderer.cpp @@ -200,7 +200,7 @@ SpriteRenderer::SpriteRenderer(const Sprite *spr, Tileset *tilesets[]) ret = new NormalImageRenderer(spr, "fireballpipe_junction.png"); break; case 82: // Fire Snake - ret = new NormalImageRenderer(spr, "fire_snake.png"); + ret = new FireSnakeRenderer(spr); break; case 83: // Fish Bone ret = new NormalImageRenderer(spr, "fish_bone.png"); @@ -362,10 +362,10 @@ SpriteRenderer::SpriteRenderer(const Sprite *spr, Tileset *tilesets[]) ret = new NormalImageRenderer(spr, "conveyor_belt_switch.png"); break; case 144: // Horizontal Lift - ret = new LiftRenderer(spr); + ret = new LiftRenderer(spr, "lift_platform"); break; case 145: // Vertical Lift - ret = new LiftRenderer(spr); + ret = new LiftRenderer(spr, "lift_platform"); break; case 146: // Track Controlled Lift ret = new TrackLiftRenderer(spr); @@ -643,6 +643,9 @@ SpriteRenderer::SpriteRenderer(const Sprite *spr, Tileset *tilesets[]) case 253: // Larry Battle Platform ret = new LarryPlatformRenderer(spr, tilesets[0]); break; + case 254: // Vertical Lift - Totem + ret = new LiftRenderer(spr, "totem_lift"); + break; case 255: // Bowser Head Statue ret = new NormalImageRenderer(spr, "bowser_head_statue.png"); break; @@ -664,6 +667,9 @@ SpriteRenderer::SpriteRenderer(const Sprite *spr, Tileset *tilesets[]) case 270: // Icy Spiked Ball ret = new NormalImageRenderer(spr, "icy_spiked_ball.png"); break; + case 271: // Big Icy Spiked Ball + ret = new NormalImageRenderer(spr, "big_icy_spiked_ball.png"); + break; case 272: // Peach Cage ret = new NormalImageRenderer(spr, "peach_cage.png"); break; @@ -757,6 +763,9 @@ SpriteRenderer::SpriteRenderer(const Sprite *spr, Tileset *tilesets[]) case 308: // Event Activated Rectangle Lift - Sand ret = new EventRecLiftRenderer(spr, "rect_lift_sand"); break; + case 310: // Big Bowser Battle Lift + ret = new BowserLiftRenderer(spr); + break; case 311: // Coin Meteor ret = new CoinMeteorRenderer(spr); break; @@ -860,61 +869,67 @@ void CircleRenderer::render(QPainter *painter, QRect *) painter->setPen(Qt::NoPen); } -MovIndicatorRenderer::MovIndicatorRenderer(int x, int y, int distX, int distY, bool vertical, QColor color) +MovIndicatorRenderer::MovIndicatorRenderer(int startX, int startY, int endX, int endY, bool vertical, QColor color) +: MovIndicatorRenderer::MovIndicatorRenderer(startX, startY, endX, endY, 4, 10, true, vertical, color) +{} + +MovIndicatorRenderer::MovIndicatorRenderer(int startX, int startY, int endX, int endY, int thickness, int radius, bool applyOffset, bool vertical, QColor color) { - this->x = x; - this->y = y; - this->distX = distX; - this->distY = distY; + this->startX = startX; + this->startY = startY; + this->endX = endX; + this->endY = endY; + this->thickness = thickness; + this->radius = radius; + this->applyOffset = applyOffset; this->vertical = vertical; this->color = color; } void MovIndicatorRenderer::render(QPainter *painter) { - QPen outline(QColor(0,0,0,150), 8, Qt::SolidLine); - QPen fill(color, 4, Qt::SolidLine); + QPen outline(QColor(0,0,0,150), thickness * 2, Qt::SolidLine); + QPen fill(color, thickness, Qt::SolidLine); painter->setPen(outline); - if (vertical && distY == y) + if (vertical && endY == startY) return; - else if (!vertical && distX == x) + else if (!vertical && endX == startX) return; for (int i = 0; i <= 1; i++) { - - if ( i == 1) + if (i == 1) painter->setPen(fill); else painter->setPen(outline); if (vertical) { - if (distY < y) // Go Up + if (endY < startY) // Go Up { - painter->drawLine(x, y+20, x, distY+18); - painter->drawEllipse(x-5, distY+5, 10, 10); + painter->drawLine(startX, startY+(20*applyOffset)+(radius/2*!applyOffset), startX, endY+(20*applyOffset)+(radius*2*!applyOffset)-2); + painter->drawEllipse(startX-(radius/2), endY+(radius/2), radius, radius); } else // Go Down { - painter->drawLine(x, y-20, x, distY-18); - painter->drawEllipse(x-5, distY-15, 10, 10); + painter->drawLine(startX, startY-(20*applyOffset), startX, endY-(20*applyOffset)-(radius*2*!applyOffset)+2); + painter->drawEllipse(startX-(radius/2), endY-(1.5*radius), radius, radius); } } else { - if (distX < x) // Go Left + if (endX < startX) // Go Left { - painter->drawLine(x+20, y, distX+18, y); - painter->drawEllipse(distX+5, y-5, 10, 10); + painter->drawLine(startX+(20*applyOffset), startY, endX+(20*applyOffset)+(radius*2*!applyOffset)-2, startY); + painter->drawEllipse(endX+(radius/2), startY-(radius/2), radius, radius); } else // Go Right { - painter->drawLine(x-20, y, distX-18, y); - painter->drawEllipse(distX-15, y-5, 10, 10); + painter->drawLine(startX-(20*applyOffset), startY, endX-(20*applyOffset)-(radius*2*!applyOffset)+2, startY); + painter->drawEllipse(endX-(1.5*radius), startY-(radius/2), radius, radius); } } } @@ -1020,18 +1035,40 @@ void BurnerRenderer::render(QPainter *painter, QRect *) WhompRenderer::WhompRenderer(const Sprite *spr) { this->spr = spr; +} + +void WhompRenderer::render(QPainter *painter, QRect *) +{ + this->spr = spr; + int x = spr->getx() + spr->getOffsetX(); + int y = spr->gety() + spr->getOffsetY(); + + QString img_name = "whomp"; if (spr->getNybble(11) == 1) - filename = "whomp_big.png"; - else - filename = "whomp.png"; + img_name += "_big"; - img = new NormalImageRenderer(spr, filename); -} + if (spr->getNybble(10) == 0) + { + img_name += "_walk"; -void WhompRenderer::render(QPainter *painter, QRect *drawrect) -{ - img->render(painter, drawrect); + // Show a distance indicator for patrol distance + int dist = spr->getNybble(8) * 20; + + if (spr->getNybble(8) > 0) + { + int offsetXL = (spr->getNybble(11) == 1) ? 0: -10; + int offsetXR = spr->getwidth() + 10; + + MovIndicatorRenderer leftIndicator(x + spr->getwidth()/2, y + spr->getheight()/2, x + offsetXL - dist, y + spr->getheight()/2, false, QColor(244, 250, 255)); + leftIndicator.render(painter); + + MovIndicatorRenderer rightIndicator(x + spr->getwidth()/2, y + spr->getheight()/2, x + offsetXR + dist, y + spr->getheight()/2, false, QColor(244, 250, 255)); + rightIndicator.render(painter); + } + } + + painter->drawPixmap(QRect(x, y, spr->getwidth(), spr->getheight()), ImageCache::getInstance()->get(SpriteImg, img_name + ".png")); } // Sprite 18: Tile God @@ -1587,6 +1624,20 @@ void FireBarRenderer::render(QPainter *painter, QRect *drawrect) painter->drawPixmap(spr->getx(), spr->gety(), 20, 20, ImageCache::getInstance()->get(SpriteImg, "firebar_fire.png")); } +// Sprite 82: Fire Snake +FireSnakeRenderer::FireSnakeRenderer(const Sprite *spr) +{ + if (spr->getNybble(11) == 1) + img = new NormalImageRenderer(spr, "fire_snake_hidden.png"); + else + img = new NormalImageRenderer(spr, "fire_snake.png"); +} + +void FireSnakeRenderer::render(QPainter *painter, QRect *drawrect) +{ + img->render(painter, drawrect); +} + // Sprite 84/85/86/87/88: Flags FlagRenderer::FlagRenderer(const Sprite *spr) { @@ -2098,13 +2149,20 @@ void MushroomPlatformRenderer::render(QPainter *painter, QRect *) // Sprite 127: Bowser Flame BowserFlameRenderer::BowserFlameRenderer(const Sprite *spr) { - if (spr->getNybble(11) == 1) img = new NormalImageRenderer(spr, "dry_bowser_flame.png"); - else img = new NormalImageRenderer(spr, "bowser_flame.png"); + this->spr = spr; } void BowserFlameRenderer::render(QPainter *painter, QRect *drawrect) { - img->render(painter, drawrect); + QString filename = "bowser_flame.png"; + + if (spr->getNybble(11) == 1) filename = "bowser_flame_blue.png"; + if (spr->getNybble(8) == 1) filename = "bowser_flame_purple.png"; + + QPixmap img = ImageCache::getInstance()->get(SpriteImg, filename); + if (spr->getNybble(10) == 1) img = img.transformed(QTransform().scale(-1, 1)); + + painter->drawPixmap(QRect(spr->getx() + spr->getOffsetX(), spr->gety() + spr->getOffsetY(), spr->getwidth(), spr->getheight()), img); } @@ -2157,10 +2215,11 @@ void GoombaTowerRenderer::render(QPainter *painter, QRect *drawrect) } -// Sprite 144/145: Horizontal/Vertical Moving Lift -LiftRenderer::LiftRenderer(const Sprite *spr) +// Sprite 144/145/254: Horizontal/Vertical/Totem Lift +LiftRenderer::LiftRenderer(const Sprite *spr, QString dirname) { this->spr = spr; + this->dirname = dirname; } void LiftRenderer::render(QPainter *painter, QRect *) @@ -2169,7 +2228,7 @@ void LiftRenderer::render(QPainter *painter, QRect *) if (spr->getNybble(7) == 1 && distance > 0) { - if (spr->getid() == 145) + if (spr->getid() == 145 || spr->getid() == 254) { MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+13, spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+distance, true, QColor(244,250,255)); track.render(painter); @@ -2182,7 +2241,7 @@ void LiftRenderer::render(QPainter *painter, QRect *) } else if (distance > 0) { - if (spr->getid() == 145) + if (spr->getid() == 145 || spr->getid() == 254) { MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()-27, spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()-20-distance, true, QColor(244,250,255)); track.render(painter); @@ -2195,13 +2254,13 @@ void LiftRenderer::render(QPainter *painter, QRect *) } - painter->drawPixmap(QRect(spr->getx()+spr->getOffsetX(), spr->gety(), 20, 22), ImageCache::getInstance()->get(SpriteImg, "lift_platform/l.png")); - if(spr->getNybble(11) == 0) - painter->drawPixmap(QRect(spr->getx()-spr->getOffsetX()+(spr->getNybble(11))*20+20, spr->gety(), 22, 22), ImageCache::getInstance()->get(SpriteImg, "lift_platform/r.png")); + painter->drawPixmap(QRect(spr->getx()+spr->getOffsetX(), spr->gety(), 20, 22), ImageCache::getInstance()->get(SpriteImg, dirname + "/l.png")); + if (spr->getNybble(11) == 0) + painter->drawPixmap(QRect(spr->getx()-spr->getOffsetX()+(spr->getNybble(11))*20+20, spr->gety(), 22, 22), ImageCache::getInstance()->get(SpriteImg, dirname + "/r.png")); else - painter->drawPixmap(QRect(spr->getx()-spr->getOffsetX()+(spr->getNybble(11)-1)*20+20, spr->gety(), 22, 22), ImageCache::getInstance()->get(SpriteImg, "lift_platform/r.png")); + painter->drawPixmap(QRect(spr->getx()-spr->getOffsetX()+(spr->getNybble(11)-1)*20+20, spr->gety(), 22, 22), ImageCache::getInstance()->get(SpriteImg, dirname + "/r.png")); for (int i = 20; i < spr->getwidth()-20; i += 20) - painter->drawPixmap(QRect(spr->getx()+spr->getOffsetX()+i, spr->gety(), 20, 22), ImageCache::getInstance()->get(SpriteImg, "lift_platform/m.png")); + painter->drawPixmap(QRect(spr->getx()+spr->getOffsetX()+i, spr->gety(), 20, 22), ImageCache::getInstance()->get(SpriteImg, dirname + "/m.png")); } @@ -2891,50 +2950,77 @@ void PathRecLiftRenderer::render(QPainter *painter, QRect *) { QString path = "tower_rectangle_lift/"; - int blockWidth = spr->getNybble(17)*20; - int blockHeight = spr->getNybble(19)*20; + bool movesDown = (spr->getNybble(9) == 1); + int posOffset = spr->getNybble(7); - if (blockHeight == 0 || blockWidth == 0) + int vOffX = 0; + int vOffY = 0; + + switch (spr->getNybble(11)) { - if (tileset == nullptr) - { - painter->drawPixmap(spr->getx(), spr->gety(), spr->getwidth(), spr->getheight(), ImageCache::getInstance()->get(TileOverride, "error.png")); - } - else - { - QPixmap block(20, 20); - block.fill(QColor(0,0,0,0)); - QPainter tempPainter(&block); + case 1: + vOffY = -20; + break; + case 3: + vOffY = -20; + break; + case 4: + vOffX = -10; + break; + case 5: + vOffX = 10; + break; + default: + break; + } - TileGrid tileGrid; - tileGrid[0xFFFFFFFF] = 1; + // Render Movement Indicators + int distance = spr->getNybble(14)*20; + int distOff = 0; - tileset->drawTile(tempPainter, tileGrid, 22, 0, 0, 1, 0); - painter->drawPixmap(spr->getx()+spr->getOffsetX(), spr->gety()+spr->getOffsetY(), 20+blockWidth, 20+blockHeight, block); - } + if ((0 < spr->getNybble(11) && spr->getNybble(11) < 3) && movesDown) + distOff = 20; + else if ((spr->getNybble(11) == 3) && movesDown) + distOff = 40; + + if (movesDown && distance > 0) + { + MovIndicatorRenderer track(spr->getx()+vOffX+posOffset+spr->getwidth()/2, spr->gety()+vOffY+posOffset+spr->getheight(), spr->getx()+vOffX+posOffset+spr->getwidth()/2, spr->gety()+vOffY+posOffset+spr->getheight()+distance+distOff, true, QColor(244,250,255)); + track.render(painter); } - else + else if (distance > 0) { - painter->drawPixmap(QRect(spr->getx(), spr->gety(), 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "tl.png")); - painter->drawPixmap(QRect(spr->getx(), spr->gety()+blockHeight, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "bl.png")); - painter->drawPixmap(QRect(spr->getx()+blockWidth, spr->gety(), 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "tr.png")); - painter->drawPixmap(QRect(spr->getx()+blockWidth, spr->gety()+blockHeight, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "br.png")); + MovIndicatorRenderer track(spr->getx()+posOffset+vOffX+spr->getwidth()/2, spr->gety()+posOffset+vOffY, spr->getx()+posOffset+vOffX+spr->getwidth()/2, spr->gety()+posOffset+vOffY-distance+distOff, true, QColor(244,250,255)); + track.render(painter); + } - for (int i = 0; i < spr->getNybble(17)-1; i++) - { - painter->drawPixmap(QRect(spr->getx() + i*20+20, spr->gety(), 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "t.png")); - painter->drawPixmap(QRect(spr->getx() + i*20+20, spr->gety()+blockHeight, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "b.png")); - } - for (int i = 0; i < spr->getNybble(19)-1; i++) - { - painter->drawPixmap(QRect(spr->getx(), spr->gety() + i*20+20, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "l.png")); - painter->drawPixmap(QRect(spr->getx()+blockWidth, spr->gety() + i*20+20, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "r.png")); - } + int blockWidth = spr->getNybble(17) > 0 ? spr->getNybble(17)*20 : 20; + int blockHeight = spr->getNybble(19) > 0 ? spr->getNybble(19)*20 : 20; - for (int x = 20; x < blockWidth; x+=20) - for (int y = 20; y < blockHeight; y+=20) - painter->drawPixmap(QRect(spr->getx()+x, spr->gety()+y, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "c.png")); + painter->drawPixmap(QRect(spr->getx()+posOffset, spr->gety()+posOffset, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "tl.png")); + painter->drawPixmap(QRect(spr->getx()+posOffset, spr->gety()+blockHeight+posOffset, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "bl.png")); + painter->drawPixmap(QRect(spr->getx()+blockWidth+posOffset, spr->gety()+posOffset, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "tr.png")); + painter->drawPixmap(QRect(spr->getx()+blockWidth+posOffset, spr->gety()+blockHeight+posOffset, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "br.png")); + + for (int i = 0; i < spr->getNybble(17)-1; i++) + { + painter->drawPixmap(QRect(spr->getx()+posOffset + i*20+20, spr->gety()+posOffset, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "t.png")); + painter->drawPixmap(QRect(spr->getx()+posOffset + i*20+20, spr->gety()+posOffset+blockHeight, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "b.png")); + } + for (int i = 0; i < spr->getNybble(19)-1; i++) + { + painter->drawPixmap(QRect(spr->getx()+posOffset, spr->gety()+posOffset + i*20+20, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "l.png")); + painter->drawPixmap(QRect(spr->getx()+posOffset+blockWidth, spr->gety()+posOffset + i*20+20, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "r.png")); } + + for (int x = 20; x < blockWidth; x+=20) + for (int y = 20; y < blockHeight; y+=20) + painter->drawPixmap(QRect(spr->getx()+x+posOffset, spr->gety()+y+posOffset, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "c.png")); + + if (spr->getNybble(11) == 1 || spr->getNybble(11) == 3) for (int x = 0; x < blockWidth+20; x+=20) painter->drawPixmap(QRect(spr->getx()+x+posOffset, spr->gety()-20+posOffset, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "s_t.png")); + if (spr->getNybble(11) == 2 || spr->getNybble(11) == 3) for (int x = 0; x < blockWidth+20; x+=20) painter->drawPixmap(QRect(spr->getx()+x+posOffset, spr->gety()+blockHeight+20+posOffset, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "s_b.png")); + if (spr->getNybble(11) == 4 || spr->getNybble(11) == 6) for (int y = 0; y < blockHeight+20; y+=20) painter->drawPixmap(QRect(spr->getx()+posOffset-20, spr->gety()+y+posOffset, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "s_l.png")); + if (spr->getNybble(11) == 5 || spr->getNybble(11) == 6) for (int y = 0; y < blockHeight+20; y+=20) painter->drawPixmap(QRect(spr->getx()+blockWidth+20+posOffset, spr->gety()+y+posOffset, 20, 20), ImageCache::getInstance()->get(SpriteImg, path + "s_r.png")); } // RecLiftRenderer @@ -2946,12 +3032,15 @@ RecLiftRenderer::RecLiftRenderer(const Sprite *spr, QString path) } void RecLiftRenderer::render(QPainter *painter, QRect *) { + Direction direction = (Direction)(spr->getNybble(5) % 4); + int hOffX = 0; int hOffY = 0; int vOffX = 0; int vOffY = 0; - switch (spr->getNybble(7)) { + switch (spr->getNybble(7)) + { case 1: hOffY = -10; vOffY = -20; @@ -2975,49 +3064,84 @@ void RecLiftRenderer::render(QPainter *painter, QRect *) default: hOffX = 0; hOffY = 0; + break; } // Render Movement Indicators int distance = spr->getNybble(14)*20; int eventDistance = spr->getNybbleData(10, 11)*20; + int distOff = 0; - - switch (spr->getNybble(5)) { - case 1: case 5: case 9: case 13: // Left + if (((0 < spr->getNybble(7) && spr->getNybble(7) < 3) && (direction == DOWN)) || + ((3 < spr->getNybble(7) && spr->getNybble(7) < 6) && (direction == RIGHT))) { - MovIndicatorRenderer track(spr->getx()+hOffX, spr->gety()+hOffY+spr->getheight()/2, spr->getx()+hOffX-distance, spr->gety()+hOffY+spr->getheight()/2, false, QColor(244,250,255)); - track.render(painter); - - MovIndicatorRenderer eventTrack(spr->getx()+hOffX, spr->gety()+hOffY+spr->getheight()/2, spr->getx()+hOffX-eventDistance, spr->gety()+hOffY+spr->getheight()/2, false, QColor(243,156,18)); - eventTrack.render(painter); + distOff = 20; } - break; - case 2: case 6: case 10: case 14: // Up + else if (((spr->getNybble(7) == 3) && (direction == DOWN)) || + ((spr->getNybble(7) == 6) && (direction == RIGHT))) { - MovIndicatorRenderer track(spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY, spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY-distance, true, QColor(244,250,255)); - track.render(painter); - - MovIndicatorRenderer eventTrack(spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY, spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY-eventDistance, true, QColor(243,156,18)); - eventTrack.render(painter); + distOff = 40; } + + switch (direction) + { + case LEFT: + { + if (distance > 0) + { + MovIndicatorRenderer track(spr->getx()+hOffX, spr->gety()+hOffY+spr->getheight()/2, spr->getx()+hOffX-distance+distOff, spr->gety()+hOffY+spr->getheight()/2, false, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx()+hOffX, spr->gety()+hOffY+spr->getheight()/2, spr->getx()+hOffX-eventDistance+distOff, spr->gety()+hOffY+spr->getheight()/2, false, QColor(243,156,18)); + eventTrack.render(painter); + } break; - case 3: case 7: case 11: case 15: // Down + } + case UP: { - MovIndicatorRenderer track(spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY+spr->getheight(), spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY+spr->getheight()+distance, true, QColor(244,250,255)); - track.render(painter); - - MovIndicatorRenderer eventTrack(spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY+spr->getheight(), spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY+spr->getheight()+eventDistance, true, QColor(243,156,18)); - eventTrack.render(painter); + if (distance > 0) + { + MovIndicatorRenderer track(spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY, spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY-distance+distOff, true, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY, spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY-eventDistance+distOff, true, QColor(243,156,18)); + eventTrack.render(painter); + } + break; } + case DOWN: + { + if (distance > 0) + { + MovIndicatorRenderer track(spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY+spr->getheight(), spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY+spr->getheight()+distance+distOff, true, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY+spr->getheight(), spr->getx()+vOffX-sideOffset+spr->getwidth()/2, spr->gety()+vOffY+spr->getheight()+eventDistance+distOff, true, QColor(243,156,18)); + eventTrack.render(painter); + } break; - default: // Right + } + case RIGHT: { - MovIndicatorRenderer track(spr->getx()+hOffX+spr->getwidth(), spr->gety()+hOffY+spr->getheight()/2, spr->getx()+hOffX+spr->getwidth()+distance, spr->gety()+hOffY+spr->getheight()/2, false, QColor(244,250,255)); - track.render(painter); - - MovIndicatorRenderer eventTrack(spr->getx()+hOffX+spr->getwidth(), spr->gety()+hOffY+spr->getheight()/2, spr->getx()+hOffX+spr->getwidth()+eventDistance, spr->gety()+hOffY+spr->getheight()/2, false, QColor(243,156,18)); - eventTrack.render(painter); + if (distance > 0) + { + MovIndicatorRenderer track(spr->getx()+hOffX+spr->getwidth(), spr->gety()+hOffY+spr->getheight()/2, spr->getx()+hOffX+spr->getwidth()+distance+distOff, spr->gety()+hOffY+spr->getheight()/2, false, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx()+hOffX+spr->getwidth(), spr->gety()+hOffY+spr->getheight()/2, spr->getx()+hOffX+spr->getwidth()+eventDistance+distOff, spr->gety()+hOffY+spr->getheight()/2, false, QColor(243,156,18)); + eventTrack.render(painter); + } + break; } + default: break; } @@ -3807,47 +3931,67 @@ LavaRectLiftRenderer::LavaRectLiftRenderer(const Sprite *spr) void LavaRectLiftRenderer::render(QPainter *painter, QRect *) { // Render Movement Indicators - int distance = spr->getNybbleData(17, 14)*20; + int distance = spr->getNybble(14)*20; int eventDistance = spr->getNybbleData(10, 11)*20; - - switch (spr->getNybble(5)) { - case 1: case 5: case 9: case 13: // Left + switch (spr->getNybble(5)) { - MovIndicatorRenderer track(spr->getx(), spr->gety()+spr->getheight()/2, spr->getx()-distance, spr->gety()+spr->getheight()/2, false, QColor(244,250,255)); - track.render(painter); - - MovIndicatorRenderer eventTrack(spr->getx(), spr->gety()+spr->getheight()/2, spr->getx()-eventDistance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); - eventTrack.render(painter); - } - break; - case 2: case 6: case 10: case 14: // Up - { - MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety(), spr->getx()+spr->getwidth()/2, spr->gety()-distance, true, QColor(244,250,255)); - track.render(painter); - - MovIndicatorRenderer eventTrack(spr->getx()+spr->getwidth()/2, spr->gety(), spr->getx()+spr->getwidth()/2, spr->gety()-eventDistance, true, QColor(243,156,18)); - eventTrack.render(painter); - } - break; - case 3: case 7: case 11: case 15: // Down - { - MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight(), spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+distance, true, QColor(244,250,255)); - track.render(painter); - - MovIndicatorRenderer eventTrack(spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight(), spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+eventDistance, true, QColor(243,156,18)); - eventTrack.render(painter); - } - break; - default: // Right - { - MovIndicatorRenderer track(spr->getx()+spr->getwidth(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getwidth()+distance, spr->gety()+spr->getheight()/2, false, QColor(244,250,255)); - track.render(painter); - - MovIndicatorRenderer eventTrack(spr->getx()+spr->getwidth(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getwidth()+eventDistance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); - eventTrack.render(painter); - } - break; + case 1: case 5: case 9: case 13: // Left + { + if (distance != 0) + { + MovIndicatorRenderer track(spr->getx(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getOffsetX()-distance, spr->gety()+spr->getheight()/2, false, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance != 0) + { + MovIndicatorRenderer eventTrack(spr->getx(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getOffsetX()-eventDistance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); + eventTrack.render(painter); + } + break; + } + case 2: case 6: case 10: case 14: // Up + { + if (distance != 0) + { + MovIndicatorRenderer track(spr->getx() + spr->getOffsetX()+spr->getwidth()/2, spr->gety(), spr->getx()+spr->getwidth()/2, spr->gety()-distance, true, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance != 0) + { + MovIndicatorRenderer eventTrack(spr->getx() + spr->getOffsetX()+spr->getwidth()/2, spr->gety(), spr->getx()+spr->getwidth()/2, spr->gety()-eventDistance, true, QColor(243,156,18)); + eventTrack.render(painter); + } + break; + } + case 3: case 7: case 11: case 15: // Down + { + if (distance != 0) + { + MovIndicatorRenderer track(spr->getx() + spr->getOffsetX()+spr->getwidth()/2, spr->gety()+spr->getheight(), spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+distance, true, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance != 0) + { + MovIndicatorRenderer eventTrack(spr->getx() + spr->getOffsetX()+spr->getwidth()/2, spr->gety()+spr->getheight(), spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+eventDistance, true, QColor(243,156,18)); + eventTrack.render(painter); + } + break; + } + default: // Right + { + if (distance != 0) + { + MovIndicatorRenderer track(spr->getx()+spr->getwidth(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getOffsetX()+spr->getwidth()+distance, spr->gety()+spr->getheight()/2, false, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance != 0) + { + MovIndicatorRenderer eventTrack(spr->getx()+spr->getwidth(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getOffsetX()+spr->getwidth()+eventDistance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); + eventTrack.render(painter); + } + break; + } } if (spr->getNybble(19) == 1) @@ -3907,15 +4051,15 @@ EventRecLiftRenderer::EventRecLiftRenderer(const Sprite *spr, QString path) { switch (spr->getNybble(19)) { - case 1: - type = "_small.png"; - break; - case 2: - type = "_big.png"; - break; - default: - type = ".png"; - break; + case 1: + type = "_small.png"; + break; + case 2: + type = "_big.png"; + break; + default: + type = ".png"; + break; } } @@ -3926,38 +4070,67 @@ void EventRecLiftRenderer::render(QPainter *painter, QRect *drawrect) { // Render Movement Indicators - int distance = 0; - - if (spr->getid() == 283) - distance = spr->getNybble(14)*20; - else - distance = spr->getNybbleData(4,5)*20; + int distance = spr->getNybble(14)*20; + int eventDistance = spr->getNybbleData(10, 11)*20; - switch (spr->getNybble(5)) { - case 1: case 5: case 9: case 13: // Left + switch (spr->getNybble(5)) { - MovIndicatorRenderer track(spr->getx(), spr->gety()+spr->getheight()/2, spr->getx()-distance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); - track.render(painter); - } - break; - case 2: case 6: case 10: case 14: // Up - { - MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety(), spr->getx()+spr->getwidth()/2, spr->gety()-distance, true, QColor(243,156,18)); - track.render(painter); - } - break; - case 3: case 7: case 11: case 15: // Down - { - MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight(), spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+distance, true, QColor(243,156,18)); - track.render(painter); - } - break; - default: // Right - { - MovIndicatorRenderer track(spr->getx()+spr->getwidth(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getwidth()+distance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); - track.render(painter); - } - break; + case 1: case 5: case 9: case 13: // Left + { + if (distance > 0) + { + MovIndicatorRenderer track(spr->getx(), spr->gety()+spr->getheight()/2, spr->getx()-distance, spr->gety()+spr->getheight()/2, false, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx(), spr->gety()+spr->getheight()/2, spr->getx()-eventDistance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); + eventTrack.render(painter); + } + break; + } + case 2: case 6: case 10: case 14: // Up + { + if (distance > 0) + { + MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety(), spr->getx()+spr->getwidth()/2, spr->gety()-distance, true, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx()+spr->getwidth()/2, spr->gety(), spr->getx()+spr->getwidth()/2, spr->gety()-eventDistance, true, QColor(243,156,18)); + eventTrack.render(painter); + } + break; + } + case 3: case 7: case 11: case 15: // Down + { + if (distance > 0) + { + MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight(), spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+distance, true, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight(), spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+eventDistance, true, QColor(243,156,18)); + eventTrack.render(painter); + } + break; + } + default: // Right + { + if (distance > 0) + { + MovIndicatorRenderer track(spr->getx()+spr->getwidth(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getwidth()+distance, spr->gety()+spr->getheight()/2, false, QColor(244,250,255)); + track.render(painter); + } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx()+spr->getwidth(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getwidth()+eventDistance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); + eventTrack.render(painter); + } + break; + } } img->render(painter, drawrect); @@ -4045,6 +4218,22 @@ void IceLiftRenderer::render(QPainter *painter, QRect *drawrect) img->render(painter, drawrect); } +// Sprite 310: Big Bowser Battle Lift +BowserLiftRenderer::BowserLiftRenderer(const Sprite *spr) +{ + switch (spr->getNybble(11)) + { + case 1: img = new NormalImageRenderer(spr, "bowser_lift/m.png"); break; + case 2: img = new NormalImageRenderer(spr, "bowser_lift/l.png"); break; + default: img = new NormalImageRenderer(spr, "bowser_lift/s.png"); break; + } +} + +void BowserLiftRenderer::render(QPainter *painter, QRect *drawrect) +{ + img->render(painter, drawrect); +} + // Sprite 311: Coin Meteor CoinMeteorRenderer::CoinMeteorRenderer(const Sprite *spr) { @@ -4070,34 +4259,68 @@ UnderwaterRecLiftRenderer::UnderwaterRecLiftRenderer(const Sprite *spr) void UnderwaterRecLiftRenderer::render(QPainter *painter, QRect *drawrect) { - int distance = spr->getNybbleData(10, 11)*20; + int distance = spr->getNybble(14)*20; + int eventDistance = spr->getNybbleData(10, 11)*20; - switch (spr->getNybble(5)) { + switch (spr->getNybble(5)) + { case 1: case 5: case 9: case 13: // Left + { + if (distance > 0) { - MovIndicatorRenderer track(spr->getx(), spr->gety()+spr->getheight()/2, spr->getx()-distance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); + MovIndicatorRenderer track(spr->getx(), spr->gety()+spr->getheight()/2, spr->getx()-distance, spr->gety()+spr->getheight()/2, false, QColor(244,250,255)); track.render(painter); } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx(), spr->gety()+spr->getheight()/2, spr->getx()-eventDistance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); + eventTrack.render(painter); + } break; + } case 2: case 6: case 10: case 14: // Up + { + if (distance > 0) { - MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety(), spr->getx()+spr->getwidth()/2, spr->gety()-distance, true, QColor(243,156,18)); + MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety(), spr->getx()+spr->getwidth()/2, spr->gety()-distance, true, QColor(244,250,255)); track.render(painter); } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx()+spr->getwidth()/2, spr->gety(), spr->getx()+spr->getwidth()/2, spr->gety()-eventDistance, true, QColor(243,156,18)); + eventTrack.render(painter); + } break; + } case 3: case 7: case 11: case 15: // Down + { + if (distance > 0) { - MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight(), spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+distance, true, QColor(243,156,18)); + MovIndicatorRenderer track(spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight(), spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+distance, true, QColor(244,250,255)); track.render(painter); } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight(), spr->getx()+spr->getwidth()/2, spr->gety()+spr->getheight()+eventDistance, true, QColor(243,156,18)); + eventTrack.render(painter); + } break; + } default: // Right + { + if (distance > 0) { - MovIndicatorRenderer track(spr->getx()+spr->getwidth(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getwidth()+distance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); + MovIndicatorRenderer track(spr->getx()+spr->getwidth(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getwidth()+distance, spr->gety()+spr->getheight()/2, false, QColor(244,250,255)); track.render(painter); } + if (eventDistance > 0) + { + MovIndicatorRenderer eventTrack(spr->getx()+spr->getwidth(), spr->gety()+spr->getheight()/2, spr->getx()+spr->getwidth()+eventDistance, spr->gety()+spr->getheight()/2, false, QColor(243,156,18)); + eventTrack.render(painter); + } break; } + } img->render(painter, drawrect); } @@ -4415,37 +4638,21 @@ LiquidRenderer::LiquidRenderer(const Sprite *liquid, const Zone *zone) void LiquidRenderer::render(QPainter *painter, QRect *drawrect) { + this->painter = painter; + this->drawrect = drawrect; + if (liquid->getid() != 14) { - QPixmap top = ImageCache::getInstance()->get(SpriteImg, filename + "_top.png"); - QPixmap base = ImageCache::getInstance()->get(SpriteImg, filename + ".png"); - - int currY = liquid->gety() - 20; - - for (int x = zone->getx(); x < zone->getx() + zone->getwidth(); x += top.width()) - { - QRect rect = QRect(x, currY, qMin(zone->getx() + zone->getwidth() - x, top.width()), qMin(zone->gety() + zone->getheight() - currY, top.height())); - - if (!drawrect->intersects(rect)) - continue; - - painter->drawPixmap(rect, top, QRect(0, 0, rect.right()-rect.left(), rect.bottom()-rect.top())); - } + bool topless = (liquid->getid() != 15 && liquid->getNybble(9) >= 8); - currY += top.height(); + bool movingDown = (liquid->getNybble(4) > 8); + int directedDistance = liquid->getNybbleData(7,8) * 20 * (movingDown ? 1 : -1); + bool moving = (liquid->getNybble(4) % 8 != 0) && (directedDistance != 0); - for (; currY < zone->gety() + zone->getheight(); currY += base.height()) - { - for (int x = zone->getx(); x < zone->getx() + zone->getwidth(); x += base.width()) - { - QRect rect = QRect(x, currY, qMin(zone->getx() + zone->getwidth() - x, base.width()), qMin(zone->gety() + zone->getheight() - currY, base.height())); - - if (!drawrect->intersects(rect)) - continue; - - painter->drawPixmap(rect, base, QRect(0, 0, rect.right()-rect.left(), rect.bottom()-rect.top())); - } - } + if (moving && movingDown) + drawLiquid(false, directedDistance, topless); + else + drawLiquid(false, 0, topless); } else { @@ -4465,3 +4672,89 @@ void LiquidRenderer::render(QPainter *painter, QRect *drawrect) } } +void LiquidRenderer::renderTranslucent(QPainter *painter, QRect *drawrect) +{ + this->painter = painter; + this->drawrect = drawrect; + + bool topless = (liquid->getid() != 15 && liquid->getNybble(9) >= 8); + + bool movingDown = (liquid->getNybble(4) > 8); + int directedDistance = liquid->getNybbleData(7,8) * 20 * (movingDown ? 1 : -1); + bool moving = (liquid->getNybble(4) % 8 != 0) && (directedDistance != 0); + + if (!moving) + return; + else if (movingDown) + drawLiquid(true, 0, topless); + else + drawLiquid(true, directedDistance, topless); +} + +void LiquidRenderer::drawLiquid(bool transparent, int yOffset, bool topless) +{ + painter->save(); + + if (transparent) + { + painter->setOpacity(0.25); + painter->setCompositionMode(QPainter::CompositionMode_Lighten); + } + + QPixmap top = ImageCache::getInstance()->get(SpriteImg, filename + "_top.png"); + QPixmap base = ImageCache::getInstance()->get(SpriteImg, filename + ".png"); + + // Calculate dimensions that never change + int x = qMax(zone->getx(), drawrect->x()); + int width = qMin(zone->getx() + zone->getwidth(), drawrect->x() + drawrect->width()) - qMax(zone->getx(), drawrect->x()); + + // Draw the top part of the liquid + int yWithOffset = liquid->getid() >= 15 ? liquid->gety() - 25 + yOffset: liquid->gety() - 7 + yOffset; + + if (!topless) + { + QRect topRect(x, yWithOffset, width, 0); + topRect.setHeight(qMin(top.height(), zone->gety() + zone->getheight() - yWithOffset)); + + // Move the texture with the sprite (as opposed to being masked by position) + int textureYOffset = yWithOffset % top.height() - 1;; + + // Check if the liquid top is past the top zone edge (i.e. needs to be cropped) + bool topNeedsCropping = (0 < zone->gety() - yWithOffset && zone->gety() - yWithOffset < top.height()); + + // "Fake" a crop when the liquid top is above the top zone edge + if (topNeedsCropping) + topRect.setY(topRect.y() + (zone->gety() - yWithOffset)); + + QBrush topBrush = QBrush(top); + topBrush.setTransform(QTransform().translate(0, textureYOffset)); + + // Ensure the liquid top doesn't render past the bottom of the zone, or past the cutoff point for cropping + if (yWithOffset > zone->gety() + zone->getheight() || zone->gety() - yWithOffset >= top.height()) + topRect.setHeight(0); + + painter->setBrush(topBrush); + painter->drawRect(topRect); + + yWithOffset += top.height() - 1; + } + else + yWithOffset += 7; + + // Draw the base (fill) part of the liquid + QBrush baseBrush = QBrush(base); + baseBrush.setTransform(QTransform().translate(0, yWithOffset % base.height())); + painter->setBrush(baseBrush); + + QRect baseRect(x, 0, width, 0); + baseRect.setY(qMax(yWithOffset, qMax(zone->gety(), drawrect->y()))); + + // Correctly resize the height to only where the liquid base is visible + int baseBottomBound = qMin(zone->gety() + zone->getheight(), drawrect->y() + drawrect->height()); + int baseTopBound = qMax(yWithOffset, qMax(zone->gety(), drawrect->y())); + baseRect.setHeight(qMax(baseBottomBound - baseTopBound, 0)); + + painter->drawRect(baseRect); + + painter->restore(); +} diff --git a/objectrenderer.h b/objectrenderer.h index 4693764f..c1633333 100644 --- a/objectrenderer.h +++ b/objectrenderer.h @@ -32,10 +32,15 @@ class LiquidRenderer: public ObjectRenderer LiquidRenderer() {} LiquidRenderer(const Sprite *liquid, const Zone *zone); void render(QPainter *painter, QRect *drawrect); + void renderTranslucent(QPainter *painter, QRect *drawrect); protected: const Sprite *liquid; const Zone *zone; QString filename; + QPainter *painter; + QRect *drawrect; +private: + void drawLiquid(bool transparent, int yOffset, bool topless); }; class NormalImageRenderer: public ObjectRenderer @@ -82,14 +87,18 @@ class MovIndicatorRenderer: public ObjectRenderer { public: MovIndicatorRenderer(); - MovIndicatorRenderer(int x, int y, int distX, int distY, bool vertical, QColor color); + MovIndicatorRenderer(int startX, int startY, int endX, int endY, bool vertical, QColor color); + MovIndicatorRenderer(int startX, int startY, int endX, int endY, int thickness, int radius, bool applyOffset, bool vertical, QColor color); using ObjectRenderer::render; void render(QPainter *painter); protected: - int x; - int y; - int distX; - int distY; + int startX; + int startY; + int endX; + int endY; + int thickness; + int radius; + bool applyOffset; bool vertical; QColor color; }; @@ -128,11 +137,7 @@ class WhompRenderer: public SpriteRenderer { public: WhompRenderer(const Sprite *spr); - ~WhompRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); -protected: - NormalImageRenderer *img; - QString filename; }; // Sprite 18: Tile God @@ -298,6 +303,17 @@ class FireBarRenderer: public SpriteRenderer CircleRenderer *radius; }; +// Sprite 82: Fire Snake +class FireSnakeRenderer: public SpriteRenderer +{ +public: + FireSnakeRenderer(const Sprite *spr); + ~FireSnakeRenderer() { delete img; } + void render(QPainter *painter, QRect *drawrect); +protected: + NormalImageRenderer *img; +}; + // Sprites 84/85/86/87/88: Flags class FlagRenderer: public SpriteRenderer { @@ -463,10 +479,7 @@ class BowserFlameRenderer: public SpriteRenderer { public: BowserFlameRenderer(const Sprite *spr); - ~BowserFlameRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); -protected: - NormalImageRenderer *img; }; // Sprite 131: Bowser Block @@ -530,8 +543,10 @@ class GoombaTowerRenderer: public SpriteRenderer class LiftRenderer: public SpriteRenderer { public: - LiftRenderer(const Sprite *spr); + LiftRenderer(const Sprite *spr, QString dirname); void render(QPainter *painter, QRect *drawrect); +protected: + QString dirname; }; // Sprite 146: Track Controlled Lift @@ -705,6 +720,7 @@ class RecLiftRenderer: public SpriteRenderer RecLiftRenderer(const Sprite *spr, QString path); void render(QPainter *painter, QRect *drawrect); protected: + enum Direction {RIGHT, LEFT, UP, DOWN}; QString path; int sideOffset = 0; }; @@ -1072,6 +1088,17 @@ class IceLiftRenderer: public SpriteRenderer NormalImageRenderer* img; }; +// Sprite 310: Big Bowser Battle Lift +class BowserLiftRenderer: public SpriteRenderer +{ +public: + BowserLiftRenderer(const Sprite *spr); + ~BowserLiftRenderer() { delete img; } + void render(QPainter *painter, QRect *drawrect); +protected: + NormalImageRenderer* img; +}; + // Sprite 311: Coin Meteor class CoinMeteorRenderer: public SpriteRenderer { diff --git a/objects.cpp b/objects.cpp index 93c5964a..3fa313ff 100644 --- a/objects.cpp +++ b/objects.cpp @@ -253,18 +253,38 @@ void Sprite::setRect() height = 25; break; case 9: // Whomp - if (getNybble(11) == 1) + if (getNybble(11) == 1) // Big { - width = 140; - height = 100; - offsetx = -50; - offsety = -40; + if (getNybble(10) == 0) // Big, walking + { + width = 105; + height = 102; + offsetx = -36; + offsety = -42; + } + else + { + width = 140; + height = 100; + offsetx = -50; + offsety = -40; + } } - else + else // Normal { - width = 80; - height = 60; - offsetx = -20; + if (getNybble(10) == 0) // Normal, walking + { + width = 58; + height = 56; + offsetx = -9; + offsety = 4; + } + else + { + width = 80; + height = 60; + offsetx = -20; + } } break; case 10: // Switchable Conveyor Belt - Lemmy Battle @@ -745,10 +765,19 @@ void Sprite::setRect() height = 40; break; case 82: // Fire Snake + { width = 19; height = 26; offsety = -5; + if (getNybble(11) == 1) + { + width = 15; + height = 17; + offsetx = 2; + offsety = 3; + } break; + } case 83: // Fish Bone width = 33; height = 21; @@ -1164,7 +1193,7 @@ void Sprite::setRect() case 127: // Bowser Flame width = 57; height = 36; - offsetx = 28; + offsetx = (getNybble(10) == 1) ? 8 : 28; offsety = -20; break; case 128: // Dry Bowser @@ -1258,42 +1287,44 @@ void Sprite::setRect() offsetx = -4; offsety = -21; break; - case 144: case 145: // Horizontal/Vertical Lift - if(getNybble(11) == 0) + case 144: case 145: case 254: // Horizontal/Vertical/Totem Lift + { + if (getNybble(11) == 0) width = 40; else width = (getNybble(11)-1)*20 + 40; height = 22; - //Down and right + + // Down and right if (getNybble(7) == 1) { - if(getid() == 145) - renderOffsetH = (getNybble(9)*20); + if (getid() == 145 || getid() == 254) + renderOffsetH = (getNybble(9)*20); else - renderOffsetW = -(getNybble(9)*20); + renderOffsetW = -(getNybble(9)*20); } else { - if(getid() == 145) - renderOffsetH = -(getNybble(9)*20); + if (getid() == 145 || getid() == 254) + renderOffsetH = -(getNybble(9)*20); else - renderOffsetW = (getNybble(9)*20); + renderOffsetW = (getNybble(9)*20); } - - //renderOffsetX = width/2; - //renderOffsetY = height/2; break; + } case 146: // Track Controlled Lift - if(getNybble(17) == 0) + { + if (getNybble(17) == 0) width = 84; - else if(getNybble(17) == 1) + else if (getNybble(17) == 1) width = 35; else width = (getNybble(17)-2)*20 + 44; height = 22; - offsetx = 40 -(width / 2); + offsetx = 40 - (width / 2); offsety = 10; break; + } case 147: // 3 plat rickshaw if (getNybble(11) != 1) { @@ -1693,6 +1724,8 @@ void Sprite::setRect() case 187: // Path controlled rect block width = 20 + getNybble(17)*20; height = 20 + getNybble(19)*20; + offsetx = getNybble(7); + offsety = offsetx; break; case 189: case 190: case 191: case 192: case 193: case 282: // Rect Blocks { @@ -1888,15 +1921,23 @@ void Sprite::setRect() break; case 205: // Red Ring + { width = 39; height = 56; offsety = 2; + if (getNybble(11) & 1) + offsetx = 10; break; + } case 206: // Gold Ring + { width = 40; height = 56; offsety = 2; + if (getNybble(11) & 1) + offsetx = 10; break; + } case 207: // Underwater Rock width = 80; height = 82; @@ -2439,10 +2480,12 @@ void Sprite::setRect() { width = 250; height = 80; + offsetx = -10; if (getNybble(19) == 1) { width = 100; height = 603; + offsetx = 0; } int distance = qMax((getNybbleData(17, 14)*20), (getNybbleData(10, 11)*20)); @@ -2475,6 +2518,11 @@ void Sprite::setRect() offsetx = 1; offsety = 1; break; + case 271: // Big Icy Spiked Ball + width = 73; + height = 73; + offsetx = 20; + break; case 272: // Peach Cage width = 68; height = 108; @@ -2723,55 +2771,77 @@ void Sprite::setRect() } break; case 307: // Event Activated Rect Lift - Ruins - { - width = 80; - height = 80; + { + width = 80; + height = 80; - int distance = getNybbleData(10, 11)*20; - switch (getNybble(5)) - { - case 1: case 5: case 9: case 13: // Left - renderOffsetW = width + distance; - renderOffsetX = -(width + distance); - break; - case 2: case 6: case 10: case 14: // Up - renderOffsetH = height + distance; - renderOffsetY = -(height + distance); - break; - case 3: case 7: case 11: case 15: // Down - renderOffsetH = height + distance; - break; - default: // Right - renderOffsetW = width + distance; - break; - } + int distance = getNybbleData(10, 11)*20; + switch (getNybble(5)) + { + case 1: case 5: case 9: case 13: // Left + renderOffsetW = width + distance; + renderOffsetX = -(width + distance); + break; + case 2: case 6: case 10: case 14: // Up + renderOffsetH = height + distance; + renderOffsetY = -(height + distance); + break; + case 3: case 7: case 11: case 15: // Down + renderOffsetH = height + distance; + break; + default: // Right + renderOffsetW = width + distance; break; } + break; + } case 308: // Event Activated Rect Lift - Sand - { - width = 120; - height = 140; + { + width = 120; + height = 140; - int distance = getNybbleData(10, 11)*20; - switch (getNybble(5)) - { - case 1: case 5: case 9: case 13: // Left - renderOffsetW = width + distance; - renderOffsetX = -(width + distance); - break; - case 2: case 6: case 10: case 14: // Up - renderOffsetH = height + distance; - renderOffsetY = -(height + distance); - break; - case 3: case 7: case 11: case 15: // Down - renderOffsetH = height + distance; - break; - default: // Right - renderOffsetW = width + distance; - break; - } + int distance = getNybbleData(10, 11)*20; + switch (getNybble(5)) + { + case 1: case 5: case 9: case 13: // Left + renderOffsetW = width + distance; + renderOffsetX = -(width + distance); + break; + case 2: case 6: case 10: case 14: // Up + renderOffsetH = height + distance; + renderOffsetY = -(height + distance); + break; + case 3: case 7: case 11: case 15: // Down + renderOffsetH = height + distance; + break; + default: // Right + renderOffsetW = width + distance; break; } + break; + } + case 310: // Big Bowser Battle Lift + { + switch (getNybble(11)) + { + case 1: + width = 82; + offsetx = -41; + break; + case 2: + width = 102; + offsetx = -51; + break; + default: + width = 62; + offsetx = -31; + break; + } + + height = 24; + offsety = -10; + break; + } case 311: // Coin Meteor if(getNybble(11) == 1) { diff --git a/settingsmanager.cpp b/settingsmanager.cpp index f0e3ca3d..90d98714 100644 --- a/settingsmanager.cpp +++ b/settingsmanager.cpp @@ -173,6 +173,14 @@ void SettingsManager::setLEUndoLimit(const quint32 &value) { settings.setValue("LE_UNDO_LIMIT", value); } +bool SettingsManager::getLERenderTransparentLiquidAboveTiles() { + return settings.value("LE_RENDER_TRANSPARENT_LIQUID_ABOVE_TILES", LE_RENDER_TRANSPARENT_LIQUID_ABOVE_TILES_DEFAULT).toBool(); +} + +void SettingsManager::setLERenderTransparentLiquidAboveTiles(const bool &value) { + settings.setValue("LE_RENDER_TRANSPARENT_LIQUID_ABOVE_TILES", value); +} + bool SettingsManager::getLESelectOnPlace() { return settings.value("LE_SELECT_ON_PLACE", LE_SELECT_ON_PLACE_DEFAULT).toBool(); } diff --git a/settingsmanager.h b/settingsmanager.h index 60e0bdb8..d5410c7f 100644 --- a/settingsmanager.h +++ b/settingsmanager.h @@ -61,6 +61,9 @@ class SettingsManager : public QObject quint32 getLEUndoLimit(); void setLEUndoLimit(const quint32 &value); + bool getLERenderTransparentLiquidAboveTiles(); + void setLERenderTransparentLiquidAboveTiles(const bool &value); + bool getLESelectOnPlace(); void setLESelectOnPlace(const bool &value); @@ -70,6 +73,7 @@ class SettingsManager : public QObject // Defaults - Level Editor static constexpr QColor LE_WINDOW_COLOR_DEFAULT = QColor(119, 136, 153); static constexpr int LE_UNDO_LIMIT_DEFAULT = 200; + static constexpr bool LE_RENDER_TRANSPARENT_LIQUID_ABOVE_TILES_DEFAULT = false; static constexpr bool LE_SELECT_ON_PLACE_DEFAULT = true; static constexpr bool LE_SHOW_STATUSBAR_DEFAULT = true;