2 registered members (AndrewAMD, 7th_zorro),
1,285
guests, and 4
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
Re: Players Health
[Re: Blacknova]
#483510
06/08/21 00:09
06/08/21 00:09
|
Joined: May 2005
Posts: 868 Chicago, IL
Dooley
User
|
User
Joined: May 2005
Posts: 868
Chicago, IL
|
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: var target_health = 0;
var cool_down = 0; So, when the player gets too close, first you will assign target_health like this: if(cool_down == 0)
{
cool_down = 10;
target_health = player_health - 10;
} Then you can say: 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);
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
}
Last edited by Dooley; 06/08/21 00:09.
|
|
|
Re: Players Health
[Re: Blacknova]
#483513
06/08/21 10:21
06/08/21 10:21
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
Senior Expert
|
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
Dooley was faster than me 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):
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!
|
|
|
Re: Players Health
[Re: Blacknova]
#483516
06/08/21 20:02
06/08/21 20:02
|
Joined: Mar 2005
Posts: 94 Schweiz
Blacknova
OP
Junior Member
|
OP
Junior Member
Joined: Mar 2005
Posts: 94
Schweiz
|
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
|
|
|
Re: Players Health
[Re: Blacknova]
#483621
06/23/21 19:04
06/23/21 19:04
|
Joined: Jul 2008
Posts: 2,107 Germany
rayp
X
|
X
Joined: Jul 2008
Posts: 2,107
Germany
|
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.
#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 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 instead of 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 Not saying whiles are bad in general, just saying use them carefully. greets
Last edited by rayp; 06/26/21 20:42.
Acknex umgibt uns...zwischen Dir, mir, dem Stein dort... "Hey Griswold ... where u gonna put a tree that big ?" 1998 i married my loved wife ... Sheeva from Mortal Kombat, not Evil-Lyn as might have been expected rayp.flags |= UNTOUCHABLE;
|
|
|
Moderated by mk_1, Perro, rayp, Realspawn, Rei_Ayanami, rvL_eXile, Spirit, Superku, Tobias, TSG_Torsten, VeT
|