Active+ Member Trial 269 Posted February 22 Active+ Member Share Posted February 22 This is a trick I implemented on a player's suggestion, the idea is to block the "regen" (mobs respawning) in some areas until a specific monster is killed. So if you want to prevent players from going AFK & macro in some areas you put a "regen blocking mob" there, preferably a range-based attacking one (magic / archer) so that this area's monsters will not be respawned until this monster is killed. These monsters will be spawned via the regen system and you will be able to control the area covered by individual monster using it's spawn position and delta x & delta y coordinates. regen.h somewhere in this struct: typedef struct regen add: bool is_anti_macro; and add it in the initializers list: regen() : prev(NULL), next(NULL), ... is_anti_macro(false), // <-- this event(NULL), id(0) {} add: extern bool is_regen_in_anti_macro_position(LPREGEN tested_regen); somewhere near: extern void regen_reset(int x, int y); regen.cpp below: LPREGEN regen_list = NULL; add: LPREGEN regen_anti_macro_list = NULL; in this function: static bool read_line(FILE* fp, LPREGEN regen) edit this case-if block case MODE_TYPE: if (szTmp[0] == 'm') to this: ... case MODE_TYPE: if (szTmp[0] == 'm') { regen->type = REGEN_TYPE_MOB; if (szTmp[1] == 'a' && szTmp[2] == 'm') regen->is_anti_macro = true; } ... add this function somewhere in the file: bool is_regen_in_anti_macro_position(LPREGEN tested_regen) { LPREGEN regen; for (regen = regen_anti_macro_list; regen; regen = regen->next) { // if "tested_regen" position is inside "regen" position if (regen->count) if (tested_regen->sx >= regen->sx && tested_regen->ex <= regen->ex && tested_regen->sy >= regen->sy && tested_regen->ey <= regen->ey) { return true; } } return false; } in this function's definition: static void regen_spawn(LPREGEN regen, bool bOnce) edit the return type to bool and add the third input parameter: static bool regen_spawn(LPREGEN regen, bool bOnce, bool bInitial = false) change: if (!num) return; to: if (!num) return true; and add this just below: if (!bInitial && !regen->is_anti_macro) { if (is_regen_in_anti_macro_position(regen)) return false; } and finally add this return at the end: return true; the whole definition should look like this: static bool regen_spawn(LPREGEN regen, bool bOnce, bool bInitial = false) { DWORD num; DWORD i; num = (regen->max_count - regen->count); if (!num) return true; if (!bInitial && !regen->is_anti_macro) { if (is_regen_in_anti_macro_position(regen)) return false; } for (i = 0; i < num; ++i) { LPCHARACTER ch = NULL; if (regen->type == REGEN_TYPE_ANYWHERE) { ch = CHARACTER_MANAGER::instance().SpawnMobRandomPosition(regen->vnum, regen->lMapIndex); if (ch) ++regen->count; } else if (regen->sx == regen->ex && regen->sy == regen->ey) { ch = CHARACTER_MANAGER::instance().SpawnMob(regen->vnum, regen->lMapIndex, regen->sx, regen->sy, regen->z_section, false, regen->direction == 0 ? number(0, 7) * 45 : (regen->direction - 1) * 45); if (ch) ++regen->count; } else { if (regen->type == REGEN_TYPE_MOB) { ch = CHARACTER_MANAGER::Instance().SpawnMobRange(regen->vnum, regen->lMapIndex, regen->sx, regen->sy, regen->ex, regen->ey, true, regen->is_aggressive, regen->is_aggressive ); if (ch) ++regen->count; } else if (regen->type == REGEN_TYPE_GROUP) { if (CHARACTER_MANAGER::Instance().SpawnGroup(regen->vnum, regen->lMapIndex, regen->sx, regen->sy, regen->ex, regen->ey, bOnce ? NULL : regen, regen->is_aggressive)) ++regen->count; } else if (regen->type == REGEN_TYPE_GROUP_GROUP) { if (CHARACTER_MANAGER::Instance().SpawnGroupGroup(regen->vnum, regen->lMapIndex, regen->sx, regen->sy, regen->ex, regen->ey, bOnce ? NULL : regen, regen->is_aggressive)) ++regen->count; } } if (ch && !bOnce) ch->SetRegen(regen); } return true; } in this function: EVENTFUNC(regen_event) edit this: regen_spawn(regen, false); return PASSES_PER_SEC(regen->time); to: if (!regen_spawn(regen, false)) { // if the regen failed (probably because there is a regen blocking mob alive in the regen area) // let's retry faster, NB: YOU CAN reduce this value further is you like return PASSES_PER_SEC(regen->time / 2); } return PASSES_PER_SEC(regen->time); the whole definition should look like this: EVENTFUNC(regen_event) { regen_event_info* info = dynamic_cast<regen_event_info*>( event->info ); if ( info == NULL ) { sys_err( "regen_event> <Factor> Null pointer" ); return 0; } LPREGEN regen = info->regen; if (regen->time == 0) regen->event = NULL; if (!regen_spawn(regen, false)) { // if the regen failed (probably because there is a regen blocking mob alive in the regen area) // let's retry faster, NB: YOU CAN reduce this value further is you like return PASSES_PER_SEC(regen->time / 2); } return PASSES_PER_SEC(regen->time); } in: void regen_free(void) add this add the end: regen_anti_macro_list = NULL; Now you can add the regen blocking monsters in your regen files as you would do for normal monsters & groups: example below with the mob vnum 2132, the regen definition remains identical to normal monster one: Spoiler mam 140 75 25 50 0 0 90s 100 1 2132 details: x: 140 y: 75 deltaX: 25 deltaY: 50 startX: 140 - 25 = 115 endX: 140 - 25 + (25 * 2) = 165 startY: 75 - 50 = 25 endY: 75 - 50 + (50 * 2) = 125 covered area: from (115, 25) to (165, 125) (= the rect: (115,25),(165,25),(115,125),(165,125) ) Bonus: if you want your regen blocking monsters to have custom hard-coded attacking range you could edit this function (in char.cpp): WORD CHARACTER::GetMobAttackRange() const to something like: WORD CHARACTER::GetMobAttackRange() const { switch (GetMobBattleType()) { case BATTLE_TYPE_RANGE: case BATTLE_TYPE_MAGIC: if (m_pkRegen && m_pkRegen->is_anti_macro) return 2400; // put your custom value here return m_pkMobData->m_table.wAttackRange + GetPoint(POINT_BOW_DISTANCE); default: return m_pkMobData->m_table.wAttackRange; } } This is a simple example of implementing this idea, you can go further if you wish 2 1 Link to comment https://metin2.dev/topic/33499-simple-anti-macro-regen-system/ Share on other sites More sharing options...
Recommended Posts
Don't use any images from : imgur, turkmmop, freakgamers, inforge, hizliresim... Or your content will be deleted without notice...
Use : https://metin2.download/media/add/
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now