Jump to content

Recommended Posts

  • Active+ Member

I believe the title is pretty straight forward but here is some more depth to the issue:

The options menu for NPC 9006 opens up normally. When I click the first one and I pay the fee I get the success dialog saying that my storage password is '000000' as it should.

When I click on the NPC again there is not any different option to choose from than before. My storage unit is not being created and basically it never does, I just keep paying the fee and get the success message forever.

No syserr logs about this.

Other quests seem to be working (not thouroughly tested yet) and so I'm suck here.

I tried compiling with different qc files such as my default Python 3 optimized one:

Spoiler
import sys
sys.dont_write_bytecode = True

from pathlib import Path
import shutil
import subprocess
import pre_qc
import os

def _clear_directory(dir_path: Path) -> None:
	for item in dir_path.iterdir():
		if item.is_dir():
			shutil.rmtree(item)
		else:
			item.unlink(missing_ok=True)

def main() -> None:
	script_dir = Path(__file__).resolve().parent

	object_dir = script_dir / "object"
	if object_dir.exists():
		_clear_directory(object_dir)
	else:
		object_dir.mkdir(parents=True, exist_ok=True)
		
	pre_qc_dir = script_dir / "pre_qc"
	if pre_qc_dir.exists():
		_clear_directory(pre_qc_dir)
	else:
		pre_qc_dir.mkdir(parents=True, exist_ok=True)

	# --- ADDED FIXES BELOW ---
	import grp # Need to import grp for proper chown/chgrp logic
    
    # 1. Set Group Ownership (equivalent to chgrp quest object)
    # NOTE: You must know the numerical GID of the 'quest' group.
    # A simpler shell-based approach is often safer in Python:
	os.system('chgrp quest ' + str(object_dir))

	# 2. Set Permissions (equivalent to chmod -R 770 object)
	os.system('chmod -R 770 ' + str(object_dir))
	# --- END ADDED FIXES ---

	qc_exe = script_dir / ("qc.exe" if sys.platform.startswith("win") else "qc")
	
	with open("locale_list") as file:
		for line in file:
			print(f"Compiling {line}...")
			r = pre_qc.run(line)
			if r:
				filename = os.path.join("pre_qc", line)
			else:
    				filename = line
				
			subprocess.run([str(qc_exe), str(filename.strip())], check=True)


if __name__ == "__main__":
	main()

 

I also tried a version made for Python 2 (optimized for Python 3 though):

Spoiler
#!/usr/local/bin/python3
import pre_qc
import os
os.system('rm -rf object')
os.system('mkdir object')
#os.system('rm -rf pre_qc')
os.system('mkdir pre_qc')
os.system('chgrp quest object')

with open("locale_list") as file:
	for line in file('locale_list'):
		r = pre_qc.run (line)
		if r == True:
			filename = 'pre_qc/'+line
		else:
			filename = line

		if os.system('./qc '+filename):
			print 'Error occured on compile ' + line
			os.system('chmod -R 770 object')
			import sys
			sys.exit(-1)

os.system('chmod -R 770 object')

 

and here is my pre_qc.py script in case it matters:

Spoiler
# -*- coding: cp949 -*-
# Literally, ¡°pre qc.¡±
# In our quest language, there are only local variables.
# You cannot use global variables that span state, when, or function.
# The use of global variables is impossible due to the language structure and is meaningless.
# However, the use of global constants is absolutely necessary in the quest view.
# Until now, to mimic global constants, we created a new table every time using functions like setting().
# This is very inefficient.
# So, just like C¡¯s preprocessor, we made a ¡°pre qc¡± to allow global constants.
# If you run pre_qc.py before compiling a quest into qc,
# pre_qc.py processes define statements and saves the results into pre_qc/filename.

import sys
from pathlib import Path


