blast / damageonlading question

msmalik681

OpenBOR Developer
Staff member
When I use damage on lading the attack boxes can hit players is there a way to set this to only hit enemies ?

I could use a ondoattack script to null these attacks to players or a script to change the candamage property but I was hoping there is a more simple solution I have overlooked !

edit: Found what I was looking for:

projectilehit {type1} {type2} ...

Optional.
Do not let the name confuse you, this is not for projectiles. This
setting specifies what types this entity will hit when thrown from a grab. * Available types are enemy, player, npc, obstacle, shot and you can use as many as you need. If you don't want entity to hit anything, just set 'none' here.

Be aware if you use this setting, you must provide all types you wish this entity to be able to hit when thrown. That is to say, an enemy with ‘projectilehit player’ will only hit players when thrown, not other enemies.
 
Last edited by a moderator:
msmalik681, I was in the midst of typing before I saw your edit. You nailed, and ninja'd me in the process.  :P

I will add you can change projectile property on the fly if need be, but keep in mind tthe engine applies bit wise logic when evaluating. This is why you are able to set multiple types for projectilehit in the model text even though it's just one property. Assuming you know bit wise logic you can do the same thing with script. If you don't understand, just let me know.

DC
 
Damon Caskey When i was reading up on c tutorials bit wise was always too confusing to comprehend maybe i just need to do a practical exercise to grasp it.

But for now anything bit wise you say would just fly over my head lol.
 
msmalik681 said:
Damon Caskey When i was reading up on c tutorials bit wise was always too confusing to comprehend maybe i just need to do a practical exercise to grasp it.

But for now anything bit wise you say would just fly over my head lol.
msmalik681,

I've seen those tutorials, they tend to overly complicate things a little. The idea behind bit wise logic is really super simple. Instead of comparing two integer values, you are comparing one or more of the individual bits that make up the integer. Integers in most programs (OpenBOR included) are 32bit. This means you can store 31 true or false flags inside one integer variable. Technically 32, but usually 31 due to logic rules I don't want to rabbit hole too much about. This gives you three big benefits:

[list type=decimal]
[*]The obvious - memory saving. One of the most common uses of an integer is for keeping true/false boolean flags. If the flags are part of a related list, you can literally use 1/31th the memory space. The engine does this a lot internally. One example is keeping track of player input. Keys are either on or off, and there are 12 per player. By using bit wise logic, we only need 4 variables for a key status instead of 48.
[*]Speed. Bit operations are blazing fast. They're one of the simplest and quickest things a CPU can do. This doesn't matter as much in OpenBOR script, but for compiled code like the engine itself it can make a substantial difference.
[*]Simplicity. Let's go back to the player key example. If you look at most key scripts used in OpenBOR, they are ridiculously monolithic, with massive lists of variables for every possible key press. That's my fault since most of them come from an old key-script I wrote years ago. In my defense we didn't have bit wise operators for script when I wrote those. Fortunately Plombo added the bit wise operators a few years ago, giving us a much better way. Now you can leverage bit wise logic to make key scripts a lot simpler. Take a look at my example below. It contains two functions. One using legacy style key evaluation and the other bit wise. They both do the same thing, but notice how much cleaner and more optimal the bit wise version is. This will only become more apparent as you start adding more advanced key logic:
[/list]

