Mega Man 8-bit Deathmatch > Projects & Creative

Endless Attack - Roguelike Mission Mode

(1/1)

Trillster:
Time to see who all remembers the Mission Mode layouts,
(click to show/hide)
--- Quote ---
--- End quote ---

Endless Attack Mission Mode

The name here's pretty self-explanatory. You get segments of various old Mission Mode maps combined with some new segments into a randomized rogue-like inspired game mode that allows you to collect weapons as you progress towards beating every boss. Segments get more difficult with harder enemy types and potential new layouts as your score rises. High scores and fastest times for each segment are recorded, so go for broke with the lives provided for each run. Defeat a boss and everyone gets a free restock of lives to get right back into the action. It's the classic Mission Mode gameplay just with extended replay value and option for mappers to create custom level segment packs and load them alongside the mod for a larger pool of pieces to fight through. Even programmers can get in on the fun with potential for custom bosses and even more weapons to fight for, so it's the ever-expanding Mission Mode experience.

Screenshots
(click to show/hide)
--- Quote --- (click to show/hide)
--- Quote ---
--- End quote ---
(click to show/hide)
--- Quote ---
--- End quote ---
(click to show/hide)
--- Quote ---
--- End quote ---
(click to show/hide)
--- Quote ---
--- End quote ---

--- End quote ---

Credits
(click to show/hide)
--- Quote ---Endless Attack by Trillster

Endless Attack Randomizer - Trillster
Boss Backend - Russel
MMSP Map Segments - CutmanMike
Testing - Pegg
Testing - Blews
Testing - Llama
Testing - Zappoola
Testing - Yair
Testing - FTX6004

Original MMSP Project by CutmanMike

Hammer Joe -  Kackebango
Needleman Stab Animation - Maxine & Korby
Sniper Armor - Kackebango, updated by Hansungkee
Apache Joe - Kackebango, updated by FTX6004
Bomb Thrown - Kackebango
Every other enemy included - CutmanMike

--- End quote ---

FAQ
(click to show/hide)
--- Quote ---Can I play this mode offline?
Yes! All you need to do is load up your files and load EAHUB in Survival Cooperative mode via Offline Skirmish in the menu.

How do I develop new level segments?
(click to show/hide)
--- Quote ---Creating new level segments is relatively painless as long as you're experienced with Doom Builder already and have some basic ACS knowledge. Just don't forget to load the Endless Attack file as a resource so you'll have access to all the enemies within the build.

For the mapping side of things, you'll want to create a teleporter for your spawn point to sit on. All you need is a single SP Player 1 Start placed right on top of it, all players are gonna spawn in this spot and telefragging is disabled, so there's no need for more. For the end of your level, you'll do similar, just this time instead of a spawn point, you'll want to add an "Actor hits floor" activator. It should activate special 226 with a named script of "sp_nextlevel". Just be careful of any spaces else the script won't properly execute.
(click to show/hide)
--- Quote ---
--- End quote ---

Take care when designing your level segments such that they don't feel too daunting with length or difficulty. The standard of play is 3 lives per run, so you certainly don't want your segment to be the de facto run killer. However, make sure to include 1-Ups in your level if you want to encourage players to take risks for potential rewards. Don't forget to include a map card with your map as well, after all, players are gonna need the person to blame for when the run loses.

Once your level segment is finished, implementing it into the Endless Attack segment pool is as easy as a single script. Make sure to drag the EA_MAPS.ACS source file into your own project, so that it can properly be imported into your own ACS file, but don't compile it. Once done, you'll want to create an ACS file that looks something like this TRL_IPRT.ACS,

--- Quote from: TRL_IPRT.ACS ---#library "trl_iprt"
#include "zcommon.acs"

#import "ea_maps.acs"

Script "trill_imports" OPEN
{
Delay(5);
defineMap("TRILL01");
defineMap("TRILL02");
defineMap("TRILL03");
}
--- End quote ---
This is the file that you'll wanna make sure that you compile every time you need to update it to introduce a new level segment. Make sure to create a LOADACS file as well, with the name of the compiled ACS file, so in this case, it would be a LOADACS file with the line "TRL_IPRT". This tells the game to make sure to load that compiled ACS with every startup.