def split_by_quat(buf):
	p = False
	l = list(buf)
	l.reverse()
	s = ""
	res = []
	while l:
		c = l.pop()
		if c == '"':
			if p is True:
				s += c
				res += [s]
				s = ""
			else:
				if len(s) != 0:
					res += [s]
				s = '"'
			p = not p
		elif c == "\\" and l and l[0] == '"':
			s += c
			s += l.pop()
		else:
			s += c

	if len(s) != 0:
		res += [s]
	return res


def AddSepMiddleOfElement(l, sep):
	l = list(l)  # avoid in-place mutation
	l.reverse()
	new_list = [l.pop()]
	while l:
		new_list.append(sep)
		new_list.append(l.pop())
	return new_list


def my_split_with_seps(s, seps):
	res = [s]
	for sep in seps:
		new_res = []
		for r in res:
			sp = r.split(sep)
			sp = AddSepMiddleOfElement(sp, sep)
			new_res += sp
		res = new_res
	new_res = []
	for r in res:
		if r != "":
			new_res.append(r)
	return new_res


def my_split(s, seps):
	res = [s]
	for sep in seps:
		new_res = []
		for r in res:
			sp = r.split(sep)
			new_res += sp
		res = new_res
	new_res = []
	for r in res:
		if r != "":
			new_res.append(r)
	return new_res


def MultiIndex(seq, key):
	l = []
	i = 0
	for s in seq:
		if s == key:
			l.append(i)
		i = i + 1
	return l


def Replace(lines, parameter_table, keys):
	r = []
	for string in lines:
		l = split_by_quat(string)
		for s in l:
			if s and s[0] == '"':
				r += [s]
			else:
				tokens = my_split_with_seps(
					s,
					["\t", ",", " ", "=", "[", "]", "-", "<", ">", "~", "!", ".", "(", ")"],
				)
				for key in keys:
					try:
						indices = MultiIndex(tokens, key)
						for i in indices:
							tokens[i] = parameter_table[key][0]
					except Exception:
						pass
				r += tokens
	return r


def MakeParameterTable(lines, parameter_table, keys):
	names = []
	values = []
	group_names = []
	group_values = []
	idx = 0
	start = 1
	for line in lines:
		idx += 1
		line = line.strip("\n")
		if line.find("--") != -1:
			line = line[0 : line.find("--")]

		tokens = my_split(line, ["\t", ",", " ", "=", "[", "]", "\r", "\n"])
		if len(tokens) == 0:
			continue
		if tokens[0] == "quest":
			start = idx
			break
		if tokens[0] == "define":
			if len(tokens) > 1 and tokens[1] == "group":
				if len(tokens) >= 3:
					group_value = []
					for value in tokens[3:]:
						if parameter_table.get(value, 0) != 0:
							value = parameter_table[value]
						group_value.append(value)
					parameter_table[tokens[2]] = group_value
					keys.append(tokens[2])
			elif len(tokens) > 5:
				print(f"{idx} Invalid syntax")
				print("define [name] = [value]")
				print('define group [name] = "["[v0],[v1], ... "]"')
			else:
				value = tokens[2] if len(tokens) > 2 else ""
				if parameter_table.get(value, 0) != 0:
					value = parameter_table[value]
				parameter_table[tokens[1]] = [value]
				keys.append(tokens[1])
	return start


def run(filename):
	parameter_table = dict()
	keys = []

	filename = filename.strip("\n")
	if filename == "":
		return
	try:
		with open(filename, "r", encoding='utf-8') as fh:
			lines = fh.readlines()
	except UnicodeDecodeError:
		with open(filename, "r", encoding='latin1') as fh:
			lines = fh.readlines()


	start = MakeParameterTable(lines, parameter_table, keys)
	if len(keys) == 0:
		return False

	lines = lines[start - 1 :]
	r = Replace(lines, parameter_table, keys)

	out_dir = Path("pre_qc")
	out_dir.mkdir(parents=True, exist_ok=True)
	out_path = out_dir / filename

	with open(out_path, "w", newline="") as f:
		for s in r:
			f.write(s)
	return True