Legacy:
Code:
/*
* Caskey, Damon  V.
* 2021-07-13
*
* Demonstrate legacy technique for reading
* key presses.
*/
int key_legacy()
{
	int player_index = getlocalvar("player");
	void acting_entity = getplayerproperty(player_index, "entity");

	/*
	* Using the legacy method, we need a variable
	* for every possible key event we want to read
	* and evaluate. There are 3 types of events and
	* 12 keys per player, meaning we might have to
	* keep a list of 36 variables for the keys alone.
	* 
	* This also means more function calls, adding a
	* slight amount of latency compared to bitwise 
	* method.
	*/
	int key_hold_attack = playerkeys(player_index, 0, "attack");
	int key_hold_attack2 = playerkeys(player_index, 0, "attack2");
	int key_hold_attack3 = playerkeys(player_index, 0, "attack3");
	int key_hold_attack4 = playerkeys(player_index, 0, "attack4");
	int key_hold_jump = playerkeys(player_index, 0, "jump");
	int key_hold_move_down = playerkeys(player_index, 0, "movedown");
	int key_hold_move_left = playerkeys(player_index, 0, "moveleft");
	int key_hold_move_right = playerkeys(player_index, 0, "moveright");
	int key_hold_move_up = playerkeys(player_index, 0, "moveup");
	int key_hold_screenshot = playerkeys(player_index, 0, "screenshot");
	int key_hold_special = playerkeys(player_index, 0, "special");
	int key_hold_start = playerkeys(player_index, 0, "start");

	int key_press_attack = playerkeys(player_index, 1, "attack");
	int key_press_attack2 = playerkeys(player_index, 1, "attack2");
	int key_press_attack3 = playerkeys(player_index, 1, "attack3");
	int key_press_attack4 = playerkeys(player_index, 1, "attack4");
	int key_press_jump = playerkeys(player_index, 1, "jump");
	int key_press_move_down = playerkeys(player_index, 1, "movedown");
	int key_press_move_left = playerkeys(player_index, 1, "moveleft");
	int key_press_move_right = playerkeys(player_index, 1, "moveright");
	int key_press_move_up = playerkeys(player_index, 1, "moveup");
	int key_press_screenshot = playerkeys(player_index, 1, "screenshot");
	int key_press_special = playerkeys(player_index, 1, "special");
	int key_press_start = playerkeys(player_index, 1, "start");

	int key_release_attack = playerkeys(player_index, 2, "attack");
	int key_release_attack2 = playerkeys(player_index, 2, "attack2");
	int key_release_attack3 = playerkeys(player_index, 2, "attack3");
	int key_release_attack4 = playerkeys(player_index, 2, "attack4");
	int key_release_jump = playerkeys(player_index, 2, "jump");
	int key_release_move_down = playerkeys(player_index, 2, "movedown");
	int key_release_move_left = playerkeys(player_index, 2, "moveleft");
	int key_release_move_right = playerkeys(player_index, 2, "moveright");
	int key_release_move_up = playerkeys(player_index, 2, "moveup");
	int key_release_screenshot = playerkeys(player_index, 2, "screenshot");
	int key_release_special = playerkeys(player_index, 2, "special");
	int key_release_start = playerkeys(player_index, 2, "start");


	/*
	* Compare true or false value of key
        * key variable.
	*/

	if (key_press_special)
	{
		log("\n\t Key press: Special.");
	}

	if (key_press_jump)
	{
		log("\n\t Pressed Jump.");
	}

	if (key_press_attack)
	{
		log("\n\t Pressed Attack 1.");
	}

	if (key_press_attack2)
	{
		log("\n\t Pressed Attack 2.");
	}

	if (key_press_attack3)
	{
		log("\n\t Pressed Attack 3.");
	}

	if (key_press_attack4)
	{
		log("\n\t Pressed Attack 4.");
	}

	if (key_press_attack4 && key_hold_move_left);
	{
		log("\n\t Pressed Attack 4, holding Move Left.");
	}
}

