From 9a17a07ef37a637a296e7694932f82fa1379c1dc Mon Sep 17 00:00:00 2001 From: AllyTally Date: Fri, 1 Sep 2023 21:21:27 -0300 Subject: [PATCH 01/12] Clean up setting enemy properties This commit cleans up setting enemy properties. It deduplicates code, makes custom levels spawn enemies better (doesn't just pretend it's a certain main game room to set the settings) and makes everything a nice registry. This is the basis of a future system which might allow for more enemy types to be used in the editor, and even custom enemy types... But it was mostly done for cleanup, since I hated how the code looked. --- desktop_version/src/Editor.cpp | 37 +---- desktop_version/src/Ent.cpp | 280 +++++++-------------------------- desktop_version/src/Entity.cpp | 137 +++++++++++++--- desktop_version/src/Entity.h | 17 ++ 4 files changed, 186 insertions(+), 285 deletions(-) diff --git a/desktop_version/src/Editor.cpp b/desktop_version/src/Editor.cpp index 2a04509e7a..83a8a0c37c 100644 --- a/desktop_version/src/Editor.cpp +++ b/desktop_version/src/Editor.cpp @@ -4017,42 +4017,7 @@ bool editorclass::autotile_connector(int x, int y, TileTypes original_type) int editorclass::get_enemy_tile(int t) { - switch(t) - { - case 0: - return 78; - break; - case 1: - return 88; - break; - case 2: - return 36; - break; - case 3: - return 164; - break; - case 4: - return 68; - break; - case 5: - return 48; - break; - case 6: - return 176; - break; - case 7: - return 168; - break; - case 8: - return 112; - break; - case 9: - return 114; - break; - default: - return 78; - break; - } + return (&obj.enemy_types[obj.legacy_id_to_entity(t)])->tile; } void editorclass::set_tile(int x, int y, int t) diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index f159547f81..ca32d61a03 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -1,5 +1,6 @@ #include "Ent.h" +#include "Entity.h" #include "Game.h" #include "Graphics.h" @@ -106,36 +107,24 @@ void entclass::setenemy( int t ) switch ((int) para) { case 0: - tile = 60; - animate = 2; - colour = 6; + obj.set_enemy_type(this, "lies_emitter"); behave = 10; - w = 32; - h = 32; x1 = -200; break; case 1: + obj.set_enemy_type(this, "lies"); yp += 10; lerpoldyp += 10; - tile = 63; - animate = 100; //LIES - colour = 6; behave = 11; - para = 9; //destroyed when outside + para = 9; // destroyed when outside x1 = -200; x2 = 400; - w = 26; - h = 10; cx = 1; cy = 1; break; case 2: - tile = 62; - animate = 100; - colour = 6; + obj.set_enemy_type(this, "lies_collector"); behave = -1; - w = 32; - h = 32; break; } break; @@ -144,39 +133,27 @@ void entclass::setenemy( int t ) switch ((int) para) { case 0: - tile = 72; - animate = 3; + obj.set_enemy_type(this, "factory_emitter"); size = 9; - colour = 6; behave = 12; - w = 64; - h = 40; cx = 0; cy = 24; break; case 1: + obj.set_enemy_type(this, "factory_clouds"); xp += 4; lerpoldxp += 4; yp -= 4; lerpoldyp -= 4; - tile = 76; - animate = 100; // Clouds - colour = 6; behave = 13; para = -6; //destroyed when outside x2 = 400; - w = 32; - h = 12; cx = 0; cy = 6; break; case 2: - tile = 77; - animate = 100; - colour = 6; + obj.set_enemy_type(this, "factory_collector"); behave = -1; - w = 32; - h = 16; break; } break; @@ -194,47 +171,26 @@ void entclass::setenemyroom( int rx, int ry ) { //Space Station 1 case rn(12, 3): //Security Drone - tile = 36; - colour = 8; - animate = 1; + obj.set_enemy_type(this, "disc"); break; case rn(13, 3): //Wavelengths - tile = 32; - colour = 7; - animate = 1; - w = 32; + obj.set_enemy_type(this, "wavelength"); break; case rn(15, 3): //Traffic - tile = 28; - colour = 6; - animate = 1; - w = 22; - h = 32; + obj.set_enemy_type(this, "stop"); break; case rn(12, 5): //The Yes Men - tile = 40; - colour = 9; - animate = 1; - w = 20; - h = 20; + obj.set_enemy_type(this, "yes"); break; case rn(13, 6): //Hunchbacked Guards - tile = 44; - colour = 8; - animate = 1; - w = 16; - h = 20; + obj.set_enemy_type(this, "guard"); break; case rn(13, 4): //Communication Station harmful = false; if (xp == 256) { //transmittor - tile = 104; - colour = 4; - animate = 7; - w = 16; - h = 16; + obj.set_enemy_type(this, "transmitter"); xp -= 24; lerpoldxp -= 24; yp -= 16; @@ -243,11 +199,7 @@ void entclass::setenemyroom( int rx, int ry ) else { //radar dish - tile =124; - colour = 4; - animate = 6; - w = 32; - h = 32; + obj.set_enemy_type(this, "radar"); cx = 4; size = 9; xp -= 4; @@ -259,18 +211,10 @@ void entclass::setenemyroom( int rx, int ry ) break; //The Lab case rn(4, 0): - tile = 78; - colour = 7; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "square"); break; case rn(2, 0): - tile = 88; - colour = 11; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "circle"); break; //Space Station 2 case rn(14, 11): @@ -288,237 +232,121 @@ void entclass::setenemyroom( int rx, int ry ) case rn(13, 8): colour = 8; break; //Factory + case rn(13,7): // MAVVERRRICK + obj.set_enemy_type(this, "bus"); + size = 9; + break; case rn(11, 13): //Truth - tile = 64; - colour = 7; - animate = 100; - w = 44; - h = 10; + obj.set_enemy_type(this, "truth"); size = 10; break; case rn(17, 7): //Brass sent us under the top - tile =82; - colour = 8; - animate = 5; - w = 28; - h = 32; + obj.set_enemy_type(this, "solider"); cx = 4; break; case rn(10, 7): // (deception) - tile = 92; - colour = 6; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "bowtie"); break; case rn(14, 13): // (chose poorly) - tile = 56; - colour = 6; - animate = 1; - w = 15; - h = 24; + obj.set_enemy_type(this, "skeleton"); break; case rn(13, 12): // (backsliders) - tile = 164; - colour = 7; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "glitch"); break; case rn(14, 8): // (wheel of fortune room) - tile = 116; - colour = 12; - animate = 1; - w = 32; - h = 32; + obj.set_enemy_type(this, "wheel"); break; case rn(16, 9): // (seeing dollar signs) - tile = 68; - colour = 7; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "coin"); break; case rn(16, 7): // (tomb of mad carew) - tile = 106; - colour = 7; - animate = 2; - w = 24; - h = 25; + obj.set_enemy_type(this, "ghost"); break; //Warp Zone case rn(15, 2): // (numbers) - tile = 100; - colour = 6; - animate = 1; - w = 32; - h = 14; + obj.set_enemy_type(this, "numbers"); yp += 1; lerpoldyp += 1; break; case rn(16, 2): // (Manequins) - tile = 52; - colour = 7; - animate = 5; - w = 16; - h = 25; + obj.set_enemy_type(this, "mannequin"); yp -= 4; lerpoldyp -= 4; break; case rn(18, 0): // (Obey) - tile = 51; - colour = 11; - animate = 100; - w = 30; - h = 14; + obj.set_enemy_type(this, "obey"); break; case rn(19, 1): // Ascending and Descending - tile = 48; - colour = 9; - animate = 5; - w = 16; - h = 16; + obj.set_enemy_type(this, "cross"); break; case rn(19, 2): // Shockwave Rider - tile = 176; - colour = 6; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "triangle"); break; case rn(18, 3): // Mind the gap - tile = 168; - colour = 7; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "ice"); break; case rn(17, 3): // Edge Games - if (yp ==96) + if (yp == 96) { - tile = 160; - colour = 8; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "edgegames_left"); } else { - tile = 156; - colour = 8; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "edgegames_right"); } break; case rn(16, 0): // I love you - tile = 112; - colour = 8; - animate = 5; - w = 16; - h = 16; + obj.set_enemy_type(this, "heart"); break; case rn(14, 2): // That's why I have to kill you - tile = 114; - colour = 6; - animate = 5; - w = 16; - h = 16; + obj.set_enemy_type(this, "broken_heart"); break; case rn(18, 2): // Thinking with Portals //depends on direction - if (xp ==88) + size = 10; + if (xp == 88) { - tile = 54+12; - colour = 12; - animate = 100; - w = 60; - h = 16; - size = 10; + obj.set_enemy_type(this, "centipede_right"); } else { - tile = 54; - colour = 12; - animate = 100; - w = 60; - h = 16; - size = 10; + obj.set_enemy_type(this, "centipede_left"); } break; //Final level case rn(50-100, 53-100): //The Yes Men - tile = 40; - colour = 9; - animate = 1; - w = 20; - h = 20; + obj.set_enemy_type(this, "yes"); break; case rn(48-100, 51-100): //Wavelengths - tile = 32; - colour = 7; - animate = 1; - w = 32; + obj.set_enemy_type(this, "wavelength"); break; case rn(43-100,52-100): // Ascending and Descending - tile = 48; - colour = 9; - animate = 5; - w = 16; - h = 16; + obj.set_enemy_type(this, "cross"); break; case rn(46-100,51-100): //kids his age - tile = 88; - colour = 11; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "circle"); break; case rn(43-100,51-100): // Mind the gap - tile = 168; - colour = 7; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "ice"); break; case rn(44-100,51-100): // vertigo? - tile = 172; - colour = 7; - animate = 100; - w = 32; - h = 32; + obj.set_enemy_type(this, "vertigo"); break; case rn(44-100,52-100): // (backsliders) - tile = 164; - colour = 7; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "glitch"); break; case rn(43-100, 56-100): //Intermission 1 - tile = 88; - colour = 21; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "circle"); break; case rn(45-100, 56-100): //Intermission 1 - tile = 88; - colour = 21; - animate = 1; - w = 16; - h = 16; + obj.set_enemy_type(this, "circle"); break; //The elephant case rn(11, 9): case rn(12, 9): case rn(11, 8): case rn(12, 8): - tile = 0; - colour = 102; - animate = 0; - w = 464; - h = 320; + obj.set_enemy_type(this, "elephant"); size = 11; harmful = false; break; diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index d329e3a876..1c5f1c1c29 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -1,6 +1,7 @@ #define OBJ_DEFINITION #include "Entity.h" +#include #include #include "CustomLevels.h" @@ -99,6 +100,117 @@ void entityclass::init(void) SDL_memset(customcollect, false, sizeof(customcollect)); k = 0; + + enemy_types.clear(); + add_default_types(); +} + +void entityclass::create_type(const char* type, int tile, int colour, int animate, int width, int height) +{ + EnemyType enemy_type; + enemy_type.tile = tile; + enemy_type.colour = colour; + enemy_type.animate = animate; + enemy_type.width = width; + enemy_type.height = height; + + enemy_types[type] = enemy_type; +} + +void entityclass::add_default_types(void) +{ + create_type("square", 78, 7, 1, 16, 16); // Vibrating String Problem + create_type("circle", 88, 11, 1, 16, 16); // Kids His Age Bounce + create_type("disc", 36, 8, 1, 16, 16); // Security Sweep + create_type("glitch", 164, 7, 1, 16, 16); // Backsliders + create_type("coin", 68, 7, 1, 16, 16); // $eeing Dollar $ign$ + create_type("cross", 48, 9, 5, 16, 16); // Ascending and Descending + create_type("triangle", 176, 6, 1, 16, 16); // Shockwave Rider + create_type("ice", 168, 7, 1, 16, 16); // Mind The Gap + create_type("heart", 112, 8, 5, 16, 16); // I Love You + create_type("broken_heart", 114, 6, 5, 16, 16); // That's Why I Have To Kill You + + create_type("bowtie", 92, 6, 1, 16, 16); // A Deception + create_type("crate", 24, 6, 1, 16, 16); // UNUSED in main game + + create_type("wavelength", 32, 7, 1, 32, 16); // Linear Collider + create_type("stop", 28, 6, 1, 22, 32); // Traffic Jam + create_type("yes", 40, 9, 1, 20, 20); // The Yes Men + create_type("bus", 96, 6, 4, 64, 44); // B-B-B-Busted + create_type("vertigo", 172, 7, 100, 32, 32); // Vertigo + create_type("guard", 44, 8, 1, 16, 20); // Trench Warfare + create_type("truth", 64, 7, 100, 44, 10); // Boldly To Go + create_type("obey", 51, 11, 100, 30, 14); // Time to get serious + create_type("mannequin", 52, 7, 5, 16, 25); // Short Circuit + create_type("numbers", 100, 6, 1, 32, 14); // Take the Red Pill + create_type("ghost", 106, 7, 2, 24, 25); // The Tomb of Mad Carew + create_type("wheel", 116, 12, 1, 32, 32); // The Hanged Man, Reversed + create_type("skeleton", 56, 6, 1, 15, 24); // You Chose... Poorly + create_type("solider", 82, 8, 5, 28, 32); // Brass Sent Us Under The Top + + create_type("transmitter", 104, 4, 7, 16, 16); // Comms Relay + create_type("radar", 124, 4, 6, 32, 32); // Comms Relay + + create_type("edgegames_left", 160, 8, 1, 16, 16); // Edge Games + create_type("edgegames_right", 156, 8, 1, 16, 16); // Edge Games + + create_type("centipede_right", 66, 12, 100, 60, 16); // Sweeney's Maze + create_type("centipede_left", 54, 12, 100, 60, 16); // Sweeney's Maze + + // LIES + create_type("lies_emitter", 60, 6, 2, 32, 32); + create_type("lies", 63, 6, 100, 26, 10); + create_type("lies_collector", 62, 6, 100, 32, 32); + + // Factory + create_type("factory_emitter", 72, 6, 3, 64, 40); + create_type("factory_clouds", 76, 6, 100, 32, 12); + create_type("factory_collector", 77, 6, 100, 32, 16); + + // Elephant + create_type("elephant", 0, 102, 0, 464, 320); +} + +void entityclass::set_enemy_type(entclass* entity, const char* type) +{ + if (enemy_types.count(type) > 0) + { + EnemyType* enemyType = &enemy_types[type]; + entity->tile = enemyType->tile; + entity->colour = enemyType->colour; + entity->animate = enemyType->animate; + entity->w = enemyType->width; + entity->h = enemyType->height; + } +} + +const char* entityclass::legacy_id_to_entity(const int id) +{ + switch (id) + { + case 0: + return "square"; + case 1: + return "circle"; + case 2: + return "disc"; + case 3: + return "glitch"; + case 4: + return "coin"; + case 5: + return "cross"; + case 6: + return "triangle"; + case 7: + return "ice"; + case 8: + return "heart"; + case 9: + return "broken_heart"; + default: + return "square"; + } } void entityclass::resetallflags(void) @@ -1371,16 +1483,6 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.setenemy(1); entity.setenemyroom(game.roomx, game.roomy); //For colour } - else if (game.roomx == 113 && game.roomy == 107) - { - //MAVVERRRICK - entity.tile = 96; - entity.colour = 6; - entity.size = 9; - entity.w = 64; - entity.h = 44; - entity.animate = 4; - } else { entity.setenemyroom(game.roomx, game.roomy); @@ -2112,19 +2214,8 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.harmful = true; - switch(customenemy){ - case 0: entity.setenemyroom(4+100, 0+100); break; - case 1: entity.setenemyroom(2+100, 0+100); break; - case 2: entity.setenemyroom(12+100, 3+100); break; - case 3: entity.setenemyroom(13+100, 12+100); break; - case 4: entity.setenemyroom(16+100, 9+100); break; - case 5: entity.setenemyroom(19+100, 1+100); break; - case 6: entity.setenemyroom(19+100, 2+100); break; - case 7: entity.setenemyroom(18+100, 3+100); break; - case 8: entity.setenemyroom(16+100, 0+100); break; - case 9: entity.setenemyroom(14+100, 2+100); break; - default: entity.setenemyroom(4+100, 0+100); break; - } + const char* type = legacy_id_to_entity(customenemy); + set_enemy_type(&entity, type); //Set colour based on room tile //Set custom colours diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index 796918b304..2d6477b1de 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -1,6 +1,7 @@ #ifndef ENTITY_H #define ENTITY_H +#include #include #include #include @@ -32,11 +33,25 @@ enum TELEPORTER = 102 }; +struct EnemyType +{ + int tile; + int colour; + int animate; + int width; + int height; +}; + class entityclass { public: void init(void); + void create_type(const char* type, int tile, int colour, int animate, int width, int height); + void add_default_types(void); + const char* legacy_id_to_entity(int id); + void set_enemy_type(entclass* entity, const char* type); + void resetallflags(void); void fatal_top(void) @@ -200,6 +215,8 @@ class entityclass std::string customactivitycolour; std::string customactivitytext; int customactivitypositiony; + + std::map enemy_types; }; #ifndef OBJ_DEFINITION From 3e4079a0d207e907a54a6d68630be6a1b672122f Mon Sep 17 00:00:00 2001 From: AllyTally Date: Fri, 1 Sep 2023 23:52:35 -0300 Subject: [PATCH 02/12] Move more properties to enemy types This should keep most of the mess outside of `setenemyroom`, however `setenemy` still has a few variables I don't know how to tackle. --- desktop_version/src/Ent.cpp | 34 ---------------- desktop_version/src/Entity.cpp | 72 +++++++++++++++++++++++++++------- desktop_version/src/Entity.h | 8 +++- 3 files changed, 65 insertions(+), 49 deletions(-) diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index ca32d61a03..f59dd08b81 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -113,14 +113,10 @@ void entclass::setenemy( int t ) break; case 1: obj.set_enemy_type(this, "lies"); - yp += 10; - lerpoldyp += 10; behave = 11; para = 9; // destroyed when outside x1 = -200; x2 = 400; - cx = 1; - cy = 1; break; case 2: obj.set_enemy_type(this, "lies_collector"); @@ -134,22 +130,13 @@ void entclass::setenemy( int t ) { case 0: obj.set_enemy_type(this, "factory_emitter"); - size = 9; behave = 12; - cx = 0; - cy = 24; break; case 1: obj.set_enemy_type(this, "factory_clouds"); - xp += 4; - lerpoldxp += 4; - yp -= 4; - lerpoldyp -= 4; behave = 13; para = -6; //destroyed when outside x2 = 400; - cx = 0; - cy = 6; break; case 2: obj.set_enemy_type(this, "factory_collector"); @@ -186,26 +173,15 @@ void entclass::setenemyroom( int rx, int ry ) obj.set_enemy_type(this, "guard"); break; case rn(13, 4): //Communication Station - harmful = false; if (xp == 256) { //transmittor obj.set_enemy_type(this, "transmitter"); - xp -= 24; - lerpoldxp -= 24; - yp -= 16; - lerpoldyp -= 16; } else { //radar dish obj.set_enemy_type(this, "radar"); - cx = 4; - size = 9; - xp -= 4; - lerpoldxp -= 4; - yp -= 32; - lerpoldyp -= 32; } break; @@ -234,15 +210,12 @@ void entclass::setenemyroom( int rx, int ry ) break; //Factory case rn(13,7): // MAVVERRRICK obj.set_enemy_type(this, "bus"); - size = 9; break; case rn(11, 13): //Truth obj.set_enemy_type(this, "truth"); - size = 10; break; case rn(17, 7): //Brass sent us under the top obj.set_enemy_type(this, "solider"); - cx = 4; break; case rn(10, 7): // (deception) obj.set_enemy_type(this, "bowtie"); @@ -265,13 +238,9 @@ void entclass::setenemyroom( int rx, int ry ) //Warp Zone case rn(15, 2): // (numbers) obj.set_enemy_type(this, "numbers"); - yp += 1; - lerpoldyp += 1; break; case rn(16, 2): // (Manequins) obj.set_enemy_type(this, "mannequin"); - yp -= 4; - lerpoldyp -= 4; break; case rn(18, 0): // (Obey) obj.set_enemy_type(this, "obey"); @@ -303,7 +272,6 @@ void entclass::setenemyroom( int rx, int ry ) break; case rn(18, 2): // Thinking with Portals //depends on direction - size = 10; if (xp == 88) { obj.set_enemy_type(this, "centipede_right"); @@ -347,8 +315,6 @@ void entclass::setenemyroom( int rx, int ry ) case rn(11, 8): case rn(12, 8): obj.set_enemy_type(this, "elephant"); - size = 11; - harmful = false; break; } } diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 1c5f1c1c29..151f6c6613 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -105,7 +105,7 @@ void entityclass::init(void) add_default_types(); } -void entityclass::create_type(const char* type, int tile, int colour, int animate, int width, int height) +EnemyType* entityclass::create_type(const char* type, int tile, int colour, int animate, int width, int height) { EnemyType enemy_type; enemy_type.tile = tile; @@ -113,12 +113,21 @@ void entityclass::create_type(const char* type, int tile, int colour, int animat enemy_type.animate = animate; enemy_type.width = width; enemy_type.height = height; + enemy_type.harmful = true; + enemy_type.corner_x = 0; + enemy_type.corner_y = 0; + enemy_type.x_offset = 0; + enemy_type.y_offset = 0; + enemy_type.size = 0; enemy_types[type] = enemy_type; + return &enemy_types[type]; } void entityclass::add_default_types(void) { + EnemyType* type; + create_type("square", 78, 7, 1, 16, 16); // Vibrating String Problem create_type("circle", 88, 11, 1, 16, 16); // Kids His Age Bounce create_type("disc", 36, 8, 1, 16, 16); // Security Sweep @@ -136,39 +145,66 @@ void entityclass::add_default_types(void) create_type("wavelength", 32, 7, 1, 32, 16); // Linear Collider create_type("stop", 28, 6, 1, 22, 32); // Traffic Jam create_type("yes", 40, 9, 1, 20, 20); // The Yes Men - create_type("bus", 96, 6, 4, 64, 44); // B-B-B-Busted create_type("vertigo", 172, 7, 100, 32, 32); // Vertigo create_type("guard", 44, 8, 1, 16, 20); // Trench Warfare - create_type("truth", 64, 7, 100, 44, 10); // Boldly To Go create_type("obey", 51, 11, 100, 30, 14); // Time to get serious - create_type("mannequin", 52, 7, 5, 16, 25); // Short Circuit - create_type("numbers", 100, 6, 1, 32, 14); // Take the Red Pill create_type("ghost", 106, 7, 2, 24, 25); // The Tomb of Mad Carew create_type("wheel", 116, 12, 1, 32, 32); // The Hanged Man, Reversed create_type("skeleton", 56, 6, 1, 15, 24); // You Chose... Poorly - create_type("solider", 82, 8, 5, 28, 32); // Brass Sent Us Under The Top - create_type("transmitter", 104, 4, 7, 16, 16); // Comms Relay - create_type("radar", 124, 4, 6, 32, 32); // Comms Relay + type = create_type("mannequin", 52, 7, 5, 16, 25); // Short Circuit + type->y_offset = -4; + type = create_type("numbers", 100, 6, 1, 32, 14); // Take the Red Pill + type->y_offset = 1; + type = create_type("solider", 82, 8, 5, 28, 32); // Brass Sent Us Under The Top + type->corner_x = 4; + type = create_type("truth", 64, 7, 100, 44, 10); // Boldly To Go + type->size = 10; + type = create_type("bus", 96, 6, 4, 64, 44); // B-B-B-Busted + type->size = 9; + + type = create_type("transmitter", 104, 4, 7, 16, 16); // Comms Relay + type->harmful = false; + type->x_offset = -24; + type->y_offset = -16; + + type = create_type("radar", 124, 4, 6, 32, 32); // Comms Relay + type->harmful = false; + type->x_offset = -4; + type->y_offset = -32; + type->corner_x = 4; + type->size = 9; create_type("edgegames_left", 160, 8, 1, 16, 16); // Edge Games create_type("edgegames_right", 156, 8, 1, 16, 16); // Edge Games - create_type("centipede_right", 66, 12, 100, 60, 16); // Sweeney's Maze - create_type("centipede_left", 54, 12, 100, 60, 16); // Sweeney's Maze + type = create_type("centipede_right", 66, 12, 100, 60, 16); // Sweeney's Maze + type->size = 10; + type = create_type("centipede_left", 54, 12, 100, 60, 16); // Sweeney's Maze + type->size = 10; // LIES create_type("lies_emitter", 60, 6, 2, 32, 32); - create_type("lies", 63, 6, 100, 26, 10); + type = create_type("lies", 63, 6, 100, 26, 10); + type->corner_x = 1; + type->corner_y = 1; + type->y_offset = 10; create_type("lies_collector", 62, 6, 100, 32, 32); // Factory - create_type("factory_emitter", 72, 6, 3, 64, 40); - create_type("factory_clouds", 76, 6, 100, 32, 12); + type = create_type("factory_emitter", 72, 6, 3, 64, 40); + type->corner_y = 24; + type->size = 9; + type = create_type("factory_clouds", 76, 6, 100, 32, 12); + type->corner_y = 6; + type->x_offset = 4; + type->y_offset = -4; create_type("factory_collector", 77, 6, 100, 32, 16); // Elephant - create_type("elephant", 0, 102, 0, 464, 320); + type = create_type("elephant", 0, 102, 0, 464, 320); + type->size = 11; + type->harmful = false; } void entityclass::set_enemy_type(entclass* entity, const char* type) @@ -181,6 +217,14 @@ void entityclass::set_enemy_type(entclass* entity, const char* type) entity->animate = enemyType->animate; entity->w = enemyType->width; entity->h = enemyType->height; + entity->harmful = enemyType->harmful; + entity->cx = enemyType->corner_x; + entity->cy = enemyType->corner_y; + entity->xp += enemyType->x_offset; + entity->lerpoldxp += enemyType->x_offset; + entity->yp += enemyType->y_offset; + entity->lerpoldyp += enemyType->y_offset; + entity->size = enemyType->size; } } diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index 2d6477b1de..0b35777d3a 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -40,6 +40,12 @@ struct EnemyType int animate; int width; int height; + int harmful; + int corner_x; + int corner_y; + int x_offset; + int y_offset; + int size; }; class entityclass @@ -47,7 +53,7 @@ class entityclass public: void init(void); - void create_type(const char* type, int tile, int colour, int animate, int width, int height); + EnemyType* create_type(const char* type, int tile, int colour, int animate, int width, int height); void add_default_types(void); const char* legacy_id_to_entity(int id); void set_enemy_type(entclass* entity, const char* type); From baf76cb78e33ef6e603f74680f17a4fcff9dfa81 Mon Sep 17 00:00:00 2001 From: AllyTally Date: Sat, 2 Sep 2023 10:44:38 -0300 Subject: [PATCH 03/12] Move rest of enemy properties out of `setenemy` There's now variables in the struct to override certain properties. --- desktop_version/src/Ent.cpp | 12 ------- desktop_version/src/Entity.cpp | 66 ++++++++++++++++++++++++++++++++-- desktop_version/src/Entity.h | 12 +++++++ 3 files changed, 75 insertions(+), 15 deletions(-) diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index f59dd08b81..0ec8aa088d 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -108,19 +108,12 @@ void entclass::setenemy( int t ) { case 0: obj.set_enemy_type(this, "lies_emitter"); - behave = 10; - x1 = -200; break; case 1: obj.set_enemy_type(this, "lies"); - behave = 11; - para = 9; // destroyed when outside - x1 = -200; - x2 = 400; break; case 2: obj.set_enemy_type(this, "lies_collector"); - behave = -1; break; } break; @@ -130,17 +123,12 @@ void entclass::setenemy( int t ) { case 0: obj.set_enemy_type(this, "factory_emitter"); - behave = 12; break; case 1: obj.set_enemy_type(this, "factory_clouds"); - behave = 13; - para = -6; //destroyed when outside - x2 = 400; break; case 2: obj.set_enemy_type(this, "factory_collector"); - behave = -1; break; } break; diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 151f6c6613..903a7ba2d5 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -119,6 +119,12 @@ EnemyType* entityclass::create_type(const char* type, int tile, int colour, int enemy_type.x_offset = 0; enemy_type.y_offset = 0; enemy_type.size = 0; + enemy_type.override_behave = false; + enemy_type.override_para = false; + enemy_type.override_x1 = false; + enemy_type.override_x2 = false; + enemy_type.override_y1 = false; + enemy_type.override_y2 = false; enemy_types[type] = enemy_type; return &enemy_types[type]; @@ -184,22 +190,46 @@ void entityclass::add_default_types(void) type->size = 10; // LIES - create_type("lies_emitter", 60, 6, 2, 32, 32); + type = create_type("lies_emitter", 60, 6, 2, 32, 32); + type->behave = 10; + type->x1 = -200; + type->override_behave = true; + type->override_x1 = true; type = create_type("lies", 63, 6, 100, 26, 10); type->corner_x = 1; type->corner_y = 1; type->y_offset = 10; - create_type("lies_collector", 62, 6, 100, 32, 32); + type->behave = 11; + type->para = 9; + type->x1 = -200; + type->x2 = 400; + type->override_behave = true; + type->override_para = true; + type->override_x1 = true; + type->override_x2 = true; + type = create_type("lies_collector", 62, 6, 100, 32, 32); + type->behave = -1; + type->override_behave = true; // Factory type = create_type("factory_emitter", 72, 6, 3, 64, 40); type->corner_y = 24; type->size = 9; + type->behave = 12; + type->override_behave = true; type = create_type("factory_clouds", 76, 6, 100, 32, 12); type->corner_y = 6; type->x_offset = 4; type->y_offset = -4; - create_type("factory_collector", 77, 6, 100, 32, 16); + type->behave = 13; + type->para = -6; + type->x2 = 400; + type->override_behave = true; + type->override_para = true; + type->override_x2 = true; + type = create_type("factory_collector", 77, 6, 100, 32, 16); + type->behave = -1; + type->override_behave = true; // Elephant type = create_type("elephant", 0, 102, 0, 464, 320); @@ -225,6 +255,36 @@ void entityclass::set_enemy_type(entclass* entity, const char* type) entity->yp += enemyType->y_offset; entity->lerpoldyp += enemyType->y_offset; entity->size = enemyType->size; + + if (enemyType->override_behave) + { + entity->behave = enemyType->behave; + } + + if (enemyType->override_para) + { + entity->para = enemyType->para; + } + + if (enemyType->override_x1) + { + entity->x1 = enemyType->x1; + } + + if (enemyType->override_x2) + { + entity->x2 = enemyType->x2; + } + + if (enemyType->override_y1) + { + entity->y1 = enemyType->y1; + } + + if (enemyType->override_y2) + { + entity->y2 = enemyType->y2; + } } } diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index 0b35777d3a..e36d77f1d4 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -46,6 +46,18 @@ struct EnemyType int x_offset; int y_offset; int size; + int behave; + bool override_behave; + int para; + bool override_para; + int x1; + bool override_x1; + int x2; + bool override_x2; + int y1; + bool override_y1; + int y2; + bool override_y2; }; class entityclass From 3aca47e8904434e8347e0aca54364325b9fffb80 Mon Sep 17 00:00:00 2001 From: AllyTally Date: Sat, 2 Sep 2023 11:23:27 -0300 Subject: [PATCH 04/12] Remove `entityclonefix` in favor of improving emitters Emitters are odd. They rely on `setenemy` to set the right type of the entities they emit. However, `setenemy` only gets called in specific rooms, so if you use these enemy types outside of those rooms, they'd just infinitely spawn themselves and, well, that's a memory leak. The prior fix for this was simply not allowing emitter types outside of those rooms. This, however, feels very hacky and is a little disappointing as well. This commit improves emitters by no longer relying on `setenemy`, and instead setting the emitted enemy type ourselves. However, `setenemy` still happens, and to make sure we don't set the enemy type *twice*, we set the `para` attribute of the spawned enemies to `-1`, so that `setenemy` will not do anything at all to the spawned enemy. The reason I don't remove the code in `setenemy` outright is a couple things: - The main game code still relies on it for spawning the initial enemies in the room - Custom levels may rely on the prior behavior (sadly) --- desktop_version/src/Entity.cpp | 225 +++++++++++++++------------------ desktop_version/src/Entity.h | 12 +- 2 files changed, 111 insertions(+), 126 deletions(-) diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 903a7ba2d5..41eca0ee65 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -239,6 +239,11 @@ void entityclass::add_default_types(void) void entityclass::set_enemy_type(entclass* entity, const char* type) { + if (entity == NULL) + { + return; + } + if (enemy_types.count(type) > 0) { EnemyType* enemyType = &enemy_types[type]; @@ -1446,33 +1451,7 @@ static bool gridmatch( int p1, int p2, int p3, int p4, int p11, int p21, int p31 return false; } -static void entityclonefix(entclass* entity) -{ - const bool is_lies_emitter = entity->behave == 10; - const bool is_factory_emitter = entity->behave == 12; - - const bool is_emitter = is_lies_emitter || is_factory_emitter; - if (!is_emitter) - { - return; - } - - const bool in_lies_emitter_room = - game.roomx >= 113 && game.roomx <= 117 && game.roomy == 111; - const bool in_factory_emitter_room = - game.roomx == 113 && game.roomy >= 108 && game.roomy <= 110; - - const bool valid = (is_lies_emitter && in_lies_emitter_room) - || (is_factory_emitter && in_factory_emitter_room); - - if (!valid) - { - /* Fix memory leak */ - entity->behave = -1; - } -} - -void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int p1, int p2, int p3, int p4) +entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int p1, int p2, int p3, int p4) { k = entities.size(); @@ -1590,7 +1569,6 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int else { entity.setenemyroom(game.roomx, game.roomy); - entityclonefix(&entity); } break; case 2: //A moving platform @@ -1750,7 +1728,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int //Check if it's already been collected entity.para = meta1; - if (!INBOUNDS_ARR(meta1, collect) || collect[meta1]) return; + if (!INBOUNDS_ARR(meta1, collect) || collect[meta1]) return NULL; break; case 9: //Something Shiny entity.rule = 3; @@ -1765,7 +1743,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int //Check if it's already been collected entity.para = meta1; - if (!INBOUNDS_ARR(meta1, collect) || collect[meta1]) return; + if (!INBOUNDS_ARR(meta1, collect) || collect[meta1]) return NULL; break; case 10: //Savepoint entity.rule = 3; @@ -1787,7 +1765,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int if (game.nodeathmode) { - return; + return NULL; } break; case 11: //Horizontal Gravity Line @@ -1961,7 +1939,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int //Check if it's already been collected entity.para = meta1; - if (INBOUNDS_ARR(meta1, collect) && !collect[meta1]) return; + if (INBOUNDS_ARR(meta1, collect) && !collect[meta1]) return NULL; break; case 23: //SWN Enemies //Given a different behavior, these enemies are especially for SWN mode and disappear outside the screen. @@ -2273,7 +2251,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int map.warpy = false; } break; - case 55: // Crew Member (custom, collectable) + case 55: // Crew Member (custom, collectable) //1 - position in array //2 - colour entity.rule = 3; @@ -2299,75 +2277,75 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int //Check if it's already been collected entity.para = meta1; - if (!INBOUNDS_ARR(meta1, customcollect) || customcollect[meta1]) return; + if (!INBOUNDS_ARR(meta1, customcollect) || customcollect[meta1]) return NULL; break; - case 56: //Custom enemy - entity.rule = 1; - entity.type = EntityType_MOVING; - entity.behave = meta1; - entity.para = meta2; - entity.w = 16; - entity.h = 16; - entity.cx = 0; - entity.cy = 0; - - entity.x1 = p1; - entity.y1 = p2; - entity.x2 = p3; - entity.y2 = p4; - - entity.harmful = true; - - const char* type = legacy_id_to_entity(customenemy); - set_enemy_type(&entity, type); - - //Set colour based on room tile - //Set custom colours - if(customplatformtile>0){ - int entcol=(customplatformtile/12); - switch(entcol){ - //RED - case 3: case 7: case 12: case 23: case 28: - case 34: case 42: case 48: case 58: - entity.colour = 6; break; - //GREEN - case 5: case 9: case 22: case 25: case 29: - case 31: case 38: case 46: case 52: case 53: - entity.colour = 7; break; - //BLUE - case 1: case 6: case 14: case 27: case 33: - case 44: case 50: case 57: - entity.colour = 12; break; - //YELLOW - case 4: case 17: case 24: case 30: case 37: - case 45: case 51: case 55: - entity.colour = 9; break; - //PURPLE - case 2: case 11: case 15: case 19: case 32: - case 36: case 49: - entity.colour = 20; break; - //CYAN - case 8: case 10: case 13: case 18: case 26: - case 35: case 41: case 47: case 54: - entity.colour = 11; break; - //PINK - case 16: case 20: case 39: case 43: case 56: - entity.colour = 8; break; - //ORANGE - case 21: case 40: - entity.colour = 17; break; - default: - entity.colour = 6; - break; + case 56: //Custom enemy + { + entity.rule = 1; + entity.type = EntityType_MOVING; + entity.behave = meta1; + entity.para = meta2; + entity.w = 16; + entity.h = 16; + entity.cx = 0; + entity.cy = 0; + + entity.x1 = p1; + entity.y1 = p2; + entity.x2 = p3; + entity.y2 = p4; + + entity.harmful = true; + + const char* type = legacy_id_to_entity(customenemy); + set_enemy_type(&entity, type); + + //Set colour based on room tile + //Set custom colours + if (customplatformtile > 0) { + int entcol = (customplatformtile / 12); + switch (entcol) { + //RED + case 3: case 7: case 12: case 23: case 28: + case 34: case 42: case 48: case 58: + entity.colour = 6; break; + //GREEN + case 5: case 9: case 22: case 25: case 29: + case 31: case 38: case 46: case 52: case 53: + entity.colour = 7; break; + //BLUE + case 1: case 6: case 14: case 27: case 33: + case 44: case 50: case 57: + entity.colour = 12; break; + //YELLOW + case 4: case 17: case 24: case 30: case 37: + case 45: case 51: case 55: + entity.colour = 9; break; + //PURPLE + case 2: case 11: case 15: case 19: case 32: + case 36: case 49: + entity.colour = 20; break; + //CYAN + case 8: case 10: case 13: case 18: case 26: + case 35: case 41: case 47: case 54: + entity.colour = 11; break; + //PINK + case 16: case 20: case 39: case 43: case 56: + entity.colour = 8; break; + //ORANGE + case 21: case 40: + entity.colour = 17; break; + default: + entity.colour = 6; + break; + } } - } - if(custom_gray){ - entity.colour = 18; - } - - entityclonefix(&entity); - break; + if (custom_gray) { + entity.colour = 18; + } + break; + } case 100: // Invalid enemy, but gets treated as a teleporter entity.type = EntityType_TELEPORTER; break; @@ -2382,48 +2360,51 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entities.push_back(entity); } + size_t indice; + if (reuse) + { + indice = entptr - entities.data(); + } + else + { + indice = entities.size() - 1; + } + /* Fix crewmate facing directions * This is a bit kludge-y but it's better than copy-pasting * and is okay to do because entity 12 does not change state on its own */ if (entity.type == EntityType_CREWMATE) { - size_t indice; - if (reuse) - { - indice = entptr - entities.data(); - } - else - { - indice = entities.size() - 1; - } updateentities(indice); } + + return &entities[indice]; } -void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int p1, int p2) +entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int p1, int p2) { - createentity(xp, yp, t, meta1, meta2, p1, p2, 320, 240); + return createentity(xp, yp, t, meta1, meta2, p1, p2, 320, 240); } -void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int p1) +entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int p1) { - createentity(xp, yp, t, meta1, meta2, p1, 0); + return createentity(xp, yp, t, meta1, meta2, p1, 0); } -void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2) +entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2) { - createentity(xp, yp, t, meta1, meta2, 0); + return createentity(xp, yp, t, meta1, meta2, 0); } -void entityclass::createentity(int xp, int yp, int t, int meta1) +entclass* entityclass::createentity(int xp, int yp, int t, int meta1) { - createentity(xp, yp, t, meta1, 0); + return createentity(xp, yp, t, meta1, 0); } -void entityclass::createentity(int xp, int yp, int t) +entclass* entityclass::createentity(int xp, int yp, int t) { - createentity(xp, yp, t, 0); + return createentity(xp, yp, t, 0); } //Returns true if entity is removed @@ -2600,7 +2581,9 @@ bool entityclass::updateentities( int i ) //Emitter: shoot an enemy every so often if (entities[i].state == 0) { - createentity(entities[i].xp+28, entities[i].yp, 1, 10, 1); + entclass* entity = createentity(entities[i].xp+28, entities[i].yp, 1, 10, -1); + set_enemy_type(entity, "lies"); + entity->setenemyroom(game.roomx, game.roomy); // For the color entities[i].state = 1; entities[i].statedelay = 12; } @@ -2635,7 +2618,9 @@ bool entityclass::updateentities( int i ) //Emitter: shoot an enemy every so often (up) if (entities[i].state == 0) { - createentity(entities[i].xp, entities[i].yp, 1, 12, 1); + entclass* entity = createentity(entities[i].xp, entities[i].yp, 1, 12, -1); + set_enemy_type(entity, "factory_clouds"); + entity->setenemyroom(game.roomx, game.roomy); // For the color entities[i].state = 1; entities[i].statedelay = 16; } diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index e36d77f1d4..582efc0c95 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -115,15 +115,15 @@ class entityclass void revertlinecross(std::vector& linecrosskludge, int t, int s); - void createentity(int xp, int yp, int t, int meta1, int meta2, + entclass* createentity(int xp, int yp, int t, int meta1, int meta2, int p1, int p2, int p3, int p4); - void createentity(int xp, int yp, int t, int meta1, int meta2, + entclass* createentity(int xp, int yp, int t, int meta1, int meta2, int p1, int p2); - void createentity(int xp, int yp, int t, int meta1, int meta2, + entclass* createentity(int xp, int yp, int t, int meta1, int meta2, int p1); - void createentity(int xp, int yp, int t, int meta1, int meta2); - void createentity(int xp, int yp, int t, int meta1); - void createentity(int xp, int yp, int t); + entclass* createentity(int xp, int yp, int t, int meta1, int meta2); + entclass* createentity(int xp, int yp, int t, int meta1); + entclass* createentity(int xp, int yp, int t); bool updateentities(int i); From 333524533d6fca16babbe86abd245f2c74a58e1f Mon Sep 17 00:00:00 2001 From: AllyTally Date: Sat, 2 Sep 2023 11:04:48 -0300 Subject: [PATCH 05/12] Add `set_enemy_colour` There's a few cases in `setenemyroom` which are only meant to override the enemy colour set in the type, so let's move that to it's own function instead. While we're at it, we should move the custom level enemy color logic there as well, because it's in an awkward place. This will also help with things like custom enemy types in the future, or using things like the emitters in custom levels, because this will correct those colors in custom levels. --- desktop_version/src/Ent.cpp | 15 --- desktop_version/src/Entity.cpp | 210 +++++++++++++++++++++++---------- desktop_version/src/Entity.h | 1 + 3 files changed, 149 insertions(+), 77 deletions(-) diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index 0ec8aa088d..80086ea017 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -181,21 +181,6 @@ void entclass::setenemyroom( int rx, int ry ) obj.set_enemy_type(this, "circle"); break; //Space Station 2 - case rn(14, 11): - colour = 17; - break; //Lies - case rn(16, 11): - colour = 8; - break; //Lies - case rn(13, 10): - colour = 11; - break; //Factory - case rn(13, 9): - colour = 9; - break; //Factory - case rn(13, 8): - colour = 8; - break; //Factory case rn(13,7): // MAVVERRRICK obj.set_enemy_type(this, "bus"); break; diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 41eca0ee65..c4034fb057 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -248,7 +248,6 @@ void entityclass::set_enemy_type(entclass* entity, const char* type) { EnemyType* enemyType = &enemy_types[type]; entity->tile = enemyType->tile; - entity->colour = enemyType->colour; entity->animate = enemyType->animate; entity->w = enemyType->width; entity->h = enemyType->height; @@ -261,6 +260,11 @@ void entityclass::set_enemy_type(entclass* entity, const char* type) entity->lerpoldyp += enemyType->y_offset; entity->size = enemyType->size; + if (enemyType->colour != -1) + { + entity->colour = enemyType->colour; + } + if (enemyType->override_behave) { entity->behave = enemyType->behave; @@ -322,6 +326,144 @@ const char* entityclass::legacy_id_to_entity(const int id) } } +void entityclass::set_enemy_colour(entclass* entity) +{ + if (entity == NULL) + { + return; + } + + // For custom levels, color should be based on the room + if (customplatformtile > 0) { + // Special case for gray Warp Zone tileset! + const RoomProperty* const room = cl.getroomprop(game.roomx - 100, game.roomy - 100); + if (room->tileset == 3 && room->tilecol == 6) + { + entity->colour = 18; + return; + } + + int entcol = (customplatformtile / 12); + switch (entcol) { + // RED + case 3: + case 7: + case 12: + case 23: + case 28: + case 34: + case 42: + case 48: + case 58: + entity->colour = 6; + break; + //GREEN + case 5: + case 9: + case 22: + case 25: + case 29: + case 31: + case 38: + case 46: + case 52: + case 53: + entity->colour = 7; + break; + // BLUE + case 1: + case 6: + case 14: + case 27: + case 33: + case 44: + case 50: + case 57: + entity->colour = 12; + break; + // YELLOW + case 4: + case 17: + case 24: + case 30: + case 37: + case 45: + case 51: + case 55: + entity->colour = 9; + break; + // PURPLE + case 2: + case 11: + case 15: + case 19: + case 32: + case 36: + case 49: + entity->colour = 20; + break; + // CYAN + case 8: + case 10: + case 13: + case 18: + case 26: + case 35: + case 41: + case 47: + case 54: + entity->colour = 11; + break; + // PINK + case 16: + case 20: + case 39: + case 43: + case 56: + entity->colour = 8; + break; + // ORANGE + case 21: + case 40: + entity->colour = 17; + break; + default: + entity->colour = 6; + break; + } + } + else + { + /* Okay, so we're not in a custom level. + * Most colors are stored in the enemy type themselves, + * because each enemy is pretty much only in a single room. + * There's some special cases, though, like LIES and factory clouds, + * so let's correct their colors to match the rooms. + */ + + switch (rn(game.roomx - 100, game.roomy - 100)) + { + // First, adjust the color of the LIES enemies + case rn(14, 11): + entity->colour = 17; + break; + case rn(16, 11): + entity->colour = 8; + break; + // Then, the factory enemies + case rn(13, 10): + entity->colour = 11; + break; + case rn(13, 9): + entity->colour = 9; + break; + case rn(13, 8): + entity->colour = 8; + break; + } + } +} + void entityclass::resetallflags(void) { SDL_memset(flags, false, sizeof(flags)); @@ -1498,18 +1640,6 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, //Rule 4 is a horizontal line, 5 is vertical //Rule 6 is a crew member - bool custom_gray; - // Special case for gray Warp Zone tileset! - if (map.custommode) - { - const RoomProperty* const room = cl.getroomprop(game.roomx - 100, game.roomy - 100); - custom_gray = room->tileset == 3 && room->tilecol == 6; - } - else - { - custom_gray = false; - } - entclass& entity = *entptr; entity.xp = xp; entity.yp = yp; @@ -1559,12 +1689,12 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, if (game.roomy == 111 && (game.roomx >= 113 && game.roomx <= 117)) { entity.setenemy(0); - entity.setenemyroom(game.roomx, game.roomy); //For colour + set_enemy_colour(&entity); } else if (game.roomx == 113 && (game.roomy <= 110 && game.roomy >= 108)) { entity.setenemy(1); - entity.setenemyroom(game.roomx, game.roomy); //For colour + set_enemy_colour(&entity); } else { @@ -2299,51 +2429,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, const char* type = legacy_id_to_entity(customenemy); set_enemy_type(&entity, type); - - //Set colour based on room tile - //Set custom colours - if (customplatformtile > 0) { - int entcol = (customplatformtile / 12); - switch (entcol) { - //RED - case 3: case 7: case 12: case 23: case 28: - case 34: case 42: case 48: case 58: - entity.colour = 6; break; - //GREEN - case 5: case 9: case 22: case 25: case 29: - case 31: case 38: case 46: case 52: case 53: - entity.colour = 7; break; - //BLUE - case 1: case 6: case 14: case 27: case 33: - case 44: case 50: case 57: - entity.colour = 12; break; - //YELLOW - case 4: case 17: case 24: case 30: case 37: - case 45: case 51: case 55: - entity.colour = 9; break; - //PURPLE - case 2: case 11: case 15: case 19: case 32: - case 36: case 49: - entity.colour = 20; break; - //CYAN - case 8: case 10: case 13: case 18: case 26: - case 35: case 41: case 47: case 54: - entity.colour = 11; break; - //PINK - case 16: case 20: case 39: case 43: case 56: - entity.colour = 8; break; - //ORANGE - case 21: case 40: - entity.colour = 17; break; - default: - entity.colour = 6; - break; - } - } - - if (custom_gray) { - entity.colour = 18; - } + set_enemy_colour(&entity); break; } case 100: // Invalid enemy, but gets treated as a teleporter @@ -2583,7 +2669,7 @@ bool entityclass::updateentities( int i ) { entclass* entity = createentity(entities[i].xp+28, entities[i].yp, 1, 10, -1); set_enemy_type(entity, "lies"); - entity->setenemyroom(game.roomx, game.roomy); // For the color + set_enemy_colour(entity); entities[i].state = 1; entities[i].statedelay = 12; } @@ -2620,7 +2706,7 @@ bool entityclass::updateentities( int i ) { entclass* entity = createentity(entities[i].xp, entities[i].yp, 1, 12, -1); set_enemy_type(entity, "factory_clouds"); - entity->setenemyroom(game.roomx, game.roomy); // For the color + set_enemy_colour(entity); entities[i].state = 1; entities[i].statedelay = 16; } diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index 582efc0c95..6e85374519 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -69,6 +69,7 @@ class entityclass void add_default_types(void); const char* legacy_id_to_entity(int id); void set_enemy_type(entclass* entity, const char* type); + void set_enemy_colour(entclass* entity); void resetallflags(void); From 5409f0715f7b212f54b5dde0534b22a6397ba9a7 Mon Sep 17 00:00:00 2001 From: AllyTally Date: Sat, 2 Sep 2023 13:04:41 -0300 Subject: [PATCH 06/12] Modify how enemy colors are set While the last commit was an attempt at making colors be set better, this one should help more. Basically, things that emitters emit now copy the emitter's color. That means, if you change the color of the emitter, what it emits will change as well. This means we don't have to worry about setting the colour ourselves, just the enemy type. `set_enemy_colour` is now called BEFORE setting the type, so the type's color will override the room color. This is what we want -- in the future there might be custom enemy types, and if you specify a specific color, you probably want that color to be used. But wait, don't the types usable in levels have their colors set? Well, this commit also duplicates the editor enemy types and sets their colors to `-1` so they'll use the room's color instead, or more accurately, they'll use the color they had previously, which was the room's enemy color. With this system, old levels which use main game enemies will have the correct colors -- the colors stored in their enemy types. And if it becomes possible to make custom enemy types, if someone makes an emitter which uses the room's color (by passing in color `-1`), the enemies which it emits will use the room's color as well, since it will copy what the emitter itself uses. All of that just to say: colors are now handled a bit more sanely. --- desktop_version/src/Entity.cpp | 135 ++++++++++++++++++--------------- desktop_version/src/Entity.h | 1 + 2 files changed, 74 insertions(+), 62 deletions(-) diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index c4034fb057..8e9f0e7fa3 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -134,6 +134,18 @@ void entityclass::add_default_types(void) { EnemyType* type; + // Copies for the editor, without the color set: + create_type("custom_square", 78, -1, 1, 16, 16); + create_type("custom_circle", 88, -1, 1, 16, 16); + create_type("custom_disc", 36, -1, 1, 16, 16); + create_type("custom_glitch", 164, -1, 1, 16, 16); + create_type("custom_coin", 68, -1, 1, 16, 16); + create_type("custom_cross", 48, -1, 5, 16, 16); + create_type("custom_triangle", 176, -1, 1, 16, 16); + create_type("custom_ice", 168, -1, 1, 16, 16); + create_type("custom_heart", 112, -1, 5, 16, 16); + create_type("custom_broken_heart", 114, -1, 5, 16, 16); + create_type("square", 78, 7, 1, 16, 16); // Vibrating String Problem create_type("circle", 88, 11, 1, 16, 16); // Kids His Age Bounce create_type("disc", 36, 8, 1, 16, 16); // Security Sweep @@ -302,27 +314,27 @@ const char* entityclass::legacy_id_to_entity(const int id) switch (id) { case 0: - return "square"; + return "custom_square"; case 1: - return "circle"; + return "custom_circle"; case 2: - return "disc"; + return "custom_disc"; case 3: - return "glitch"; + return "custom_glitch"; case 4: - return "coin"; + return "custom_coin"; case 5: - return "cross"; + return "custom_cross"; case 6: - return "triangle"; + return "custom_triangle"; case 7: - return "ice"; + return "custom_ice"; case 8: - return "heart"; + return "custom_heart"; case 9: - return "broken_heart"; + return "custom_broken_heart"; default: - return "square"; + return "custom_square"; } } @@ -432,35 +444,35 @@ void entityclass::set_enemy_colour(entclass* entity) break; } } - else +} + +void entityclass::correct_emitter_colours(entclass* entity) +{ + /* Most colors are stored in the enemy type themselves, + * because each enemy is pretty much only in a single room. + * There's some special cases, though, like LIES and factory clouds, + * so let's correct their colors to match the rooms. + */ + + switch (rn(game.roomx - 100, game.roomy - 100)) { - /* Okay, so we're not in a custom level. - * Most colors are stored in the enemy type themselves, - * because each enemy is pretty much only in a single room. - * There's some special cases, though, like LIES and factory clouds, - * so let's correct their colors to match the rooms. - */ - - switch (rn(game.roomx - 100, game.roomy - 100)) - { - // First, adjust the color of the LIES enemies - case rn(14, 11): - entity->colour = 17; - break; - case rn(16, 11): - entity->colour = 8; - break; + // First, adjust the color of the LIES enemies + case rn(14, 11): + entity->colour = 17; + break; + case rn(16, 11): + entity->colour = 8; + break; // Then, the factory enemies - case rn(13, 10): - entity->colour = 11; - break; - case rn(13, 9): - entity->colour = 9; - break; - case rn(13, 8): - entity->colour = 8; - break; - } + case rn(13, 10): + entity->colour = 11; + break; + case rn(13, 9): + entity->colour = 9; + break; + case rn(13, 8): + entity->colour = 8; + break; } } @@ -1689,12 +1701,12 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, if (game.roomy == 111 && (game.roomx >= 113 && game.roomx <= 117)) { entity.setenemy(0); - set_enemy_colour(&entity); + correct_emitter_colours(&entity); } else if (game.roomx == 113 && (game.roomy <= 110 && game.roomy >= 108)) { entity.setenemy(1); - set_enemy_colour(&entity); + correct_emitter_colours(&entity); } else { @@ -2411,26 +2423,25 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, break; case 56: //Custom enemy { - entity.rule = 1; - entity.type = EntityType_MOVING; - entity.behave = meta1; - entity.para = meta2; - entity.w = 16; - entity.h = 16; - entity.cx = 0; - entity.cy = 0; - - entity.x1 = p1; - entity.y1 = p2; - entity.x2 = p3; - entity.y2 = p4; - - entity.harmful = true; - - const char* type = legacy_id_to_entity(customenemy); - set_enemy_type(&entity, type); - set_enemy_colour(&entity); - break; + entity.rule = 1; + entity.type = EntityType_MOVING; + entity.behave = meta1; + entity.para = meta2; + entity.w = 16; + entity.h = 16; + entity.cx = 0; + entity.cy = 0; + + entity.x1 = p1; + entity.y1 = p2; + entity.x2 = p3; + entity.y2 = p4; + + entity.harmful = true; + + const char* type = legacy_id_to_entity(customenemy); + set_enemy_type(&entity, type); + set_enemy_colour(&entity); } case 100: // Invalid enemy, but gets treated as a teleporter entity.type = EntityType_TELEPORTER; @@ -2669,7 +2680,7 @@ bool entityclass::updateentities( int i ) { entclass* entity = createentity(entities[i].xp+28, entities[i].yp, 1, 10, -1); set_enemy_type(entity, "lies"); - set_enemy_colour(entity); + entity->colour = entities[i].colour; entities[i].state = 1; entities[i].statedelay = 12; } @@ -2706,7 +2717,7 @@ bool entityclass::updateentities( int i ) { entclass* entity = createentity(entities[i].xp, entities[i].yp, 1, 12, -1); set_enemy_type(entity, "factory_clouds"); - set_enemy_colour(entity); + entity->colour = entities[i].colour; entities[i].state = 1; entities[i].statedelay = 16; } diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index 6e85374519..caac02cdb9 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -70,6 +70,7 @@ class entityclass const char* legacy_id_to_entity(int id); void set_enemy_type(entclass* entity, const char* type); void set_enemy_colour(entclass* entity); + void correct_emitter_colours(entclass* entity); void resetallflags(void); From f926ebd08083e38e33488c8857e8283bd2efcaa2 Mon Sep 17 00:00:00 2001 From: AllyTally Date: Sat, 2 Sep 2023 13:56:29 -0300 Subject: [PATCH 07/12] Fix typo (solider -> soldier) --- desktop_version/src/Ent.cpp | 2 +- desktop_version/src/Entity.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index 80086ea017..76727282b3 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -188,7 +188,7 @@ void entclass::setenemyroom( int rx, int ry ) obj.set_enemy_type(this, "truth"); break; case rn(17, 7): //Brass sent us under the top - obj.set_enemy_type(this, "solider"); + obj.set_enemy_type(this, "soldier"); break; case rn(10, 7): // (deception) obj.set_enemy_type(this, "bowtie"); diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 8e9f0e7fa3..b052182782 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -174,7 +174,7 @@ void entityclass::add_default_types(void) type->y_offset = -4; type = create_type("numbers", 100, 6, 1, 32, 14); // Take the Red Pill type->y_offset = 1; - type = create_type("solider", 82, 8, 5, 28, 32); // Brass Sent Us Under The Top + type = create_type("soldier", 82, 8, 5, 28, 32); // Brass Sent Us Under The Top type->corner_x = 4; type = create_type("truth", 64, 7, 100, 44, 10); // Boldly To Go type->size = 10; From 4bf2d23b349eb4e48c2f6930df675dff98e2b7c3 Mon Sep 17 00:00:00 2001 From: AllyTally Date: Sat, 2 Sep 2023 18:18:08 -0300 Subject: [PATCH 08/12] Rename `size` to `render_type`, turn magic numbers into enum --- desktop_version/src/Ent.cpp | 22 +++--- desktop_version/src/Ent.h | 22 +++++- desktop_version/src/Entity.cpp | 101 +++++++++++++------------- desktop_version/src/Entity.h | 2 +- desktop_version/src/Graphics.cpp | 35 ++++----- desktop_version/src/LevelDebugger.cpp | 2 +- desktop_version/src/Logic.cpp | 2 +- desktop_version/src/Map.cpp | 2 +- desktop_version/src/Script.cpp | 11 +-- 9 files changed, 108 insertions(+), 91 deletions(-) diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index 76727282b3..9df8e2c893 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -13,7 +13,7 @@ void entclass::clear(void) { invis = false; type = EntityType_PLAYER; - size = 0; + render_type = EntityRenderType_SPRITE; tile = 0; rule = 0; state = 0; @@ -377,22 +377,22 @@ void entclass::settreadmillcolour( int rx, int ry ) void entclass::updatecolour(void) { - switch (size) + switch (render_type) { - case 0: // Sprites - case 7: // Teleporter - case 9: // Really Big Sprite! (2x2) - case 10: // 2x1 Sprite - case 13: // Special for epilogue: huge hero! + case EntityRenderType_SPRITE: // Sprites + case EntityRenderType_TELEPORTER: // Teleporter + case EntityRenderType_SPRITE_2x2: // Really Big Sprite! (2x2) + case EntityRenderType_SPRITE_2x1: // 2x1 Sprite + case EntityRenderType_SPRITE_6x: // Special for epilogue: huge hero! realcol = graphics.getcol(colour); break; - case 3: // Big chunky pixels! + case EntityRenderType_PARTICLE: // Big chunky pixels! realcol = graphics.bigchunkygetcol(colour); break; - case 4: // Small pickups + case EntityRenderType_COIN: // Small pickups realcol = graphics.huetilegetcol(); break; - case 11: // The fucking elephant + case EntityRenderType_ELEPHANT: // The fucking elephant if (game.noflashingmode) { realcol = graphics.getcol(22); @@ -402,7 +402,7 @@ void entclass::updatecolour(void) realcol = graphics.getcol(colour); } break; - case 12: // Regular sprites that don't wrap + case EntityRenderType_SPRITE_NO_WRAP: // Regular sprites that don't wrap // if we're outside the screen, we need to draw indicators if ((xp < -20 && vx > 0) || (xp > 340 && vx < 0)) { diff --git a/desktop_version/src/Ent.h b/desktop_version/src/Ent.h index d422a519f2..cb0d1a9276 100644 --- a/desktop_version/src/Ent.h +++ b/desktop_version/src/Ent.h @@ -33,6 +33,25 @@ enum EntityType EntityType_TELEPORTER = 100 }; +enum EntityRenderType +{ + EntityRenderType_INVALID = -1, + EntityRenderType_SPRITE, + EntityRenderType_TILE, + EntityRenderType_PLATFORM, + EntityRenderType_PARTICLE, + EntityRenderType_COIN, + EntityRenderType_HORIZONTAL_LINE, + EntityRenderType_VERTICAL_LINE, + EntityRenderType_TELEPORTER, + EntityRenderType_PLATFORM_LONG, + EntityRenderType_SPRITE_2x2, + EntityRenderType_SPRITE_2x1, + EntityRenderType_ELEPHANT, + EntityRenderType_SPRITE_NO_WRAP, + EntityRenderType_SPRITE_6x +}; + class entclass { public: @@ -55,7 +74,8 @@ class entclass //Fundamentals bool invis; EntityType type; - int size, tile, rule; + EntityRenderType render_type; + int tile, rule; int state, statedelay; int behave, animate; float para; diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index b052182782..bc92dec8ef 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -118,7 +118,7 @@ EnemyType* entityclass::create_type(const char* type, int tile, int colour, int enemy_type.corner_y = 0; enemy_type.x_offset = 0; enemy_type.y_offset = 0; - enemy_type.size = 0; + enemy_type.render_type = EntityRenderType_SPRITE; enemy_type.override_behave = false; enemy_type.override_para = false; enemy_type.override_x1 = false; @@ -177,9 +177,9 @@ void entityclass::add_default_types(void) type = create_type("soldier", 82, 8, 5, 28, 32); // Brass Sent Us Under The Top type->corner_x = 4; type = create_type("truth", 64, 7, 100, 44, 10); // Boldly To Go - type->size = 10; + type->render_type = EntityRenderType_SPRITE_2x1; type = create_type("bus", 96, 6, 4, 64, 44); // B-B-B-Busted - type->size = 9; + type->render_type = EntityRenderType_SPRITE_2x2; type = create_type("transmitter", 104, 4, 7, 16, 16); // Comms Relay type->harmful = false; @@ -191,15 +191,15 @@ void entityclass::add_default_types(void) type->x_offset = -4; type->y_offset = -32; type->corner_x = 4; - type->size = 9; + type->render_type = EntityRenderType_SPRITE_2x2; create_type("edgegames_left", 160, 8, 1, 16, 16); // Edge Games create_type("edgegames_right", 156, 8, 1, 16, 16); // Edge Games type = create_type("centipede_right", 66, 12, 100, 60, 16); // Sweeney's Maze - type->size = 10; + type->render_type = EntityRenderType_SPRITE_2x1; type = create_type("centipede_left", 54, 12, 100, 60, 16); // Sweeney's Maze - type->size = 10; + type->render_type = EntityRenderType_SPRITE_2x1; // LIES type = create_type("lies_emitter", 60, 6, 2, 32, 32); @@ -226,7 +226,7 @@ void entityclass::add_default_types(void) // Factory type = create_type("factory_emitter", 72, 6, 3, 64, 40); type->corner_y = 24; - type->size = 9; + type->render_type = EntityRenderType_SPRITE_2x2; type->behave = 12; type->override_behave = true; type = create_type("factory_clouds", 76, 6, 100, 32, 12); @@ -245,7 +245,7 @@ void entityclass::add_default_types(void) // Elephant type = create_type("elephant", 0, 102, 0, 464, 320); - type->size = 11; + type->render_type = EntityRenderType_ELEPHANT; type->harmful = false; } @@ -270,7 +270,7 @@ void entityclass::set_enemy_type(entclass* entity, const char* type) entity->lerpoldxp += enemyType->x_offset; entity->yp += enemyType->y_offset; entity->lerpoldyp += enemyType->y_offset; - entity->size = enemyType->size; + entity->render_type = enemyType->render_type; if (enemyType->colour != -1) { @@ -1507,7 +1507,7 @@ bool entityclass::disableentity(int t) } entities[t].invis = true; - entities[t].size = -1; + entities[t].render_type = EntityRenderType_INVALID; entities[t].type = EntityType_INVALID; entities[t].rule = -1; entities[t].isplatform = false; @@ -1617,7 +1617,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, for (size_t i = 0; i < entities.size(); ++i) { if (entities[i].invis - && entities[i].size == -1 + && entities[i].render_type == EntityRenderType_INVALID && entities[i].type == EntityType_INVALID && entities[i].rule == -1 && !entities[i].isplatform) @@ -1637,20 +1637,20 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entptr->clear(); } - //Size 0 is a sprite - //Size 1 is a tile - //Beyond that are special cases (to do) - //Size 2 is a moving platform of width 4 (32) - //Size 3 is apparently a "bug chunky pixel" - //Size 4 is a coin/small pickup - //Size 5 is a horizontal line, 6 is vertical - - //Rule 0 is the playable character - //Rule 1 is anything harmful - //Rule 2 is anything decorative (no collisions) - //Rule 3 is anything that results in an entity to entity collision and state change - //Rule 4 is a horizontal line, 5 is vertical - //Rule 6 is a crew member + // Size 0 is a sprite + // Size 1 is a tile + // Beyond that are special cases (to do) + // Size 2 is a moving platform of width 4 (32) + // Size 3 is apparently a "bug chunky pixel" + // Size 4 is a coin/small pickup + // Size 5 is a horizontal line, 6 is vertical + + // Rule 0 is the playable character + // Rule 1 is anything harmful + // Rule 2 is anything decorative (no collisions) + // Rule 3 is anything that results in an entity to entity collision and state change + // Rule 4 is a horizontal line, 5 is vertical + // Rule 6 is a crew member entclass& entity = *entptr; entity.xp = xp; @@ -1716,7 +1716,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 2: //A moving platform entity.rule = 2; entity.type = EntityType_MOVING; - entity.size = 2; + entity.render_type = EntityRenderType_PLATFORM; entity.tile = 1; if (customplatformtile > 0){ @@ -1747,7 +1747,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.w = 64; entity.h = 8; meta1 -= 2; - entity.size = 8; + entity.render_type = EntityRenderType_PLATFORM_LONG; } entity.behave = meta1; @@ -1784,7 +1784,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 3: //Disappearing platforms entity.rule = 3; entity.type = EntityType_DISAPPEARING_PLATFORM; - entity.size = 2; + entity.render_type = EntityRenderType_PLATFORM; entity.tile = 2; //appearance again depends on location if(customplatformtile>0) @@ -1814,7 +1814,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 4: //Breakable blocks entity.rule = 6; entity.type = EntityType_QUICKSAND; - entity.size = 1; + entity.render_type = EntityRenderType_TILE; entity.tile = 10; entity.cy = -1; entity.w = 8; @@ -1829,7 +1829,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 5: //Gravity Tokens entity.rule = 3; entity.type = EntityType_GRAVITY_TOKEN; - entity.size = 0; + entity.render_type = EntityRenderType_SPRITE; entity.tile = 11; entity.w = 16; entity.h = 16; @@ -1842,7 +1842,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.rule = 2; entity.type = EntityType_PARTICLE; //Particles entity.colour = 1; - entity.size = 3; + entity.render_type = EntityRenderType_PARTICLE; entity.vx = meta1; entity.vy = meta2; @@ -1852,7 +1852,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.rule = 2; entity.type = EntityType_PARTICLE; //Particles entity.colour = 2; - entity.size = 3; + entity.render_type = EntityRenderType_PARTICLE; entity.vx = meta1; entity.vy = meta2; @@ -1861,7 +1861,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 8: //Small collectibles entity.rule = 3; entity.type = EntityType_COIN; - entity.size = 4; + entity.render_type = EntityRenderType_COIN; entity.tile = 48; entity.w = 8; entity.h = 8; @@ -1875,7 +1875,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 9: //Something Shiny entity.rule = 3; entity.type = EntityType_TRINKET; - entity.size = 0; + entity.render_type = EntityRenderType_SPRITE; entity.tile = 22; entity.w = 16; entity.h = 16; @@ -1890,7 +1890,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 10: //Savepoint entity.rule = 3; entity.type = EntityType_CHECKPOINT; - entity.size = 0; + entity.render_type = EntityRenderType_SPRITE; entity.tile = 20 + meta1; entity.w = 16; entity.h = 16; @@ -1913,7 +1913,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 11: //Horizontal Gravity Line entity.rule = 4; entity.type = EntityType_HORIZONTAL_GRAVITY_LINE; - entity.size = 5; + entity.render_type = EntityRenderType_HORIZONTAL_LINE; entity.life = 0; entity.w = meta1; entity.h = 1; @@ -1922,7 +1922,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 12: //Vertical Gravity Line entity.rule = 5; entity.type = EntityType_VERTICAL_GRAVITY_LINE; - entity.size = 6; + entity.render_type = EntityRenderType_VERTICAL_LINE; entity.life = 0; entity.w = 1; entity.h = meta1; @@ -1932,7 +1932,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 13: //Warp token entity.rule = 3; entity.type = EntityType_WARP_TOKEN; - entity.size = 0; + entity.render_type = EntityRenderType_SPRITE; entity.tile = 18; entity.w = 16; entity.h = 16; @@ -1946,7 +1946,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 14: // Teleporter entity.rule = 3; entity.type = EntityType_TELEPORTER; - entity.size = 7; + entity.render_type = EntityRenderType_TELEPORTER; entity.tile = 1; //inactive entity.w = 96; entity.h = 96; @@ -2047,7 +2047,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 20: //Terminal entity.rule = 3; entity.type = EntityType_TERMINAL; - entity.size = 0; + entity.render_type = EntityRenderType_SPRITE; entity.tile = 16 + meta1; entity.w = 16; entity.h = 16; @@ -2059,7 +2059,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 21: //as above, except doesn't highlight entity.rule = 3; entity.type = EntityType_TERMINAL; - entity.size = 0; + entity.render_type = EntityRenderType_SPRITE; entity.tile = 16 + meta1; entity.w = 16; entity.h = 16; @@ -2071,7 +2071,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 22: //Fake trinkets, only appear if you've collected them entity.rule = 3; entity.type = EntityType_TRINKET; - entity.size = 0; + entity.render_type = EntityRenderType_SPRITE; entity.tile = 22; entity.w = 16; entity.h = 16; @@ -2102,7 +2102,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.harmful = true; //initilise tiles here based on behavior - entity.size = 12; //don't wrap around + entity.render_type = EntityRenderType_SPRITE_NO_WRAP; //don't wrap around entity.colour = 21; entity.tile = 78; //default case entity.animate = 1; @@ -2158,7 +2158,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 25: //Trophies entity.rule = 3; entity.type = EntityType_TROPHY; - entity.size = 0; + entity.render_type = EntityRenderType_SPRITE; entity.w = 16; entity.h = 16; entity.colour = 4; @@ -2321,7 +2321,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, { entity.tile = 3; entity.colour = 102; - entity.size = 13; + entity.render_type = EntityRenderType_SPRITE_6x; entity.xp -= 64; entity.yp -= 128; } @@ -2333,7 +2333,6 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 26: //Epilogue super warp token entity.rule = 3; entity.type = EntityType_WARP_TOKEN; - entity.size = 0; entity.tile = 18; entity.w = 16; entity.h = 16; @@ -2341,7 +2340,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.onentity = 0; entity.animate = 100; entity.para = meta2; - entity.size = 13; + entity.render_type = EntityRenderType_SPRITE_6x; break; /* Warp lines */ @@ -2374,14 +2373,14 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, case 51: case 52: entity.rule = 5; - entity.size = 6; + entity.render_type = EntityRenderType_VERTICAL_LINE; entity.w = 1; entity.h = meta1; break; case 53: case 54: entity.rule = 7; - entity.size = 5; + entity.render_type = EntityRenderType_HORIZONTAL_LINE; entity.w = meta1; entity.h = 1; break; @@ -4256,7 +4255,7 @@ int entityclass::getlineat( int t ) //Get the entity which is a horizontal line at height t (for SWN game) for (size_t i = 0; i < entities.size(); i++) { - if (entities[i].size == 5) + if (entities[i].render_type == EntityRenderType_HORIZONTAL_LINE) { if (entities[i].yp == t) { @@ -5101,7 +5100,7 @@ void entityclass::collisioncheck(int i, int j, bool scm /*= false*/) //person i hits enemy or enemy bullet j if (entitycollide(i, j) && !map.invincibility) { - if (entities[i].size == 0 && (entities[j].size == 0 || entities[j].size == 12)) + if (entities[i].render_type == EntityRenderType_SPRITE && (entities[j].render_type == EntityRenderType_SPRITE || entities[j].render_type == EntityRenderType_SPRITE_NO_WRAP)) { //They're both sprites, so do a per pixel collision SDL_Point colpoint1; diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index caac02cdb9..4fc07a10bd 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -45,7 +45,7 @@ struct EnemyType int corner_y; int x_offset; int y_offset; - int size; + EntityRenderType render_type; int behave; bool override_behave; int para; diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index be992db016..a235f31d47 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -2091,9 +2091,9 @@ void Graphics::drawentity(const int i, const int yoff) const int xp = lerp(obj.entities[i].lerpoldxp, obj.entities[i].xp); const int yp = lerp(obj.entities[i].lerpoldyp, obj.entities[i].yp); - switch (obj.entities[i].size) + switch (obj.entities[i].render_type) { - case 0: + case EntityRenderType_SPRITE: { // Sprites tpoint.x = xp; @@ -2159,7 +2159,7 @@ void Graphics::drawentity(const int i, const int yoff) } break; } - case 1: + case EntityRenderType_TILE: // Tiles tpoint.x = xp; tpoint.y = yp - yoff; @@ -2169,15 +2169,15 @@ void Graphics::drawentity(const int i, const int yoff) draw_grid_tile(grphx.im_tiles, obj.entities[i].drawframe, drawRect.x, drawRect.y, 8, 8); break; - case 2: - case 8: + case EntityRenderType_PLATFORM: + case EntityRenderType_PLATFORM_LONG: { // Special: Moving platform, 4 tiles or 8 tiles tpoint.x = xp; tpoint.y = yp - yoff; int thiswidth = 4; - if (obj.entities[i].size == 8) + if (obj.entities[i].render_type == EntityRenderType_PLATFORM_LONG) { thiswidth = 8; } @@ -2198,16 +2198,16 @@ void Graphics::drawentity(const int i, const int yoff) } break; } - case 3: // Big chunky pixels! + case EntityRenderType_PARTICLE: // Big chunky pixels! fill_rect(xp, yp - yoff, 4, 4, obj.entities[i].realcol); break; - case 4: // Small pickups + case EntityRenderType_COIN: // Small pickups { const SDL_Color color = obj.entities[i].realcol; drawcoloredtile(xp, yp - yoff, obj.entities[i].tile, color.r, color.g, color.b); break; } - case 5: // Horizontal Line + case EntityRenderType_HORIZONTAL_LINE: // Horizontal Line { int oldw = obj.entities[i].w; if ((game.swngame == SWN_START_GRAVITRON_STEP_2 || kludgeswnlinewidth) @@ -2218,16 +2218,13 @@ void Graphics::drawentity(const int i, const int yoff) drawgravityline(i, xp, yp - yoff, lerp(oldw, obj.entities[i].w) - 1, 0); break; } - case 6: // Vertical Line + case EntityRenderType_VERTICAL_LINE: // Vertical Line drawgravityline(i, xp, yp - yoff, 0, obj.entities[i].h - 1); break; - case 7: // Teleporter + case EntityRenderType_TELEPORTER: // Teleporter drawtele(xp, yp - yoff, obj.entities[i].drawframe, obj.entities[i].realcol); break; - // case 8: // Special: Moving platform, 8 tiles - // Note: This code is in the 4-tile code - break; - case 9: // Really Big Sprite! (2x2) + case EntityRenderType_SPRITE_2x2: // Really Big Sprite! (2x2) { const SDL_Color ct = obj.entities[i].realcol; @@ -2268,7 +2265,7 @@ void Graphics::drawentity(const int i, const int yoff) draw_grid_tile(sprites, obj.entities[i].drawframe + 13, drawRect.x, drawRect.y, 32, 32, ct); break; } - case 10: // 2x1 Sprite + case EntityRenderType_SPRITE_2x1: // 2x1 Sprite { const SDL_Color ct = obj.entities[i].realcol; @@ -2291,10 +2288,10 @@ void Graphics::drawentity(const int i, const int yoff) draw_grid_tile(sprites, obj.entities[i].drawframe + 1, drawRect.x, drawRect.y, 32, 32, ct); break; } - case 11: // The fucking elephant + case EntityRenderType_ELEPHANT: // The fucking elephant drawimagecol(IMAGE_ELEPHANT, xp, yp - yoff, obj.entities[i].realcol); break; - case 12: // Regular sprites that don't wrap + case EntityRenderType_SPRITE_NO_WRAP: // Regular sprites that don't wrap { tpoint.x = xp; tpoint.y = yp - yoff; @@ -2350,7 +2347,7 @@ void Graphics::drawentity(const int i, const int yoff) } break; } - case 13: + case EntityRenderType_SPRITE_6x: { // Special for epilogue: huge hero! draw_grid_tile(grphx.im_sprites, obj.entities[i].drawframe, xp, yp - yoff, sprites_rect.w, sprites_rect.h, obj.entities[i].realcol, 6, 6); diff --git a/desktop_version/src/LevelDebugger.cpp b/desktop_version/src/LevelDebugger.cpp index b180b70466..4081db3285 100644 --- a/desktop_version/src/LevelDebugger.cpp +++ b/desktop_version/src/LevelDebugger.cpp @@ -382,7 +382,7 @@ namespace level_debugger line++; render_info(line++, "Tile", help.String(entity->tile)); render_info(line++, "Draw Frame", help.String(entity->drawframe)); - render_info(line++, "Size", help.String(entity->size)); + //render_info(line++, "Size", help.String(entity->size)); render_info(line++, "Direction", help.String(entity->dir)); line++; diff --git a/desktop_version/src/Logic.cpp b/desktop_version/src/Logic.cpp index 958bc8b229..7054ada070 100644 --- a/desktop_version/src/Logic.cpp +++ b/desktop_version/src/Logic.cpp @@ -1040,7 +1040,7 @@ void gamelogic(void) || obj.entities[i].type == EntityType_WARP_LINE_RIGHT || obj.entities[i].type == EntityType_WARP_LINE_TOP || obj.entities[i].type == EntityType_WARP_LINE_BOTTOM /* Don't warp warp lines */ - || obj.entities[i].size == 12) /* Don't warp gravitron squares */ + || obj.entities[i].render_type == EntityRenderType_SPRITE_NO_WRAP) /* Don't warp gravitron squares */ { continue; } diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index c06d21a679..4be62d091d 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -818,7 +818,7 @@ void mapclass::resetplayer(const bool player_died) } if (!GlitchrunnerMode_less_than_or_equal(Glitchrunner2_2)) { - obj.entities[i].size = 0; + obj.entities[i].render_type = EntityRenderType_SPRITE; obj.entities[i].cx = 6; obj.entities[i].cy = 2; obj.entities[i].w = 12; diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 5aa50fe5d8..995d55cc41 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -8,6 +8,7 @@ #include "Constants.h" #include "CustomLevels.h" #include "Editor.h" +#include "Ent.h" #include "Entity.h" #include "Enums.h" #include "Exit.h" @@ -909,7 +910,7 @@ void scriptclass::run(void) obj.entities[i].yp = 46; obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].lerpoldyp = obj.entities[i].yp; - obj.entities[i].size = 13; + obj.entities[i].render_type = EntityRenderType_SPRITE_6x; obj.entities[i].colour = 23; obj.entities[i].cx = 36;// 6; obj.entities[i].cy = 12+80;// 2; @@ -924,7 +925,7 @@ void scriptclass::run(void) { obj.entities[i].xp = 100; obj.entities[i].lerpoldxp = obj.entities[i].xp; - obj.entities[i].size = 0; + obj.entities[i].render_type = EntityRenderType_SPRITE; obj.entities[i].colour = 0; obj.entities[i].cx = 6; obj.entities[i].cy = 2; @@ -2627,7 +2628,7 @@ void scriptclass::startgamemode(const enum StartMode mode) struct { bool initialized; - int size; + EntityRenderType render_type; int cx; int cy; int w; @@ -2644,7 +2645,7 @@ void scriptclass::startgamemode(const enum StartMode mode) { const entclass* player = &obj.entities[player_idx]; player_hitbox.initialized = true; - player_hitbox.size = player->size; + player_hitbox.render_type = player->render_type; player_hitbox.cx = player->cx; player_hitbox.cy = player->cy; player_hitbox.w = player->w; @@ -2997,7 +2998,7 @@ void scriptclass::startgamemode(const enum StartMode mode) if (INBOUNDS_VEC(player_idx, obj.entities)) { entclass* player = &obj.entities[player_idx]; - player->size = player_hitbox.size; + player->render_type = player_hitbox.render_type; player->cx = player_hitbox.cx; player->cy = player_hitbox.cy; player->w = player_hitbox.w; From a82bd39871c0aa25692af2fd6e55e995b0fddff3 Mon Sep 17 00:00:00 2001 From: AllyTally Date: Sat, 2 Sep 2023 19:29:54 -0300 Subject: [PATCH 09/12] Change radar from 32x32 -> 64x64 So, the radar enemy type was originally 16x16. I meant to change it to something that made more sense, but I messed up and made it 32x32 instead of 64x64 like it is visually. --- desktop_version/src/Entity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index bc92dec8ef..8b3e0f1858 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -186,7 +186,7 @@ void entityclass::add_default_types(void) type->x_offset = -24; type->y_offset = -16; - type = create_type("radar", 124, 4, 6, 32, 32); // Comms Relay + type = create_type("radar", 124, 4, 6, 64, 64); // Comms Relay type->harmful = false; type->x_offset = -4; type->y_offset = -32; From fd831dcb27e9e5ea8b1252730554e24ecd732985 Mon Sep 17 00:00:00 2001 From: AllyTally Date: Mon, 4 Sep 2023 00:30:46 -0300 Subject: [PATCH 10/12] Completely replace `animate` system for entities This removes the magic numbers used for `animate`, and makes the animation system far more flexible, instead giving entities the option to control what they need, instead of having a bunch of duplicated hardly-readable code. --- desktop_version/src/Ent.cpp | 5 +- desktop_version/src/Ent.h | 15 +- desktop_version/src/Entity.cpp | 357 +++++++++++++-------------------- desktop_version/src/Entity.h | 11 +- desktop_version/src/Map.cpp | 14 +- desktop_version/src/Script.cpp | 12 +- 6 files changed, 180 insertions(+), 234 deletions(-) diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index 9df8e2c893..c27da0f903 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -22,7 +22,6 @@ void entclass::clear(void) colour = 0; para = 0; behave = 0; - animate = 0; xp = 0; yp = 0; @@ -69,6 +68,10 @@ void entclass::clear(void) SDL_zero(realcol); lerpoldxp = 0; lerpoldyp = 0; + + animation_frames = 4; + animation_type = EntityAnimationType_OSCILLATE; + animation_speed = 8; } bool entclass::outside(void) diff --git a/desktop_version/src/Ent.h b/desktop_version/src/Ent.h index cb0d1a9276..ffb7892e00 100644 --- a/desktop_version/src/Ent.h +++ b/desktop_version/src/Ent.h @@ -52,6 +52,16 @@ enum EntityRenderType EntityRenderType_SPRITE_6x }; +enum EntityAnimationTypes +{ + EntityAnimationType_STILL, + EntityAnimationType_OSCILLATE, + EntityAnimationType_LOOP, + EntityAnimationType_ONESHOT, + EntityAnimationType_CONVEYOR_LEFT, + EntityAnimationType_CONVEYOR_RIGHT +}; + class entclass { public: @@ -77,7 +87,7 @@ class entclass EntityRenderType render_type; int tile, rule; int state, statedelay; - int behave, animate; + int behave; float para; int life, colour; @@ -98,6 +108,9 @@ class entclass int onground, onroof; //Animation int framedelay, drawframe, walkingframe, dir, actionframe; + int animation_frames; + EntityAnimationTypes animation_type; + int animation_speed; int collisionframedelay, collisiondrawframe, collisionwalkingframe; int visualonground, visualonroof; int yp;int xp; diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 8b3e0f1858..b4ef76ca5f 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -105,12 +105,18 @@ void entityclass::init(void) add_default_types(); } -EnemyType* entityclass::create_type(const char* type, int tile, int colour, int animate, int width, int height) +EnemyType* entityclass::create_type( + const char* type, int tile, int colour, + EntityAnimationTypes animation_type, int animation_frames, int animation_speed, + int width, int height +) { EnemyType enemy_type; enemy_type.tile = tile; enemy_type.colour = colour; - enemy_type.animate = animate; + enemy_type.animation_type = animation_type; + enemy_type.animation_frames = animation_frames; + enemy_type.animation_speed = animation_speed; enemy_type.width = width; enemy_type.height = height; enemy_type.harmful = true; @@ -135,79 +141,79 @@ void entityclass::add_default_types(void) EnemyType* type; // Copies for the editor, without the color set: - create_type("custom_square", 78, -1, 1, 16, 16); - create_type("custom_circle", 88, -1, 1, 16, 16); - create_type("custom_disc", 36, -1, 1, 16, 16); - create_type("custom_glitch", 164, -1, 1, 16, 16); - create_type("custom_coin", 68, -1, 1, 16, 16); - create_type("custom_cross", 48, -1, 5, 16, 16); - create_type("custom_triangle", 176, -1, 1, 16, 16); - create_type("custom_ice", 168, -1, 1, 16, 16); - create_type("custom_heart", 112, -1, 5, 16, 16); - create_type("custom_broken_heart", 114, -1, 5, 16, 16); - - create_type("square", 78, 7, 1, 16, 16); // Vibrating String Problem - create_type("circle", 88, 11, 1, 16, 16); // Kids His Age Bounce - create_type("disc", 36, 8, 1, 16, 16); // Security Sweep - create_type("glitch", 164, 7, 1, 16, 16); // Backsliders - create_type("coin", 68, 7, 1, 16, 16); // $eeing Dollar $ign$ - create_type("cross", 48, 9, 5, 16, 16); // Ascending and Descending - create_type("triangle", 176, 6, 1, 16, 16); // Shockwave Rider - create_type("ice", 168, 7, 1, 16, 16); // Mind The Gap - create_type("heart", 112, 8, 5, 16, 16); // I Love You - create_type("broken_heart", 114, 6, 5, 16, 16); // That's Why I Have To Kill You - - create_type("bowtie", 92, 6, 1, 16, 16); // A Deception - create_type("crate", 24, 6, 1, 16, 16); // UNUSED in main game - - create_type("wavelength", 32, 7, 1, 32, 16); // Linear Collider - create_type("stop", 28, 6, 1, 22, 32); // Traffic Jam - create_type("yes", 40, 9, 1, 20, 20); // The Yes Men - create_type("vertigo", 172, 7, 100, 32, 32); // Vertigo - create_type("guard", 44, 8, 1, 16, 20); // Trench Warfare - create_type("obey", 51, 11, 100, 30, 14); // Time to get serious - create_type("ghost", 106, 7, 2, 24, 25); // The Tomb of Mad Carew - create_type("wheel", 116, 12, 1, 32, 32); // The Hanged Man, Reversed - create_type("skeleton", 56, 6, 1, 15, 24); // You Chose... Poorly - - type = create_type("mannequin", 52, 7, 5, 16, 25); // Short Circuit + create_type("custom_square", 78, -1, EntityAnimationType_LOOP, 4, 8, 16, 16); + create_type("custom_circle", 88, -1, EntityAnimationType_LOOP, 4, 8, 16, 16); + create_type("custom_disc", 36, -1, EntityAnimationType_LOOP, 4, 8, 16, 16); + create_type("custom_glitch", 164, -1, EntityAnimationType_LOOP, 4, 8, 16, 16); + create_type("custom_coin", 68, -1, EntityAnimationType_LOOP, 4, 8, 16, 16); + create_type("custom_cross", 48, -1, EntityAnimationType_LOOP, 2, 6, 16, 16); + create_type("custom_triangle", 176, -1, EntityAnimationType_LOOP, 4, 8, 16, 16); + create_type("custom_ice", 168, -1, EntityAnimationType_LOOP, 4, 8, 16, 16); + create_type("custom_heart", 112, -1, EntityAnimationType_LOOP, 2, 6, 16, 16); + create_type("custom_broken_heart", 114, -1, EntityAnimationType_LOOP, 2, 6, 16, 16); + + create_type("square", 78, 7, EntityAnimationType_LOOP, 4, 8, 16, 16); // Vibrating String Problem + create_type("circle", 88, 11, EntityAnimationType_LOOP, 4, 8, 16, 16); // Kids His Age Bounce + create_type("disc", 36, 8, EntityAnimationType_LOOP, 4, 8, 16, 16); // Security Sweep + create_type("glitch", 164, 7, EntityAnimationType_LOOP, 4, 8, 16, 16); // Backsliders + create_type("coin", 68, 7, EntityAnimationType_LOOP, 4, 8, 16, 16); // $eeing Dollar $ign$ + create_type("cross", 48, 9, EntityAnimationType_LOOP, 2, 6, 16, 16); // Ascending and Descending + create_type("triangle", 176, 6, EntityAnimationType_LOOP, 4, 8, 16, 16); // Shockwave Rider + create_type("ice", 168, 7, EntityAnimationType_LOOP, 4, 8, 16, 16); // Mind The Gap + create_type("heart", 112, 8, EntityAnimationType_LOOP, 2, 6, 16, 16); // I Love You + create_type("broken_heart", 114, 6, EntityAnimationType_LOOP, 2, 6, 16, 16); // That's Why I Have To Kill You + + create_type("bowtie", 92, 6, EntityAnimationType_LOOP, 4, 8, 16, 16); // A Deception + create_type("crate", 24, 6, EntityAnimationType_LOOP, 4, 8, 16, 16); // UNUSED in main game + + create_type("wavelength", 32, 7, EntityAnimationType_LOOP, 4, 8, 32, 16); // Linear Collider + create_type("stop", 28, 6, EntityAnimationType_LOOP, 4, 8, 22, 32); // Traffic Jam + create_type("yes", 40, 9, EntityAnimationType_LOOP, 4, 8, 20, 20); // The Yes Men + create_type("vertigo", 172, 7, EntityAnimationType_STILL, 1, 1, 32, 32); // Vertigo + create_type("guard", 44, 8, EntityAnimationType_LOOP, 4, 8, 16, 20); // Trench Warfare + create_type("obey", 51, 11, EntityAnimationType_STILL, 1, 1, 30, 14); // Time to get serious + create_type("ghost", 106, 7, EntityAnimationType_LOOP, 2, 2, 24, 25); // The Tomb of Mad Carew + create_type("wheel", 116, 12, EntityAnimationType_LOOP, 4, 8, 32, 32); // The Hanged Man, Reversed + create_type("skeleton", 56, 6, EntityAnimationType_LOOP, 4, 8, 15, 24); // You Chose... Poorly + + type = create_type("mannequin", 52, 7, EntityAnimationType_LOOP, 2, 6, 16, 25); // Short Circuit type->y_offset = -4; - type = create_type("numbers", 100, 6, 1, 32, 14); // Take the Red Pill + type = create_type("numbers", 100, 6, EntityAnimationType_LOOP, 4, 8, 32, 14); // Take the Red Pill type->y_offset = 1; - type = create_type("soldier", 82, 8, 5, 28, 32); // Brass Sent Us Under The Top + type = create_type("soldier", 82, 8, EntityAnimationType_LOOP, 2, 6, 28, 32); // Brass Sent Us Under The Top type->corner_x = 4; - type = create_type("truth", 64, 7, 100, 44, 10); // Boldly To Go + type = create_type("truth", 64, 7, EntityAnimationType_STILL, 1, 1, 44, 10); // Boldly To Go type->render_type = EntityRenderType_SPRITE_2x1; - type = create_type("bus", 96, 6, 4, 64, 44); // B-B-B-Busted + type = create_type("bus", 96, 6, EntityAnimationType_LOOP, 2, 6, 64, 44); // B-B-B-Busted type->render_type = EntityRenderType_SPRITE_2x2; - type = create_type("transmitter", 104, 4, 7, 16, 16); // Comms Relay + type = create_type("transmitter", 104, 4, EntityAnimationType_LOOP, 2, 6, 16, 16); // Comms Relay type->harmful = false; type->x_offset = -24; type->y_offset = -16; - type = create_type("radar", 124, 4, 6, 64, 64); // Comms Relay + type = create_type("radar", 124, 4, EntityAnimationType_LOOP, 4, 4, 64, 64); // Comms Relay type->harmful = false; type->x_offset = -4; type->y_offset = -32; type->corner_x = 4; type->render_type = EntityRenderType_SPRITE_2x2; - create_type("edgegames_left", 160, 8, 1, 16, 16); // Edge Games - create_type("edgegames_right", 156, 8, 1, 16, 16); // Edge Games + create_type("edgegames_left", 160, 8, EntityAnimationType_LOOP, 4, 8, 16, 16); // Edge Games + create_type("edgegames_right", 156, 8, EntityAnimationType_LOOP, 4, 8, 16, 16); // Edge Games - type = create_type("centipede_right", 66, 12, 100, 60, 16); // Sweeney's Maze + type = create_type("centipede_right", 66, 12, EntityAnimationType_STILL, 1, 1, 60, 16); // Sweeney's Maze type->render_type = EntityRenderType_SPRITE_2x1; - type = create_type("centipede_left", 54, 12, 100, 60, 16); // Sweeney's Maze + type = create_type("centipede_left", 54, 12, EntityAnimationType_STILL, 1, 1, 60, 16); // Sweeney's Maze type->render_type = EntityRenderType_SPRITE_2x1; // LIES - type = create_type("lies_emitter", 60, 6, 2, 32, 32); + type = create_type("lies_emitter", 60, 6, EntityAnimationType_LOOP, 2, 2, 32, 32); type->behave = 10; type->x1 = -200; type->override_behave = true; type->override_x1 = true; - type = create_type("lies", 63, 6, 100, 26, 10); + type = create_type("lies", 63, 6, EntityAnimationType_STILL, 1, 1, 26, 10); type->corner_x = 1; type->corner_y = 1; type->y_offset = 10; @@ -219,17 +225,17 @@ void entityclass::add_default_types(void) type->override_para = true; type->override_x1 = true; type->override_x2 = true; - type = create_type("lies_collector", 62, 6, 100, 32, 32); + type = create_type("lies_collector", 62, 6, EntityAnimationType_STILL, 1, 1, 32, 32); type->behave = -1; type->override_behave = true; // Factory - type = create_type("factory_emitter", 72, 6, 3, 64, 40); + type = create_type("factory_emitter", 72, 6, EntityAnimationType_LOOP, 2, 2, 64, 40); type->corner_y = 24; type->render_type = EntityRenderType_SPRITE_2x2; type->behave = 12; type->override_behave = true; - type = create_type("factory_clouds", 76, 6, 100, 32, 12); + type = create_type("factory_clouds", 76, 6, EntityAnimationType_STILL, 1, 1, 32, 12); type->corner_y = 6; type->x_offset = 4; type->y_offset = -4; @@ -239,12 +245,12 @@ void entityclass::add_default_types(void) type->override_behave = true; type->override_para = true; type->override_x2 = true; - type = create_type("factory_collector", 77, 6, 100, 32, 16); + type = create_type("factory_collector", 77, 6, EntityAnimationType_STILL, 1, 1, 32, 16); type->behave = -1; type->override_behave = true; // Elephant - type = create_type("elephant", 0, 102, 0, 464, 320); + type = create_type("elephant", 0, 102, EntityAnimationType_STILL, 1, 1, 464, 320); type->render_type = EntityRenderType_ELEPHANT; type->harmful = false; } @@ -260,7 +266,9 @@ void entityclass::set_enemy_type(entclass* entity, const char* type) { EnemyType* enemyType = &enemy_types[type]; entity->tile = enemyType->tile; - entity->animate = enemyType->animate; + entity->animation_frames = enemyType->animation_frames; + entity->animation_speed = enemyType->animation_speed; + entity->animation_type = enemyType->animation_type; entity->w = enemyType->width; entity->h = enemyType->height; entity->harmful = enemyType->harmful; @@ -1693,10 +1701,12 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.harmful = true; entity.tile = 24; - entity.animate = 0; entity.colour = 8; entity.type = EntityType_MOVING; + entity.animation_frames = 4; + entity.animation_type = EntityAnimationType_OSCILLATE; + entity.animation_speed = 8; if (game.roomy == 111 && (game.roomx >= 113 && game.roomx <= 117)) { @@ -1756,20 +1766,20 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, if (meta1 >= 8 && meta1 <= 9) { horplatforms = true; //threadmill! - entity.animate = 10; + entity.animation_type = EntityAnimationType_CONVEYOR_LEFT; if(customplatformtile>0){ entity.tile = customplatformtile+4; if (meta1 == 8) entity.tile += 4; - if (meta1 == 9) entity.animate = 11; + if (meta1 == 9) entity.animation_type = EntityAnimationType_CONVEYOR_RIGHT; }else{ entity.settreadmillcolour(game.roomx, game.roomy); if (meta1 == 8) entity.tile += 40; - if (meta1 == 9) entity.animate = 11; + if (meta1 == 9) entity.animation_type = EntityAnimationType_CONVEYOR_RIGHT; } } else { - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; } entity.x1 = p1; @@ -1807,7 +1817,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.behave = meta1; entity.para = meta2; entity.onentity = 1; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; createblock(0, xp, yp, 32, 8); break; @@ -1822,7 +1832,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.behave = meta1; entity.para = meta2; entity.onentity = 1; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; createblock(0, xp, yp, 8, 8); break; @@ -1836,7 +1846,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.behave = meta1; entity.para = meta2; entity.onentity = 1; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; break; case 6: //Decorative particles entity.rule = 2; @@ -1866,7 +1876,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.w = 8; entity.h = 8; entity.onentity = 1; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; //Check if it's already been collected entity.para = meta1; @@ -1881,7 +1891,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.h = 16; entity.colour = 3; entity.onentity = 1; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; //Check if it's already been collected entity.para = meta1; @@ -1896,7 +1906,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.h = 16; entity.colour = 4; entity.onentity = 1; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; entity.para = meta2; if (game.savepoint == meta2) @@ -1938,7 +1948,6 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.h = 16; entity.colour = 10; entity.onentity = 1; - entity.animate = 2; //Added in port, hope it doesn't break anything entity.behave = meta1; entity.para = meta2; @@ -1952,7 +1961,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.h = 96; entity.colour = 100; entity.onentity = 1; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; entity.para = meta2; break; case 15: // Crew Member (warp zone) @@ -2053,7 +2062,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.h = 16; entity.colour = 4; entity.onentity = 1; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; entity.para = meta2; break; case 21: //as above, except doesn't highlight @@ -2065,7 +2074,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.h = 16; entity.colour = 4; entity.onentity = 0; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; entity.para = meta2; break; case 22: //Fake trinkets, only appear if you've collected them @@ -2077,7 +2086,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.h = 16; entity.colour = 3; entity.onentity = 0; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; //Check if it's already been collected entity.para = meta1; @@ -2105,7 +2114,9 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.render_type = EntityRenderType_SPRITE_NO_WRAP; //don't wrap around entity.colour = 21; entity.tile = 78; //default case - entity.animate = 1; + entity.animation_frames = 4; + entity.animation_speed = 8; + entity.animation_type = EntityAnimationType_LOOP; if (game.swngame == SWN_SUPERGRAVITRON) { //set colour based on current state @@ -2163,7 +2174,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.h = 16; entity.colour = 4; entity.onentity = 1; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; entity.para = meta2; //Decide tile here based on given achievement: both whether you have them and what they are @@ -2338,7 +2349,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, entity.h = 16; entity.colour = 3; entity.onentity = 0; - entity.animate = 100; + entity.animation_type = EntityAnimationType_STILL; entity.para = meta2; entity.render_type = EntityRenderType_SPRITE_6x; break; @@ -3799,156 +3810,62 @@ void entityclass::animateentities( int _i ) break; case EntityType_MOVING: case EntityType_GRAVITRON_ENEMY: - //Variable animation - switch(entities[_i].animate) - { - case 0: - //Simple oscilation - entities[_i].framedelay--; - if(entities[_i].framedelay<=0) - { - entities[_i].framedelay = 8; - if(entities[_i].actionframe==0) - { - entities[_i].walkingframe++; - if (entities[_i].walkingframe == 4) - { - entities[_i].walkingframe = 2; - entities[_i].actionframe = 1; - } - } - else - { - entities[_i].walkingframe--; - if (entities[_i].walkingframe == -1) - { - entities[_i].walkingframe = 1; - entities[_i].actionframe = 0; - } - } - } - - entities[_i].drawframe = entities[_i].tile; - entities[_i].drawframe += entities[_i].walkingframe; - break; - case 1: - //Simple Loop - entities[_i].framedelay--; - if(entities[_i].framedelay<=0) - { - entities[_i].framedelay = 8; - entities[_i].walkingframe++; - if (entities[_i].walkingframe == 4) - { - entities[_i].walkingframe = 0; - } - } - - entities[_i].drawframe = entities[_i].tile; - entities[_i].drawframe += entities[_i].walkingframe; - break; - case 2: - //Simpler Loop (just two frames) - entities[_i].framedelay--; - if(entities[_i].framedelay<=0) - { - entities[_i].framedelay = 2; - entities[_i].walkingframe++; - if (entities[_i].walkingframe == 2) - { - entities[_i].walkingframe = 0; - } - } - - entities[_i].drawframe = entities[_i].tile; - entities[_i].drawframe += entities[_i].walkingframe; - break; - case 3: - //Simpler Loop (just two frames, but double sized) - entities[_i].framedelay--; - if(entities[_i].framedelay<=0) - { - entities[_i].framedelay = 2; - entities[_i].walkingframe++; - if (entities[_i].walkingframe == 2) - { - entities[_i].walkingframe = 0; - } - } + { + int offset = 1; - entities[_i].drawframe = entities[_i].tile; - entities[_i].drawframe += (entities[_i].walkingframe*2); - break; - case 4: - //Simpler Loop (just two frames, but double sized) (as above but slower) - entities[_i].framedelay--; - if(entities[_i].framedelay<=0) - { - entities[_i].framedelay = 6; - entities[_i].walkingframe++; - if (entities[_i].walkingframe == 2) - { - entities[_i].walkingframe = 0; - } - } + if (entities[_i].render_type == EntityRenderType_SPRITE_2x1 || entities[_i].render_type == EntityRenderType_SPRITE_2x2) + { + offset = 2; + } - entities[_i].drawframe = entities[_i].tile; - entities[_i].drawframe += (entities[_i].walkingframe*2); - break; - case 5: - //Simpler Loop (just two frames) (slower) + switch (entities[_i].animation_type) + { + case EntityAnimationType_LOOP: entities[_i].framedelay--; - if(entities[_i].framedelay<=0) + if (entities[_i].framedelay <= 0) { - entities[_i].framedelay = 6; + entities[_i].framedelay = entities[_i].animation_speed; entities[_i].walkingframe++; - if (entities[_i].walkingframe == 2) + if (entities[_i].walkingframe >= entities[_i].animation_frames) { entities[_i].walkingframe = 0; } } - entities[_i].drawframe = entities[_i].tile; - entities[_i].drawframe += entities[_i].walkingframe; + entities[_i].drawframe = entities[_i].tile + entities[_i].walkingframe * offset; break; - case 6: - //Normal Loop (four frames, double sized) + case EntityAnimationType_OSCILLATE: entities[_i].framedelay--; - if(entities[_i].framedelay<=0) + if (entities[_i].framedelay <= 0) { - entities[_i].framedelay = 4; - entities[_i].walkingframe++; - if (entities[_i].walkingframe == 4) + entities[_i].framedelay = entities[_i].animation_speed; + if (entities[_i].actionframe == 0) { - entities[_i].walkingframe = 0; + entities[_i].walkingframe++; + if (entities[_i].walkingframe >= entities[_i].animation_frames) + { + entities[_i].walkingframe = entities[_i].animation_frames - 1; + entities[_i].actionframe = 1; + } } - } - - entities[_i].drawframe = entities[_i].tile; - entities[_i].drawframe += (entities[_i].walkingframe*2); - break; - case 7: - //Simpler Loop (just two frames) (slower) (with directions!) - entities[_i].framedelay--; - if(entities[_i].framedelay<=0) - { - entities[_i].framedelay = 6; - entities[_i].walkingframe++; - if (entities[_i].walkingframe == 2) + else { - entities[_i].walkingframe = 0; + entities[_i].walkingframe--; + if (entities[_i].walkingframe < 0) + { + entities[_i].walkingframe = 1; + entities[_i].actionframe = 0; + } } } entities[_i].drawframe = entities[_i].tile; - entities[_i].drawframe += entities[_i].walkingframe; - - if (entities[_i].vx > 0.000f ) entities[_i].drawframe += 2; + entities[_i].drawframe += entities[_i].walkingframe * offset; break; - case 10: + case EntityAnimationType_CONVEYOR_LEFT: //Threadmill left entities[_i].framedelay--; - if(entities[_i].framedelay<=0) + if (entities[_i].framedelay <= 0) { entities[_i].framedelay = 3;//(6-entities[_i].para); entities[_i].walkingframe--; @@ -3961,10 +3878,10 @@ void entityclass::animateentities( int _i ) entities[_i].drawframe = entities[_i].tile; entities[_i].drawframe += entities[_i].walkingframe; break; - case 11: + case EntityAnimationType_CONVEYOR_RIGHT: //Threadmill right entities[_i].framedelay--; - if(entities[_i].framedelay<=0) + if (entities[_i].framedelay <= 0) { entities[_i].framedelay = 3;//(6-entities[_i].para); entities[_i].walkingframe++; @@ -3977,37 +3894,35 @@ void entityclass::animateentities( int _i ) entities[_i].drawframe = entities[_i].tile; entities[_i].drawframe += entities[_i].walkingframe; break; - case 100: - //Simple case for no animation (platforms, etc) - entities[_i].drawframe = entities[_i].tile; - break; + case EntityAnimationType_STILL: default: entities[_i].drawframe = entities[_i].tile; break; } + break; + } case EntityType_DISAPPEARING_PLATFORM: //Disappearing platforms entities[_i].drawframe = entities[_i].tile + entities[_i].walkingframe; break; case EntityType_WARP_TOKEN: entities[_i].drawframe = entities[_i].tile; - if(entities[_i].animate==2) + + // Two frame loop + entities[_i].framedelay--; + if (entities[_i].framedelay <= 0) { - //Simpler Loop (just two frames) - entities[_i].framedelay--; - if(entities[_i].framedelay<=0) + entities[_i].framedelay = 10; + entities[_i].walkingframe++; + if (entities[_i].walkingframe == 2) { - entities[_i].framedelay = 10; - entities[_i].walkingframe++; - if (entities[_i].walkingframe == 2) - { - entities[_i].walkingframe = 0; - } + entities[_i].walkingframe = 0; } - - entities[_i].drawframe = entities[_i].tile; - entities[_i].drawframe += entities[_i].walkingframe; } + + entities[_i].drawframe = entities[_i].tile; + entities[_i].drawframe += entities[_i].walkingframe; + break; case EntityType_CREWMATE: case EntityType_COLLECTABLE_CREWMATE: diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index 4fc07a10bd..c0f4c221e1 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -37,7 +37,9 @@ struct EnemyType { int tile; int colour; - int animate; + int animation_frames; + EntityAnimationTypes animation_type; + int animation_speed; int width; int height; int harmful; @@ -65,7 +67,12 @@ class entityclass public: void init(void); - EnemyType* create_type(const char* type, int tile, int colour, int animate, int width, int height); + EnemyType* create_type( + const char* type, int tile, int colour, + EntityAnimationTypes animation_type, int animation_frames, int animation_speed, + int width, int height + ); + void add_default_types(void); const char* legacy_id_to_entity(int id); void set_enemy_type(entclass* entity, const char* type); diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index 4be62d091d..eeba7d27d4 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -521,21 +521,25 @@ void mapclass::changefinalcol(int t) { if (obj.entities[i].type == EntityType_MOVING) { - if (obj.entities[i].animate == 10 || obj.entities[i].animate == 11) //treadmill + if (obj.entities[i].animation_type == EntityAnimationType_CONVEYOR_LEFT || obj.entities[i].animation_type == EntityAnimationType_CONVEYOR_RIGHT) //treadmill { - if(temp<3) + if (temp < 3) { obj.entities[i].tile = 907 + (temp * 80); } else { - obj.entities[i].tile = 911 + ((temp-3) * 80); + obj.entities[i].tile = 911 + ((temp - 3) * 80); + } + + if (obj.entities[i].animation_type == EntityAnimationType_CONVEYOR_LEFT) + { + obj.entities[i].tile += 40; } - if(obj.entities[i].animate == 10) obj.entities[i].tile += 40; } else if (obj.entities[i].isplatform) { - obj.entities[i].tile = 915+(temp*40); + obj.entities[i].tile = 915 + (temp * 40); } else //just an enemy { diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 995d55cc41..29a5362bc1 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -314,13 +314,17 @@ void scriptclass::run(void) } else if (words[1] == "platforms" || words[1] == "moving") { - const bool fixed = words[1] == "moving"; - for (size_t edi = 0; edi < obj.entities.size(); edi++) { - if (obj.entities[edi].rule == 2 && obj.entities[edi].animate == 100) + if (obj.entities[edi].type == EntityType_DISAPPEARING_PLATFORM) { - if (fixed) + if (obj.entities[edi].behave >= 8 && obj.entities[edi].behave < 10) + { + // We don't want conveyors, moving platforms only + continue; + } + + if (words[1] == "moving") { obj.disableblockat(obj.entities[edi].xp, obj.entities[edi].yp); } From 44e8bce9a0b5ecb9b808d4f53d046b35ae9c1259 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Sun, 17 Nov 2024 15:16:28 -0400 Subject: [PATCH 11/12] Don't hardcode what emitters spawn! --- desktop_version/src/Ent.h | 5 +++++ desktop_version/src/Entity.cpp | 26 ++++++++++++++++++++++++-- desktop_version/src/Entity.h | 1 + 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/desktop_version/src/Ent.h b/desktop_version/src/Ent.h index ffb7892e00..b7fd532d5e 100644 --- a/desktop_version/src/Ent.h +++ b/desktop_version/src/Ent.h @@ -3,6 +3,8 @@ #include +#include + #define rn( rx, ry) ((rx) + ((ry) * 100)) enum EntityType @@ -117,6 +119,9 @@ class entclass SDL_Color realcol; int lerpoldxp, lerpoldyp; + + // Emitter specific + std::string to_spawn; }; #endif /* ENT_H */ diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index b4ef76ca5f..0f392b1369 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -131,6 +131,7 @@ EnemyType* entityclass::create_type( enemy_type.override_x2 = false; enemy_type.override_y1 = false; enemy_type.override_y2 = false; + enemy_type.to_spawn = ""; enemy_types[type] = enemy_type; return &enemy_types[type]; @@ -213,6 +214,8 @@ void entityclass::add_default_types(void) type->x1 = -200; type->override_behave = true; type->override_x1 = true; + type->to_spawn = "lies"; + type = create_type("lies", 63, 6, EntityAnimationType_STILL, 1, 1, 26, 10); type->corner_x = 1; type->corner_y = 1; @@ -225,6 +228,7 @@ void entityclass::add_default_types(void) type->override_para = true; type->override_x1 = true; type->override_x2 = true; + type = create_type("lies_collector", 62, 6, EntityAnimationType_STILL, 1, 1, 32, 32); type->behave = -1; type->override_behave = true; @@ -235,6 +239,8 @@ void entityclass::add_default_types(void) type->render_type = EntityRenderType_SPRITE_2x2; type->behave = 12; type->override_behave = true; + type->to_spawn = "factory_clouds"; + type = create_type("factory_clouds", 76, 6, EntityAnimationType_STILL, 1, 1, 32, 12); type->corner_y = 6; type->x_offset = 4; @@ -245,6 +251,7 @@ void entityclass::add_default_types(void) type->override_behave = true; type->override_para = true; type->override_x2 = true; + type = create_type("factory_collector", 77, 6, EntityAnimationType_STILL, 1, 1, 32, 16); type->behave = -1; type->override_behave = true; @@ -279,6 +286,7 @@ void entityclass::set_enemy_type(entclass* entity, const char* type) entity->yp += enemyType->y_offset; entity->lerpoldyp += enemyType->y_offset; entity->render_type = enemyType->render_type; + entity->to_spawn = enemyType->to_spawn; if (enemyType->colour != -1) { @@ -2688,8 +2696,15 @@ bool entityclass::updateentities( int i ) //Emitter: shoot an enemy every so often if (entities[i].state == 0) { + std::string to_spawn = entities[i].to_spawn; + if (to_spawn == "") + { + // A default, for supporting older custom levels + to_spawn = "lies"; + } + entclass* entity = createentity(entities[i].xp+28, entities[i].yp, 1, 10, -1); - set_enemy_type(entity, "lies"); + set_enemy_type(entity, to_spawn.c_str()); entity->colour = entities[i].colour; entities[i].state = 1; entities[i].statedelay = 12; @@ -2725,8 +2740,15 @@ bool entityclass::updateentities( int i ) //Emitter: shoot an enemy every so often (up) if (entities[i].state == 0) { + std::string to_spawn = entities[i].to_spawn; + if (to_spawn == "") + { + // A default, for supporting older custom levels + to_spawn = "factory_clouds"; + } + entclass* entity = createentity(entities[i].xp, entities[i].yp, 1, 12, -1); - set_enemy_type(entity, "factory_clouds"); + set_enemy_type(entity, to_spawn.c_str()); entity->colour = entities[i].colour; entities[i].state = 1; entities[i].statedelay = 16; diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index c0f4c221e1..e448a99a5b 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -60,6 +60,7 @@ struct EnemyType bool override_y1; int y2; bool override_y2; + std::string to_spawn; }; class entityclass From bd869d928662dfca42727e95eeb25fcbdb00f5ff Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Sun, 17 Nov 2024 15:18:10 -0400 Subject: [PATCH 12/12] Fix a couple issues --- desktop_version/src/Entity.cpp | 1 + desktop_version/src/Graphics.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 0f392b1369..bab71973cb 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -2460,6 +2460,7 @@ entclass* entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, const char* type = legacy_id_to_entity(customenemy); set_enemy_type(&entity, type); set_enemy_colour(&entity); + break; } case 100: // Invalid enemy, but gets treated as a teleporter entity.type = EntityType_TELEPORTER; diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index a235f31d47..587a1a8cac 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -2353,6 +2353,8 @@ void Graphics::drawentity(const int i, const int yoff) draw_grid_tile(grphx.im_sprites, obj.entities[i].drawframe, xp, yp - yoff, sprites_rect.w, sprites_rect.h, obj.entities[i].realcol, 6, 6); break; } + case EntityRenderType_INVALID: + break; } }