For a standard level segment, this is where you can stop and all will be well with its introduction. However, Endless Attack offers the option to include an increased difficulty layout for each map. The map variant is created the exact same way as before, but the ACS definition is a bit different. You can see an example of how you'd define TRILL01 and its variant EXTRLL01 in the following code,

--- Quote from: TRL_IPRT.ACS ---#library "trl_iprt"
#include "zcommon.acs"

#import "ea_maps.acs"

Script "trill_imports" OPEN
{
Delay(5);
defineMapWithEX("TRILL01", "EXTRLL01");
defineMap("TRILL02");
defineMap("TRILL03");
}
--- End quote ---
So every time TRILL01 is rolled for the next map, if the stage is also rolled to be a variant stage, it'll instead opt to use EXTRLL01 as the map.

That's all there is to know for developing new level segments and there's plenty of existing content to reference if any issues are ran into, so good luck with the mapping!

--- End quote ---

How do I make Sniper Joes stand still?
A few of the enemies defined in Endless Attack have special behavior when you toggle their first argument. Here's a list of them,
(click to show/hide)
--- Quote ---Metool - With its first argument toggled to 1, it'll immediately go back into its helmet after shooting rather than running around.
Sniper Joe Shielder - With its first argument toggled to 1, it'll stand still between firing rounds.
Sniper Joe Grenadier - With its first argument toggled to 1, it'll stand still between attacks. With its second argument toggled to 1, it'll only toss grenades without using the buster.
Time Pendulum - The speed that the pendulum swings at is determined by its first argument.
Hammer Joe - With its first argument toggled to 1, it'll stand still between tossing its hammers.
Puyopon - With its first argument toggled to 1, it'll start on the ceiling wherever you placed it rather than beginning on the floor.
Escaroo - With its first argument toggled to 1, it'll become invincible and only fire bombs around it in a spiral, good for creating a stationary hazard!
Flamethrower Joe - With its first argument toggled to 1, it'll stand still between usages of the flamethrower.
--- End quote ---

How do I develop new enemies for my maps?
(click to show/hide)
--- Quote ---The main important notes with enemy creation is to make use of the standardization already in place for enemies, otherwise your enemies might feel nonfunctional or out of place. To do this, make sure to inherit your enemy off of "GenericRobot" so that it receives the standard flags that most enemies in the project have. This makes sure that weapons will feel consistent against your enemies and they won't have any difficulties traversing your maps.

Additionally, you'll want to make sure that each enemy you create calls "ACS_NamedExecuteAlways("sp_enemystart",0)" on its first frame, and preferably in a way such that it won't attempt to call the script again to reduce network usage. This script is responsible for multiple things, most importantly the HP scaling for additional players, and the pain feedback for when they receive damage. In the case that you want an enemy to not experience HP scaling, such as with respawning enemies, failing to call that script isn't a proper method of doing that. Instead, you should call "A_GiveInventory("HealthScaled",1)" first, then still proceed to call "ACS_NamedExecuteAlways("sp_enemystart",0)".

For any instance of damage an enemy does, make sure that it is followed by "*ACS_NamedExecuteWithResult("sp_cbmHP")". This script checks whether or not a mod with higher base HP values, such as CBM, is loaded, and appropriately scales the damage so that it matches up. It allows your enemies to be compatible with more than just vanilla being ran with it. Additionally, make sure that it uses a damagetype of "Enemy", "Misc", or "FlingDamage". "Enemy" has standard hitstun, "Misc" has no hitstun, and "FlingDamage" applies a Wind Storm effect to the player. These ensure that your enemy won't be able to friendly fire any of their comrades on the field.

Finally, make sure that you give your enemy a DoomEditor number that doesn't conflict with any existing enemies or props, alongside including "//$Category MM8BDM-Enemies" among its flags. This allows your enemy to be placed into maps and organized into a category with all other enemies from Endless Attack.