Bitwise:
Code:
/* 
* Caskey, Damon  V.
* 2021-07-13
*
* Demonstrate use of bitwise logic to read
* player key presses.
*/
int key_bitwise()
{
	int player_index = getlocalvar("player");	
	void acting_entity = getplayerproperty(player_index, "entity");

	/*
	* OpenBOR uses bit logic to combine the on/off
	* status of every key into one value for each 
	* type of key event: Press, hold, and release.
	* 
	* If we acquire these three values, we now have
	* the status of every possible key event for the
	* player.
	*/
	int key_hold = getplayerproperty(player_index, "keys");
	int key_press = getplayerproperty(player_index, "newkeys");
	int key_release = getplayerproperty(player_index, "releasekeys");

	log("\n Key hold value: " + key_hold);
	log("\n Key press value: " + key_press);
	log("\n Key release value: " + key_release);

	/* 
	* Compare keypress to key flags using 
	* bitwise logic, and take action according
	* to which key is pressed.
	* 
	* Basically, the variable is a list of 12
	* true or false flags. The constant is true 
	* value for one of the list items.
	*
	* IOW, the logic reads like this: "Is the
	* n'th flag true?"
	*/
	
	if (key_press & openborconstant("FLAG_SPECIAL"))
	{
		log("\n\t Key press: Special.");
	}

	if (key_press & openborconstant("FLAG_JUMP"))
	{
		log("\n\t Pressed Jump.");
	}

	if (key_press & openborconstant("FLAG_ATTACK"))
	{
		log("\n\t Pressed Attack 1.");
	}

	if (key_press & openborconstant("FLAG_ATTACK2"))
	{
		log("\n\t Pressed Attack 2.");
	}

	if (key_press & openborconstant("FLAG_ATTACK3"))
	{
		log("\n\t Pressed Attack 3.");
	}

	if (key_press & openborconstant("FLAG_ATTACK4"))
	{
		log("\n\t Pressed Attack 4.");
	}

	if (key_press & openborconstant("FLAG_ATTACK4") && key_hold & openborconstant("FLAG_MOVELEFT"));
	{
		log("\n\t Pressed Attack 4, holding Move Left.");
	}
}

There's a lot more you can do, but I didn't want to overwhelm you. The engine code is loaded with bit wise work. Roel was (is) a master of squeezing every drop of performance from the code, and this was one of his more often used techniques. I still find his bit shift pseudo random number generator to be a stroke of brilliance.

DC
 
100% the bit wise example is much cleaner. Will that example work in the engine now ? I need to learn bit wise as it sounds like a huge asset to the engine.

One thing is confusing me with your example there are 12 keys but each key needs 3 flags press, hold and release so true and false only cover 2 what about the 3rd ?

Would a 64bit build break anything ?
 
msmalik681:

100% the bit wise example is much cleaner. Will that example work in the engine now ? I need to learn bit wise as it sounds like a huge asset to the engine.

Yes. As I said in my post above, we've supported bit wise operators for years now.

One thing is confusing me with your example there are 12 keys but each key needs 3 flags press, hold and release so true and false only cover 2 what about the 3rd ?

Sorry, I'm not sure what you mean. Please explain and indicate the code that confuses you.

Would a 64bit build break anything ?

No. In fact it theoretically means you could use 64bit integers, and thus compress 63 values into one integer value. In practice though, using 64 bit values is a waste of memory for no real gain and would almost certainly cause compatibility issues with certain ports, so we don't do that.

DC


 
When I use damage on lading the attack boxes can hit players is there a way to set this to only hit enemies ?

I could use a ondoattack script to null these attacks to players or a script to change the candamage property but I was hoping there is a more simple solution I have overlooked !

edit: Found what I was looking for:
I haven't been able to make this work since my Power Rangers mod I think, ages ago. Is it a limitation of the engine? I'm using OpenBoR v3.0 Build 7142 (commit hash: 9dcd966), Compile Date: Dec 8 2019

I had to make a personalized system for Bloody Paws but I don't want to do that on all my projects - feels like overkill. Is there something I'm missing regarding current usage of projectilehit?
 
Well, can you elaborate more on your issue? and what projectilehit setting do you have?
Thanks Bloodbane. Well in the header of the enemy file I'm adding

Code:
projectilehit enemy

plus adding an attackbox to the fall animation of the enemy.

What's essentially happening is that projectilehit is not taking effect. The thrower (player) gets hit by thrown entity (the attackbox in enemy's fall animation affects the player), and surrounding enemies are not harmed.

I'm not doing anything different from my approach back when I did my Power Rangers mod. It worked back then, but not anymore in newer builds (unless I'm missing something). The original Power Rangers game was created using OpenBoR v3.0 Build 3984, Compile Date: Aug 23 2013

