diff options
Diffstat (limited to 'src/map/pet.c')
-rw-r--r-- | src/map/pet.c | 228 |
1 files changed, 111 insertions, 117 deletions
diff --git a/src/map/pet.c b/src/map/pet.c index 52a8017b4..2865cc901 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -4,39 +4,41 @@ #define HERCULES_CORE +#include "config/core.h" // DBPATH #include "pet.h" +#include "map/atcommand.h" // msg_txt() +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/unit.h" +#include "common/db.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" // msg_txt() -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "path.h" -#include "pc.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "unit.h" -#include "../common/db.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct pet_interface pet_s; +struct pet_interface *pet; #define MIN_PETTHINKTIME 100 @@ -91,7 +93,7 @@ int pet_unlocktarget(struct pet_data *pd) pd->target_id=0; pet_stop_attack(pd); - pet_stop_walking(pd,1); + pet_stop_walking(pd, STOPWALKING_FLAG_FIXPOS); return 0; } @@ -105,7 +107,7 @@ int pet_attackskill(struct pet_data *pd, int target_id) { if (DIFF_TICK(pd->ud.canact_tick, timer->gettick()) > 0) return 0; - + if (rnd()%100 < (pd->a_skill->rate +pd->pet.intimate*pd->a_skill->bonusrate/1000)) { //Skotlex: Use pet's skill int inf; @@ -131,7 +133,7 @@ int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type) int rate; pd = sd->pd; - + Assert_ret(pd->msd == 0 || pd->msd->pd == pd); if( bl == NULL || bl->type != BL_MOB || bl->prev == NULL @@ -184,7 +186,7 @@ int pet_sc_check(struct map_session_data *sd, int type) return 1; pd->recovery->timer = timer->add(timer->gettick()+pd->recovery->delay*1000,pet->recovery_timer,sd->bl.id,0); - + return 0; } @@ -209,7 +211,7 @@ int pet_hungry(int tid, int64 tick, int id, intptr_t data) { if (pd->pet.intimate <= 0) return 1; //You lost the pet already, the rest is irrelevant. - + pd->pet.hungry--; if( pd->pet.hungry < 0 ) { @@ -280,7 +282,7 @@ int pet_performance(struct map_session_data *sd, struct pet_data *pd) else val = 1; - pet_stop_walking(pd,2000<<8); + pet_stop_walking(pd,STOPWALKING_FLAG_NONE | (2000<<8)); // Stop walking for 2000ms clif->send_petdata(NULL, pd, 4, rnd()%val + 1); pet->lootitem_drop(pd,NULL); return 1; @@ -301,7 +303,7 @@ int pet_return_egg(struct map_session_data *sd, struct pet_data *pd) tmp_item.card[3] = pd->pet.rename_flag; if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) { clif->additem(sd,0,0,flag); - map->addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } pd->pet.incubate = 1; unit->free(&pd->bl,CLR_OUTSIGHT); @@ -335,7 +337,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo) //The pet_id value was lost? odd... restore it. sd->status.pet_id = petinfo->pet_id; } - + i = pet->search_petDB_index(petinfo->class_,PET_CLASS); if(i < 0) { sd->status.pet_id = 0; @@ -365,10 +367,10 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo) pd->last_thinktime = timer->gettick(); pd->state.skillbonus = 0; - + if( battle_config.pet_status_support ) - script->run(pet->db[i].pet_script,0,sd->bl.id,0); - + script->run_pet(pet->db[i].pet_script,0,sd->bl.id,0); + if( pd->petDB ) { if( pd->petDB->equip_script ) status_calc_pc(sd,SCO_NONE); @@ -378,7 +380,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo) else interval = pd->petDB->hungry_delay; } - + if( interval <= 0 ) interval = 1; pd->pet_hungry_timer = timer->add(timer->gettick() + interval, pet->hungry, sd->bl.id, 0); @@ -445,7 +447,7 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) { return 1; } if (!pet->birth_process(sd,p)) //Pet hatched. Delete egg. - pc->delitem(sd,i,1,0,0,LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); } else { pet->data_init(sd,p); if(sd->pd && sd->bl.prev != NULL) { @@ -565,7 +567,7 @@ bool pet_get_egg(int account_id, short pet_class, int pet_id ) { // the first request. [Panikon] i = pet->search_petDB_index(pet_class,PET_CLASS); sd->catch_target_class = -1; - + if(i < 0) { intif->delete_petdata(pet_id); return false; @@ -580,7 +582,7 @@ bool pet_get_egg(int account_id, short pet_class, int pet_id ) { tmp_item.card[3] = 0; //New pets are not named. if((ret = pc->additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER))) { clif->additem(sd,0,0,ret); - map->addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } return true; @@ -592,11 +594,11 @@ int pet_menu(struct map_session_data *sd,int menunum) nullpo_ret(sd); if (sd->pd == NULL) return 1; - + //You lost the pet already. if(!sd->status.pet_id || sd->pd->pet.intimate <= 0 || sd->pd->pet.incubate) return 1; - + egg_id = itemdb->exists(sd->pd->petDB->EggID); if (egg_id) { if ((egg_id->flag.trade_restriction&ITR_NODROP) && !pc->inventoryblank(sd)) { @@ -604,7 +606,7 @@ int pet_menu(struct map_session_data *sd,int menunum) return 1; } } - + switch(menunum) { case 0: clif->send_petstatus(sd); @@ -670,15 +672,15 @@ int pet_equipitem(struct map_session_data *sd,int index) { nullpo_retr(1, sd); pd = sd->pd; if (!pd) return 1; - + nameid = sd->status.inventory[index].nameid; - + if(pd->petDB->AcceID == 0 || nameid != pd->petDB->AcceID || pd->pet.equip != 0) { clif->equipitemack(sd,0,0,EIA_FAIL); return 1; } - pc->delitem(sd,index,1,0,0,LOG_TYPE_OTHER); + pc->delitem(sd, index, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); pd->pet.equip = nameid; status->set_viewdata(&pd->bl, pd->pet.class_); //Updates view_data. clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); @@ -711,7 +713,7 @@ int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) { tmp_item.identify = 1; if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) { clif->additem(sd,0,0,flag); - map->addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } if( battle_config.pet_equip_required ) { // Skotlex: halt support timers if needed @@ -743,7 +745,7 @@ int pet_food(struct map_session_data *sd, struct pet_data *pd) { clif->pet_food(sd, food_id, 0); return 1; } - pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); if (pd->pet.hungry > 90) { pet->set_intimate(pd, pd->pet.intimate - pd->petDB->r_full); @@ -793,7 +795,7 @@ int pet_randomwalk(struct pet_data *pd, int64 tick) int r=rnd(); int x=pd->bl.x+r%(d*2+1)-d; int y=pd->bl.y+r/(d*2+1)%(d*2+1)-d; - if(map->getcell(pd->bl.m,x,y,CELL_CHKPASS) && unit->walktoxy(&pd->bl,x,y,0)) { + if(map->getcell (pd->bl.m, &pd->bl, x, y, CELL_CHKPASS) && unit->walktoxy(&pd->bl, x, y, 0)) { pd->move_fail_count=0; break; } @@ -841,7 +843,7 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick pet->randomwalk(pd,tick); return 0; } - + if (!check_distance_bl(&sd->bl, &pd->bl, pd->db->range3)) { //Master too far, chase. if(pd->target_id) @@ -865,7 +867,7 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick pd->status.speed = pd->petDB->speed; pd->ud.state.change_walk_target = pd->ud.state.speed_changed = 1; } - + if (pd->target_id) { target= map->id2bl(pd->target_id); if (!target || pd->bl.m != target->m || status->isdead(target) @@ -875,13 +877,13 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick pet->unlocktarget(pd); } } - + if(!target && pd->loot && pd->msd && pc_has_permission(pd->msd, PC_PERM_TRADE) && pd->loot->count < pd->loot->max && DIFF_TICK(tick,pd->ud.canact_tick)>0) { //Use half the pet's range of sight. map->foreachinrange(pet->ai_sub_hard_lootsearch,&pd->bl, pd->db->range2/2, BL_ITEM,pd,&target); } - + if (!target) { //Just walk around. if (check_distance_bl(&sd->bl, &pd->bl, 3)) @@ -896,7 +898,7 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick return 0; } - + if(pd->ud.target == target->id && (pd->ud.attacktimer != INVALID_TIMER || pd->ud.walktimer != INVALID_TIMER)) return 0; //Target already locked. @@ -960,7 +962,7 @@ int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap) if(sd_charid && sd_charid != pd->msd->status.char_id) return 0; - + if(unit->can_reach_bl(&pd->bl,bl, pd->db->range2, 1, NULL, NULL) && ((*target) == NULL || //New target closer than previous one. !check_distance_bl(&pd->bl, *target, distance_bl(&pd->bl, bl)))) @@ -980,9 +982,9 @@ int pet_delay_item_drop(int tid, int64 tick, int id, intptr_t data) { ditem = list->item; while (ditem) { struct item_drop *ditem_prev; - map->addflooritem(&ditem->item_data,ditem->item_data.amount, - list->m,list->x,list->y, - list->first_charid,list->second_charid,list->third_charid,0); + map->addflooritem(NULL, &ditem->item_data, ditem->item_data.amount, + list->m, list->x, list->y, + list->first_charid, list->second_charid, list->third_charid, 0); ditem_prev = ditem; ditem = ditem->next; ers_free(pet->item_drop_ers, ditem_prev); @@ -1045,18 +1047,18 @@ int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data) { struct pet_data *pd; int bonus; int duration = 0; - + if(sd == NULL || sd->pd==NULL || sd->pd->bonus == NULL) return 1; - + pd=sd->pd; - + if(pd->bonus->timer != tid) { ShowError("pet_skill_bonus_timer %d != %d\n",pd->bonus->timer,tid); pd->bonus->timer = INVALID_TIMER; return 0; } - + // determine the time for the next timer if (pd->state.skillbonus && pd->bonus->delay > 0) { bonus = 0; @@ -1068,7 +1070,7 @@ int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data) { pd->bonus->timer = INVALID_TIMER; return 0; } - + if (pd->state.skillbonus != bonus) { pd->state.skillbonus = bonus; status_calc_pc(sd, SCO_NONE); @@ -1084,10 +1086,10 @@ int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data) { int pet_recovery_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd=map->id2sd(id); struct pet_data *pd; - + if(sd==NULL || sd->pd == NULL || sd->pd->recovery == NULL) return 1; - + pd=sd->pd; if(pd->recovery->timer != tid) { @@ -1104,7 +1106,7 @@ int pet_recovery_timer(int tid, int64 tick, int id, intptr_t data) { } pd->recovery->timer = INVALID_TIMER; - + return 0; } @@ -1118,14 +1120,14 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { short rate = 100; if(sd==NULL || sd->pd == NULL || sd->pd->s_skill == NULL) return 1; - + pd=sd->pd; - + if(pd->s_skill->timer != tid) { ShowError("pet_skill_support_timer %d != %d\n",pd->s_skill->timer,tid); return 0; } - + st = status->get_status_data(&sd->bl); if (DIFF_TICK(pd->ud.canact_tick, tick) > 0) { @@ -1133,7 +1135,7 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { pd->s_skill->timer=timer->add(pd->ud.canact_tick,pet->skill_support_timer,sd->bl.id,0); return 0; } - + if(pc_isdead(sd) || (rate = get_percentage(st->sp, st->max_sp)) > pd->s_skill->sp || (rate = get_percentage(st->hp, st->max_hp)) > pd->s_skill->hp || @@ -1142,9 +1144,9 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { pd->s_skill->timer=timer->add(tick+(rate>10?rate:10)*100,pet->skill_support_timer,sd->bl.id,0); return 0; } - + pet_stop_attack(pd); - pet_stop_walking(pd,1); + pet_stop_walking(pd, STOPWALKING_FLAG_FIXPOS); pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000,pet->skill_support_timer,sd->bl.id,0); if (skill->get_inf(pd->s_skill->id) & INF_GROUND_SKILL) unit->skilluse_pos(&pd->bl, sd->bl.x, sd->bl.y, pd->s_skill->id, pd->s_skill->lv); @@ -1153,26 +1155,24 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } -/*========================================== - * Pet read db data - * pet->db.txt - * pet->db2.txt - *------------------------------------------*/ +/** + * Loads (or reloads) the pet database. + */ int read_petdb() { - char* filename[] = {"pet_db.txt","pet_db2.txt"}; - int nameid,i,j,k; + const char *filename[] = { + DBPATH"pet_db.txt", + "pet_db2.txt", + }; + int i,j; // Remove any previous scripts in case reloaddb was invoked. - for( j = 0; j < MAX_PET_DB; j++ ) - { - if( pet->db[j].pet_script ) - { + for (j = 0; j < MAX_PET_DB; j++) { + if (pet->db[j].pet_script) { script->free_code(pet->db[j].pet_script); pet->db[j].pet_script = NULL; } - if( pet->db[j].equip_script ) - { + if (pet->db[j].equip_script) { script->free_code(pet->db[j].equip_script); pet->db[j].equip_script = NULL; } @@ -1182,59 +1182,56 @@ int read_petdb() memset(pet->db,0,sizeof(pet->db)); j = 0; // entry counter - for( i = 0; i < ARRAYLENGTH(filename); i++ ) { + for (i = 0; i < ARRAYLENGTH(filename); i++) { char line[1024]; int lines, entries; FILE *fp; sprintf(line, "%s/%s", map->db_path, filename[i]); fp=fopen(line,"r"); - if( fp == NULL ) { - if( i == 0 ) + if (fp == NULL) { + if (i == 0) ShowError("can't read %s\n",line); continue; } lines = entries = 0; - while( fgets(line, sizeof(line), fp) && j < MAX_PET_DB ) { + while (fgets(line, sizeof(line), fp) && j < MAX_PET_DB) { char *str[22], *p; + int nameid, k; lines++; - if(line[0] == '/' && line[1] == '/') + if (line[0] == '/' && line[1] == '/') continue; memset(str, 0, sizeof(str)); p = line; - while( ISSPACE(*p) ) + while (ISSPACE(*p)) ++p; - if( *p == '\0' ) + if (*p == '\0') continue; // empty line - for( k = 0; k < 20; ++k ) - { + for (k = 0; k < 20; ++k) { str[k] = p; p = strchr(p,','); - if( p == NULL ) + if (p == NULL) break; // comma not found *p = '\0'; ++p; } - if( p == NULL ) - { + if (p == NULL) { ShowError("read_petdb: Insufficient columns in line %d, skipping.\n", lines); continue; } // Pet Script - if( *p != '{' ) - { + if (*p != '{') { ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines); continue; } str[20] = p; p = strstr(p+1,"},"); - if( p == NULL ) - { + if (p == NULL) { ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines); continue; } @@ -1242,18 +1239,17 @@ int read_petdb() p += 2; // Equip Script - if( *p != '{' ) - { + if (*p != '{') { ShowError("read_petdb: Invalid format (Equip Script column) in line %d, skipping.\n", lines); continue; } str[21] = p; - if( (nameid = atoi(str[0])) <= 0 ) + nameid = atoi(str[0]); + if (nameid <= 0) continue; - if( !mob->db_checkid(nameid) ) - { + if (!mob->db_checkid(nameid)) { ShowWarning("pet_db reading: Invalid mob-class %d, pet not read.\n", nameid); continue; } @@ -1268,7 +1264,7 @@ int read_petdb() pet->db[j].fullness=atoi(str[7]); pet->db[j].hungry_delay=atoi(str[8])*1000; pet->db[j].r_hungry=atoi(str[9]); - if( pet->db[j].r_hungry <= 0 ) + if (pet->db[j].r_hungry <= 0) pet->db[j].r_hungry=1; pet->db[j].r_full=atoi(str[10]); pet->db[j].intimate=atoi(str[11]); @@ -1283,16 +1279,16 @@ int read_petdb() pet->db[j].pet_script = NULL; pet->db[j].equip_script = NULL; - if( *str[20] ) + if (*str[20]) pet->db[j].pet_script = script->parse(str[20], filename[i], lines, 0, NULL); - if( *str[21] ) + if (*str[21]) pet->db[j].equip_script = script->parse(str[21], filename[i], lines, 0, NULL); j++; entries++; } - if( j >= MAX_PET_DB ) + if (j >= MAX_PET_DB) ShowWarning("read_petdb: Reached max number of pets [%d]. Remaining pets were not read.\n ", MAX_PET_DB); fclose(fp); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' pets in '"CL_WHITE"%s"CL_RESET"'.\n", entries, filename[i]); @@ -1311,7 +1307,7 @@ int do_init_pet(bool minimal) { pet->item_drop_ers = ers_new(sizeof(struct item_drop),"pet.c::item_drop_ers",ERS_OPT_NONE); pet->item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"pet.c::item_drop_list_ers",ERS_OPT_NONE); - + timer->add_func_list(pet->hungry,"pet_hungry"); timer->add_func_list(pet->ai_hard,"pet_ai_hard"); timer->add_func_list(pet->skill_bonus_timer,"pet_skill_bonus_timer"); // [Valaris] @@ -1345,16 +1341,14 @@ int do_final_pet(void) } void pet_defaults(void) { pet = &pet_s; - + memset(pet->db,0,sizeof(pet->db)); pet->item_drop_ers = NULL; pet->item_drop_list_ers = NULL; - - /* */ + pet->init = do_init_pet; pet->final = do_final_pet; - - /* */ + pet->hungry_val = pet_hungry_val; pet->set_intimate = pet_set_intimate; pet->create_egg = pet_create_egg; |