For an example of how an enemy should look in this format, reference this Flamethrower Joe,
(click to show/hide)
--- Quote ---actor FlamethrowerJoe : GenericRobot 30039
{
//$Category MM8BDM-Enemies
Height 52
Radius 32
Obituary "%o was burnt to crisps by a Flamethrower Joe."
Health 95

translation "192:192=4:4", "198:198=227:227"

maxstepheight 50
+MISSILEEVENMORE
+MISSILEMORE
+LOOKALLAROUND

dropitem "WeaponEnergy", 16
dropitem "SmallHealth", 16
speed 8
States
{
Spawn:
TNT1 A 0
TNT1 A 0 ACS_NamedExecuteAlways("sp_enemystart",0)
Look:
SNIP A 5 A_LookEx(LOF_NOSOUNDCHECK,0,0,0,360,"See")
loop
See:
SNIP B 1
SNIP B 1 A_JumpIf(Args[0]==1, "See2")
SNIP B 1 //A_JumpIfTargetInLOS("ShieldUp") // THIS FUNCTION IS BUGGED ONLINE ARGH!
SNIP BBBB 1 A_Chase
SNIP A 0// A_JumpIfTargetInLOS("ShieldUp")
SNIP CCCC 1 A_Chase
SNIP A 0 //A_JumpIfTargetInLOS("ShieldUp")
SNIP DDDD 1 A_Chase
SNIP A 0 //A_JumpIfTargetInLOS("ShieldUp")
SNIP EEEE 1 A_Chase
Goto See+3
See2:
SNIP A 1 //A_JumpIfTargetInLOS("ShieldUp")
Goto Missile
ShieldUp:
Missile:
TNT1 A 0 A_SpawnItemEx("SP_SniperJoeShieldX",23,-17,8,momx, momy, momz, 0, SXF_NOCHECKPOSITION|SXF_ABSOLUTEMOMENTUM, 0)
TNT1 A 0 A_SpawnItemEx("SP_SniperJoeShieldFX",23,-17,8,momx, momy, momz, 0, SXF_NOCHECKPOSITION|SXF_ABSOLUTEMOMENTUM|SXF_TRANSFERTRANSLATION, 0)
SNIP A 2 A_FaceTarget
TNT1 A 0 A_GiveInventory("CutterFlag",1)
TNT1 A 0 A_JumpIfInventory("CutterFlag",30,"ReadyFire")
loop
ReadyFire:
TNT1 A 0 A_TakeInventory("CutterFlag",999)
TNT1 A 0 A_SpawnItemEx("SP_SniperJoeShieldX",23,-17,8,momx, momy, momz, 0, SXF_NOCHECKPOSITION|SXF_ABSOLUTEMOMENTUM, 0)
TNT1 A 0 A_SpawnItemEx("SP_SniperJoeShieldFX",23,-17,8,momx, momy, momz, 0, SXF_NOCHECKPOSITION|SXF_ABSOLUTEMOMENTUM|SXF_TRANSFERTRANSLATION, 0)
SNIP A 2 A_FaceTarget
SNIP A 0 A_JumpIfCloser(512,"ShieldFire")
Goto ReadyFire

ShieldFire:
SNIP FFFFF 5 A_FaceTarget
SNIP F 0 A_FaceTarget
SNIP F 0 A_PlaySoundEx("weapon/magmabazooka","Weapon")
SNIP F 0 A_PlaySoundEx("weapon/heatshot","SoundSlot6")
SNIP F 2 A_CustomMissile("JoeFlamethrower",12,6,frandom(-3,3),0,frandom(-3,3))
SNIP F 0 A_FaceTarget
SNIP F 2 A_CustomMissile("JoeFlamethrower",12,6,frandom(-3,3),0,frandom(-3,3))
SNIP F 0 A_FaceTarget
SNIP F 2 A_CustomMissile("JoeFlamethrower",12,6,frandom(-3,3),0,frandom(-3,3))
SNIP F 0 A_FaceTarget
SNIP F 2 A_CustomMissile("JoeFlamethrower",12,6,frandom(-3,3),0,frandom(-3,3))
SNIP F 0 A_FaceTarget
SNIP F 2 A_CustomMissile("JoeFlamethrower",12,6,frandom(-3,3),0,frandom(-3,3))
SNIP F 0 A_FaceTarget
SNIP F 2 A_CustomMissile("JoeFlamethrower",12,6,frandom(-3,3),0,frandom(-3,3))
SNIP F 0 A_FaceTarget
SNIP F 2 A_CustomMissile("JoeFlamethrower",12,6,frandom(-3,3),0,frandom(-3,3))
SNIP F 0 A_FaceTarget
SNIP F 2 A_CustomMissile("JoeFlamethrower",12,6,frandom(-3,3),0,frandom(-3,3))
SNIP F 0 A_FaceTarget
SNIP F 2 A_CustomMissile("JoeFlamethrower",12,6,frandom(-3,3),0,frandom(-3,3))
SNIP F 0 A_FaceTarget
SNIP F 2 A_CustomMissile("JoeFlamethrower",12,6,frandom(-3,3),0,frandom(-3,3))
SNIP F 15
SNIP F 1 A_JumpIf(Args[0]==0, "See")
SNIP A 0 A_ClearTarget
Goto Look

Death:
CRAZ A 0 A_Pain
CRAZ A 0 A_Fall
TNT1 A 5 A_SpawnItem("EnemyDeathFX",0,32)
TNT1 A -1
stop
}
}

