version 1.38 | | version 1.39 |
---|
| | |
/* | | /* |
* static char *rcsid_attack_c = | | * static char *rcsid_attack_c = |
* "$Id: attack.c,v 1.38 2001/06/13 12:51:58 michtoen Exp $"; | | * "$Id: attack.c,v 1.39 2001/06/29 05:59:46 mwedel Exp $"; |
*/ | | */ |
/* | | /* |
CrossFire, A Multiplayer game for X-windows | | CrossFire, A Multiplayer game for X-windows |
| | |
{ | | { |
if (guile_use_weapon_script(hitter, op, base_dam, base_wc)) | | if (guile_use_weapon_script(hitter, op, base_dam, base_wc)) |
{ | | { |
return; | | return 0; |
}; | | }; |
}; | | }; |
}; | | }; |
| | |
{ | | { |
char buf[MAX_BUF]; | | char buf[MAX_BUF]; |
object *old_hitter=NULL; /* this is used in case of servant monsters */ | | object *old_hitter=NULL; /* this is used in case of servant monsters */ |
int maxdam=0,ndam,attacktype=1,attacknum,magic=(type & AT_MAGIC); | | int maxdam=0; |
int body_attack = op && op->head; /* Did we hit op's head? */ | | |
int simple_attack; | | |
tag_t op_tag, hitter_tag; | | |
int battleg=0; /* true if op standing on battleground */ | | int battleg=0; /* true if op standing on battleground */ |
int killed_script_rtn = 0; | | int killed_script_rtn = 0; |
object *owner=NULL; | | object *owner=NULL; |
| | |
{ | | { |
killed_script_rtn = guile_call_event(hitter, op ,NULL, type, NULL, 0,0, op->script_death, SCRIPT_FIX_ALL); | | killed_script_rtn = guile_call_event(hitter, op ,NULL, type, NULL, 0,0, op->script_death, SCRIPT_FIX_ALL); |
if (killed_script_rtn) | | if (killed_script_rtn) |
return; | | return 0; |
} | | } |
else | | else { |
{ | | |
if (op->script_str_death!=NULL) | | if (op->script_str_death!=NULL) |
{ | | { |
killed_script_rtn = guile_call_event_str(hitter, op ,NULL, type, NULL, 0,0, op->script_str_death, SCRIPT_FIX_ALL); | | killed_script_rtn = guile_call_event_str(hitter, op ,NULL, type, NULL, 0,0, op->script_str_death, SCRIPT_FIX_ALL); |
if (killed_script_rtn) | | if (killed_script_rtn) |
return; | | return 0; |
}; | | } |
}; | | } |
| | |
/* Object has been killed. Lets clean it up */ | | /* Object has been killed. Lets clean it up */ |
if (op->stats.hp<0) { | | if (op->stats.hp<0) { |
| | |
if(QUERY_FLAG(op,FLAG_BLOCKSVIEW)) | | if(QUERY_FLAG(op,FLAG_BLOCKSVIEW)) |
update_all_los(op->map); /* makes sure los will be recalculated */ | | update_all_los(op->map); /* makes sure los will be recalculated */ |
| | |
if(op->type==DOOR) | | if(op->type==DOOR) { |
{ | | |
op->speed = 0.1; | | op->speed = 0.1; |
update_ob_speed(op); | | update_ob_speed(op); |
op->speed_left= -0.05; | | op->speed_left= -0.05; |
return maxdam; | | return maxdam; |
}; | | } |
if(QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) | | if(QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) { |
{ | | |
remove_friendly_object(op); | | remove_friendly_object(op); |
if (get_owner (op) != NULL && op->owner->type == PLAYER) | | if (get_owner (op) != NULL && op->owner->type == PLAYER) |
op->owner->contr->golem=NULL; | | op->owner->contr->golem=NULL; |
| | |
remove_ob(op); | | remove_ob(op); |
free_object(op); | | free_object(op); |
return maxdam; | | return maxdam; |
}; | | } |
| | |
/* Now lets start dealing with experience we get for killing something */ | | /* Now lets start dealing with experience we get for killing something */ |
| | |
| | |
if (op_on_battleground(op, NULL, NULL)) battleg=1; | | if (op_on_battleground(op, NULL, NULL)) battleg=1; |
| | |
/* Player killed something */ | | /* Player killed something */ |
if(owner->type==PLAYER) | | if(owner->type==PLAYER) { |
{ | | |
Log_Kill(owner->name, | | Log_Kill(owner->name, |
query_name(op),op->type, | | query_name(op),op->type, |
(owner!=hitter) ? query_name(hitter) : NULL, | | (owner!=hitter) ? query_name(hitter) : NULL, |
| | |
/* This appears to be doing primitive filtering to only | | /* This appears to be doing primitive filtering to only |
* display the more interesting monsters. | | * display the more interesting monsters. |
*/ | | */ |
if ( owner->level/2<op->level || op->stats.exp>1000) | | if ( owner->level/2<op->level || op->stats.exp>1000) { |
{ | | if(owner!=hitter) { |
if(owner!=hitter) | | |
{ | | |
(void) sprintf(buf,"You killed %s with %s.",query_name(op) | | (void) sprintf(buf,"You killed %s with %s.",query_name(op) |
,query_name(hitter)); | | ,query_name(hitter)); |
old_hitter = hitter; | | old_hitter = hitter; |
owner->exp_obj=hitter->exp_obj; | | owner->exp_obj=hitter->exp_obj; |
} | | } |
else | | else { |
{ | | |
(void) sprintf(buf,"You killed %s.",query_name(op)); | | (void) sprintf(buf,"You killed %s.",query_name(op)); |
} | | } |
play_sound_map(owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); | | play_sound_map(owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); |
| | |
| | |
/* If a player kills another player with melee, not on | | /* If a player kills another player with melee, not on |
* battleground, the "killer" looses 1 luck. Since this is | | * battleground, the "killer" looses 1 luck. Since this is |
* not reversible, it's actually quite a pain IMHO. -AV */ | | * not reversible, it's actually quite a pain IMHO. -AV |
| | */ |
if(op->type == PLAYER && hitter != op && !battleg) | | if(op->type == PLAYER && hitter != op && !battleg) |
change_luck(hitter, -1); | | change_luck(hitter, -1); |
} /* was a player that hit this creature */ | | } /* was a player that hit this creature */ |
| | |
/* Pet killed something. */ | | /* Pet killed something. */ |
if(get_owner(hitter)!=NULL) | | if(get_owner(hitter)!=NULL) { |
{ | | |
(void) sprintf(buf,"%s killed %s with %s%s.",hitter->owner->name, | | (void) sprintf(buf,"%s killed %s with %s%s.",hitter->owner->name, |
query_name(op),query_name(hitter), battleg? " (duel)":""); | | query_name(op),query_name(hitter), battleg? " (duel)":""); |
old_hitter = hitter; | | old_hitter = hitter; |
| | |
battleg? " (duel)":""); | | battleg? " (duel)":""); |
| | |
/* If you didn't kill yourself, and your not the wizard */ | | /* If you didn't kill yourself, and your not the wizard */ |
if(hitter!=op&&!QUERY_FLAG(op, FLAG_WAS_WIZ)) | | if(hitter!=op&&!QUERY_FLAG(op, FLAG_WAS_WIZ)) { |
{ | | |
int exp=op->stats.exp; | | int exp=op->stats.exp; |
| | |
if(!settings.simple_exp && hitter->level>op->level) | | if(!settings.simple_exp && hitter->level>op->level) |
| | |
hitter->chosen_skill=old_hitter->chosen_skill; | | hitter->chosen_skill=old_hitter->chosen_skill; |
exp = calc_skill_exp(hitter,op); | | exp = calc_skill_exp(hitter,op); |
hitter->chosen_skill = old_skill; | | hitter->chosen_skill = old_skill; |
}; | | } |
| | |
/* Really don't give much experience for killing other players */ | | /* Really don't give much experience for killing other players */ |
if (op->type==PLAYER) | | if (op->type==PLAYER) { |
{ | | if (battleg) { |
if (battleg) | | |
{ | | |
new_draw_info(NDI_UNIQUE, 0,hitter, "Your foe has fallen!"); | | new_draw_info(NDI_UNIQUE, 0,hitter, "Your foe has fallen!"); |
new_draw_info(NDI_UNIQUE, 0,hitter, "VICTORY!!!"); | | new_draw_info(NDI_UNIQUE, 0,hitter, "VICTORY!!!"); |
} | | } |
| | |
/* Don't know why this is set this way - doesn't make | | /* Don't know why this is set this way - doesn't make |
* sense to just divide everything by two for no reason. | | * sense to just divide everything by two for no reason. |
*/ | | */ |
| | |
if (!settings.simple_exp) | | if (!settings.simple_exp) |
exp=exp/2; | | exp=exp/2; |
| | |
/* if op is standing on "battleground" (arena), no way to gain | | /* if op is standing on "battleground" (arena), no way to gain |
* exp by killing him */ | | * exp by killing him |
| | */ |
if (battleg) exp = 0; | | if (battleg) exp = 0; |
if(hitter->type!=PLAYER || hitter->contr->party_number<=0) | | if(hitter->type!=PLAYER || hitter->contr->party_number<=0) { |
{ | | |
add_exp(hitter,exp); | | add_exp(hitter,exp); |
} | | } |
else | | else { |
{ | | |
int shares=0,count=0; | | int shares=0,count=0; |
player *pl; | | player *pl; |
int no=hitter->contr->party_number; | | int no=hitter->contr->party_number; |
#ifdef PARTY_KILL_LOG | | #ifdef PARTY_KILL_LOG |
add_kill_to_party(no,query_name(hitter),query_name(op),exp); | | add_kill_to_party(no,query_name(hitter),query_name(op),exp); |
#endif | | #endif |
for(pl=first_player;pl!=NULL;pl=pl->next) | | for(pl=first_player;pl!=NULL;pl=pl->next) { |
{ | | if(pl->ob->contr->party_number==no && (pl->ob->map == hitter->map)) { |
if(pl->ob->contr->party_number==no && (pl->ob->map == hitter->map)) | | |
{ | | |
count++; | | count++; |
shares+=(pl->ob->level+4); | | shares+=(pl->ob->level+4); |
} | | } |
} | | } |
if(count==1 || shares>exp) | | if(count==1 || shares>exp) |
add_exp(hitter,exp); | | add_exp(hitter,exp); |
else | | else { |
{ | | |
int share=exp/shares,given=0,nexp; | | int share=exp/shares,given=0,nexp; |
for(pl=first_player;pl!=NULL;pl=pl->next) | | for(pl=first_player;pl!=NULL;pl=pl->next) { |
{ | | |
if(pl->ob->contr->party_number==no && (pl->ob->map == hitter->map)) | | if(pl->ob->contr->party_number==no && (pl->ob->map == hitter->map)) |
{ | | { |
nexp=(pl->ob->level+4)*share; | | nexp=(pl->ob->level+4)*share; |
| | |
} | | } |
} | | } |
} | | } |
if(op->type!=PLAYER) | | if(op->type!=PLAYER) { |
{ | | |
new_draw_info(NDI_ALL, 10, NULL, buf); | | new_draw_info(NDI_ALL, 10, NULL, buf); |
if(QUERY_FLAG(op,FLAG_FRIENDLY)) | | if(QUERY_FLAG(op,FLAG_FRIENDLY)) { |
{ | | |
object *owner = get_owner(op); | | object *owner = get_owner(op); |
if(owner!= NULL && owner->type == PLAYER) | | if(owner!= NULL && owner->type == PLAYER) { |
{ | | |
sprintf(buf,"Your pet, the %s, is killed by %s.", | | sprintf(buf,"Your pet, the %s, is killed by %s.", |
op->name,hitter->name); | | op->name,hitter->name); |
play_sound_player_only(owner->contr, SOUND_PET_IS_KILLED,0,0); | | play_sound_player_only(owner->contr, SOUND_PET_IS_KILLED,0,0); |
| | |
free_object(op); | | free_object(op); |
} | | } |
/* Player has been killed! */ | | /* Player has been killed! */ |
else | | else { |
{ | | |
new_draw_info(NDI_ALL, 1, NULL, buf); | | new_draw_info(NDI_ALL, 1, NULL, buf); |
if(hitter->type==PLAYER) | | if(hitter->type==PLAYER) { |
{ | | |
sprintf(buf,"%s the %s",hitter->name,hitter->contr->title); | | sprintf(buf,"%s the %s",hitter->name,hitter->contr->title); |
strncpy(op->contr->killer,buf,BIG_NAME); | | strncpy(op->contr->killer,buf,BIG_NAME); |
} | | } |
else | | else { |
{ | | |
strncpy(op->contr->killer,hitter->name,BIG_NAME); | | strncpy(op->contr->killer,hitter->name,BIG_NAME); |
op->contr->killer[BIG_NAME-1]='\0'; | | op->contr->killer[BIG_NAME-1]='\0'; |
} | | } |
}; | | } |
}; | | } |
return -1; | | return -1; |
}; | | } |
| | |
/* This isn't used just for players, but in fact most objects. | | /* This isn't used just for players, but in fact most objects. |
* op is the object to be hit, dam is the amount of damage, hitter | | * op is the object to be hit, dam is the amount of damage, hitter |
| | |
* which needs new attacktype AT_HOLYWORD to work . b.t. */ | | * which needs new attacktype AT_HOLYWORD to work . b.t. */ |
| | |
int hit_player(object *op,int dam, object *hitter, int type) { | | int hit_player(object *op,int dam, object *hitter, int type) { |
char buf[MAX_BUF]; | | |
object *old_hitter=NULL; /* this is used in case of servant monsters */ | | |
int maxdam=0,ndam,attacktype=1,attacknum,magic=(type & AT_MAGIC); | | int maxdam=0,ndam,attacktype=1,attacknum,magic=(type & AT_MAGIC); |
int body_attack = op && op->head; /* Did we hit op's head? */ | | int body_attack = op && op->head; /* Did we hit op's head? */ |
int simple_attack; | | int simple_attack; |
tag_t op_tag, hitter_tag; | | tag_t op_tag, hitter_tag; |
int battleg=0; /* true if op standing on battleground */ | | |
int rtn_kill = 0; | | int rtn_kill = 0; |
| | |
if (get_attack_mode (&op, &hitter, &simple_attack)) | | if (get_attack_mode (&op, &hitter, &simple_attack)) |