Players Health

Posted By: Blacknova

Players Health - 06/07/21 20:45

Hello,

How can I make it that only ( -10 ) are deducted when touching?

The whole life is always deducted from it.


///////////////////////////////////////////////

action health_taker()

{

while (!player) {wait (1);}

while (1)

{

if (vec_dist(player.x, my.x) < 200)

players_health -= 2 * time_step;

wait (1);

}

}


///////////////////////////////////////////////


Thank you...
Posted By: Dooley

Re: Players Health - 06/08/21 00:09

This means that for every frame in which the health taker is less than 200 quants from the player, it will subract 2*time_step from player_health.

To limit the amount you would need to add a limit, and a cool down period.
So inside of "health_taker" you could initialize two variables:
Code
var target_health = 0; 
var cool_down = 0;


So, when the player gets too close, first you will assign target_health like this:

Code
if(cool_down == 0)
{
cool_down = 10;
target_health = player_health - 10;
}


Then you can say:
Code
if(player_health > target_health)
{
player_health -= 2 * time_step;
}
else
{
player_health = target_health;//so it does not go below the target health
}


Finally, add the timer script after all this, but before the wait(1);
Code
if(cool_down > 0)
{
cool_down -= .5 * time_step;//play with this number ... .5 might be too fast or too slow
}
else
{
cool_down = 0;//now it's ready to do damage again
}

Posted By: 3run

Re: Players Health - 06/08/21 10:21

Dooley was faster than me grin
But if it's ok, I would like to share my 2 cents too.

Here is a commented code (you can simply run it to see how it works):
Code
var player_health = 100;

action health_taker()
{
	while(!player){ wait(1); }
	
	int touching = false;
	var touching_counter = 0;
	
	while(my) // never create endless loops !
	{
		if(vec_dist(player.x, my.x) < 200) // if we are close enough?
		{
			if(touching == false) // and we yet can do damage to player ?
			{
				player_health -= 10; // take 10 health points from player
				touching = true; // make sure that if statement is going to be false in next loop
				// so we wouldn't take any more health points !
			}
			
			// if you need to take player's health, let's say 10 points each second
			// you can reset 'touching' to false each 1 second
			touching_counter += time_frame / 16;
			if(touching_counter >= 1)
			{
				touching = false;
				touching_counter -= 1;
			}
		}
		else // far enough ?
		{
			if(touching == true) // and we previosly touched player ?
			{
				touching = false; // reset touching switch
			}	
		}
		
		wait(1);
	}
}

action player_controller()
{
	player = my;
	
	while(my)
	{
		if(player_health <= 0)
		{
			break;
		}
		wait(1);
	}
	
	ptr_remove(my);
}

void main()
{
	fps_max = 60;
	warn_level = 6;
	
	level_load("");
	
	ent_create(CUBE_MDL, vector(128, 32, 0), health_taker);
	ent_create(SPHERE_MDL, vector(128, -32, 0), player_controller);
	
	while(!key_esc)
	{
		DEBUG_VAR(player_health, 0);
		wait(1);
	}
	sys_exit(NULL);
}
There are few thing that I would like to mention.

Firstly this code (same as your original one) doesn't take into account 'touching' between 'health_taker' entity and 'player' entity. It only checks if they are close enough to eachother. To check for touching, I would recommend looking into events. F.e. EVENT_IMPACT or EVENT_ENTITY. But checking for distance might be better way (just keep the distance small enough, so enemies f.e. won't cause damage though walls).

Secondly I would recommend not to use 'player' pointer at all. Because if player pointer will be invalid (f.e. after removing him with safe_remove macros), your 'health_taker' entities will crash/cause errors. As as simpliest workaround, I would use global vector, which will be changed to player's position at the end of the player's main loop (where you move the player) and then, in 'health_taker' action, I would check for distance between that global vector and health_taker's position.

Best regards!
Posted By: Blacknova

Re: Players Health - 06/08/21 20:02

Thank you so much...

I'll give it a try. When I have some time again.

If anyone is interested. I'm currently trying to create a TimeRacer game.

It's nothing special. But it's fun. And I like to do it too.

Website : www.timeracer.ch
Posted By: 3run

Re: Players Health - 06/09/21 08:57

Cool project! Keep it up!

Best regards!
Posted By: rayp

Re: Players Health - 06/23/21 19:04

Also i would use EVENT_FRAME instead of all those whiles. If you use a while for every ent this will slow down your code.
Code
#define health skill90
#define mytimer skill89

void healthtakerevent(){
   /*if (event_type == EVENT_IMPACT || event_type == EVENT_ENTITY){
      if (you){
         //dont do c_move etc here but u can store the handle and do it in event frame my.skill10 = handle(you)...ent = ptr_for_handle (my.skill10)
      } 
   }*/
   if (event_type == EVENT_FRAME){ // do every frame		
      if (player){
         if (!is (my, FLAG1)){
            if (vec_dist (player.x, my.x) <= my.skill1){ // && random (1) > 0.98){
                //c_trace (my.x, player.x,IGNORE_ME|IGNORE_PASSABLE|IGNORE_SPRITES|USE_POLYGON);
                //if (HIT_TARGET) if (you) if (you == player){
              	   player.health -= my.skill3;
            	   set (my, FLAG1);
                   //if (!snd_playing (my.skill4)) my.skill4 = ent_playsound (me, snd_healthtaker_hurtplayer, 100+random(100));
                //}
            }
         }
         else{
            my.mytimer += time_step;
            if (vec_dist (player.x, my.x) > my.skill1 || my.mytimer > my.skill2){
                my.mytimer = 0;
            	reset (my, FLAG1);
            }
         }
      }
      /*
      if (my.health <= 0){        // example how to remove "me" in event_frame
         my.event = NULL;
         //wait(1);
         safe_remove (me);
         //return; // only if this block is not at event's end,dont execute further lines
      }
      */
   }
}
// --- those lines below will mask the WED skills like define ----
//skill1 TakeRange 200
//skill2 DamageTime 100
//skill3 HealthTaken 10
//flag1 touched 0
action health_taker(){
	if (my.skill1 <= 0) my.skill1 = 200;  // react range
	if (my.skill2 <= 0) my.skill2 = 100;  // time to take health again even if player is still close
	if (my.skill3 <= 0) my.skill3 = 10;   // take this amount of player's health
        //my.health = 100;
	my.event = healthtakerevent;
	my.emask |= ENABLE_FRAME;//|ENABLE_ENTITY|ENABLE_IMPACT;
}
One of the secrets to fast code. 3run warned already, but u can use a var like player_died to simply avoid those error like
Code
if(event_type == EVENT_FRAME && !player_died) {use the pointer etc}

For myself i use a global var "level_loading" in every(!) event_frame event/while. Before doing stuff like switching the level i set this to 1. This will stop ALL running frame-events/break every while running, and prevent using lost pointers during the next frame(and i only use around two global ent pointers).

Better use
Code
safe_remove(ent)
instead of
Code
ptr_remove(ent)

If you want to make it a bit more realistic, do a c_trace when close. Now healthtaker will always reduce health when close, even with a wall in between.
edit: see above.

Wish i had used event_frame in the past. i was also stuck to this while-stuff. One day 3run(thanks again) told me to look into event_frame, i totally forgot about.
Still using whiles of course in my code, but i can count them with one hand laugh
Not saying whiles are bad in general, just saying use them carefully.

greets
© 2024 lite-C Forums