actor JoeFlamethrower
{
PROJECTILE
+BRIGHT
Damage (3*ACS_NamedExecuteWithResult("sp_cbmHP"))
Speed 30
Obituary "%o was burnt to crisps by a Flamethrower Joe."
damagetype "Enemy"
Radius 20
Height 20
reactiontime 1
scale 2.5
States
{
Spawn:
TNT1 A 0
SpawnLoop:
XE01 ABC 2 A_SpawnItemEx("JoeFlamethrowerFX",0,0,0,0,0,0,0,1)
XE01 DEF 2 A_SpawnItemEx("JoeFlamethrowerFX2",0,0,0,0,0,0,0,1)
XE01 F 1 A_Countdown
wait
Death:
TNT1 A 1 A_SpawnItemEx("OilPitIgnite",0,0,8)
stop
}
}

actor JoeFlamethrowerFX : BasicGraphicEffect
{
+BRIGHT
renderstyle add
Alpha 0.8
states
{
Spawn:
XE01 A 0
XE01 BCD 1 A_FadeOut(0.2)
stop
}
}

actor JoeFlamethrowerFX2 : BasicGraphicEffect
{
+BRIGHT
renderstyle add
Alpha 0.8
states
{
Spawn:
XE01 A 0
XE01 EFG 1 A_FadeOut(0.2)
stop
}
}
--- End quote ---

If that's all you want out of your enemy, you can stop here. However, if you want your enemy to have harder AI and change colors as the run progresses, you'll need to define it as an EX enemy. This is done with some basic ACS definition in the same vein of defining a new level segment. You'll want to make sure to drag the EA_EX.ACS source file into your project, but again, don't compile it, it'll be used for importing instead. Then, you'll want to create a file that looks something like the following,

--- Quote from: SP_IMPRT.ACS ---#library "sp_imprt"
#include "zcommon.acs"

#import "ea_ex.acs"

#DEFINE MACHINEGUNJOE 10500
#DEFINE MACHINEGUNJOESCOUT 10501
#DEFINE MACHINEGUNJOEGRENADE 10502

Script "sp_translations" OPEN CLIENTSIDE
{
Delay(25);
CreateTranslation(MACHINEGUNJOE, 192:192=4:4, 198:198=42:42);
CreateTranslation(MACHINEGUNJOESCOUT, 192:192=4:4, 198:198=171:171);
CreateTranslation(MACHINEGUNJOEGRENADE, 192:192=4:4, 198:198=41:41);
}

Script "sp_imports" OPEN
{
Delay(5);
defineEXEnemy("SniperJoeScout", "SniperJoeScoutEXPackage");
defineEXEnemy("SniperJoeShielded", "SniperJoeShieldedEXPackage");
defineEXEnemy("SniperJoeGrenader", "SniperJoeGrenaderEXPackage");
defineEXEnemy("SniperArmor", "EXEnemyToggled");
defineEXEnemy("MetEnemy", "EXEnemyToggled");
}
--- End quote ---
The defineEXEnemy function first specifies the actor name of the enemy, then the inventory item to give to that enemy to allow it to take on EX enemy traits. Since Sniper Armors only begin to walk when they've become an EX enemy, they only need the "EXEnemyToggled" flag that their AI checks for. However, you can see that since SniperJoeScout changes color as well, he is given a CustomInventory actor which you can see below,

