I think that one's a bug in ZC. Seems to do it no matter what.
I think that one's a bug in ZC. Seems to do it no matter what.
Updated for builds 1174 and up. Handles stunning better now, and a couple of small bugs are fixed.
Another update. Added a new init method, improvements to stunning and thrown eweapons.
Does anyone besides me actually use this, or have any interest in doing so? I could write up a tutorial, if it'd be helpful.
(Edit: Small update: fixed a minor issue in the demo and a significant mistake in the documentation.)
(Another edit: Gah, I broke knockback last time. Fixed now. Added a couple more functions while I was at it.)
This header seems pretty useful..
Here's something I made with it
And the up/down one for good measure.Code://This script creates an enemy that walks left to right between solid combos, //similar to a Goomba from Super Mario Bros. //Set D0 to 0 to start right and 1 to start left. //D1 = Enemy type to use for ghosting ffc script goomba_left_right { void run(bool startleft, int enemtype) { npc goomba; int timer; bool left; bool right; if(startleft){left = true; right = false;} else {right = true; left = false;} goomba=GhostInitCreate(this, enemtype); SetFlags(this, GHF_NORMAL); timer = 2; for(int i=0; true; i++) { if(i==timer) { i=0; if(!right && left && CanMove(this,goomba,2,1,0)) Move(this,goomba,-1,0,0); else right = true; if(right && CanMove(this,goomba,3,1,0))Move(this,goomba,1,0,0); else { left = true; right = false;} } GhostWaitframeF(this, goomba, true, true); } } }
If you're going to use these, be sure to import "ghost.zh"!Code://This script creates an enemy that walks down and up between solid combos, //Set D0 to 0 to start down and 1 to start up. //D1 = Enemy type to use for ghosting ffc script goomba_up_down { void run(bool startup, int enemtype) { npc goomba; int timer; bool up; bool down; if(startup){up = true; down = false;} else {down = true; up = false;} goomba=GhostInitCreate(this, enemtype); SetFlags(this, GHF_NORMAL); timer = 2; for(int i=0; true; i++) { if(i==timer) { i=0; if(!down && up && CanMove(this,goomba,0,1,0)) Move(this,goomba,0,-1,0); else down = true; if(down && CanMove(this,goomba,1,1,0))Move(this,goomba,0,1,0); else { up = true; down = false;} } GhostWaitframeF(this, goomba, true, true); } } }
EDIT: I am a very poor scripter, so a tutorial on how to put together a custom boss with this would be very nice
First boss I made with it:
Code:// Zora King // Will work best with a Freeform Combo set to Combo W: 32, Combo H: 32, Tile W: 2, Tile H: 2, with provided graphics. // NOTE: Using a SkipX setting of 1 on the combo will allow // you to animate using 2x2 tile chunks. // D0 - The number pointing to another Freeform Combo // Used to display the diving, as well as house more variables. // (Check below for details) // D1 - The total duration the zora will stay on the screen. // D2 - Enemy Type to use for ghosting // D3 - Total hit points // D4 - Fire every this amount of frames when above water; // D5 - Damage of projectile; // D6 - Fireballs Per Shot (set to an odd number up to 9. Even numbers may function but are not recommended) // D7 - Sprite to use for fireball // As mentioned above, further customization is allowed by // By using the D variables stored in the FFC called by D0 // D0 = Projectile movement pattern(0 for normal shot) // D1 = Projectile movement argument (0 for none) // See ghost.zh for its EWM constants for what to use as patterns // See ghost_zh_readme.txt for what to use as argument. // Use ZRB_CHECKPOINT Floats to specify in percentages when the Zora will be submerged, rise, appear, and sink. const float ZRB_CHECKPOINT1 = 0.30;// Time From Phase 1 to 2. Decimal indicates a percentage. const float ZRB_CHECKPOINT2 = 0.45;// Time From Phase 2 to 3. Decimal indicates a percentage. const float ZRB_CHECKPOINT3 = 0.60;// Time from Phase 3 to 4. Decimal indicates a percentage. const float ZRB_CHECKPOINT4 = 0.75;// Time from Phase 4 to end(staytime). Decimal indicates a percentage. const int ZRB_PRJ_X_OFFSET = 8; // Offset of projectile from origin in X const int ZRB_PRJ_Y_OFFSET = 16; // Offset of projectile from origin in Y ffc script zora_king { //Running part of script void run(int diveffc_s, int staytime, int enemtype, int enemhp, int fireat, int firedmg, int fireperarc, int firesprite) { npc zoraboss; eweapon zora_fire; //Loads an FFC ffc diveffc = Screen->LoadFFC(diveffc_s); int fire_mtype = diveffc->InitD[0]; int fire_arg = diveffc->InitD[1]; TraceNL(); Trace(fire_mtype); TraceNL(); Trace(fire_arg); int time_check = 0; int water_check = 1; int checkpoint_1 = (staytime*ZRB_CHECKPOINT1); int checkpoint_2 = (staytime*ZRB_CHECKPOINT2); int checkpoint_3 = (staytime*ZRB_CHECKPOINT3); int checkpoint_4 = (staytime*ZRB_CHECKPOINT4); int pop_up_x = 16 * Rand(15); int pop_up_y = 16 * Rand(10); zoraboss = GhostInitCreate(this,enemtype); SetHP(this,zoraboss,enemhp); while(true){ if(water_check == 1){pop_up_x = 16 * Rand(15);pop_up_y = 16 * Rand(10); water_check = 0;} if(IsWater(ComboAt(pop_up_x,pop_up_y)) && IsWater(ComboAt(pop_up_x + 16,pop_up_y)) && IsWater(ComboAt(pop_up_x,pop_up_y + 16)) && IsWater(ComboAt(pop_up_x + 16,pop_up_y + 16))){} else {pop_up_x = 16 * Rand(15);pop_up_y = 16 * Rand(10);} if(time_check < staytime) time_check++; if(time_check <= checkpoint_1){ change_x_y_2(this, 256, 176, diveffc, 256, 176); } if(time_check > checkpoint_1 && time_check <= checkpoint_2){ change_x_y_2(this, 256, 176, diveffc, pop_up_x, pop_up_y); } if(time_check > checkpoint_2 && time_check <= checkpoint_3){ change_x_y_2(this, pop_up_x, pop_up_y, diveffc, 256, 176); if(time_check % fireat == 0){ if (fireperarc >= 1){ zora_fire=FireAimedEWeapon(129, this->X + ZRB_PRJ_X_OFFSET, this->Y + ZRB_PRJ_Y_OFFSET, 0, 200, firedmg,false, firesprite, false, 0); if(fire_mtype > 0) SetEWeaponMovement(zora_fire, fire_mtype, fire_arg); } if (fireperarc >= 3){ zora_fire=FireAimedEWeapon(129, this->X + ZRB_PRJ_X_OFFSET, this->Y + ZRB_PRJ_Y_OFFSET, -0.1, 200, firedmg,false, firesprite, false, 0); if(fire_mtype > 0)SetEWeaponMovement(zora_fire, fire_mtype, fire_arg); zora_fire=FireAimedEWeapon(129, this->X + ZRB_PRJ_X_OFFSET, this->Y + ZRB_PRJ_Y_OFFSET, 0.1, 200, firedmg,false, firesprite, false, 0); if(fire_mtype > 0)SetEWeaponMovement(zora_fire, fire_mtype, fire_arg); } if (fireperarc >= 5){ zora_fire=FireAimedEWeapon(129, this->X + ZRB_PRJ_X_OFFSET, this->Y + ZRB_PRJ_Y_OFFSET, -0.2, 200, firedmg,false, firesprite, false, 0); if(fire_mtype > 0)SetEWeaponMovement(zora_fire, fire_mtype, fire_arg); zora_fire=FireAimedEWeapon(129, this->X + ZRB_PRJ_X_OFFSET, this->Y + ZRB_PRJ_Y_OFFSET, 0.2, 200, firedmg,false, firesprite, false, 0); if(fire_mtype > 0)SetEWeaponMovement(zora_fire, fire_mtype, fire_arg); } if (fireperarc >= 7){ zora_fire=FireAimedEWeapon(129, this->X + ZRB_PRJ_X_OFFSET, this->Y + ZRB_PRJ_Y_OFFSET, -0.3, 200, firedmg,false, firesprite, false, 0); if(fire_mtype > 0)SetEWeaponMovement(zora_fire, fire_mtype, fire_arg); zora_fire=FireAimedEWeapon(129, this->X + ZRB_PRJ_X_OFFSET, this->Y + ZRB_PRJ_Y_OFFSET, 0.3, 200, firedmg,false, firesprite, false, 0); if(fire_mtype > 0)SetEWeaponMovement(zora_fire, fire_mtype, fire_arg); } if (fireperarc >= 9){ zora_fire=FireAimedEWeapon(129, this->X + ZRB_PRJ_X_OFFSET, this->Y + ZRB_PRJ_Y_OFFSET, -0.4, 200, firedmg,false, firesprite, false, 0); if(fire_mtype > 0)SetEWeaponMovement(zora_fire, fire_mtype, fire_arg); zora_fire=FireAimedEWeapon(129, this->X + ZRB_PRJ_X_OFFSET, this->Y + ZRB_PRJ_Y_OFFSET, 0.4, 200, firedmg,false, firesprite, false, 0); if(fire_mtype > 0)SetEWeaponMovement(zora_fire, fire_mtype, fire_arg); } if (fireperarc >= 11){ zora_fire=FireAimedEWeapon(129, this->X + ZRB_PRJ_X_OFFSET, this->Y + ZRB_PRJ_Y_OFFSET, -0.5, 200, firedmg,false, firesprite, false, 0); if(fire_mtype > 0)SetEWeaponMovement(zora_fire, fire_mtype, fire_arg); zora_fire=FireAimedEWeapon(129, this->X + ZRB_PRJ_X_OFFSET, this->Y + ZRB_PRJ_Y_OFFSET, 0.5, 200, firedmg,false, firesprite, false, 0); if(fire_mtype > 0)SetEWeaponMovement(zora_fire, fire_mtype, fire_arg); } } } if(time_check > checkpoint_3 && time_check <= checkpoint_4){ change_x_y_2(this, pop_up_x, pop_up_y, diveffc, 256, 176); } if(time_check > checkpoint_4 && time_check <= staytime){ change_x_y_2(this, 256, 176, diveffc, pop_up_x, pop_up_y); } if(time_check >= staytime){water_check = 1; time_check = 0;} GhostWaitframeF(this, zoraboss, true, true); } } void change_x_y_2(ffc f1, int x1, int y1, ffc f2, int x2, int y2) { f1->X = x1; f1->Y = y1; f2->X = x2; f2->Y = y2; } }
Updated. It needs build 1326+ now, so it's only for Linux and the debug build at the moment.
- Fixed a couple of small bugs.
- Enemies can now have combos set automatically based on direction.
- Added a function to adjust the enemy's hitbox.
- Eweapons can now flicker and cast shadows, and there's now a falling movement type.
- Added functions to create eweapons larger than 1x1.
- The SetFlags() and all three FireEWeapon functions have changed; the old versions are deprecated.
I've also added on to the demo. Do try it, I'm rather proud of it. If you can't/won't play it, I also made a video of it.
Also, bigjoe, you'd suggested adding functions for lweapons and items? Not a bad idea, but I think that'd be a different file. I probably will do that in the future.
So, I kind of screwed up the last update. The link was pointing to an older version. Sorry. Fixed now.
There are currently 2 users browsing this thread. (0 members and 2 guests)