O Ilusionista
Captain 80K
This code can damage all the enemies on the screen with some custom things:
Last edited by a moderator:
Now I have a chance to use this script but somehow it is not working for me as it only damages 1 enemy on the screen. I know this because I set the damage to 400 just to see.Damage All Enemies on the screen
Function: This code can damage all the enemies on the screen with sime custom things:
- It can damage the enemies even if they have no bbox. IOW, it can damage the enemies anytime. Maybe we can add a life check to avoid any bug.
- you can choose the damage, if it knock down the enemies, which kind of attack, a specific flash and a specific sound.
C:void damage_all_enemies(int damage, int drop, void atk_type, void vName, char sound) // By O Ilusionista //thanks Lagarto, Piccolo and White Dragon { int iEntity; void vEntity; void self = getlocalvar("self"); int iMax = openborvariant("count_entities"); playSound("data/sounds/"+sound); for(iEntity=0; iEntity<iMax; iEntity++) { vEntity = getentity(iEntity); float x = getentityproperty(vEntity, "x") - openborvariant("xpos"); float a = getentityproperty(vEntity, "a"); float z = getentityproperty(vEntity, "z"); void Spawn; if(getentityproperty(vEntity, "type")==openborconstant("TYPE_enemy")) { clearspawnentry(); setspawnentry("name", vName); setspawnentry("coords", x, z+1, a+30); spawn(); clearspawnentry(); damageentity(vEntity,self,damage,drop,openborconstant(atk_type)); } } }
Usage:
@cmd damage_all_enemies 2 0 "ATK_NORMAL" "flash" "beat2.wav"
It will damage all the enemies on the screen, doing 2 as damage, not knocking the enemies down (0), using "ATTACK1" as the attack, spawing a specific flash and using a custom sound.
Because I do want to damage only the type enemy entities and I need to be sure about the type.I am confused that why are we using "count_entities" then check to see if they are enemies?
It's a common mistake to use "ent_max" on this case. I just need to know how much entities are on the screen, not the maximum entities allowed.I saw another thread which was using "ent_max"
void damage_all_enemies2(int damage, int drop, void atk_type)
//thanks Lagarto, Piccolo and White Dragon
//damage without effects
{
int iEntity;
void vEntity;
void self = getlocalvar("self");
int iMax = openborvariant("count_entities");
for(iEntity=0; iEntity<iMax; iEntity++)
{
vEntity = getentity(iEntity);
float x = getentityproperty(vEntity, "x") - openborvariant("xpos");
float a = getentityproperty(vEntity, "a");
float z = getentityproperty(vEntity, "z");
if(getentityproperty(vEntity, "type")==openborconstant("TYPE_enemy"))
{
damageentity(vEntity,self,damage,drop,openborconstant(atk_type));
}
}
}
Ahh it makes more sense now. Somehow I thought "ent_max" counts the total of numbers of entities on the screen instead of the whole game.@Bruce I can guarantee that the code works because I use it in my Avengers project (You can see it in action when Jean Gray attacks).
Because I do want to damage only the type enemy entities and I need to be sure about the type.
On the code above, I am getting information from a pointer (the entity, on this case) and, after that, I am referencing that pointer to spawn things.
Trying to get information from a invalid point (a null pointer) isn't a problem, but referencing it (using its info) is a problem - a null pointer causes softwares to crash.
I even should add a safe check there to take care of it (althought I haven't experienced any issue yet)
Keep in mind this script works as "brute force" - I am not checking if the enemy is under a certain animation, if its on air/ground or even if it still have health left; the code will hurt them anyway. For example, if you have an enemy doing a pose or waiting (like the thugs in Final Fight), the code will break it and hurt them anyway. So use it with caution.
It's a common mistake to use "ent_max" on this case. I just need to know how much entities are on the screen, not the maximum entities allowed.
Using "ent_max" would be a waste of resources here. Why? Let's say we have 20 entitties on the screen:
Using count_entities speeds up the code a bit
- Using "count_entities" I will get the number 20. Them the code will try execute a loop (checking all the stuff and spawing needed effects) and retry it again 19 times (as it need to do a loop for each entity, so we are talking about 20 loops.
- If I am not mistake, "ent_max" comes from the constantc MAX_ENTS, which is set to 150 on the engine source
#define MAX_ENTS 150
So using ent_max here will make the engine to try the loop 150 times instead of just 20.
I understood your first script completely and I was able to modify it to work with my case. and it looks like it should work.C-like:
void damage_all_enemies2(int damage, int drop, void atk_type)
//thanks Lagarto, Piccolo and White Dragon
//damage without effects
{
int iEntity;
void vEntity;
void self = getlocalvar("self");
int iMax = openborvariant("count_entities");
for(iEntity=0; iEntity<iMax; iEntity++)
{
vEntity = getentity(iEntity);
float x = getentityproperty(vEntity, "x") - openborvariant("xpos");
float a = getentityproperty(vEntity, "a");
float z = getentityproperty(vEntity, "z");
if(getentityproperty(vEntity, "type")==openborconstant("TYPE_enemy"))
{
damageentity(vEntity,self,damage,drop,openborconstant(atk_type));
}
}
}
Usage:
@cmd damage_all_enemies 2 0 "ATK_NORMAL"
It will damage all the enemies on the screen, doing 2 as damage, not knocking the enemies down (0), using "ATTACK1" as the attack type
Not on this case - I need to check if my target is a enemy, not only to know how many enemies are active. Without that check, the script would damage everything on the screen - including youWhat about the "count_enemies". Wouldn't it be better to use this since it only counts the total number of the enemies?
lol I know that check is a must. I was saying that "count_enemies" will count the total of enemies instead of counting all entities including objects, etc.. on the screen with "count_entities". Wouldn't it be less looping to do for the for-loop? lol they are just too many functions that I don't really understand how they work yet. I am learning them one by one. Greatly appreciated for your help!Not on this case - I need to check if my target is a enemy, not only to know how many enemies are active. Without that check, the script would damage everything on the screen - including you
ah you are probably right about this one - since I got this code from another code (where I have other cases, not only enemies), maybe I can change it to count only the enemies.I was saying that "count_enemies" will count the total of enemies instead of counting all entities including objects, etc
Thanks, I knew I had a reason but I couldn't remember why exactly.You can't use enemy count to loop over entities, because you're getting entities in the loop by their index,
Ahh, this makes alot of sense. I even tried "count_enemies" myself and it did not work well.You can't use enemy count to loop over entities, because you're getting entities in the loop by their index, and that index is 0 to total entity count. Ex: There might be 20 enemies on screen, but one of the twenty enemies may have an index of 32 if there are 50 total entities. So when the loop stops at 20, it never reaches that enemy.
DC
void damageall(int damage, int drop, void atk_type, int mp_cost)
// thanks Lagarto, Piccolo, and White Dragon
// damage without effects, consumes MP when attack hits
{
int iEntity;
void vEntity;
void self = getlocalvar("self");
int iMax = openborvariant("count_entities");
// Get current MP of the attacker
int currentMP = getentityproperty(self, "mp");
// Check if the attacker has enough MP
if (currentMP < mp_cost) {
return; // Not enough MP to perform the attack
}
// Spend MP
changeentityproperty(self, "mp", currentMP - mp_cost);
for (iEntity = 0; iEntity < iMax; iEntity++) {
vEntity = getentity(iEntity);
float x = getentityproperty(vEntity, "x") - openborvariant("xpos");
float a = getentityproperty(vEntity, "a");
float z = getentityproperty(vEntity, "z");
if (getentityproperty(vEntity, "type") == openborconstant("TYPE_enemy")) {
damageentity(vEntity, self, damage, drop, openborconstant(atk_type));
}
}
}
// Function to kill the calling entity
void suicide()
{
void self = getlocalvar("self");
killentity(self);
}
// Function to spawn a flash entity and handle its lifespan
void flash_all_enemies(void vName)
{
int iEntity;
void vEntity;
int iMax = openborvariant("count_entities");
void lastSpawned = NULL(); // Variable to store last spawned entity
// Spawn all enemies
for (iEntity = 0; iEntity < iMax; iEntity++)
{
vEntity = getentity(iEntity);
// Check if the entity is an enemy
if (getentityproperty(vEntity, "type") == openborconstant("TYPE_enemy"))
{
// Get entity properties
float x = getentityproperty(vEntity, "x") - openborvariant("xpos");
float a = getentityproperty(vEntity, "a");
float z = getentityproperty(vEntity, "z");
// Clear spawn entry and set new values
clearspawnentry();
setspawnentry("name", vName);
setspawnentry("coords", x, z + 1, a + 30);
// Spawn entity and store its handle
spawn();
lastSpawned = getlocalvar("lastspawned");
// Clear spawn entry for safety
clearspawnentry();
}
}
// After spawning, check and handle the last spawned entity
if (lastSpawned != NULL())
{
// Example: Check if the last spawned entity's health reaches zero
if (getentityproperty(lastSpawned, "health") <= 0)
{
suicide(); // Kill the last spawned entity
}
}
}
By defaullt, a scripted entity will only do whatever you tell it to do.so i tried adding suicide and still the same... i dont kmpw much about scripts , theres no errors either,, the flash just wont kill itself xD
@cmd killentity getlocalvar("self")
frame data/chars/empty.gif
that empty gif trick did it for me... thank you so much brother... its been a while and am old and feels like starting from scratch lolBy defaullt, a scripted entity will only do whatever you tell it to do.
Keep in mind that working with scripts gives you a lot of control over things, but here the word control is literal: you have to control what happens and the engine will only do what you tell it to do (excluding internal routines).
For example, when you invoke an entity using "knife", there are a series of variables that the engine fills in, such as "owner". However, when you do this via script, this does not happen - because you did not give this instruction.
When you use an entity as a flash and use the same entity via scripted spawn, they are very different things. If you don't say how long the entity has to remain active on the screen, it will remain active until some condition occurs (such as leaving the screen, colliding with another entity in the case of projectiles, etc.). If you just spawn her, she will stay on the screen and that's it.
In my case, to prevent what you report - which is something that can sometimes happen randomly in the engine and I never discovered the reason, I just know that it has been happening for many years now - I use two options:
1 - Provide the "lifespan" parameter in the entity header. In the Avengers project, all entities that are used as flash have this information
2 - To ensure that the entity is actually destroyed (as there are rare cases that lifespan does not kill the entity), I add an additional frame with an empty sprite - or you can simply duplicate the last frame and add the following code
lol is a big one too .. man ive been gone for far to long.. i got your avengers game...never finished it, then again i hardly play since i am always doing artwork for attract mode buildsFunny enough, I just saw a video about my game where this bug appears. See at 12:12
I am using the "@cmd killentity getlocalvar("self")" code and, yet, after the entity had been killed....it appears again, using a different frame from the last animation frame and get stuck forever. This is an old engine bug.
To bypass this, I have to use that script + set a lifespan on its header.