--- Quote ---actor SniperJoeScoutEXPackage : CustomInventory
{
States
{
Pickup:
TNT1 A 0 Thing_SetTranslation(0,10501)
TNT1 A 0 A_GiveInventory("EXEnemyToggled",1)
stop
}
}
--- End quote ---
As a closing note, just make sure to design your enemies fairly so that they don't feel overbearing to deal with as a player. Bosses are where players are challenged in combat, so there's no need to create levels filled with crazy enemies out to take everyone's lives.

--- End quote ---

How do I develop new bosses?
(click to show/hide)
--- Quote ---Creating bosses is very similar to creating enemies, as in, it's just a matter of keeping to the standardization already set by the other bosses. You'll want to have your boss inherit off of BasicBoss and call its Spawn state and Intro states in a very similar way as to the other bosses do currently. This will ensure that the boss doesn't skip any important steps of the introduction sequence.

Failure to follow that can lead to your boss not having proper pain feedback when hit, or not receiving the proper item to signify that their super is available for usage. You'd find yourself unable to "BossSuperAvailable50%" or "BossSuperAvailable25%".

As with the enemies, any instance of damage the boss does should be followed by "*ACS_NamedExecuteWithResult("sp_cbmHP")", again, to ensure that their damage properly scales when mods such as CBM are in play.

