-
Posts
48 -
Joined
-
Last visited
-
Days Won
1 -
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by astroNOT
-
-
There's no LLM atm that can "remember" as many tokens as a full game source requires, even gemini, it will only mean it has a long input stream, not that it remembers much of it, so we'll still have to wait
Anyhow llms are definitelly good, for me gpts was the best at cpp for example- 1
-
Hello, here's a item list generator, for them lazy people (or with really tired eyes)
Adds at eof, new item upgrades and respective location for icon/textures
Req python 3.11
import re def generate_item_code(items): item_codes = [] for item in items: icon_location = item["icon_location"] texture_location = item["texture_location"] vnums = item["vnums"] for item_id in vnums: for i in range(10): item_code = f"{item_id + i}\tWEAPON\t{icon_location.replace('*', str(item_id))}\t{texture_location.replace('*', str(item_id))}" item_codes.append(item_code) return item_codes def write_to_txt(item_codes, file_path): with open(file_path, "r+") as file: existing_lines = file.readlines() for item_code in item_codes: if item_code + "\n" in existing_lines: item_vnum = re.split(r'\t+', item_code)[0] print(f"SKIPPED - Item code {item_vnum} already exists in item list") else: file.write(item_code + "\n") print(item_code) if __name__ == "__main__": # In order to use the locations params # If ur file requires any prefix "0*.tga", before * include ur prefix, also ur desired extension .tga in my case location_dict = [ { "icon_location": "icon/item/0*.tga", "texture_location": "d:/ymir work/item/weapon/0*.gr2", "vnums": [8190, 8290] } ] item_codes = generate_item_code(location_dict) txt_file_path = r"client_location\item_list.txt" write_to_txt(item_codes, txt_file_path)
-
Can confirm that adding any instruction prior to while idle, seems to not give enough time for the maps & mobs to load
try { // Hardcoded values const DWORD dwVnum = 101; const int count = 10; const bool isAggressive = false; const int iMapIndex = 352; const int iMapX = 360; const int iMapY = 360; // Assume SECTREE_MANAGER and CHARACTER_MANAGER are properly initialized and available PIXEL_POSITION pos; if (!SECTREE_MANAGER::instance().GetMapBasePositionByMapIndex(iMapIndex, pos)) { sys_log(0, "PPPPPPQQQ Error: Cannot find base position in this map %d", iMapIndex); } const CMob *pMonster = CMobManager::instance().Get(dwVnum); if (pMonster == NULL) { sys_log(0, "PPPPPPQQQ Error: No mob data for VNUM %d", dwVnum); } size_t SpawnCount = 0; for (size_t i = 0; i < count; ++i) { LPCHARACTER pSpawnMonster = CHARACTER_MANAGER::instance().SpawnMobRange( dwVnum, iMapIndex, pos.x - number(5, 5) + (iMapX * 100), pos.y - number(5, 5) + (iMapY * 100), pos.x + number(5, 5) + (iMapX * 100), pos.y + number(5, 5) + (iMapY * 100), false, pMonster->m_table.bType == CHAR_TYPE_MONSTER, isAggressive); if (pSpawnMonster != NULL) { SpawnCount++; } } sys_log(0, "Spawned %u monsters successfully.", SpawnCount); } catch (const std::exception &e) { sys_log(0, "An exception occurred: %s", e.what()); } while (idle()) ;
What it logs is:
./srv1/chan/ch1/core1/syslog:Apr 17 19:23:11 :: PPPPPPQQQ Error: Cannot find base position in this map 352 ./srv1/chan/ch1/core1/syslog:Apr 17 19:23:11 :: PPPPPPQQQ Error: No mob data for VNUM 101
Trial and error continues
-
Hello!
Lets say I have the follow scenario:
At server startup:
I want to spawn two mobs, as an example function(correctness does not matter)void SpawnMobs(DWORD mob_vnum, int count, int map_index, int x, int y) { for (int i = 0; i < count; ++i) { LPCHARACTER mob = CHARACTER_MANAGER::instance().SpawnMob(mob_vnum, map_index, x, y, 0, false, -1); if (!mob) sys_err("Failed to spawn mob VNUM %d on map %d at (%d, %d)", mob_vnum, map_index, x, y); } }
And at a given date-time, to make the mobs move to a specific location(Again function correctness is probably wrong, but this is just a POCE)
void MoveMobTo(DWORD mob_vid, int target_x, int target_y) { using namespace std::chrono; //April 18, 2024, at 18:00 std::tm scheduled_time = {}; scheduled_time.tm_year = 2024 scheduled_time.tm_mon = 4 - 1; scheduled_time.tm_mday = 18; scheduled_time.tm_hour = 18; scheduled_time.tm_min = 0; scheduled_time.tm_sec = 0; auto scheduled_time_t = std::mktime(&scheduled_time); system_clock::time_point scheduled_tp = system_clock::from_time_t(scheduled_time_t); // Get current time system_clock::time_point now = system_clock::now(); // Check if the current time matches the scheduled time if (now == scheduled_tp) { LPCHARACTER mob = CHARACTER_MANAGER::instance().Find(mob_vid); if (mob) { mob->Goto(target_x, target_y); sys_log(0, "Mob with VID %d moved to (%d, %d) as scheduled", mob_vid, target_x, target_y); } else { sys_err("Failed to find mob with VID %d to move", mob_vid); } } else { sys_log(0, "MoveMobTo called, but it is not the scheduled time yet."); } }
I have two main questions
1. !Where should i be calling these functions within the source game, in main seems like it might not be a good idea
2. Checking time constantly until desired time is true, seems quite tricky, a while true surely is not good, if u have any basic suggestions it would be more then welcomed
Basically my goal is to have mobs spawn, if not already spawned, move them at a specific hour to a exact spot on the map, make em fight each other, while fighting pc can't attack, after pc can attack the surviver, but not instantly, spawn another boss, keep it there for a specific time, if not dead, despawn it
Realistically, if i'd know where to call my functions with the instructions and how to not use while loops to check for specific states, it would be enough
Thank you in advance!
-
The idea is, i want this quest to run regardless of player actions, at the moment it seems to start at player login
ideally the quest would start at day Y(could have daily flag) hour X so basically a scheduler, so it won't be dependent on any player events
quest test_npcmove begin state start begin when letter begin chat("Started") set_state("spawn_monster_in_map_boss_1") end end -- State to check for/spawn boss 1 state spawn_monster_in_map_boss_1 begin when letter begin chat("Spawning first boss") local mob_vnum = 102 -- Adjust VNUM for boss 1 local map_index = 352 local mobs = find_mobs_in_map(mob_vnum, map_index) local vid_boss1 = 0 local mobs_str = "BOSS 1 VIDs: {" .. table.concat(mobs, ", ") .. "}" chat(mobs_str) chat("Player X: " .. 339 .. " Y: " .. 363) if table.getn(mobs) > 0 then vid_boss1 = mobs[1] chat("Boss 1 found, using existing with VID: " .. tostring(vid_boss1)) else local vids = spawn_monster_in_map(mob_vnum, 1, false, map_index, 339, 363 + 10, true) vid_boss1 = vids[1] if vids[1] ~= nil then vid_boss1 = vids[1] chat("Boss 1 spawned with VID: " .. tostring(vid_boss1)) else vids = find_mobs_in_map(mob_vnum, map_index) vid_boss1 = vids[1] chat("Boss 2 fetched vid for spwaned mob: " .. tostring(vid_boss1)) end end pc.setqf("vid_boss1", vid_boss1) set_state("spawn_monster_in_map_boss_2") end end -- State to check for/spawn boss 2 state spawn_monster_in_map_boss_2 begin when letter begin local mob_vnum = 101 -- Adjust VNUM for boss 2 local map_index = 352 local mobs = find_mobs_in_map(mob_vnum, map_index) local vid_boss2 = 0 local mobs_str = "BOSS 2 VIDs: {" .. table.concat(mobs, ", ") .. "}" chat(mobs_str) if table.getn(mobs) > 0 then vid_boss2 = mobs[1] chat("Boss 2 found, using existing with VID: " .. tostring(vid_boss2)) else local vids = spawn_monster_in_map(mob_vnum, 1, false, map_index, 339, 363 - 10, true) vid_boss2 = vids[1] if vids[1] ~= nil then vid_boss2 = vids[1] chat("Boss 1 spawned with VID: " .. tostring(vid_boss2)) else vids = find_mobs_in_map(mob_vnum, map_index) vid_boss2 = vids[1] chat("Boss 2 fetched vid for spwaned mob: " .. tostring(vid_boss2)) end end pc.setqf("vid_boss2", vid_boss2) set_state("move_bosses") end end -- State to move both bosses state move_bosses begin when letter begin local vid_boss1 = pc.getqf("vid_boss1") local vid_boss2 = pc.getqf("vid_boss2") local target_x = 339 local target_y = 363 mob_move(vid_boss1, target_x, target_y) mob_move(vid_boss2, target_x, target_y) chat("Both bosses moved to player's position.") set_state("bosses_fight") end end -- State where bosses fight state bosses_fight begin when letter begin local vid_boss1 = pc.getqf("vid_boss1") local vid_boss2 = pc.getqf("vid_boss2") local map_index = 352 chat("Boss 1 VID: " .. tostring(vid_boss1)) chat("Boss 2 VID: " .. tostring(vid_boss2)) local success2, message2 = set_pc_can_attack_monster(vid_boss1, false, map_index) local success3, message3 = set_pc_can_attack_monster(vid_boss2, false, map_index) chat("Attempt to make boss 1 invinciple " .. tostring(success2) .. " - " .. message2) chat("Attempt to make boss 2 invinciple " .. tostring(success3) .. " - " .. message3) -- Attempt to make boss 1 attack boss 2 local success1, message1 = attack_mob(vid_boss1, vid_boss2, map_index) if success1 ~= nil and message1 ~= nil then chat("Attack attempt from Boss 1 to Boss 2: " .. tostring(success1) .. " - " .. message1) else chat("Attack attempt from Boss 1 to Boss 2: success or message is nil") end -- Attempt to make boss 2 attack boss 1 local success2, message2 = attack_mob(vid_boss2, vid_boss1, map_index) if success2 ~= nil and message2 ~= nil then chat("Attack attempt from Boss 2 to Boss 1: " .. tostring(success2) .. " - " .. message2) else chat("Attack attempt from Boss 2 to Boss 1: success or message is nil") end chat("Bosses are now set to fight each other.") chat("---------------------------------END------------------------------------") set_state("bosses_alive") end end state bosses_alive begin when letter begin chat("Checking if boss died") local vid_boss1 = pc.getqf("vid_boss1") local vid_boss2 = pc.getqf("vid_boss2") local map_index = 352 -- Check if Boss 1 is alive local is_boss1_alive, boss1_msg = is_mob_alive_in_map(vid_boss1, map_index) chat("Boss 1 alive check: " .. tostring(is_boss1_alive) .. " - " .. boss1_msg) -- Check if Boss 2 is alive local is_boss2_alive, boss2_msg = is_mob_alive_in_map(vid_boss2, map_index) chat("Boss 2 alive check: " .. tostring(is_boss2_alive) .. " - " .. boss2_msg) -- Determine the next state based on the bosses' statuses if not is_boss1_alive or not is_boss2_alive then if is_mob_alive_in_map(vid_boss1, map_index) then local success2, message2 = set_pc_can_attack_monster(vid_boss1, true, map_index) chat("Resetting invicibility for boss1 " .. tostring(success2) .. " - " .. message2) end if is_mob_alive_in_map(vid_boss2, map_index) then local success3, message3 = set_pc_can_attack_monster(vid_boss2, true, map_index) chat("Resetting invicibility for boss2 " .. tostring(success3) .. " - " .. message3) end chat("One of the bosses is dead. Resetting quest.") set_state("start") else chat("Both bosses are alive. Continuing the fight.") set_state("bosses_alive") end end end end
And the last state, called bosses_alive seems to also reexecute only at player relog (login)
Is there a way to make it so the states are independent of player events and just execute as soon as sv starts? -
Hello,
So I m trying to find where this vnum.kill function is defined on serverside, seems quite tricky, if anybody knows where it is defined and what name it has, please lmk
Thanks,
Gabimight be this guy
void CQuestManager::Kill(unsigned int pc, unsigned int npc) { //m_CurrentNPCRace = npc; PC * pPC; sys_log(0, "CQuestManager::Kill QUEST_KILL_EVENT (pc=%d, npc=%d)", pc, npc); if ((pPC = GetPC(pc))) { if (!CheckQuestLoaded(pPC)) return; // kill call script if (npc >= MAIN_RACE_MAX_NUM) //@fixme109 m_mapNPC[npc].OnKill(*pPC); //@warme004 m_mapNPC[QUEST_NO_NPC].OnKill(*pPC); #ifdef ENABLE_PARTYKILL // party_kill call script LPCHARACTER ch = GetCurrentCharacterPtr(); LPPARTY pParty = ch->GetParty(); LPCHARACTER leader = pParty ? pParty->GetLeaderCharacter() : ch; if (leader) { m_pCurrentPartyMember = ch; if (npc >= MAIN_RACE_MAX_NUM) //@fixme109 m_mapNPC[npc].OnPartyKill(*GetPC(leader->GetPlayerID())); //@warme004 m_mapNPC[QUEST_NO_NPC].OnPartyKill(*GetPC(leader->GetPlayerID())); pPC = GetPC(pc); } #endif } else sys_err("QUEST: no such pc id : %d", pc); }
-
ALUA(_spawn_monster_in_map) { if (false == lua_isnumber(L, 1) || false == lua_isnumber(L, 2) || false == lua_isboolean(L, 3) || false == lua_isnumber(L, 4) || false == lua_isnumber(L, 5) || false == lua_isnumber(L, 6)) { lua_pushnumber(L, 0); // Return an error in the form of 0 if inputs are incorrect return 1; } const DWORD dwVnum = static_cast<DWORD>(lua_tonumber(L, 1)); const size_t count = MINMAX(1, static_cast<size_t>(lua_tonumber(L, 2)), 10); const bool isAggressive = static_cast<bool>(lua_toboolean(L, 3)); const int iMapIndex = static_cast<int>(lua_tonumber(L, 4)); const int iMapX = static_cast<int>(lua_tonumber(L, 5)); const int iMapY = static_cast<int>(lua_tonumber(L, 6)); PIXEL_POSITION pos; if (!SECTREE_MANAGER::instance().GetMapBasePositionByMapIndex(iMapIndex, pos)) { sys_err("QUEST _spawn_mob_in_map: cannot find base position in this map %d", iMapIndex); lua_pushnumber(L, 0); // Push 0 to indicate failure return 1; } const CMob *pMonster = CMobManager::instance().Get(dwVnum); if (pMonster == NULL) { sys_err("QUEST _spawn_mob_in_map: no mob data for VNUM %d", dwVnum); lua_pushnumber(L, 0); // Push 0 to indicate failure return 1; } lua_newtable(L); // Create a new table on the stack to hold the VIDs size_t SpawnCount = 0; for (size_t i = 0; i < count; ++i) { LPCHARACTER pSpawnMonster = CHARACTER_MANAGER::instance().SpawnMobRange(dwVnum, iMapIndex, pos.x - number(200, 750) + (iMapX * 100), pos.y - number(200, 750) + (iMapY * 100), pos.x + number(200, 750) + (iMapX * 100), pos.y + number(200, 750) + (iMapY * 100), true, pMonster->m_table.bType == CHAR_TYPE_MONSTER, isAggressive); if (pSpawnMonster != NULL) { lua_pushnumber(L, SpawnCount + 1); // Push the index in the table lua_pushnumber(L, pSpawnMonster->GetVID()); // Push the VID lua_settable(L, -3); // Set the table at index -3 with key at -2 and value at -1 SpawnCount++; } } sys_log(0, "QUEST Spawn Monster: VNUM(%u) COUNT(%u) isAggressive(%b)", dwVnum, SpawnCount, isAggressive); return 1; // Returns the table at the top of the stack }
As u can see above i spawn the mob as `CHAR_TYPE_MONSTER` but when I m checking if
if (attacker->IsNPC() || target->IsNPC()) { sys_log(0, "MOB_ATTACK_FUNC Victim is NPC not Monster not attackable"); lua_pushboolean(L, 0); lua_pushstring(L, "MOB_ATTACK_FUNC Victim is NPC not Monster not attackable"); return 0; }
This is always returning true, and bcs of it, i cannot set `bool bAttackSuccess1 = attacker->Attack(target, 0);`
Because apparently a npc cannot attack
does anybody know how to spawn a mob (Character instance) that is not NPC but mosnter so it can attack other monsters? -
I m trying to make a mob, attack another mob, by specific attacker vid and victim vid, but can't figure out which Character class method does the actual attack
int game_mob_attack_mob(lua_State *L) { if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2) || !lua_isnumber(L, 3)) { lua_pushboolean(L, 0); lua_pushstring(L, "Invalid argument. Usage: mob_attack_mob(attacker_vid, target_vid, map_index)"); return 2; } int attacker_vid = (int)lua_tonumber(L, 1); int target_vid = (int)lua_tonumber(L, 2); int map_index = (int)lua_tonumber(L, 3); // Expected map index LPCHARACTER attacker = CHARACTER_MANAGER::instance().Find(attacker_vid); LPCHARACTER target = CHARACTER_MANAGER::instance().Find(target_vid); if (!attacker || !attacker->IsMonster()) { lua_pushboolean(L, 0); lua_pushstring(L, "Attacker not found or is not a monster."); return 2; } if (!target || !target->IsMonster()) { lua_pushboolean(L, 0); lua_pushstring(L, "Target not found or is not a monster."); return 2; } if (attacker->GetMapIndex() != map_index || target->GetMapIndex() != map_index) { lua_pushboolean(L, 0); lua_pushstring(L, "Either attacker or target is not in the specified map."); return 2; } // All checks passed, proceed to set victim attacker->SetVictim(target); attacker->BeginFight(target); lua_pushboolean(L, 1); lua_pushstring(L, "Attack set successfully."); return 2; }
Basically, "Attack set successfully is triggered but the mobs do not attack each otther, even if they are loading by their vid...
Updated it to use
attacker->SetVictim(target); target->SetVictim(attacker); // Trigger the initial attack and capture the return values bool bAttackSuccess1 = attacker->Attack(target, 0); // Return the result of the first attack attempt to Lua for debugging lua_pushboolean(L, bAttackSuccess1); if (bAttackSuccess1) lua_pushstring(L, "Attack by attacker was successful."); else lua_pushstring(L, "Attack by attacker failed."); return 2; }
But for some reason Attack method does not get triggered at all.. but the Attack by attacker failed is pushed succesfully
-
-
Dosen't seem like anything special, just 3 classes from initial implementation of ui.py that had to be added CheckBox, ExpandedButton and CustomScrollBar that I just had to copy pasted.
But it seems like most actions are defined here, so in terms of accuracy for ui part ur spot on, i expect on launcher side that I might have some problems, even tho i did double check a couple of times and it seems like i p much moved everything where it should be..
Thank you tho, I'll keep looking -
So Back in 2021, i bought @ Ikarus_'s shop offline, as most ppl know, V1 of the shop is not supported by ikarus anymore, so I am on my own out here hahaha
The idea is back in 2021 I wanted to open a server, long story short svf was compromised and couldn't go further with the idea
Now, i bought marty's svf, and I want to transfer the shop from my old server to this one
But i hit a dead end with debugging, can't figure out how a click event is handle
The problem is:
So problem seems to be that from uinewofflineshop.py, NewOfflineShopBoard.__OnLeftClickShopItem method is not called at all when i click on a item that is already in a shop, and i now do not know what to look for to understand how it works, what function/class handles the mouse over stuff and triggers specific events when an item is clicked, basically to understand how __OnLeftClickShopItem is triggered and when.
There is a method NewOfflineShopBoard.RefreshOpenShopPage that is triggered and sets this "mouse up" eventslot.SetOnMouseLeftButtonUpEvent(self.__OnLeftClickShopItem)
But for some reason it aint working, not sure where to go from here realistically
-
Hi guys, in which file on launcher C++ side do i need to declare a variable/object for it to be visible and so I can import it in client pack .py files?
- 1
-
import os #no of channels channels = 4 #no of cores cores = 2 #Channels path chan_location = "/usr/home/main/srv1/chan/" #New ip to replace the old ip_value = "123.443.9.1" try: os.mkdir("%sbackup_config" % chan_location) except Exception: pass for i in range(1, channels + 1): # print(i) for core in range(1, cores + 1): with open(f"%sch{i}/core{core}/CONFIG" % chan_location, 'r') as cfg: count = 0 proxy_index = 0 list_of_lines = cfg.readlines() with open(f"%sbackup_config/config_channel{i}_core{core}" % chan_location, "w") as bk_file: bk_file.writelines(list_of_lines) for line in list_of_lines: count += 1 # print(line) if "proxy" in line.lower(): proxy_index = count - 1 # print(len(list_of_lines), 'list of lines len') print("proxy index ", proxy_index) list_of_lines[proxy_index] = "proxy_ip: %s\n" % ip_value with open(f"%sch{i}/core{core}/CONFIG" % chan_location, 'w') as cfg_w: cfg_w.writelines(list_of_lines) print(f"Succesfully updated config for Channel{i}, Core{core}")
- 2
- 1
- 1
-
22 hours ago, PetePeter said:
"Because of this stupid line of code `tokens = line[:-1].split("\t")` you gotta have an extra char(space) after 'SA'"
This is for remove the line break, just add an empty line if it's the last line of your file. Because if you add another line after this one, the script will take your space at function name also
Indeed it removes the last char, in our chase the /n, aaand if its the last line in the file w/o a nl, then its doomed, updated the topic accordingly, thanks!
-
Hello,
When adding the bellow string to locale_game.txtAPPLY_ANTI_RESIST_MAGIC Magic Pen: %d%% SA
A key error is raised:
0613 21:44:08342 :: system.py(line:287) RunMainScript system.py(line:204) execfile prototype.py(line:3) <module> system.py(line:151) __hybrid_import system.py(line:116) _process_result localeInfo.py(line:210) <module> localeInfo.py(line:167) LoadLocaleFile Run - <type 'exceptions.KeyError'>:'S' 0613 21:44:08343 :: ============================================================================================================ 0613 21:44:08343 :: Abort!!!!
Without the SA at the end, the bonus name is not properly displayed in game
W/o the SA at the end, the bonus name is displayed as "UNKNOWN_NAME(93), the 93 is the index for the bonus in `enum EApplyTypes` from itemData.h
Any ideas?
LoadLocalFile py function:
Spoilerdef LoadLocaleFile(srcFileName, localeDict): def SNA(text): def f(x): return text return f def SA(text): def f(x): return text % x return f funcDict = {"SA":SA, "SNA":SNA} lineIndex = 1 try: lines = open(srcFileName, "r").readlines() except IOError: import dbg dbg.LogBox("LoadLocaleError(%(srcFileName)s)" % locals()) app.Abort() for line in lines: try: tokens = line[:-1].split("\t") if len(tokens) == 2: localeDict[tokens[0]] = tokens[1] elif len(tokens) >= 3: type = tokens[2].strip() if type: localeDict[tokens[0]] = funcDict[type](tokens[1]) #---------------- LINE 167 from error traceback else: localeDict[tokens[0]] = tokens[1] else: raise RuntimeError, "Unknown TokenSize" lineIndex += 1 except: import dbg dbg.LogBox("%s: line(%d): %s" % (srcFileName, lineIndex, line), "Error") raise
Thanks!
EDIT:
SOLVED:Because of this stupid line of code `tokens = line[:-1].split("\t")` you gotta have an extra char(space/new line) after 'SA' *only if its the last line in the file*
- 2
-
The script updates item prices (buy/sell) for an item vnum:
Considering item vnum is 110, it can update till 119 (or starting vnum 112 can go till 115, or 117, or w/e you desire)
It can update for a single vnum (upgrade items, aswell), more in comments below
Combined with can be pretty efficientfrom halo import Halo import bcolors class Append_new_prices: def __init__(self, value_dict, proto_location): self.proto_location = proto_location self.protoLst = [] self.value_dict = value_dict def get_proto_asList(self): with open(self.proto_location, 'r', encoding="utf8") as file: for line in file.readlines(): lineLst = line.split('\t') self.protoLst.append(lineLst) self.modified_protoLst = [] def update_protoLst(self): count = 0 for vnum, prices in self.value_dict.items(): try: upp_range = prices['uppLimit'] except KeyError: upp_range = 1 vnum_lst = self.get_item_VnumRange(vnum, upp_range) # while upp_range >= 0: for lineLst in self.protoLst: if "buy" not in prices.keys(): prices['buy'] = 0 if "sell" not in prices.keys(): prices['sell'] = 0 # print((lineLst[0]), " == ", vnum_lst) try: line_vnum = int(lineLst[0]) except ValueError: line_vnum = "VNUM NOT INT PFFFFF" if line_vnum in vnum_lst: lineLst[9] = prices['buy'] lineLst[10] = prices['sell'] self.protoLst[self.protoLst.index(lineLst)] = lineLst @staticmethod def get_item_VnumRange(vnum, range_lim): vnum_lst = [] plus_val = 0 # if range_lim == 0: # range_lim = 1 vnum = int(vnum) for i in range(0, range_lim + 1): vnum += plus_val vnum_lst.append(vnum) plus_val = 1 return vnum_lst def write_new_proto_fromList(self): with open(self.proto_location, 'w', encoding="utf8") as file: for line in self.protoLst: file.write('\t'.join(self.str_list(line))) def str_list(self, lst): new_lst = [] for i in lst: new_lst.append(str(i)) return new_lst if __name__ == "__main__": #First number (110) is the starting vnum, uppLimit is till when to stop adding prices, upplimit 9 means => 110, 111, 112, 113, 114...119 #It can have h/e many "item" objects as dictionary elements #!!!!!Count starts from 0! items = \ { "110": { "buy": 55, "sell": 43, "uppLimit": 1 }, # "120":{ # "buy":4000, # "sell":400000, # "uppLimit":9 # } } setPrices = Append_new_prices(value_dict=items, proto_location=r'C:\Users\itsas\Desktop\M2\versionControl\DumpProto\Release\item_proto.txt') with Halo(text='Loading', spinner='dots'): setPrices.get_proto_asList() setPrices.update_protoLst() setPrices.write_new_proto_fromList() print(f'{bcolors.OKMSG}{bcolors.OK} Done!')
Prereq:
Libs: Halo, bcoloros
Python 3.9- 10
- 7
- 1
- 7
-
Hello peeps!
Got some more utilities that i use to automate boring stuff, so, maybe it can help u guys too
The script kills the client processes, generates dump_proto and moves it into locale_xx directory (optional), crypts a list of files(root, locale, icon, ...etc) and starts the client.
import os import shutil import bcolors import time class utilities: def __init__(self, packer_path, client_path, launcher_Name, dumpProto_path, locale_XX_path): self.packer_path = packer_path self.client_path = client_path self.launcher_Name = launcher_Name self.dumpProto_path = dumpProto_path self.locale_XX_path = locale_XX_path def fox_Pack(self, filesList): for i in filesList: print(f"\t* Will exec :> [{i}]") os.chdir(self.packer_path) os.system(f"tools\\Archiver.exe make_xml/{i}_create.xml") os.system(f"tools\\Archiver.exe xml/{i}_create.xml") time.sleep(0.5) # os.system(archiver_path) def killProcess(self): import psutil for proc in psutil.process_iter(): # check whether the process name matches if proc.name() == self.launcher_Name: proc.kill() time.sleep(0.5) def createItemProto(self): os.chdir(self.dumpProto_path) os.system(f"{self.dumpProto_path}\\dump_proto.exe") if os.path.isfile(self.locale_XX_path + r"\item_proto_old"): os.remove(self.locale_XX_path + r"\item_proto_old") os.rename(self.locale_XX_path + "\\item_proto", self.locale_XX_path + "\\item_proto_old") shutil.copy2("item_proto", self.locale_XX_path) def startClient(self): os.chdir(self.client_path) os.startfile(self.client_path + "\\" + self.launcher_Name) if __name__ == "__main__": start_time = time.time() print(f"{bcolors.OKMSG}{bcolors.OK}#-------[START]-------#\n{bcolors.ENDC}") utils = utilities( #packer Location packer_path = r"C:\Users\itsas\Desktop\M2\versionControl\client\Packer", #client Location client_path = r"C:\Users\itsas\Desktop\M2\versionControl\client\Metin2", launcher_Name = "metin2_launcher.exe", #dumpProto RELEASE Location dumpProto_path = r"C:\Users\itsas\Desktop\M2\versionControl\DumpProto\Release", #locale\XX Location locale_XX_path = r"C:\Users\itsas\Desktop\M2\versionControl\client\Client\locale_general\ro") utils.killProcess() utils.createItemProto() #To pack multiple files, addd in the below list more, directory names utils.fox_Pack(["locale_general", "icon", "item"]) utils.startClient() print(f"{bcolors.BLUE}--- {bcolors.WAITMSG}{bcolors.BLUE}{(time.time() - start_time)} seconds ---\n{bcolors.ENDC}") print(f"{bcolors.OKMSG}{bcolors.OK}#-------[STOP]-------#")
Prereq:
Python 3.9
Libraries: bcolors, shutil- 44
- 1
- 1
- 2
- 20
- 5
- 28
-
4 hours ago, Helia01 said:
Thanks for sharing
No biggie
-
Hello,
Some boring clicking automated that I use, feel free to improve it, add waits, w/e, w/eimport time, os from pywinauto import Desktop, Application import bcolors from pywinauto.keyboard import send_keys import psutil class mySession: app = Application(backend='uia') def __init__(self, vm_Name='', ssh_Name='', cliente_exe_Path='', winSCP_path='', vbox_exe_path=''): self.vm_Name = vm_Name self.ssh_Name = ssh_Name self.cliente_exe_Path = cliente_exe_Path pathList = cliente_exe_Path.split('\\') self.client_path = '/'.join(pathList[:-1]) self.exe_name = pathList[-1] self.vbox_exe_path = vbox_exe_path self.winSCP_path = winSCP_path def openVM(self, waitServer): self.killProcess("VirtualBox.exe") self.app.start(self.vbox_exe_path) self.app = Application(backend='uia').connect(title='Oracle VM VirtualBox Manager', timeout=10) # self.app.Dialog.print_control_identifiers() self.app.OracleVMVirtualBoxManager.child_window(title=self.vm_Name, control_type="ListItem").wrapper_object().click_input(button='left', double=True) # self.app = Application(backend='uia').connect(title=self.whoAmI('Starting')[0], timeout=10) time.sleep(waitServer) print(f"\t{bcolors.OK}{bcolors.OKMSG}VM is ready{bcolors.ENDC}") def openWinSCP(self): self.killProcess("WinSCP.exe") self.app.start(self.winSCP_path) self.app = Application(backend='uia').connect(title=self.whoAmI(keyword='wins')[0], timeout=40) time.sleep(1) if self.app.Dialog.child_window(title=self.ssh_Name + " ", control_type="TabItem").exists(): self.app.Dialog.child_window(title="Reconnect Session", control_type="Button").wrapper_object().click_input( button='left') else: self.app.Dialog.child_window(title="New Session", control_type="TabItem").wrapper_object().click_input(button='left') auth_win = self.app.Dialog.child_window(title=self.ssh_Name, control_type="TreeItem") auth_win.wait('visible', timeout=50) auth_win.wrapper_object().click_input(button='left', double=True) input_pass = self.app.Dialog.child_window(control_type="Edit") input_pass.wait('visible', timeout=50) input_pass.wrapper_object().type_keys("dev") self.app.Dialog.child_window(title="OK", control_type="Button").wrapper_object().click_input(button='left') time.sleep(2) print(f"\t{bcolors.OK}{bcolors.OKMSG}WinScp is ready{bcolors.ENDC}") def startClient(self, do_login=True): os.chdir(self.client_path) os.startfile(self.client_path + "\\" + self.exe_name) # self.app = Application(backend='uia').connect(title='Metin2', timeout=10) def whoAmI(self, keyword='', retryLimit=2, isFull=False): while retryLimit: windows = Desktop(backend="uia").windows() windowsList = [w.window_text() for w in windows] resultList = [] for i in windowsList: if keyword.lower() in i.lower(): resultList.append(i) if not len(resultList): time.sleep(0.5) self.whoAmI(keyword=keyword, retryLimit=retryLimit-1, isFull=isFull) else: # print('Matches: ', resultList) if not isFull: return resultList else: return windowsList def killProcess(self, proc_nmame, kill_=True): if kill_: for proc in psutil.process_iter(): # check whether the process name matches if proc.name() == proc_nmame: proc.kill() time.sleep(0.5) if __name__ == "__main__": print(f"{bcolors.OK}#########[START]#########{bcolors.ENDC}") #Here you have to give the name of ur Virtual Machine(vm_Name), winSCP ssh connetion name(ssh_Name), and ur client executable path controller = mySession(vm_Name="11.3_5.5_v4", ssh_Name="alpha_server", cliente_exe_Path=r"C:\Users\itsas\Desktop\M2\versionControl\client\Metin2\metin2_launcher.exe", vbox_exe_path='"C:\Program Files\Oracle\VirtualBox\VirtualBox.exe"', winSCP_path="C:\Program Files (x86)\WinSCP\WinSCP.exe") controller.openVM(waitServer=15) controller.openWinSCP() controller.startClient() print(f"{bcolors.OK}#########[END]#########{bcolors.ENDC}")
Prereq:
Python 3.9
Libs: pywinauto, psutil, bcolors
Note: The script does kill existing processes of WinSCP and oracle VM, you can disable it, if u feel the need, search for killProcess method and set default param to FalseEdit: Parametrized paths for vbox, winSCP also
- 1
-
-
Indeed it worked, with a slight catch..
What i had 2 to do is to add more height to all the parent elements, starting from the first parent, and following the nesting
Thank you!- 1
-
Hello,
I have this 1 button which is not clickable in the following position:Faulty position: https://metin2.download/picture/s0R43DwyDza6rwDugokoZ5sbXG2cLg2F/.gif
But if i move it higher it works just fine, I not sure what to do, any ideas would be appreciated
Working position: https://metin2.download/picture/NWzWf64BnX17546rkVJMMmVfxK863eLq/.gif
The actual ui dictionary:Spoilerimport uiScriptLocale import item BELT_START_INDEX = item.BELT_INVENTORY_SLOT_START BUTTON_ROOT = "d:/ymir work/ui/public/" window = { "name" : "BeltInventoryWindow", "x" : SCREEN_WIDTH - 176 - 148, "y" : SCREEN_HEIGHT - 37 - 565 + 209 + 32, "width" : 148, "height" : 199, "type" : "image", "image" : "d:/ymir work/ui/game/belt_inventory/bg.tga", "children" : ( ## Expand Buttons { "name" : "ExpandBtn", "type" : "button", "x" : 2, "y" : 15, "default_image" : "d:/ymir work/ui/game/belt_inventory/btn_expand_normal.tga", "over_image" : "d:/ymir work/ui/game/belt_inventory/btn_expand_over.tga", "down_image" : "d:/ymir work/ui/game/belt_inventory/btn_expand_down.tga", "disable_image" : "d:/ymir work/ui/game/belt_inventory/btn_expand_disabled.tga", }, ## Belt Inventory Layer (include minimize button) { "name" : "BeltInventoryLayer", # "type" : "board", # "style" : ("attach", "float"), "x" : 5, "y" : 0, "width" : 148, "height" : 139, "children" : ( ## Minimize Button { "name" : "MinimizeBtn", "type" : "button", "x" : 2, "y" : 15, "width" : 10, "default_image" : "d:/ymir work/ui/game/belt_inventory/btn_minimize_normal.tga", "over_image" : "d:/ymir work/ui/game/belt_inventory/btn_minimize_over.tga", "down_image" : "d:/ymir work/ui/game/belt_inventory/btn_minimize_down.tga", "disable_image" : "d:/ymir work/ui/game/belt_inventory/btn_minimize_disabled.tga", }, ## Real Belt Inventory Board { "name" : "BeltInventoryBoard", "type" : "board", "style" : ("attach", "float"), "x" : 10, "y" : 0, "width" : 138, "height" : 179, "children" : ( ## Belt Inventory Slots { "name" : "BeltInventorySlot", "type" : "grid_table", "x" : 5, "y" : 5, "start_index" : BELT_START_INDEX, "x_count" : 4, "y_count" : 4, "x_step" : 32, "y_step" : 32, "image" : "d:/ymir work/ui/public/Slot_Base.sub" }, ##Activate all potions button { "name" : "UseBeltItemsButton", "type" : "button", "x" : 0, "y" : 138, "horizontal_align" : "center", "default_image" : BUTTON_ROOT + "AcceptButton00.sub", "over_image" : BUTTON_ROOT + "AcceptButton01.sub", "down_image" : BUTTON_ROOT + "AcceptButton02.sub", }, ), }, ) }, ), }
-
Hello,
I'm keen to know, is there a way to increase a specific item texture specular (weapon/armor/etc) beyond the 100 that you can set in specular column?
Or better yet to edit the texture to define what 100 specular should be.
Point is, some items aren't as shiny as they should be at 100 specularPS. I assume the specular is tied to the texture.
Thanks!
-
Any chance u got the set for all characters?
Windows Regen Creator
in Tools & Programs
Posted · Edited by astroNOT
Ransomware just false positive i assume?
Also
************** Exception Text ************** System.Exception: 0x33545844 texture compression not implemented.
For this map