if __name__ == "__main__":
	if len(sys.argv) >= 2:
		run(sys.argv[1])

 

and of course the warehouse.quest script:

Spoiler
quest stash begin
	state start begin --Status when nothing is open
		when warehouse_keeper.chat.gameforge.warehouse._10_npcChat  begin
			say_title(gameforge.warehouse._20_sayTitle)
			-- changed handling, after we get a new button to open the storeage directly
			say(gameforge.warehouse._30_say)
			wait()

			if pc.gold < 500 then
				
				
				say_title(gameforge.warehouse._20_sayTitle)
				say(gameforge.warehouse._40_say)
			else
				local s =  select(gameforge.locale.stash.pay_ok, gameforge.locale.stash.pay_no)

				if s == 1 then
					pc.changegold(-500)
					game.set_safebox_level(1)
					set_state(use)
					say_title(gameforge.subquest_26._30_sayTitle)
					say(gameforge.warehouse._50_say)
					say_reward(gameforge.warehouse._60_sayReward)
					say(gameforge.warehouse._70_say)
				else
					say_title(gameforge.warehouse._20_sayTitle)
					say(gameforge.warehouse._80_say)
				end
			end
		end
		when warehouse_keeper.chat.gameforge.warehouse._120_npcChat  begin
			if pc.getqf("open_item_storage_count") < 3 then
				say_title(gameforge.subquest_26._30_sayTitle)
				say(gameforge.warehouse._140_say)
				wait()
				say_title(gameforge.subquest_26._30_sayTitle)
				say_show_item(90013) -- icon of item
				say(gameforge.warehouse._150_say)
				wait()
				pc.setqf("open_item_storage_count", pc.getqf("open_item_storage_count") + 1)
			end
			
			setskin(NOWINDOW)
			game.open_mall()
		end
	end
	state use begin
		when warehouse_keeper.chat.gameforge.warehouse._90_npcChat begin
			if pc.getqf("open_count") < 3 then
				say_title(gameforge.subquest_26._30_sayTitle)
				say(gameforge.warehouse._100_say)
				wait()
				say_title(gameforge.subquest_26._30_sayTitle)
				say(gameforge.warehouse._110_say)
				wait()
				pc.setqf("open_count", pc.getqf("open_count") + 1)
			end
			setskin(NOWINDOW)
			game.open_safebox()
		end
		when warehouse_keeper.chat.gameforge.warehouse._120_npcChat begin
			if pc.getqf("open_item_storage_count") < 3 then
				say_title(gameforge.subquest_26._30_sayTitle)
				say(gameforge.warehouse._140_say)
			    wait()
				say_title(gameforge.subquest_26._30_sayTitle)
				say_show_item(90013) -- icon of item
				say(gameforge.warehouse._150_say)
				wait()
				pc.setqf("open_item_storage_count", pc.getqf("open_item_storage_count") + 1)
			end
			
			setskin(NOWINDOW)
			game.open_mall()
			
		end
		when warehouse_keeper.chat.gameforge.locale.stash.buy_silver_and_gold_bar begin
			npc.open_shop()
			say_title(gameforge.subquest_26._30_sayTitle)
			say(gameforge.warehouse._130_say)
		end 

	end -- end_of_state: use
end -- end_of_quest

 

Btw when warehouse_keeper.chat.gameforge.locale.stash.buy_silver_and_gold_bar begin never shows, it's just the Create new storage unit and Open Mall options.

I compared the script with ones from other systems and it is identical.

I'm stuck as to what to check next... Where could the issue be here?

I appreciate all the help in advance

Link to comment
https://metin2.dev/topic/34131-warehouse-quest-ignores-creation/
Share on other sites

  • Replies 0
  • Created
  • Last Reply

Top Posters In This Topic

Popular Days

Top Posters In This Topic

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 use https://metin2.download/ when uploading files smaller than 100MB, otherwise the approval will take longer due to manual upload.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.