For an example of how a boss should look in this format, reference Needleman's boss,
(click to show/hide)
--- Quote ---actor NeedlemanBoss : BasicBoss
{
Obituary "%o was pricked by \chNeedle Man\c-."

speed 0
States
{
Intro:
NEED K 0
NEED K 0 A_TakeInventory("BossIntroFlag", 1)
NEED K 0 A_ChangeFlag("CANTSEEK", true)
NEED K 0 A_ChangeFlag("INVULNERABLE", true)
NEED K 1 A_JumpIf(floorz-z==0,"Intro2")
wait
Intro2:
NEED A 5
NEED I 5
wait

Spawn:
NEED K 0
NEED K 0 A_ChangeFlag("CANTSEEK", false)
NEED K 0 A_ChangeFlag("INVULNERABLE", false)
NEED K 0 A_JumpIfInventory("HealthScaled",1,"Spawn2")
NEED K 0 ACS_NamedExecuteAlways("EA_BossManage", 0)
NEED K 0 A_JumpIfInventory("BossIntroFlag", 1, "Intro")
Spawn2:
NEED K 0 A_ClearTarget
NEED A 0 A_ChangeFlag("INVULNERABLE",0)
NEED A 5 A_LookEx(LOF_NOSOUNDCHECK,0,0,0,360,"Found")
Goto Spawn2+2
Found:
NEED A 20
Goto See
See:
NEED A 10 A_FaceTarget
NEED K 15 A_ChangeVelocity(0.0,0.0,19.0,CVF_REPLACE|CVF_RELATIVE)
Goto Attack1
SuperChance:
NEED A 0 A_Jump(200,"Super")
Goto See

Attack1:
NEED K 1
CUTM J 0 A_JumpIf(floorz-z==0,"Land")
NEED K 1
NEED A 0 A_Jump(80,"Missile")
NEED K 1
loop
Missile:
NEED K 1
NEED A 0 A_ChangeVelocity(0.0,0.0,0.0,CVF_REPLACE|CVF_RELATIVE)
NEED A 0 A_ChangeFlag("NOGRAVITY",1)
NEED K 1 A_FaceTarget
NEED K 0 A_PlaySoundEx("enemy/needlemanfire","Voice")
NEED J 4 A_CustomMissile("NeedlemanNeedle",40,-28,random(-2,2))
NEED K 4 A_FaceTarget
NEED K 0 A_PlaySoundEx("enemy/needlemanfire","Voice")
NEED L 4 A_CustomMissile("NeedlemanNeedle",40,28,random(-2,2))
NEED K 4 A_FaceTarget
NEED K 12 A_ChangeFlag("NOGRAVITY",0)
Goto Attack1

Land:
NEED A 1
NEED A 3 A_ChangeVelocity(0.0,0.0,0.0,CVF_REPLACE|CVF_RELATIVE)
NEED A 1
NEED AAAA 2 A_LookEx(LOF_NOSOUNDCHECK,0,190,0,360,"Stab")
Goto Leap
Land2:
NEED A 1
NEED A 3 A_ChangeVelocity(0.0,0.0,0.0,CVF_REPLACE|CVF_RELATIVE)
NEED A 1
NEED AAAA 2 A_LookEx(LOF_NOSOUNDCHECK,0,190,0,360,"Stab2")
NEED A 0 A_JumpIfInventory("BossSuperAvailable50%",1,"SuperChance")
Goto Spawn2
Stab:
NEED P 5 A_FaceTarget
NEED P 0 A_PlaySoundEx("weapon/slashclaw","Voice")
NEED O 5 A_CustomBulletAttack(0,0,1,15*ACS_NamedExecuteWithResult("sp_cbmHP"),"NoPuff",250)
NEED P 5 A_FaceTarget
NEED A 15
Goto Leap
Stab2:
NEED P 5 A_FaceTarget
NEED P 0 A_PlaySoundEx("weapon/slashclaw","Voice")
NEED O 5 A_CustomBulletAttack(0,0,1,15*ACS_NamedExecuteWithResult("sp_cbmHP"),"NoPuff",250)
NEED P 5 A_FaceTarget
NEED A 15
Goto See

Leap:
NEED K 1 A_FaceTarget
NEED A 1 //A_SetAngle(angle + random(-32,32))
NEED A 0 A_ChangeVelocity(17.0,0.0,15.0,CVF_REPLACE|CVF_RELATIVE)
NEED K 8
Goto Leaping
Melee:
NEED K 5 A_SpawnItemEx("NeedlemanMelee")//A_CustomMeleeAttack(20)
Goto Leaping

Leaping:
NEED K 1 A_JumpIf(floorz-z==0,"Land2")
loop
Leaping2:
NEED K 1 A_JumpIf(floorz-z==0,"Spawn")
loop

Super:
NEED A 0 A_PlaySoundEx("enemy/bosssuper","Voice",0,1)
NEED A 0 A_ChangeFlag("INVULNERABLE",1)
NEED G 0 A_FaceTarget
NEED A 4 Thing_SetTranslation(0,62)
NEED A 4 Thing_SetTranslation(0,0)
NEED A 4 Thing_SetTranslation(0,62)
NEED A 4 Thing_SetTranslation(0,0)
NEED A 0 A_FaceTarget
NEED K 10 A_ChangeVelocity(0.0,0.0,19.0,CVF_REPLACE|CVF_RELATIVE)
NEED K 0 A_ChangeFlag("NOGRAVITY",1)
NEED M 10 A_ChangeVelocity(0.0,0.0,0.0,CVF_REPLACE|CVF_RELATIVE)
Goto Spin
Spin:
NEED Q 0 A_JumpIfInventory("CutterFlag",30,"Finish")
NEED Q 0 A_PlaySoundEx("enemy/needlemanfire","Auto")
NEED QQ 0 A_SpawnItemEx("NeedlemanNeedle2",0,0,32,14,0,random(-3,-6),random(0,360))
NEED Q 1
NEED Q 0 //A_PlaySoundEx("enemy/needlemanfire","Voice")
NEED QQ 0 A_SpawnItemEx("NeedlemanNeedle2",0,0,32,14,0,random(-3,-6),random(0,360))
NEED Q 1
NEED R 0 //A_PlaySoundEx("enemy/needlemanfire","Voice"
NEED QR 0 A_SpawnItemEx("NeedlemanNeedle2",0,0,32,14,0,random(-3,-6),random(0,360))
NEED R 1
NEED R 0 //A_PlaySoundEx("enemy/needlemanfire","Voice")
NEED QR 0 A_SpawnItemEx("NeedlemanNeedle2",0,0,32,14,0,random(-3,-6),random(0,360))
NEED R 1
NEED Q 0 A_GiveInventory("CutterFlag",1)
loop
Finish:
NEED M 16 A_ChangeVelocity(0.0,0.0,0.0,CVF_REPLACE|CVF_RELATIVE)
NEED K 0 A_ChangeFlag("NOGRAVITY",0)
NEED M 0 A_TakeInventory("CutterFlag",999)
NEED M 0 A_ChangeFlag("INVULNERABLE",0)
Goto Leaping2
}
}

