/*========================================== * kick an user from a chatroom *------------------------------------------*/ int chat_kickchat(struct map_session_data* sd, const char* kickusername) { struct chat_data* cd; int i; nullpo_retr(1, sd); cd = (struct chat_data *)map_id2bl(sd->chatID); if( cd==NULL || (struct block_list *)sd != cd->owner ) return -1; ARR_FIND( 0, cd->users, i, strncmp(cd->usersd[i]->status.name, kickusername, NAME_LENGTH) == 0 ); if( i == cd->users ) return -1; if (pc_has_permission(cd->usersd[i], PC_PERM_NO_CHAT_KICK)) return 0; //gm kick protection [Valaris] idb_put(cd->kick_list,cd->usersd[i]->status.char_id,(void*)1); chat_leavechat(cd->usersd[i],1); return 0; }
/*========================================== * 既存チャットルームに参加 *------------------------------------------ */ int chat_joinchat (struct map_session_data *sd, int chatid, char* pass) { struct chat_data *cd; nullpo_retr(0, sd); cd = (struct chat_data*)map_id2bl(chatid); //No need for a nullpo check. The chatid was sent by the client, if they lag or mess with the packet //a wrong chat id can be received. [Skotlex] if (cd == NULL) return 1; if (cd->bl.m != sd->bl.m || sd->vender_id || sd->chatID || cd->limit <= cd->users) { clif_joinchatfail(sd,0); return 0; } //Allows Gm access to protected room with any password they want by valaris if ((cd->pub == 0 && strncmp(pass, (char *)cd->pass, 8) && (pc_isGM(sd) < battle_config.gm_join_chat || !battle_config.gm_join_chat)) || chatid == (int)sd->chatID) //Double Chat fix by Alex14, thx CHaNGeTe { clif_joinchatfail(sd,1); return 0; } cd->usersd[cd->users] = sd; cd->users++; pc_setchatid(sd,cd->bl.id); clif_joinchatok(sd,cd); // 新たに参加した人には全員のリスト clif_addchat(cd,sd); // 既に中に居た人には追加した人の報告 clif_dispchat(cd,0); // 周囲の人には人数変化報告 chat_triggerevent(cd); // イベント return 0; }
static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, unsigned int tick) { struct block_list *target = NULL; int master_dist, view_range, mode; nullpo_ret(ed); nullpo_ret(sd); if( ed->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL ) return 0; // Check if caster can sustain the summoned elemental if( DIFF_TICK(tick,ed->last_spdrain_time) >= 10000 ){// Drain SP every 10 seconds int sp = 5; switch(ed->vd->class_){ case ELEMENTALID_AGNI_M: case ELEMENTALID_AQUA_M: case ELEMENTALID_VENTUS_M: case ELEMENTALID_TERA_M: sp = 8; break; case ELEMENTALID_AGNI_L: case ELEMENTALID_AQUA_L: case ELEMENTALID_VENTUS_L: case ELEMENTALID_TERA_L: sp = 11; break; } if( status_get_sp(&sd->bl) < sp ){ // Can't sustain delete it. elemental_delete(sd->ed,0); return 0; } status_zap(&sd->bl,0,sp); ed->last_spdrain_time = tick; } if( DIFF_TICK(tick,ed->last_thinktime) < MIN_ELETHINKTIME ) return 0; ed->last_thinktime = tick; if( ed->ud.skilltimer != INVALID_TIMER ) return 0; if( ed->ud.walktimer != INVALID_TIMER && ed->ud.walkpath.path_pos <= 2 ) return 0; //No thinking when you just started to walk. if(ed->ud.walkpath.path_pos < ed->ud.walkpath.path_len && ed->ud.target == sd->bl.id) return 0; //No thinking until be near the master. if( ed->sc.count && ed->sc.data[SC_BLIND] ) view_range = 3; else view_range = ed->db->range2; mode = status_get_mode(&ed->bl); master_dist = distance_bl(&sd->bl, &ed->bl); if( master_dist > AREA_SIZE ) { // Master out of vision range. elemental_unlocktarget(ed); unit_warp(&ed->bl,sd->bl.m,sd->bl.x,sd->bl.y,CLR_TELEPORT); clif_elemental_updatestatus(sd,SP_HP); clif_elemental_updatestatus(sd,SP_SP); return 0; } else if( master_dist > MAX_ELEDISTANCE ) { // Master too far, chase. short x = sd->bl.x, y = sd->bl.y; if( ed->target_id ) elemental_unlocktarget(ed); if( ed->ud.walktimer != INVALID_TIMER && ed->ud.target == sd->bl.id ) return 0; //Already walking to him if( DIFF_TICK(tick, ed->ud.canmove_tick) < 0 ) return 0; //Can't move yet. if( map_search_freecell(&ed->bl, sd->bl.m, &x, &y, MIN_ELEDISTANCE, MIN_ELEDISTANCE, 1) && unit_walktoxy(&ed->bl, x, y, 0) ) return 0; } if( mode == EL_MODE_AGGRESSIVE ) { target = map_id2bl(ed->ud.target); if( !target ) map_foreachinrange(elemental_ai_sub_timer_activesearch, &ed->bl, view_range, BL_CHAR, ed, &target, status_get_mode(&ed->bl)); if( !target ) { //No targets available. elemental_unlocktarget(ed); return 1; } if( battle_check_range(&ed->bl,target,view_range) && rnd()%100 < 2 ) { // 2% chance to cast attack skill. if( elemental_action(ed,target,tick) ) return 1; } //Attempt to attack. //At this point we know the target is attackable, we just gotta check if the range matches. if( ed->ud.target == target->id && ed->ud.attacktimer != INVALID_TIMER ) //Already locked. return 1; if( battle_check_range(&ed->bl, target, ed->base_status.rhw.range) ) {//Target within range, engage unit_attack(&ed->bl,target->id,1); return 1; } //Follow up if possible. if( !unit_walktobl(&ed->bl, target, ed->base_status.rhw.range, 2) ) elemental_unlocktarget(ed); } return 0; }
/*========================================== * leave a chatroom *------------------------------------------*/ int chat_leavechat(struct map_session_data *sd, bool kicked) { struct chat_data *cd; int i; int leavechar; nullpo_retr(1, sd); cd = (struct chat_data *)map_id2bl(sd->chatID); if(cd == NULL) { pc_setchatid(sd, 0); return 1; } ARR_FIND(0, cd->users, i, cd->usersd[i] == sd); if(i == cd->users) { // Not found in the chatroom? pc_setchatid(sd, 0); return -1; } clif_leavechat(cd, sd, kicked); pc_setchatid(sd, 0); cd->users--; leavechar = i; for(i = leavechar; i < cd->users; i++) cd->usersd[i] = cd->usersd[i+1]; if(cd->users == 0 && cd->owner->type == BL_PC) { // Delete empty chatroom struct skill_unit *unit; struct skill_unit_group *group; clif_clearchat(cd, 0); db_destroy(cd->kick_list); map_deliddb(&cd->bl); map_delblock(&cd->bl); map_freeblock(&cd->bl); unit = map_find_skill_unit_oncell(&sd->bl, sd->bl.x, sd->bl.y, AL_WARP, NULL, 0); group = (unit != NULL) ? unit->group : NULL; if(group != NULL) ext_skill_unit_onplace(unit, &sd->bl, group->tick); return 1; } if(leavechar == 0 && cd->owner->type == BL_PC) { // Set and announce new owner cd->owner = (struct block_list *) cd->usersd[0]; clif_changechatowner(cd, cd->usersd[0]); clif_clearchat(cd, 0); //Adjust Chat location after owner has been changed. map_delblock(&cd->bl); cd->bl.x=cd->usersd[0]->bl.x; cd->bl.y=cd->usersd[0]->bl.y; map_addblock(&cd->bl); clif_dispchat(cd,0); } else clif_dispchat(cd,0); // refresh chatroom return 0; }
static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, unsigned int tick) { struct block_list *target = NULL; int master_dist, view_range, mode; nullpo_ret(ed); nullpo_ret(sd); if( ed->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL ) return 0; if( DIFF_TICK(tick,ed->last_thinktime) < MIN_ELETHINKTIME ) return 0; ed->last_thinktime = tick; if( ed->ud.skilltimer != -1 ) return 0; if( ed->ud.walktimer != -1 && ed->ud.walkpath.path_pos <= 2 ) return 0; //No thinking when you just started to walk. if(ed->ud.walkpath.path_pos < ed->ud.walkpath.path_len && ed->ud.target == sd->bl.id) return 0; //No thinking until be near the master. if( ed->sc.count && ed->sc.data[SC_BLIND] ) view_range = 3; else view_range = ed->db->range2; mode = status_get_mode(&ed->bl); master_dist = distance_bl(&sd->bl, &ed->bl); if( master_dist > AREA_SIZE ) { // Master out of vision range. elemental_unlocktarget(ed); unit_warp(&ed->bl,sd->bl.m,sd->bl.x,sd->bl.y,3); return 0; } else if( master_dist > MAX_ELEDISTANCE ) { // Master too far, chase. short x = sd->bl.x, y = sd->bl.y; if( ed->target_id ) elemental_unlocktarget(ed); if( ed->ud.walktimer != -1 && ed->ud.target == sd->bl.id ) return 0; //Already walking to him if( DIFF_TICK(tick, ed->ud.canmove_tick) < 0 ) return 0; //Can't move yet. if( map_search_freecell(&ed->bl, sd->bl.m, &x, &y, MIN_ELEDISTANCE, MIN_ELEDISTANCE, 1) && unit_walktoxy(&ed->bl, x, y, 0) ) return 0; } if( mode == EL_MODE_AGGRESSIVE ) { target = map_id2bl(ed->ud.target); if( !target ) map_foreachinrange(elemental_ai_sub_timer_activesearch, &ed->bl, ed->db->range2, BL_CHAR, ed, &target, status_get_mode(&ed->bl)); if( !target ) { //No targets available. elemental_unlocktarget(ed); return 1; } if( battle_check_range(&ed->bl,target,ed->db->range2) && rand()%100 < 2 ) // 2% chance to cast attack skill. { if( elemental_action(ed,target,tick) ) return 1; } //Attempt to attack. //At this point we know the target is attackable, we just gotta check if the range matches. if( ed->ud.target == target->id && ed->ud.attacktimer != -1 ) //Already locked. return 1; if( battle_check_range(&ed->bl, target, ed->base_status.rhw.range) ) { //Target within range, engage unit_attack(&ed->bl,target->id,1); return 1; } //Follow up if possible. if( !unit_walktobl(&ed->bl, target, ed->base_status.rhw.range, 2) ) elemental_unlocktarget(ed); } return 0; }
void harmony_action_request_global(int task, int id, intptr data) { switch (task) { case HARMTASK_LOGIN_ACTION: chrif_harmony_request((uint8*)data, id); break; case HARMTASK_GET_FD: { TBL_PC *sd = BL_CAST(BL_PC, map_id2bl(id)); *(int32*)data = (sd ? sd->fd : 0); } break; case HARMTASK_SET_LOG_METHOD: log_method = id; break; case HARMTASK_INIT_GROUPS: if (chrif_isconnected()) harmony_register_groups(); else { // Register groups as soon as the char server is available again if (tid_group_register != INVALID_TIMER) _athena_delete_timer(tid_group_register, harmony_group_register_timer); tid_group_register = _athena_add_timer_interval(_athena_gettick()+1000, harmony_group_register_timer, 0, 0, 500); } break; case HARMTASK_RESOLVE_GROUP: #if HARMSW == HARMSW_RATHENA_GROUP *(int32*)data = pc_group_id2level(id); #else *(int32*)data = id; #endif break; case HARMTASK_PACKET: clif_send((const uint8*)data, id, NULL, ALL_CLIENT); break; case HARMTASK_GET_ADMINS: { #if HARMSW == HARMSW_RATHENA_GROUP // Iterate groups and register each group individually current_groupscan_minlevel = id; pc_group_iterate(harmony_iterate_groups_adminlevel); #else // int account_id; int level = id; if (SQL_SUCCESS != SqlStmt_BindParam(admin_stmt, 0, SQLDT_INT, (void*)&level, sizeof(level)) || SQL_SUCCESS != SqlStmt_Execute(admin_stmt)) { ShowError("Fetching GM accounts failed.\n"); Sql_ShowDebug(mmysql_handle); break; } SqlStmt_BindColumn(admin_stmt, 0, SQLDT_INT, &account_id, 0, NULL, NULL); while (SQL_SUCCESS == SqlStmt_NextRow(admin_stmt)) { harm_funcs->zone_register_admin(account_id, false); } #endif break; } case HARMTASK_IS_CHAR_CONNECTED: *(int*)data = chrif_isconnected(); break; default: ShowError("Harmony requested unknown action! (Global; ID=%d)\n", task); ShowError("This indicates that you are running an incompatible version.\n"); break; } }
static void stringify (val_t * v, int within_op) { static char *dirs[8] = { "south", "south-west", "west", "north-west", "north", "north-east", "east", "south-east" }; char *buf; switch (v->ty) { case TY_UNDEF: buf = strdup ("UNDEF"); break; case TY_INT: buf = malloc (32); sprintf (buf, "%i", v->v.v_int); break; case TY_STRING: return; case TY_DIR: buf = strdup (dirs[v->v.v_int]); break; case TY_ENTITY: buf = strdup (show_entity (v->v.v_entity)); break; case TY_LOCATION: buf = malloc (128); sprintf (buf, "<\"%s\", %d, %d>", map[v->v.v_location.m].name, v->v.v_location.x, v->v.v_location.y); break; case TY_AREA: buf = strdup ("%area"); free_area (v->v.v_area); break; case TY_SPELL: buf = strdup (v->v.v_spell->name); break; case TY_INVOCATION: { invocation_t *invocation = within_op ? v->v.v_invocation : (invocation_t *) map_id2bl (v->v.v_int); buf = strdup (invocation->spell->name); } break; default: fprintf (stderr, "[magic] INTERNAL ERROR: Cannot stringify %d\n", v->ty); return; } v->v.v_string = buf; v->ty = TY_STRING; }
static void stringify(val_t *v, int within_op) { static earray<ZString, DIR, DIR::COUNT> dirs //= {{ {"south"}, {"south-west"}, {"west"}, {"north-west"}, {"north"}, {"north-east"}, {"east"}, {"south-east"}, }}; FString buf; switch (v->ty) { case TYPE::UNDEF: buf = "UNDEF"; break; case TYPE::INT: buf = STRPRINTF("%i", v->v.v_int); break; case TYPE::STRING: return; case TYPE::DIR: buf = dirs[v->v.v_dir]; break; case TYPE::ENTITY: buf = show_entity(v->v.v_entity); break; case TYPE::LOCATION: buf = STRPRINTF("<\"%s\", %d, %d>", v->v.v_location.m->name_, v->v.v_location.x, v->v.v_location.y); break; case TYPE::AREA: buf = "%area"; free_area(v->v.v_area); break; case TYPE::SPELL: buf = v->v.v_spell->name; break; case TYPE::INVOCATION: { dumb_ptr<invocation> invocation_ = within_op ? v->v.v_invocation : map_id2bl(v->v.v_int)->as_spell(); buf = invocation_->spell->name; } break; default: FPRINTF(stderr, "[magic] INTERNAL ERROR: Cannot stringify %d\n", v->ty); return; } v->v.v_string = dumb_string::copys(buf); v->ty = TYPE::STRING; }
int pet_catch_process2(struct map_session_data *sd,int target_id) { struct mob_data *md; int i=0,pet_catch_rate=0; nullpo_retr(1, sd); md=(struct mob_data*)map_id2bl(target_id); if(!md || md->bl.type != BL_MOB || md->bl.prev == NULL){ //Abort capture. sd->catch_target_class = -1; sd->itemid = sd->itemindex = -1; return 1; } if (sd->menuskill_id != SA_TAMINGMONSTER) { //Exploit? clif_pet_rulet(sd,0); sd->catch_target_class = -1; return 1; } if (sd->menuskill_lv > 0) { //Consume the pet lure [Skotlex] i=pc_search_inventory(sd,sd->menuskill_lv); if (i < 0) { //they tried an exploit? clif_pet_rulet(sd,0); sd->catch_target_class = -1; return 1; } //Delete the item if (sd->itemid == sd->menuskill_lv) sd->itemid = sd->itemindex = -1; sd->menuskill_id = sd->menuskill_lv = 0; pc_delitem(sd,i,1,0); } i = search_petDB_index(md->class_,PET_CLASS); //catch_target_class == 0 is used for universal lures. [Skotlex] //for now universal lures do not include bosses. if (sd->catch_target_class == 0 && !(md->status.mode&MD_BOSS)) sd->catch_target_class = md->class_; if(i < 0 || sd->catch_target_class != md->class_) { clif_emotion(&md->bl, 7); //mob will do /ag if wrong lure is used on them. clif_pet_rulet(sd,0); sd->catch_target_class = -1; return 1; } pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - md->level)*30 + sd->battle_status.luk*20)*(200 - md->status.hp*100/md->status.max_hp)/100; if(pet_catch_rate < 1) pet_catch_rate = 1; if(battle_config.pet_catch_rate != 100) pet_catch_rate = (pet_catch_rate*battle_config.pet_catch_rate)/100; if(rand()%10000 < pet_catch_rate) { unit_remove_map(&md->bl,0); status_kill(&md->bl); clif_pet_rulet(sd,1); // if(battle_config.etc_log) // printf("rulet success %d\n",target_id); intif_create_pet(sd->status.account_id,sd->status.char_id,pet_db[i].class_,mob_db(pet_db[i].class_)->lv, pet_db[i].EggID,0,pet_db[i].intimate,100,0,1,pet_db[i].jname); } else { sd->catch_target_class = -1; clif_pet_rulet(sd,0); } return 0; }
inline dumb_ptr<invocation> map_id_is_spell(int id) { dumb_ptr<block_list> bl = map_id2bl(id); return bl ? bl->is_spell() : nullptr; }
inline dumb_ptr<flooritem_data> map_id_is_item(int id) { dumb_ptr<block_list> bl = map_id2bl(id); return bl ? bl->is_item() : nullptr; }
inline dumb_ptr<mob_data> map_id_is_mob(int id) { dumb_ptr<block_list> bl = map_id2bl(id); return bl ? bl->is_mob() : nullptr; }
inline dumb_ptr<map_session_data> map_id_is_player(int id) { dumb_ptr<block_list> bl = map_id2bl(id); return bl ? bl->is_player() : nullptr; }