I have tried over the years (!!) different combinations - turning on and off attackonlanding, changing throw command (the one that changes trajectory of thrown entity), getting rid of attackboxes, you name it. Nothing works.

The only thing that works is adding script to change candamage during fall animation, but then the enemies hit other enemies when falling from a common knockdown attack. So at this point the script needs to be more involved and I think I'm reinventing the wheel without need.
 
@mersox,

The one thing you didn't mention was the throw itself. I think the thrown enemy's internal "blasted" flag might not be applied for some reason. That's what tells the engine to treat it as a thrown body and use projectilehit instead of candamage.

Mind posting the throw animation text?
 
@mersox,

The one thing you didn't mention was the throw itself. I think the thrown enemy's internal "blasted" flag might not be applied for some reason. That's what tells the engine to treat it as a thrown body and use projectilehit instead of candamage.

Mind posting the throw animation text?

Thanks DC. My throw animation has nothing special, so maybe that's the issue. Here it is:

Code:
anim throw
    loop    0
    offset    57 88
    bbox    56 43 15 47
    flipframe 0
    delay    7
    frame    data/chars/hero_pink/throw01.png
    frame    data/chars/hero_pink/throw02.png
    delay 25
    frame    data/chars/hero_pink/throw03.png
 
Sure, this is the enemy header

Code:
name    knife_guy
type    enemy
health    12
speedf    0.8
jumpheight  3.5
nolife 1
shadow    2
riseinv 0 1
makeinv 0 1
noquake 1
bounce 0
falldie 2
nodieblink 1
subject_to_basemap 1
risetime 100000
aggression 2

projectilehit enemy
throw 2.5 3
damageonlanding 1 1

dust    og_smoke_small_dust_fall
palette data/chars/knife_guy/walk04.png

animationscript    data/scripts/script.c

remap data/chars/knife_guy/idle.png data/chars/knife_guy/idle_purple.png

There's nothing in script.c regarding throws, just in case.
Fall animation:

Code:
anim fall
    loop    0
    landframe 1
    offset     43 77
    delay 200
    attack    37 17 17 61 1 1
    frame    data/chars/knife_guy/fall.png
    sound    data/sounds/fall_01.wav
    delay 1
    frame    data/chars/knife_guy/death.png
 
Away from desk so I can't look deep, but I do see one thing from a quick glance. Damageonlanding is an attack parameter, it's not for entity headers. Try removing that. May not fix the issue, but it's certainly not helping you.

DC
 
Away from desk so I can't look deep, but I do see one thing from a quick glance. Damageonlanding is an attack parameter, it's not for entity headers. Try removing that. May not fix the issue, but it's certainly not helping you.

DC
Ah, thank you. Good to know.
I did try last night without any instance of damageonlanding and yeah, didn't have an effect on projectilehit.

But certainly good to know for whenever I do need to use damageonlanding. :)
 
just tested on a very basic mod and it worked as expected so I am guessing there is some kind of misbehaving script if you can try disabling all scripts and test again.
 
just tested on a very basic mod and it worked as expected so I am guessing there is some kind of misbehaving script if you can try disabling all scripts and test again.
Thanks Malik. I tried that but no luck.

But I made it work in the end. I tried a different OpenBOR build. I downloaded build 3691 from the resources section here, and now throwing works fine. So there's definitely an issue with projectilehit in the build I was using previously (7142).

Based on the numbers it seems like I reverted back to an outdated version of the engine ( I wonder if some features are missing now from my game, need to test). However the build 3691 was uploaded to the site last year and the description says that it's the most recent official build, so I don't know what to think.
 
The latest stable is 6391 i am guessing you have your numbers mixed up a bit. I always recommend you target the latest stable release for your games.
 
You're right Malek, the build is 6391, I mixed up the numbers in my previous post.

Lesson learned - won't be messing around with alpha builds. Thanks guys!
 
Back
Top Bottom