actor NoPuff
{
-SOLID
+NOINTERACTION
States
{
Spawn:
TNT1 A 0
stop
}
}

actor NeedlemanNeedle
{
PROJECTILE
+RIPPER
damage (8*ACS_NamedExecuteWithResult("sp_cbmHP"))
scale 2.5
translation "13:246=4:4"
damagetype "Enemy"
Height 8
Radius 8
Speed 42
States
{
Spawn:
NHAR F 2
loop
}
}

actor NeedlemanMelee
{
+MISSILE
damage (0)
scale 2.5
damagetype "Enemy"
Height 8
Radius 8
renderstyle none
States
{
Spawn:
NHAR A 2
NHAR A 2 A_Explode(130*ACS_NamedExecuteWithResult("sp_cbmHP"),300,0)
stop
}
}

actor NeedlemanNeedle2 : NeedlemanNeedle
{
damage(6*ACS_NamedExecuteWithResult("sp_cbmHP"))
}
--- End quote ---

The next step in developing a boss would be to create a custom arena for it, it's important that this arena be a unique map from all other ones or at least have a different name, otherwise it'll overlap with other boss checks. To create this arena, just create a simple space for you to fight the boss in that has an SP Player 1 Start and a map spot with a tag of 1. The map spot is where the boss will always be spawned, so it's important to make sure that it exists and specifically has a tag of 1. You should also make sure that each sector that a player can land on within the arena has an "Actor hits floor" activator that calls the named script, "EA_BossActivate". Make sure that you don't leave any space when entering that script name or else it'll fail to be recognized. This is necessary to make sure that the boss is properly started once players land into the arena.
(click to show/hide)
--- Quote ---

--- End quote ---

The final prerequisite of implementing your boss is to create a server variable in CVARINFO that can log whether or not your boss has been defeated. This is important so that players can properly gain the boss's weapon upon his death. It should look as follows,

--- Quote ---server noarchive bool ea_needleman = false;
--- End quote ---
Once those three aspects are in place, you can start the ACS definition needed to properly implement the boss. As like the other import files, you'll wanna start by dragging EA_BOSS.ACS into your project, but don't compile it. Then you'll want to create a new file that looks as such,

--- Quote ---#library "sp_imprt"
#include "zcommon.acs"

#import "ea_boss.acs"

Script "sp_imports" OPEN
{
Delay(5);
defineBoss("CUTBOSS","ea_cutman","RollingCutterWep","RollingCutterWepC","CutmanBoss","RollingCutterWep","TripleCutterWep","CutterArmWep","GroundCutterWep","DuoCutterWep","GargantuanCutterWep","CutterTwinsWep","CondorSlicerWep","RollingCutterWep");
defineBoss("HEABOSS","ea_heatman","AtomicFireWep","AtomicFireWepC","HeatmanBoss","AtomicFireWep","AtomicFlamesWep","AtomicDashWep","AtomicRadianceWep","AtomicExcursionWep","AtomicWaveWep","AtomicOverheatWep","AtomicChainWep","AtomicFireWep");
defineBoss("NEEBOSS","ea_needleman","NeedleCannonWep","NeedleCannonWepC","NeedlemanBoss","NeedleCannonWep","NeedleBombWep","NeedleSprayerWep","PunctureNeedleWep","NeedleHammerWep","NeedleTwisterWep","NeedleRingWep","RevolverNeedleWep","NeedleCannonWep");
defineBoss("TOABOSS","ea_toadman","RainFlushWep","RainFlushWepC","ToadmanBoss","RainFlushWep","FlushGrenadeWep","RainTorrentWep","RainShowerWep","JusticeRainWep","FloodFlushWep","FlushRestoreWep","RiotFlushWep","RainFlushWep");
}
--- End quote ---
You'll notice that each call of that function has a lot of parameters, and that's to support the Megaman Singleplayer Classes which need to know which copywep each class should get. As a quick cheat sheet for what each parameter means, refer to this list.

--- Quote ---//  0 - Map code that your boss is fought on (Ex. CUTBOSS)
//  1 - CVAR to toggle and check for your boss being defeated (Ex. ea_cutman)
//  2 - Vanilla weapon name according to the engine (Ex. RollingCutterWep)
//  3 - CBM weapon name according to the engine (Ex. RollingCutterWepC)
//  4 - Boss actor to be spawned according to the engine (Ex. CutmanBoss)
//  5 - Megaman weapon name according to the engine (Ex. RollingCutterWep)
//  6 - Protoman weapon name according to the engine (Ex. TripleCutterWep)
//  7 - Bass weapon name according to the engine (Ex. CutterArmWep)
//  8 - Roll weapon name according to the engine (Ex. GroundCutterWep)
//  9 - Duo weapon name according to the engine (Ex. DuoCutterWep)
// 10 - DocRobot weapon name according to the engine (Ex. GargantuanCutterWep)
// 11 - Darkman weapon name according to the engine (Ex. CutterTwinsWep)
// 12 - Fakeman weapon name according to the engine (Ex. CondorSlicerWep)
// 13 - BBAMegaman weapon name according to the engine (Ex. TrollingCutterWep)
--- End quote ---
If you know that a weapon doesn't exist for your boss for a certain class, then it is best to resort to a weapon that can be found in vanilla until it's implemented. Make sure to give a shoutout to Blews#9696 so he can know that he's got new weapons to make for the Megaman Singleplayer classes.

That's the bulk of what's needed for the implementation of a boss, so have fun creating new capstone challenges for players!
--- End quote ---

Cossack Crusaders?
I figured a quick Mission Mode inspired project would be the perfect thing to get myself and some other people around the community inspired for development again. Progress is going forward with resolve, but now I'm sure everyone will have this gameplay style in the front of their mind again.

--- End quote ---

Download Here!

For any inquiries or feedback, you can contact me on Discord at Trillster#2887

Trillster:
Endless Attack Addons

To save others the trouble of needing to make separate forum threads, gonna keep track of various addons in this secondary post. These can be a mix of level segment packs, bosses, or even a class mod designed to be ran with the mod for a more fleshed out experience.

Megaman Singleplayer SiN Classes
(click to show/hide)
--- Quote ---Brought back to recent times by Blews#9696, this addon reintroduces the Megaman, Protoman, Bass, and Roll class who all start with their own unique weapons and gain different weapons from each boss defeated. While Roll's weapons might be more supportive or poke based, Bass's are all for going straight in and causing mayhem. Megaman gets the vanilla weapons as usual, however. It's a staple way to play the mod if you're in for the old school authentic experience.

Download Here!
--- End quote ---

Yair Pack
(click to show/hide)
--- Quote ---For those looking for a set of harder difficulty segments that are sure to add some tension to the run, this pack of level segments created by Yair#5454 is sure to do the trick. It introduces level segments inspired by some classic MM8BDM platforming such as Obstacle and Ragestacle Course while introducing new and original level segments with various gimmicks.

Download Here!
--- End quote ---

FTX Pack
(click to show/hide)
--- Quote ---Created by FTX6004#0283, his pack aims to add some more laid-back robot master inspired level segments that mimic the style of the original MMSP stages. You can expect to see some familiar level set pieces used for all new platforming experiences.

Download Here!
--- End quote ---

Trillster:
Base file, MMSP Classes, and FTX Pack have seen various updates, make sure you're running the most recent versions of each of them.

FAQ has been updated to reflect changes in the base file updates, make sure you're referring to the most recent version of it when making content.

Navigation

[0] Message Index

Go to full version