diff options
358 files changed, 47532 insertions, 53392 deletions
diff --git a/.travis.yml b/.travis.yml index dd58b51..fd6d110 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,15 +48,15 @@ script: - mkdir build - cd build - git init - - ../configure --dev CPPFLAGS=-DQUIET `! [[ $CXX =~ clang* ]] || echo --disable-abi6` + - ../configure --build=x86_64-linux-gnu --dev CPPFLAGS=-DQUIET `! [[ $CXX =~ clang* ]] || echo --disable-abi6` $EXTRA_CONFIGURE_ARGS - make -R -k -j2 - make -R -k -j2 test TESTER='valgrind --error-exitcode=1 --track-fds=yes' ## Do something after the main test script -after_script: +#after_script: - make -R -k -j2 format - git --git-dir=../.git --work-tree=.. diff --exit-code - - make -R -k -j2 dist + - make -R -k -j2 dist bindist ### The rest of the file creates a build matrix ### containing gcc-4.6 through gcc-4.8 and clang-3.1 through clang-3.3 @@ -76,25 +76,24 @@ env: matrix: allow_failures: - compiler: clang - env: REAL_CC=clang-3.1 REAL_CXX=clang++-3.1 PPA=ppa:h-rayflood/llvm PACKAGE=clang-3.1 + env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PPA=ppa:h-rayflood/llvm PACKAGE=clang-3.2 exclude: - env: ignore=this include: - compiler: clang - env: REAL_CC=clang-3.1 REAL_CXX=clang++-3.1 PPA=ppa:h-rayflood/llvm PACKAGE=clang-3.1 - - compiler: clang env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PPA=ppa:h-rayflood/llvm PACKAGE=clang-3.2 - compiler: clang env: REAL_CC=clang-3.3 REAL_CXX=clang++-3.3 PPA=ppa:h-rayflood/llvm PACKAGE=clang-3.3 - compiler: clang env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PPA=ppa:h-rayflood/llvm PACKAGE=clang-3.4 - compiler: gcc - env: REAL_CC=gcc-4.6 REAL_CXX=g++-4.6 PPA= PACKAGE=g++-4.6 - - compiler: gcc env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PPA=ppa:ubuntu-toolchain-r/test PACKAGE=g++-4.7 - compiler: gcc env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PPA=ppa:ubuntu-toolchain-r/test PACKAGE=g++-4.8 + - compiler: gcc + env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PPA=ppa:ubuntu-toolchain-r/test PACKAGE=g++-4.7 EXTRA_CONFIGURE_ARGS=--disable-warnings + # everything that was pushed to stable was already on 'master', except # the version change and some doc changes. branches: @@ -1,3 +1,21 @@ +v14.6.30: + - packet names (thanks evets) + - silence secondary output from tests + - port the variant + - fix anti-purge thing by giving every account a date + - prevent null session crash during shutdown + - specialize inventory/storage indices to avoid out-of-bounds + - don't crash when giving invalid ID to @item + - play with obscure corners of the C++ standard that no one can interpret + - replace hand-coded network protocols with generate ones + - lots source layout and formatting cleanup + - faster depedency calculation + - strict ids (yay less bugs, boo account/block entanglement) + - beginning of integers + - support libc++ (experimental) + - drop gcc 4.6 support + - completely remove flex/bison dependency + - fix duplication in npctalk v14.4.19: - emergency backport of security fix, since v14.7.1 is too buggy v14.4.18: diff --git a/Makefile.in b/Makefile.in index bfaf436..3777000 100644 --- a/Makefile.in +++ b/Makefile.in @@ -5,14 +5,17 @@ PACKAGE = @PACKAGE@ PACKAGE_NAME = @PACKAGE_NAME@ PREFIX = @PREFIX@ -EPREFIX = @EPREFIX@ +EPREFIX = @EXEC_PREFIX@ +# EPREFIX = @EPREFIX@ BINDIR = @BINDIR@ SBINDIR = @SBINDIR@ LIBEXECDIR = @LIBEXECDIR@ SYSCONFDIR = @SYSCONFDIR@ +PACKAGESYSCONFDIR := ${SYSCONFDIR}/${PACKAGE} SHAREDSTATEDIR = @SHAREDSTATEDIR@ LOCALSTATEDIR = @LOCALSTATEDIR@ +PACKAGELOCALSTATEDIR := ${LOCALSTATEDIR}/${PACKAGE} LIBDIR = @LIBDIR@ INCLUDEDIR = @INCLUDEDIR@ OLDINCLUDEDIR = @OLDINCLUDEDIR@ @@ -29,12 +32,13 @@ PDFDIR = @PDFDIR@ PSDIR = @PSDIR@ DEBUGDIR = @DEBUGDIR@ +BUILD = @BUILD@ +HOST = @HOST@ -BISON = @BISON@ -FLEX = @FLEX@ CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ -LDLIBS = @LDLIBS@ +LDLIBS = @LIBS@ +# LDLIBS = @LDLIBS@ CXX = @CXX@ CXXFLAGS = @CXXFLAGS@ GTEST_DIR = @GTEST_DIR@ @@ -45,6 +49,7 @@ ENABLE_ABI6 = @ENABLE_ABI6@ ENABLE_CYGWIN_HACKS = @ENABLE_CYGWIN_HACKS@ ENABLE_COMPAT_SYMLINKS = @ENABLE_COMPAT_SYMLINKS@ ENABLE_DEBUG = @ENABLE_DEBUG@ +ENABLE_RPATH = @ENABLE_RPATH@ TESTER = TEST_ARGS = @@ -165,83 +170,73 @@ export PATH:=$(realpath ${SRC_DIR}/tools):${PATH} SHELL=bash # path lists -LEXERS := $(shell cd ${SRC_DIR}; find src/ -name '*.lpp') -PARSERS := $(shell cd ${SRC_DIR}; find src/ -name '*.ypp') -GEN_SOURCES := \ - $(patsubst %.lpp,%.cpp,${LEXERS}) \ - $(patsubst %.ypp,%.cpp,${PARSERS}) -GEN_HEADERS := \ - $(patsubst %.lpp,%.hpp,${LEXERS}) \ - $(patsubst %.ypp,%.hpp,${PARSERS}) REAL_SOURCES := $(shell cd ${SRC_DIR}; find src/ -name '*.cpp') -REAL_HEADERS := $(shell cd ${SRC_DIR}; find src/ -name '*.hpp' -o -name '*.tcc') -REAL_SOURCES := $(filter-out ${GEN_SOURCES},${REAL_SOURCES}) -REAL_HEADERS := $(filter-out ${GEN_HEADERS},${REAL_HEADERS}) -SOURCES := ${GEN_SOURCES} ${REAL_SOURCES} -HEADERS := ${GEN_HEADERS} ${REAL_HEADERS} +REAL_HEADERS := $(shell cd ${SRC_DIR}; find include/ src/ -name '*.hpp' -o -name '*.tcc') +PIES := $(shell cd ${SRC_DIR}; find src/ -name '*.py') +SOURCES := ${REAL_SOURCES} +HEADERS := ${REAL_HEADERS} +PATTERN_ROOTS := $(patsubst src/%.cpp,%,${SOURCES}) +PATTERN_MAINS := $(patsubst %/main,%,$(filter %/main,${PATTERN_ROOTS})) +PATTERN_LIBS := $(patsubst %/lib,%,$(filter %/lib,${PATTERN_ROOTS})) +PATTERN_TESTS := $(patsubst %/test,%,$(filter %/test,${PATTERN_ROOTS})) DEPENDS := $(patsubst src/%.cpp,obj/%.d,${SOURCES}) PREPROCESSED := $(patsubst %.d,%.ii,${DEPENDS}) IRS := $(patsubst %.d,%.ll,${DEPENDS}) BITCODES := $(patsubst %.d,%.bc,${DEPENDS}) ASSEMBLED := $(patsubst %.d,%.s,${DEPENDS}) -OBJECTS := $(patsubst %.d,%.o,${DEPENDS}) -GEN_DEPENDS := $(patsubst src/%.cpp,obj/%.d,${GEN_SOURCES}) -GEN_PREPROCESSED := $(patsubst %.d,%.ii,${GEN_DEPENDS}) -GEN_IRS := $(patsubst %.d,%.ll,${GEN_DEPENDS}) -GEN_BITCODES := $(patsubst %.d,%.bc,${GEN_DEPENDS}) -GEN_ASSEMBLED := $(patsubst %.d,%.s,${GEN_DEPENDS}) -GEN_OBJECTS := $(patsubst %.d,%.o,${GEN_DEPENDS}) +PDC_OBJECTS := $(patsubst %.d,%.pdc.o,${DEPENDS}) +PIC_OBJECTS := $(patsubst %.d,%.pic.o,${DEPENDS}) MAIN_SOURCES := $(filter %/main.cpp,${SOURCES}) +LIB_SOURCES := $(filter %/lib.cpp,${SOURCES}) +TEST_SOURCES := $(filter %/test.cpp,${SOURCES}) BINARIES := $(patsubst src/%/main.cpp,bin/tmwa-%,${MAIN_SOURCES}) - -TEST_DEPENDS := $(patsubst src/%/test.cpp,obj/%/autolist.d,$(filter %/test.cpp,${SOURCES})) -DEPENDS += ${TEST_DEPENDS} -TEST_BINARIES := $(patsubst obj/%/autolist.d,bin/test-%,${TEST_DEPENDS}) +LIBRARIES := $(patsubst src/%/lib.cpp,lib/libtmwa-%.so,${LIB_SOURCES}) +TEST_BINARIES := $(patsubst src/%/test.cpp,bin/test-%,${TEST_SOURCES}) # tricky part # We can't put comments in a macro so here goes: # 1: Include the contents of the current %.d file ($1). # 2: For each header, substitute the corresponding %.o's dependency file. -# 3: Blank, reserved for header->libtmwa-common.a if that gets implemented. +# 3: For each lib.hpp header, substitute the corresponding .so library # 4: Remove all non-deps - clutter and lonely headers. # 5: Prevent infinite loops later by filtering out deps we've already seen. # 6: Merge new deps into the existing dep list. # 7: Recurse over all new deps (see 5). define RECURSIVE_DEPS_IMPL -$(eval more_deps := $(shell cat $(patsubst %/test.d,%/autolist.d,${1}))) -$(eval more_deps := $(patsubst src/%.hpp,obj/%.d,${more_deps})) - -$(eval more_deps := $(filter ${DEPENDS},${more_deps})) +$(eval more_deps := $(value ${1})) +$(eval more_deps := $(patsubst src/%.hpp,%,${more_deps})) +$(eval lib_deps += $(patsubst include/tmwa/%.hpp,lib/libtmwa-%.${SO_LONG},$(filter include/tmwa/%.hpp,${more_deps}))) +$(eval more_deps := $(filter ${PATTERN_ROOTS},${more_deps})) $(eval more_deps := $(filter-out ${cur_deps},${more_deps})) $(eval cur_deps += ${more_deps}) -$(foreach dep,${more_deps},$(call RECURSIVE_DEPS_IMPL,${dep})) +$(foreach dep,${more_deps},${call RECURSIVE_DEPS_IMPL,${dep}}) endef + # 1: Initialize the dep list ($1 is a %.d). # 2: Call the real function on it. # 3: Blank for clarity. # 4: Expand to text. Note that *nothing* else actually produces anything! define RECURSIVE_DEPS $(eval cur_deps := ${1}) +$(eval lib_deps :=) $(call RECURSIVE_DEPS_IMPL,${1}) ${cur_deps} endef # Apply the rules to all the main.cpp files -$(foreach exe,${BINARIES},$(eval ${exe}: $(strip $(patsubst %.d,%.o,$(call RECURSIVE_DEPS,$(patsubst bin/tmwa-%,obj/%/main.d,${exe})))))) -$(foreach exe,${TEST_BINARIES},$(eval ${exe}: $(strip $(patsubst %.d,%.o,$(call RECURSIVE_DEPS,$(patsubst bin/test-%,obj/%/test.d,${exe})))))) +# (now below, since it has to go below the include) # utility functions for the rules MKDIR_FIRST = @mkdir -p ${@D} # Stuff sensitive to attoconf -CXXFLAGS += ${WARNINGS} +CPPFLAGS += ${WARNINGS} ifeq (${ENABLE_WARNINGS},yes) WARNINGS := -include ${SRC_DIR}/src/warnings.hpp endif -${GEN_DEPENDS} ${GEN_PREPROCESSED} ${GEN_IRS} ${GEN_BITCODES} ${GEN_ASSEMBLED} ${GEN_OBJECTS}: override WARNINGS := # related to gdb bug 15801 ifeq (${ENABLE_ABI6},yes) @@ -260,53 +255,120 @@ CXXFLAGS += -fstack-protector override CXXFLAGS += -fno-strict-aliasing override CXXFLAGS += -fvisibility=hidden -# actual rules -vpath %.ypp ${SRC_DIR} -vpath %.lpp ${SRC_DIR} +nothing= +space=${nothing} ${nothing} +define relpath +$(subst ${space},/,$(foreach component,$(subst /,${space},$1),..))$2 +endef + +,=, +ifeq (${ENABLE_RPATH},relative) +rel_BINDIR := $(subst ${EPREFIX},,${BINDIR}) +rel_LIBDIR := $(subst ${EPREFIX},,${LIBDIR}) +ifneq (${EPREFIX}${rel_BINDIR},${BINDIR}) +$(error BINDIR must be within EPREFIX to use relative rpath) +endif +ifneq (${EPREFIX}${rel_LIBDIR},${LIBDIR}) +$(error LIBDIR must be within EPREFIX to use relative rpath) +endif +override LDFLAGS += -Wl,-rpath='$$ORIGIN/$(call relpath,${rel_BINDIR},${rel_LIBDIR})' +endif + +ifeq (${ENABLE_RPATH},absolute) +override LDFLAGS += -Wl,rpath=${LIBDIR} +override LDFLAGS += $(patsubst -L%,-Wl$,rpath=%,$(filter -L%,${LDFLAGS})) +endif + + + + + +# above is configury +# below are actual rules + +# first pass, include silently, but force rebuild +ifndef MAKE_RESTARTS +-include ${DEPENDS} +else +include ${DEPENDS} +endif + +include ${SRC_DIR}/version.make + + +thisdir := $(abspath .) +#$(foreach root,${PATTERN_ROOTS},$(info pre-root: ${root} := $(value ${root}))$(info )) +# can't do $(filter %.hpp yet) +$(foreach root,${PATTERN_ROOTS},$(eval ${root} := $(sort $(patsubst ${thisdir}/%,%,$(abspath $(patsubst ${SRC_DIR}/%,%,$(wildcard $(value ${root})) $(filter conf-raw/%.h,$(value ${root})))))))) +# have to redo what we undid to get it as a variable +$(foreach root,${PATTERN_ROOTS},$(eval obj/${root}.ii obj/${root}.ll obj/${root}.bc obj/${root}.s obj/${root}.pdc.o obj/${root}.pic.o obj/${root}.d : $(value ${root})) ) +#$(foreach root,${PATTERN_ROOTS},$(info post-root: ${root} := $(value ${root}))$(info )) + +# test.o implicitly (NOT explicitly) depends on all (nonexistent) test_*.hpp +# TODO actually have more than one test.o, each with its own set of files +$(foreach test,${PATTERN_TESTS},$(eval ${test}/test += $(patsubst %,src/%.hpp,$(filter %_test,${PATTERN_ROOTS})))) + + +$(foreach main,${PATTERN_MAINS},$(eval main-${main} := $(strip $(call RECURSIVE_DEPS,${main}/main))) $(eval main-${main}-libs := ${lib_deps})) +# actual rule deps +$(foreach main,${PATTERN_MAINS},$(eval bin/tmwa-${main} : $(patsubst %,obj/%.pdc.o,$(value main-${main})) $(value main-${main}-libs))) +$(foreach main,${PATTERN_MAINS},$(eval bin/tmwa-${main}-gdb.py : $(filter ${PIES},$(patsubst %,src/%.py,$(value main-${main}))))) +#$(foreach main,${PATTERN_MAINS},$(info post-main: main-${main}: $(value main-${main})) $(info post-main: main-${main}-libs: $(value main-${main}-libs)) $(info )) + +$(foreach lib,${PATTERN_LIBS},$(eval lib-${lib} := $(strip $(call RECURSIVE_DEPS,${lib}/lib))) $(eval lib-${lib}-libs := ${lib_deps})) +# actual rule deps +$(foreach lib,${PATTERN_LIBS},$(eval lib/libtmwa-${lib}.${SO_LONG} : $(patsubst %,obj/%.pic.o,$(value lib-${lib})) $(filter-out lib/libtmwa-${lib}.${SO_LONG},$(value lib-${lib}-libs)))) +$(foreach lib,${PATTERN_LIBS},$(eval lib/libtmwa-${lib}.${SO_LONG}-gdb.py : $(filter ${PIES},$(patsubst %,src/%.py,$(value lib-${lib}))))) +#$(foreach lib,${PATTERN_LIBS},$(info post-lib: lib-${lib}: $(value lib-${lib})) $(info post-lib: lib-${lib}-libs: $(value lib-${lib}-libs)) $(info )) + +$(foreach test,${PATTERN_TESTS},$(eval test-${test} := $(strip $(call RECURSIVE_DEPS,${test}/test))) $(eval test-${test}-libs := ${lib_deps})) +# actual rule deps +$(foreach test,${PATTERN_TESTS},$(eval bin/test-${test} : $(patsubst %,obj/%.pdc.o,$(value test-${test})) $(value test-${test}-libs))) +$(foreach test,${PATTERN_TESTS},$(eval bin/test-${test}-gdb.py : $(filter ${PIES},$(patsubst %,src/%.py,$(value test-${test}))))) +#$(foreach test,${PATTERN_TESTS},$(info post-test: test-${test}: $(value test-${test})) $(info post-test: test-${test}-libs: $(value test-${test}-libs)) $(info )) + + vpath %.cpp ${SRC_DIR} vpath %.hpp ${SRC_DIR} vpath %.tcc ${SRC_DIR} vpath tools/% ${SRC_DIR} +vpath %.py ${SRC_DIR} .DELETE_ON_ERROR: .DEFAULT_GOAL := all # main goals all: ${BINARIES} -cpp: ${GEN_SOURCES} ${GEN_HEADERS} ii: ${PREPROCESSED} ll: ${IRS} bc: ${BITCODES} s: ${ASSEMBLED} -o: ${OBJECTS} - -mostlyclean: - $c rm -rf obj conf-raw +o: ${PDC_OBJECTS} +# why not PIC objects? Because this is only for debugging, so we don't need +# duplicates, and PDC is more common, and also some override rules are only +# currently defined for PDC + +clean-deps: + -$l find obj -name '*.d' -delete +clean-format: + -$l find obj -name '*.formatted' -delete +clean-obj: + -$l find obj -name '*.o' -delete +clean-conf: + $l rm -rf conf-raw +mostlyclean: clean-conf + $l rm -rf obj clean: mostlyclean - $c rm -rf bin + $l rm -rf bin lib distclean: clean gen-clean -gen-clean: - $c rm -f ${GEN_SOURCES} ${GEN_HEADERS} - -# This rule is now deleted by default because it's sensitive to versions -ifeq (${LUCKY},1) -%.cpp %.hpp: %.lpp - $(MKDIR_FIRST) - $c ${FLEX} --header-file=$*.hpp -o $*.cpp $< -%.cpp %.hpp: %.ypp - $(MKDIR_FIRST) - $c ${BISON} --defines=$*.hpp -o $*.cpp $< -endif +gen-clean: ; ifndef MAKE_RESTARTS -# prevent errors if missing header obj/%.d: src/%.cpp $(MKDIR_FIRST) - set -o pipefail; \ - ${CXX} ${CPPFLAGS} -DGENERATING_DEPENDENCIES ${CXXFLAGS} -MG -MP -MM $< \ - -MT '$(patsubst %.d,%.ii,$@) $(patsubst %.d,%.ll,$@) $(patsubst %.d,%.bc,$@) $(patsubst %.d,%.s,$@) $(patsubst %.d,%.o,$@) $@' \ - | sed -e ':again; s:/[^/. ]*/\.\./:/:; t again' \ - -e 's: ${SRC_DIR}/: :g' \ - > $@ +# Not using $c because it's slow and this should be fast + ${CXX} ${CPPFLAGS} -DGENERATING_DEPENDENCIES ${CXXFLAGS} -MG -MM \ + -MT '$(patsubst obj/%.d,%,$@) := ' \ + -MF $@ $< endif # the above SRC_DIR replacement is not really safe, but it works okayish. obj/%.ii: src/%.cpp @@ -321,31 +383,41 @@ obj/%.bc: src/%.cpp obj/%.s: src/%.cpp $(MKDIR_FIRST) $c ${CXX} ${CPPFLAGS} ${CXXFLAGS} -S -o $@ $< -obj/%.o: src/%.cpp +obj/%.pdc.o: src/%.cpp $(MKDIR_FIRST) $c ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -o $@ $< +obj/%.pic.o: src/%.cpp + $(MKDIR_FIRST) + $c ${CXX} ${CPPFLAGS} ${CXXFLAGS} -fPIC -c -o $@ $< -obj/%/autolist.d: $(filter-out %/autolist.d,${DEPENDS}) - echo $@: $(filter %_test.d,$^) > $@ -include ${DEPENDS} +bin/%-gdb.py: + $(MKDIR_FIRST) + cat ${SRC_DIR}/src/main-gdb-head.py \ + $^ \ + ${SRC_DIR}/src/main-gdb-tail.py \ + > $@ +bin/%: bin/%-gdb.py + $(MKDIR_FIRST) + $l ${CXX} ${LDFLAGS} $(filter-out bin/%-gdb.py,$^) ${LDLIBS} -o $@ -# I'm not convinced keeping the bin/ is a good idea -# TODO - for development, regenerate -gdb.py even if the binary -# doesn't need to be rebuilt. For release, the version forces rebuild. -bin/%: +lib/%.${SO_LONG}-gdb.py: $(MKDIR_FIRST) - $l ${CXX} ${LDFLAGS} $^ ${LDLIBS} -o $@ cat ${SRC_DIR}/src/main-gdb-head.py \ - $(wildcard $(patsubst obj/%.o,${SRC_DIR}/src/%.py,$^)) \ + $^ \ ${SRC_DIR}/src/main-gdb-tail.py \ - > $@-gdb.py + > $@ +lib/%.${SO_LONG}: lib/%.${SO_LONG}-gdb.py + $(MKDIR_FIRST) + $l ${CXX} -shared -Wl,-soname=$*.${SO_SHORT} ${LDFLAGS} $(filter-out lib/%-gdb.py,$^) ${LDLIBS} -o $@ + $c ln -sf $*.${SO_LONG} lib/$*.${SO_SHORT} + $c ln -sf $*.${SO_SHORT} lib/$*.so -${TEST_BINARIES}: obj/gtest-all.o +${TEST_BINARIES}: obj/gtest-all.pdc.o # This isn't perfect. -$(filter %_test.o,${OBJECTS}) obj/gtest-all.o: override CPPFLAGS += -DGTEST_HAS_PTHREAD=0 -I${GTEST_DIR} -obj/gtest-all.o: override WARNINGS := -obj/gtest-all.o: ${GTEST_DIR}/src/gtest-all.cc +$(filter %_test.pdc.o,${PDC_OBJECTS}) obj/gtest-all.pdc.o: override CPPFLAGS += -DGTEST_HAS_PTHREAD=0 -I${GTEST_DIR} +obj/gtest-all.pdc.o: override WARNINGS := +obj/gtest-all.pdc.o: ${GTEST_DIR}/src/gtest-all.cc $(MKDIR_FIRST) $c ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -o $@ $< @@ -382,6 +454,17 @@ else @echo - Not installing compatibility symlinks endif +install: install-lib +install-lib: + @echo + Install libraries + ${install_dir} ${DESTDIR}${LIBDIR} + ${install_data} -t ${DESTDIR}${LIBDIR} \ + $(patsubst %.so,%.${SO_LONG},${LIBRARIES}) + for lib in $(patsubst lib/%.so,%,${LIBRARIES}); do \ + ln -sf $$lib.${SO_LONG} ${DESTDIR}${LIBDIR}/$$lib.${SO_SHORT}; \ + ln -sf $$lib.${SO_SHORT} ${DESTDIR}${LIBDIR}/$$lib.so; \ + done + install: install-debug install-debug: ifeq (${ENABLE_DEBUG},yes) @@ -389,10 +472,40 @@ ifeq (${ENABLE_DEBUG},yes) ${install_dir} ${DESTDIR}${DEBUGDIR}${BINDIR} ${install_data} -t ${DESTDIR}${DEBUGDIR}${BINDIR} \ $(patsubst %,%-gdb.py,${BINARIES}) + ${install_dir} ${DESTDIR}${DEBUGDIR}${LIBDIR} + ${install_data} -t ${DESTDIR}${DEBUGDIR}${LIBDIR} \ + $(patsubst %.so,%.${SO_LONG}-gdb.py,${LIBRARIES}) else @echo - Not installing debug files endif +install: install-include +install-include: + @echo + Install headers + ${install_dir} ${DESTDIR}${INCLUDEDIR} + ${install_data} -t ${DESTDIR}${INCLUDEDIR} \ + $(addprefix ${SRC_DIR}/,$(filter include/%,${HEADERS})) + +install: install-state +install-state: + @echo + Install statedir + ${install_dir} ${DESTDIR}${PACKAGELOCALSTATEDIR} + touch ${DESTDIR}${PACKAGELOCALSTATEDIR}/.keep + +install: install-data +install-data: + @echo + Install data + ${install_dir} ${DESTDIR}${PACKAGEDATADIR} + ${install_data} -t ${DESTDIR}${PACKAGEDATADIR} \ + ${SRC_DIR}/share/tmwa/* + +install: install-conf +install-conf: + @echo + Install config files + ${install_dir} ${DESTDIR}${PACKAGESYSCONFDIR} + ${install_data} -t ${DESTDIR}${PACKAGESYSCONFDIR} \ + ${SRC_DIR}/etc/tmwa/* + tags: ${SOURCES} ${HEADERS} $l ctags --totals -h .tcc --langmap=C++:+.tcc --c-kinds=+px -f $@ $^ @@ -400,25 +513,23 @@ Makefile: ${SRC_DIR}/Makefile.in @echo Makefile.in updated, reconfiguring ... ./config.status -include ${SRC_DIR}/version.make - # TODO - fix pattern priority bug so I can make these .hpp # # This is complicated and still isn't optimal. conf-raw/int-%.h: FORCE $(MKDIR_FIRST) - echo '#define $* $(value $*)' | maybe-replace $@ + @echo '#define $* $(value $*)' | maybe-replace $@ bool_yes := true bool_no := false conf-raw/bool-%.h: FORCE $(MKDIR_FIRST) - echo '#define $* $(bool_$(value $*))' | maybe-replace $@ + @echo '#define $* $(bool_$(value $*))' | maybe-replace $@ conf-raw/str-%.h: FORCE $(MKDIR_FIRST) - echo '#define $* "$(value $*)"' | maybe-replace $@ + @echo '#define $* "$(value $*)"_s' | maybe-replace $@ FORCE: ; .PHONY: FORCE -override CPPFLAGS += -I . +override CPPFLAGS += -I . -I ${SRC_DIR}/include # distribution tarballs # this only works from within a git checkout @@ -438,41 +549,57 @@ dist/%-attoconf-only.tar: dist/%-bundled.tar: dist/%-src.tar dist/%-attoconf-only.tar cp dist/$*-src.tar $@ tar Af $@ dist/$*-attoconf-only.tar +dist/%-bin-${HOST}.tar: all + ${MAKE} install DESTDIR=$(abspath dist/${HOST}/$*) + if test -n '${BUNDLED_LIBS}'; then cp ${BUNDLED_LIBS} dist/${HOST}/$*/${LIBDIR}/; fi + tar cf $@ -C dist/${HOST} $* + rm -r dist/${HOST}/ dist: dist/tmwa-${VERSION_FULL}-src.tar dist/tmwa-${VERSION_FULL}-bundled.tar +ifneq '' '${HOST}' +bindist: dist/tmwa-${VERSION_FULL}-bin-${HOST}.tar +else +bindist: + @echo + @echo + @echo "Fatal Error: 'make bindist' requires './configure --host='." + @echo "Maybe you want `${CXX} -v 2>&1 | sed -n '/Target: /{s///;p}'`, but I refuse to guess," + @echo "because there are too many options like -m32 that confuse me." + @echo + @echo + @false +endif .PHONY: dist -# lpp and ypp are (currently) very slow, so do them first (parallel) -format: format-lpp format-ypp format-cpp format-hpp +format: format-cpp format-hpp format-cpp: $(patsubst src/%,obj/%.formatted,${REAL_SOURCES}) format-hpp: $(patsubst src/%,obj/%.formatted,${REAL_HEADERS}) -format-lpp: $(patsubst src/%,obj/%.formatted,${LEXERS}) -format-ypp: $(patsubst src/%,obj/%.formatted,${PARSERS}) obj/%.cpp.formatted: src/%.cpp tools/indenter $(MKDIR_FIRST) apply-filter 'indenter -cpp' $< fgrep -q Copyright $< + fgrep -q $(notdir $<) $< fgrep -q ../poison.hpp $< + grep -q '^namespace tmwa$$' $< + grep -q '^} // namespace tmwa$$' $< touch $@ obj/%.hpp.formatted: src/%.hpp tools/indenter $(MKDIR_FIRST) apply-filter 'indenter -cpp' $< fgrep -q Copyright $< - fgrep -q ../sanity.hpp $< + fgrep -q $(notdir $<) $< + if [[ $< == *fwd* ]]; then fgrep -q ../sanity.hpp $<; else fgrep -q '"fwd.hpp"' $<; fi + if [[ $< == *fwd* ]]; then ! fgrep -q '"fwd.hpp"' $<; else ! fgrep -q ../sanity.hpp $<; fi + grep -q '^namespace tmwa$$' $< + grep -q '^} // namespace tmwa$$' $< + grep -q '^#pragma once$$' $< touch $@ obj/%.tcc.formatted: src/%.tcc tools/indenter $(MKDIR_FIRST) apply-filter 'indenter -cpp' $< fgrep -q Copyright $< + fgrep -q $(notdir $<) $< + grep -q '^namespace tmwa$$' $< + grep -q '^} // namespace tmwa$$' $< touch $@ -obj/%.lpp.formatted: src/%.lpp tools/indenter - $(MKDIR_FIRST) - apply-filter 'indenter -lpp' $< - fgrep -q Copyright $< - touch $@ -obj/%.ypp.formatted: src/%.ypp tools/indenter - $(MKDIR_FIRST) - apply-filter 'indenter -ypp' $< - fgrep -q Copyright $< - touch $@ -.PHONY: format format-cpp format-hpp format-lpp format-ypp +.PHONY: format format-cpp format-hpp @@ -53,23 +53,20 @@ platform dependencies: filesystem: must support symlinks build dependencies: + python: + required: 2.7.x only, installed in $PATH as 'python' C library: recommended: glibc 2.17 or higher supported: glibc 2.13 known bad: glibc 2.8 or below unsupported: anything that's not glibc C++ compiler: - required: g++ 4.6.1 or higher - recommended: g++ 4.7.2 or higher - likely to work: clang++ 3.2 or higher + required: g++ 4.7.2 or higher + recommended: g++ 4.8.1 or higher + likely to work: clang++ 3.3 or higher C++ library: recommended: libstdc++ to match g++; may need patch for clang++ - untested: libc++ - flex: - tested: 2.5 - bison: - tested: 2.7 - bad: 2.3 + may work: libc++ attoconf: special: see below runtime dependencies: @@ -28,15 +28,13 @@ except ImportError: sys.exit('attoconf missing - please run: git submodule update --init') else: try: - require_version(0, 8) + require_version(0, 9) except SystemExit as e: e.code += '\nPlease run: git submodule update' raise from attoconf.classy import add_slots from attoconf.lib.c import Cxx -from attoconf.lib.lex import Flex -from attoconf.lib.yacc import Bison from attoconf.lib.install import Install from attoconf.lib.config_hash import ConfigHash from attoconf.lib.templates import Templates @@ -46,19 +44,19 @@ from attoconf.types import enum, filepath yesno = enum('yes', 'no') @add_slots -class Configuration(Cxx, Flex, Bison, Install, ConfigHash, Templates): +class Configuration(Cxx, Install, ConfigHash, Templates): def general(self): super(Configuration, self).general() home = os.path.expanduser('~') - self.add_alias('--user', ['--prefix=%s' % home], - help='alias for --prefix=$HOME', hidden=False) + self.add_alias('--user', ['--prefix=%s' % home, '--enable-rpath=relative'], + help='alias for --prefix=$HOME --enable-rpath=relative', hidden=False) self.add_alias('--dev', ['--user', '--enable-warnings', '--enable-abi6'], help=None, hidden=False) def paths(self): super(Configuration, self).paths() - self.add_option('--debugdir', init='/', + self.add_option('--debugdir', init='/.', type=filepath, check=lambda build, DIR: None, help='root for split debug files (often /usr/lib/debug)', hidden=False, help_var='DIR') @@ -80,12 +78,15 @@ class Configuration(Cxx, Flex, Bison, Install, ConfigHash, Templates): self.add_bool_feature('cygwin-hacks', init='no', check=lambda build, ENABLE_CYGWIN_HACKS: None, help='Work around bugs in certain cygwin versions') - self.add_bool_feature('compat-symlinks', init='yes', + self.add_bool_feature('compat-symlinks', init='no', check=lambda build, ENABLE_COMPAT_SYMLINKS: None, help='Install symlinks to avoid breaking old scripts') self.add_bool_feature('debug', init='yes', check=lambda build, ENABLE_DEBUG: None, help='Install extra files useful for debugging') + self.add_option('--enable-rpath', init='none', + type=enum('none', 'relative', 'absolute'), check=lambda build, ENABLE_RPATH: None, + help='Use rpaths to find libraries', hidden=False) def vars(self): super(Configuration, self).vars() diff --git a/deps/attoconf b/deps/attoconf -Subproject 0f0e6300534b8b847f139c04b9e6ed1cc1100d9 +Subproject d33fcf6cc7380633329fdaf2e7f7543bbdd2490 diff --git a/doc/Changelog.txt b/doc/Changelog.txt deleted file mode 100644 index 474abbb..0000000 --- a/doc/Changelog.txt +++ /dev/null @@ -1,1729 +0,0 @@ -Date Added -10/15 - * another fix to oA2eA-rc5.sql to fix the sell_price [MouseJstr] - * Redid readme, updated content a bit, and made ps2 poster in preperation for 1.0 RC5 release. [Evera] - * made MAX_HAIR_STYLE, MAX_HAIR_COLOR, and MAX_CLOTH_COLOR - configurable via battle_config. [MouseJstr] - * made the dex spell cast time scaling configurable via battle_config - [MouseJstr] - * made the visible area_size configurable via battle_config - [MouseJstr] - * Reorganized and added the warps into their respective folders, updated map_athena.conf. [Nana] - * Added 2 script commands GETLOOK, GETSAVEPOINT (thanks to Lorky). [Lupus] - * Added kafra_bank NPC - a new bank with daily interst of 0.1#%. [Lupus] - * Changed cast time for champion soul collect to 1 sec (thanks to midas). [Valaris] - * Added midas's fix for +30 hitrate with Sonic Blow. [Valaris] - -10/14 - * Fixed help.txt for some @gm commands [MouseJstr] - * made login.c compile on gcc 2.95 [MouseJstr] - * Fix backwards compatability with old mob skill formats [MouseJstr] - * Added mail system commands and @refreshonline to help.txt. [Valaris] - * Fixed char guild storage bug [MouseJstr] - * Prevented breakage of Weapons/Armor if the respective Alchemist Chemical Protection skill is applied. [spira] - * Added so nochat end will set manner to 0. [Valaris] - * Added broken item check before breaking (to prevent an item from breaking more than once) [Valaris] - * Re-wrote parts of equipment breaking. It will check to make sure it was not a miss before doing break calculations. [Valaris] - * Re-added negative value exploit fix. [Valaris] - * Fixed guardian opposition search. [Valaris] - * Added @unmute. [Valaris] - * Added check for map existing before cleanup (server will exit instead of crashing if maps aren't found). [Valaris] - -10/13 - * Fixed parse of antifreeze enable/disable flag. [Valaris] - * Fixed end-of-line flags in source tree [MouseJstr] - -10/12 - * Prevent attack/skill usage while wearing tux/wedding dress. [Valaris] - * Remove item unequip on tux/wedding equip. [Valaris] - -10/11 - * Added mail system (for SQL version only). [Valaris] - - @checkmail - - @listmail - - @listnewmail - - @readmail <#> - - @deletemail <#> - - @sendmail <name> <message> - - @sendprioritymail <name> <message> - - Added battle_athena.conf option to enable/disable mail system. - - Added mail.sql for sql mail system. - - Use "*" for name to send to all players. Level must be >= to @sendprioritymail level. - - * Added @refreshonline to refresh player online status in SQL version. [Valaris] - -10/10 - * Modified ja blacksmith repair code to function with our broken equipment system. [Valaris] - * Removed ja repair script commands, they aren't compatible with our broken equipment. [Valaris] - * Fixed error in Morroc jewel dealer. [Valaris] - * Added so supernovices will get flee from improve dodge. [Valaris] - * Fixed assassin and rogue flee bonus, was giving +50 instead of +40. [Valaris] - * Fixed bug with using remove trap on a snared monsters and the monster would stay stuck. [Valaris] - * Added a check for row return in an sql statement in login. [Valaris] - * Added some pointer initializations in map.c. [Valaris] - * Calculate pc status when equipping or unequipping pet items. [Valaris] - * Fixed crash in looting pet skills if loot size was greater than 10. [Valaris] - -10/05 - * Fixed all mob spawn names (typos, errors, wrong names) according to the mob_db.txt [Lupus] - * Added YggdrasilKid's fixed exp.txt. [valaris] - -10/04 - * Added missed close file functions in pc.c [Lupus] - * Added some new items, fixed some item names and translated all grabled items in item_db.txt [Lupus] - * Fixed bug in MOB_DB and in MOB_BRANCH DB related to wrong "Elder" ID number [Lupus] - * Fixed toggle for using sql item db in char-server. [Valaris] - * Added interval settings for anti-freeze system. [Valaris] - * Added enable/disable options in char_athena.conf and login_athena.conf for anti-freeze system. [Valaris] - * Re-added anti-freeze system. [Valaris] - * Cleaned up warning in src/common/db.c. [MouseJstr] - * Removed afm map checking from char. [Valaris] - * npc.c - Re-enabled new "OnTouch" function. Added a missing line to npc_event in npc.c(line 667). - pc.c - Added 2 missing "else" statements on (line 3702 and 3842). Now ontouch works correctly and activates - everytime instead of only once like in RC4. [kobra_k88] - * clif.c - Added: npc_scriptcont(sd,RFIFOL(fd,2)); to "void cliff_parse_NpcCloseClicked" function. - Now "close2" script command works properly. Previously, it would freeze the server.[kobra_k88] - -10/03 - * added oA to eA database conversion .sql [MouseJstr] - * renamed sql to sql-files to eliminate a problem with make [MouseJstr] - * Fixed Assassin Quest where "Nameless One" NPC would freeze after clicking "next". [Shinigami] - * charkillable now returns status on target [MouseJstr] - * skill names now have descriptions pulled from the client [Mousejstr] - * Mapflag "petals" has been changed to "sakura". [Valaris] - * The weather @commands will now set that particular mapflag on until server is restarted, and will send weather effect - to everyone on that map. It also will not allow the occurance of the command more than once. This method means - everyone coming onto the map after the command has been used will see the effect. [Valaris] - * Added yor's latest ladmin.c. [Valaris] - * Fixed bug in delitem script command that caused it to delete all of an item. [Valaris] - * Modified Makefile's to work better in non-sql environment [MouseJstr] - * A lot of work on source tree making it more ANSI C compliant [MouseJstr] - * Finalized the timers on shutdown - turned off malloc debugging on db's. [MouseJstr] - * Added release hook's into db's [MouseJstr] - * Added runflag to core to allow cleaner shutdown [MouseJstr] - * Work on LCCWIN32 for building under Windows natively [MouseJstr] - * modified @mapexit to use runflag for cleaner shutdown [MouseJstr] - * Improve cleanup on exit of map server of all objects [MouseJstr] - * statpoint reader can now be larger then 1432 bytes [MouseJstr] - * Fixed so dancing effect is cleared when warping. [Valaris] - -10/02 - * Modified battle config muting players option to work more effectively. [Valaris] - * Fixed mute from showing red bubble to players. [Valaris] - * Fixed disguise sprite staying when teleporting. [Valaris] - * Added a special mob ai check in mob.c. [Valaris] - * Fixed petit pet skill's damage from ever increasing. [Valaris] - * Removed pet weight and pet loot options, someone re-added them, and this conflicts with pet skills. [Valaris] - * Added new skills to mob_skill_db (skills for Alchemist summon marine sphere among others) [Valaris] - * Updated skill_cast_db and skill_require_db for summon marine sphere and biocanniablize skills. [Valaris] - * Fix for drops by luck crashing. [Valaris] - * Removed @nuke for now. [Valaris] - * Added japanese ankle snare code. [Valaris] - * Using better code for alchemist marine sphere. [Valaris] - * Reverted back to old method of OnTouch for now for compatibility with older scripts. [Valaris] - * Fixed an infinite loop with preventing multi level up and high novices. [Valaris] - * Storage saving in SQL was based on MAX_INVENTORY. Switched to MAX_STORAGE and MAX_GUILD_STORAGE. [Valaris] - Should resolve items disappearing. Thanks to fov for pointing this out. - * Updated skill_db entries for biocannibalize and summon marine sphere. [Valaris] - * Changed sql item name row sizes to 24, and changed memory allocation to 25 bytes instead of 29. [Valaris] - * Added upgrade_1.0.0-rc5_database.sql (will set name columns of item db to varchar(24). [Valaris] - * Removed anti-freeze system. [Valaris] - * Began removing AFM, unless someone wants to complete this. [Valaris] - * Added an online status timer. Will check online status of players every hour (for sql version). [Valaris] - * Added malloc to map.c. [Valaris] - * Added some variables for new mob exclusion. [Valaris] - * Using malloc in pc.c. [Valaris] - * Added skill reset checks to high/advanced/baby classes. [Valaris] - -10/01 - * Fixed up const.db. [Valaris] - - Added - bBreakWeaponRate 1068 - bBreakArmorRate 1069 - bAddStealRate 1070 - - - Fixed - bMagicDamageReturn 1071 - bRandomAttackIncrease 1072 - bAllStats 1073 - bAgiVit 1074 - bAgiDexStr 1075 - bPerfectHide 1076 - bDisguise 1077 - - * Rewrote mute disable option in clif.c, it did not need to end status. [Valaris] - * Added a missing check for SC_NOCHAT in clif.c. [Valaris] - * Changed comments on max_lv in battle_config to be less - confusing [MouseJstr] - * Fixed Gypsy Job Quest, added Crusader Job Quest [Lupus] - * Adding missing noquests from previous tree [MouseJstr] - * merged conf files between txt and sql [MouseJstr] - * According to item_db.txt and mob_db.txt fixed some name differences, wrong item names in - pet_db.txt,mob_branch.txt,item_violetbox.txt,item_giftbox.txt,item_cardalbum.txt [Lupus] - * Added specialeffect2 script command. Works the same as specialeffect, but the effect will be applied - to the player interacting with the npc instead of being applied on the npc. [Valaris] - * Added hasitems script command. If a player has any items it will return 1 in an if statement. [Valaris] - * Added npctalk script command. Syntax : npctalk "These are my words"; [Valaris] - * Removed script::say in favor of Valaris's version. [MouseJstr] - * Fixed a bug in guild alliances where it was treating a friend as a foe. [MouseJstr] - * Fixed crash in weapon breaking. Was not doing a block type check on the source. [Valaris] - - -09/29 - * Fixed small, almost non-existing memoryleak, in grfio.c that could - cause some systems to exit the application [Kalaspuff] - -09/26 - (Dated On Aegis Website) - *--Released 1.0.0 RC4--* -09/25 - * Reorganized Npc folder for release - * Updated map_athena.conf - * Remove certain statuses when warping (Cloaking, Sitting, Gangster's Paradise) that would allow the effect to - continue and a player to walk normally. [Valaris] - * Remove speed increase of theif and high thief from improve dodge (only assassins and assassin cross's are - supposed to get this bonus) [Valaris] - * removed more #ifdef's between TXT and SQL [MouseJstr] -09/24 - - * Added @charkillable (to make players killable) [MouseJstr] - * Added @dropall (throws all items on ground) [MouseJstr] - * Added @chardropall (throws all players items on ground) [MouseJstr] - * Added @storeall (put all items in store) [MouseJstr] - * Added @charstoreall (put all players items in storage) [MouseJstr] - * Added @skillid (look up a skill by name) [MouseJstr] - * Added @useskill (use a skill by id) [MouseJstr] - -09/23 - * Update Some Npc Stuff In Payon [Darkchild] - * Added Sage Quest [Darkchild] - * added @killable - all players can hit you, even out of pvp [MouseJstr] - * Changed Basilica to prevent the priest from walking [MouseJstr] - * Restore base files in save directory [Yor] - * Castle spawn/conquering fix: [Akaru] - - Spawns monster when the guild is not owned when the server starts - - Spawns emperium with the monsters when guild is not owned yet - - If AgitStart and AgitEnd occurs while castle had not been owned, it is just ignored so that the monsters that are guarding the castle and the emperium would not be killed. - - Prevent spawn of emperium/monsters after castle is owned - - In short, you can clear and conquer the castle any time even when it's not agitstart'ed if the castle is unowned, like in official servers - -09/22 - * added @killer to let GM's hit players outside of pvp [MouseJstr] - * added @skilloff to turn off skills on a map [MouseJstr] - * added @skillon to turn on skills on a map [MouseJstr] - * added @follow to follow players (including warping after them) [MouseJstr] - * added battle_config option to control the max number of castles a guild can have [MouseJstr] - * upgraded the guild alliance checker [MouseJstr] - * added battle_config to control if ghosty armor works for mobs [MouseJstr] - * Fixed battle_config to control how much GTB actually helps [MouseJstr] - * Fixed battle_config to control if pvp battles give exp or drops [MouseJstr] - * Added map aliasing [MouseJstr] - * changed the map_nick2sd to be able to handle sub-strings for refering to players [MouseJstr] - * made turning of skills on a map actually work [MouseJstr] - * Updated Makefiles/GNUMakefiles to include the compilation of /common/malloc.o [PoW] - -09/19 - * Corrected @charstoragelist: [Yor] - - because account2storage function create a void storage if it's not exist, somethimes a player could lost its storage. - -> creation of account2storage2 to just ask pointer of storage if exist and use it in @charstoragelist. - * Improved range system of @monster/@spawn (nearest of GM when less monsters) [Yor] - * Client until 2004-09-06 (included) is now completely recognized [Yor] - * Fixed kafra storage request for all new clients [Yor] - -09/18 - * Changed to Yor's code that doesn't try and read when it's already not found [Akaru] - * Removed check for resnametable in data folder exit -> the resnametable isn't even used if present and it should be optional and not compulsory to have a resnametable in the data folder! [Akaru] - * Added an option to choose which clients are accepted on the server (2nd part and finish: Check accepted versions) [Yor] - * Added an option to choose which clients are accepted on the server (1st part: reading of the option) [Yor] - * Fixed action request (sit, attack, etc..) for all new clients [Yor] - * Fixed solve char name for all new clients [Yor] - * Fixed get char name for all new clients [Yor] - * Fixed an error about packet number on char name function [Yor] - * Added items drop packet for all new clients [Yor] - * Fixed: in clif_send (global send, not individual send) don't send a packet that client doesn't recognize [Yor] - -09/17 - * Added check to make sure mob is already moving before initiating random walk - when the item they are going to loot disappears. [Valaris] - * Client of 2004-07-13 is now completely recognized [Yor] - * Fixed items take packet for all new clients [Yor] - * Corrected packet sizes for each client version (not set packet size if packet doesn't exist) [Yor] - * Fixed direction position for all new clients [Yor] - -09/16 - * Client of 2004-07-06 is now completely recognized [Yor] - * Fixed skills to position with all new clients [Yor] - * Fixed incomplete packet of authentification [Yor] - * Fixed size of packets for all clients [Yor] - * Improved detection of client version at authentification [Yor] - * Improved packet parsing of client (search packet version before to parse) [Yor] - * Added packets size of 0x20d and 0x20e [Yor] - -09/15 - * Added "nude" script command, will strip player of all equipment. Syntax : nude; [Valaris] - * Removed sandstorm flag, since it does not work as intended (is not a constant effect like believed) [Valaris] - * Added specialeffect script command. Syntax: specialeffect #; [Valaris] - * Moved noicewall flag to a better position. [Valaris] - * Added mob type check to skill_castfix to prevent crashing. [Valaris] - * corrected error: skill to id (RFIFOW->RFIFOL) [Yor] - * Added packets size of 0x204 and 0x20b [Yor] - * Fixed skill_to_id with all new clients [Yor] - * Fixed tick sending with all new clients [Yor] - * Fixed items use with all new clients [Yor] - * Fixed move with all new clients [Yor] - * Speedup WantToConnect function [Yor] - * Call correct function with any clients packet - size is not correctly set actually [Yor] - -09/14 - * Resetlvl will unequip items that require more than level 1. [Valaris] - * Added message about new clients (not actually supported) [Yor] - * Added correct call of clif_parse_WantToConnection function for all client types [Yor] - * Added size of packet 0x0214 [Yor] - * Fixed calls of 'clif_send' function [Yor] - -09/13 - * Modified item_db to have more name consistency, added more translations for items [Akaru] - * Fixed in clif_sitting usage of a buffer [Yor] - * Fixed in clif_movechar usage of a buffer for clif_set007b [Yor] - * Fixed in clif_spawnpc usage of a buffer for clif_set0078 [Yor] - * Corrected a commented printf in packet 0x2b0e for debug [Yor] - -09/12 - * Put (commented) parse printf in char.c at the right place (to have all informations) [Yor] - * Added Alchemist JobQuest [Darkchild] - * Added Inn Npcs [Darkchild] - -09/11 - * Added @charitemlist/@charstoragelist/@charcartlist GM commands to display items of a player [Yor] - -09/10 - * Added a better id control of monster id in @spawn/@monster... GM commands [Yor] - * Correction of an error at reading of 'wisp_server_name' option (char.c) [Yor] - -09/09 - * Change @spawn/@monster2... GM commands to spawn in close area [Yor] - * commented some printf in char.c to reduce (a little) lag [Yor] - * Put @timer messages in msg_athena.conf [Yor] - * Add a file for SQL developpers [Yor] - * Changed name of newpacket variable of session (packet_ver) and add a message for nex client version [Yor] - * Added new client packet sizes and expanded packet acception. [Valaris] - * Added snow, fog, rain, leaves, petals, and sandstorm map flags. [Valaris] - -09/08 - * added clif_specialeffect to clif.c, for displaying a wide variety of effects (information from rofx) [Valaris] - * Corrected in map: creation of new session before to delete previous session_data [Yor] - * Corrected in login/char/ladmin: creation of new session before to delete previous session_data [Yor] - * Prevented redeal dupe. Checks to make sure inventory index has not already been added (client prevents - the possibility of stacking items, but server did not.) [Valaris] - -09/07 - * Added an option to determinate at which GM level nowarp and nowarpto flags are not more used [Yor] - - new option in battle.conf: any_warp_GM_min_level - - new checks and message about 'from' (nowarp) and 'to' (nowarpto) in GM commands - * Third part of new authentification method (clif_parse_CloseKafra): ignore new 0xF7 [Yor] - * Change name of new0x0072 variable by new_auth (because now, auth packet is 0x72 or 0x7E) [Yor] - * Second part of new authentification method (clif_parse_WantToConnection): Auth by char-server of new packets resolved [Yor] - * Improved check of new packet 0x7E to enter in WantToConnect Function [Yor] - -09/06 - * First part of new authentification method (clif_parse_WantToConnection) [Yor] - - accepted new 0x7E for wantto connect - - begin to found first authentificaiton and answer to client, but not found - * Improved Char-server: [Yor] - - Fixed a possible error on multi-map servers (no lastpoint) - - Added log about character with same name of wisp server name. - - Added a sub function to disconnect a player (used 3 times) - * Improved. In global message, use buffer to send to other (avoid possible overwriting). [Yor] - * Added Super Novice Job Quest [Darkchild] - -09/05 - * Fixed noskill flag to actually stop all usable skills when used. [AppleGirl] - * Removed last lag on char-server causing by too much savings (on accreg) [Yor] - * Removed a lag on char-server with a lot of players (for party, like guild) [Yor] - * Removed a big lag on char-server with a lot of players: [Yor] - - guilds was saved every time a player is online and a lot of other time (removed). - - guilds are save only when characters are saved (no more bring forward with characters file, and less savings) - * Added GM message that informs when a player blocks wisps of the server (against some bots that auto ignore wisps from a player) [Yor] - * Added perfect GM hide in @where GM command [Yor on suggestion of PoW] - * Correct NEW shops.txt with error displayed AT START of map-server! [Yor] - * Correct NEW payon.txt that crash map-server AT START! [Yor] - * More changes and official locations for new payon, things in correct place: - - Guild Flags - - Kafra - - Shops/Refiners (except Pet Shop!) - - Most Normal Npcs (not all!) - All Based On ScreenShots From kRO!! [Darkchild] - * Payon Warps about 80% finished, others were no screens taken from! [Darkchild] - * Removed nowarp mapflag and new internal check about gmlevel [Yor] - - gmlevel are checked before to call the function (of the GM comand). If you give gmlevel, people can use the function, including if you give level 0. - if you want refuse some GM commands to normal players, set the level of the command with a value upper than 0 (of set GM_only_command option to yes). - Not add new tests for nothing and use more cpu. - - mapflag: no limit for GM commands: what'is the interest to have gm commands limited like player? (it's rule for all GM commands) - A gm can have the possibility to go anywhere, specialy to check/control player ==> no mapflag! - * Stopped client crashes when jobchanging into another class that doesn't support the weapon you are holding. [Valaris] - -09/04 - * Added nowarp mapflag [PoW] - * Fixed nowarpto mapflag in atcommand.c [PoW] - * Improved: On hack about name in global message, GM of ALL map-server received hack messages. [Yor] - * Moved some GM messages of GM command from at_command.c to msg_athena.txt. [Yor] - * Added @whogm GM command. [Yor] - * Added a warning when a character has same name than wisp server name. [Yor] - -09/03 - * Added gm level display in all @who(map) GM command. [Yor] - * Correction: [Yor] - Thanks to [EvilEden] - - Soul Strike mistake (according to http://iro.ragnarokonline.com/game/jobmagskill.asp) - corrected cast time - - npc/quests/monstertamers.txt: The Monster Tamer Shogo gives the Deviruchi 'Contracts in Shadow' (641) -> the Bapho Jr. Tamming Item 'Book_of_theDevil' (642). - * Added monster/egg name to create egg in @makeegg GM command. [Yor] - * Added an option to fix started limited time of a new account. [Yor] - * Added @hatch in help.txt. [Yor] - * Fixed ChaseWalk so now you can't use skills while in chase walk mode. [AppleGirl] - * Fixed Looping of Broken Weapon if you continued to use it even after its broken [AppleGirl] - * Updated Weapon Breaking So Now Icon Will Disappear when you unequip the broken item [AppleGirl] - * Re-Added @hatch and added makepet to atcommand_athena.conf [Darkchild] - * Moved job monsters to their respected files [Darkchild] - * Fixed a bug in sence (showing wrong info!) [Darkchild] - * Changed the npc/jobs/ folders heavily! [Darkchild] - * Added COMPLETE Umbala NPC script [Darkchild] - * Added New Payon maps @ bottom of the map_athena.conf [Darkchild] - * Added New Payon NPCs and Warps [Darkchild] - * Fixed typo and made layout a litle bit better of the readme files [Darkchild] - * Added Items Ability to be unbreakable (using bonus bUnbreakable,100;) it will totally unbreakable - any lower than a 100 it still has a chance of breaking but call it more durable ;p[AppleGirl] - * Added Start_Weapon and Start_Armor to all the other starts in char_athena.conf [AppleGirl] - * Updated skill_require_db and skill_cast_db.txt [AppleGirl] - * Finish to add a (reserved) wisp name for server - part 3: in map-server replace name where server name is used for wisp [Yor] - * Continue to add a (reserved) wisp name for server - part 2: in map-server, reception of the name [Yor] - * Begin to add a (reserved) wisp name for server - part 1: in char-server [Yor] - -09/02 - * Added Meltdown's weapon breaking ability [AppleGirl] - * Added GM level in front of each line to display only enable GM command of the help.txt. [Yor] - * Removed message about limited time if your have unlimited account (that was for tests. sorry). [Yor] - * Set day/night messages in msg_athena.conf (for foreign people). [Yor] - * Added a function to return a string of msg_table outside of at_command. [Yor] - * Fixed clean database at disconnect when session is not auth. [Yor] - * Fixed a bug (but not solve the bug - need more research to found where solve it) in map_id2sd function. [Yor] - * Set initialisation of ignore list after authentification (not need to be done before) [Yor] - * Reduced size of packet 0x2afe (removed not used value) [Yor] - * Improve first auth part (wanttoconnect) [Yor] - * Added TODO 35 [Yor] - * Made a few adjustments to Archer based class skills making more like normal classes instead of Uber Classes. [AppleGirl] - * Updated the weapon and armor breaking to be more like official RO adding status icons and so on. [AppleGirl] - * Updated a few skills based off a few sites, also fixed other skills that were coded incorrectly. [AppleGirl] - * Fixed double connection with same account [Yor] - - disconnect immediatly - - no enter in database (block or others) - - no creation of session - - no more need to have 'new_fd' - -> less memory usage, less tests - * Removed 'other_fd' not used [Yor] - -09/01 - * Fixed Rainbow Egg quest in quests_lutie NPC [PoW] - * Added packet length for client server-side friend list, if they choose add the client will not disconnect. [Valaris] - Need to figure out the rest of the packets, then can implement. - * Added server-side friend list 'add' send packet info to packet documentation. [Valaris] - * Fixed: in chrif_authreq, don't send a request to char server if session is not found [Yor] - * Fixed: amatsu.txt, when Carter Moores say: remove 10000 zeny, he removes them now! [Yor] - * Removed an unknown item in shops.txt [Yor] - * Fixed 3 goto in father - acolyte.txt [Yor] - * Fixed bug with colors of 5 numbers/digits (warp to city instead of display with color) - wizard.txt [Yor] - * Reduce size of mage.txt and fix a text in mes (no bug) [Yor] - * Fixed thief.txt script (error on a goto) [Yor] - * Fixed account length (WFIFOL(fd,2) instead of WFIFOW(fd,2)) when char-srv doesn't auth an account for map-srv (0x2afe packet) [Yor] - * Added @job and @charjobchange to be similar with @charjob and @jobchange [Yor] - -08/31 - * Fixed messages of @(char)jobchange GM commands. [Yor] - * Fixed a return value of jobchange function (pc.c). [Yor] - * Added coredumps by system when crash. [Yor] - thanks MagicalTux - -08/30 - * Added some comments on gravity commands. [Yor] - * Improved /mm, /monster and /item to have some answers. [Yor] - * Modified skill_cast_db and skill.c to allow for status effect chance of wizard skills - (stun for WZ_METEOR and blind for WZ_VERMILLION) [moonsoul] - * Modified skill_cast_db and skill_db to properly reflect cast params and delay times for assassin cross - skills Create Deadly Poison(407) and Soul Breaker(379) [moonsoul] - * Added damage calcs to battle.c for Assassin Cross skill Soul Breaker(379) [moonsoul] - -08/29 - * Modified skill_require_db to reflect item requirements for assassin cross skills Create Deadly Poison(407) - and Enchant Deadly Poison(378) [moonsoul] - * Added @charmountpeco/@charpetrename/@charquestskill/@charlostskill GM commands. [Yor] - * Added noicewall.txt to map_athena.conf (commented out), noicewall flag [Valaris] - will not function when pvp is enabled on map. - * Added noicewall flag, noicewall.txt. [Valaris] - * Added wiz's temp fix for higher skill ids and skillnodex db. [Valaris] - * Added: Usage of At command when failed (100%). - * Modified: try to have samme presentation for all at-command code (100%). - * Improved/fixed some GM commands [Yor] - * Added some 'usages' in some GM commands [Yor] - * Added baby classes to equipment codes, they will equip the same as their normal and advanced counter-parts. [Valaris] - * Improved some GM commands [Yor] - - Added in @(char)baselvlup/@(char)joblevelup GM command: - When there are some status/skill points available and we reduce level -> remove points. - - Added counter in @statsall GM command. - - Fixed in @charsave GM command when map doesn't exist. - - Fixed @charbaselvl GM command overflow - - Fixed skill value (and crash) in @questskill/@lostskill GM command - - Fixed number of spiritballs (@spiritball GM command) - * Fixed random PvP crash bug [Lupus] - -08/28 - * Improved some GM commands [Yor] - - Added memo points in @go GM commmand. - - Added negativ value for @heal GM command. - - Fixed @(6stat-adjustement) GM commands overflow. - - Simplified @Statall GM commands. - - Fixed @guildlvup GM commands. - -08/27 - * Fixed @(char)zeny/stpoint/skpoint GM commands (no more overflow, etc...) [Yor] - * Improved @memo GM command: [Yor] - You can memo anywhere (it's GM command, not /memo command like for any player). - Without value, display actual memo points. - * Improved @refine GM command: you can reduce refinement. [Yor] - * Fixed @broadcast GM command send broadcast to all Map-servers. [Yor] - * Fixed @(char)base/joblevelup command (any adjustement can be entered). [Yor] - -08/26 - * In at_command.c: [Yor] - Fixed: initialisation of all strings. - Added: Usage of At command when failed (75%). - Modified: try to have samme presentation for all at-command code (75%). - * Made it so that the pvp_nightmaredrop mapflag would work even without pvp being enabled, now works any time it is set. [Ancyker] - * Added level check on /item and /monster. GM level must be >= both @monster and @item [Valaris] - level specifications (both since they share the same packet) - * Added my own extream mode map flags (disabled by default), makes players drop items at random everywhere (except towns). Full details in map_athena.conf. [Ancyker] - -08/25 - * Added: display usage when GM command failed (some GM commands) [Yor] - * Added @email GM command to change your account e-mail [Yor] - -08/24 - * Modified changesex script command use same function as @charchangesex now [Yor] - * Added @charchangesex GM command can be used on offline players [Yor] - * Added gm ladmin command to change GM level of an account [Yor] - -08/23 - * Fixed some at_command messages: [yor] - - remove all unused messages - - create commented line of all messages in msg_athena.conf to have english, and under, translation if necessary - - add some (arround 80, but not all) messages in msg_athena.conf - -08/22 - * Fixed: In GM commands, add a 'standard' message when GM level is too low [Yor] - * Changed in battle_athena.conf [Yor] - - atcommand_spawn_quantity_limit: 100 (20 is too short for mass spawnings.) - - unknow: give translation of babelfish to help on the explanation (not writing: 'unknow' to not lost the information!) - - day_duration: 7200000 & night_duration: 1800000 (set default to 30 min night, 2 hours day to show improvement of eathena by DEFAULT) - -08/21 - * Updated battle_athena.conf to be in English (not Engrish) [Ancyker] - * Updated WZ_FIREPILLAR according 8-10 patch [AppleGirl] - * Updated skill_cast_db and skill_require_db according to 8-10 kRO patch [AppleGirl] - * Added how to use skill_castnodex_db.txt [AppleGirl] - * Added skill_castnodex_db.txt, allowing some skills to be casted with out dex's effect on them - Midas' idea [AppleGirl] - * Improved answer messages of char-server on @(un)ban/@(un)block GM commands [Yor] - * Added answer messages of char-server on @(un)ban/@(un)block GM commands [Yor] - * Added block command (ladmin c) [Yor] - * Added block command (ladmin perl) [Yor] - * Fixed job_db1.txt comments to be in english, also spaced the columns to make it easier to read. [Ancyker] - * Added: possibility to use "" or '' to give an account name in ladmin (Perl) (no more problem with account name which have spaces). [Yor] - * Changed: atcommand_gm_only is set to 'no' by default, because: [Yor] - - GM commands level now works correctly - - GM commands levels are now set by default with diffrent types of GM - * Added @inall/@exall GM command to block/unblock ALL wispers of a player [Yor] - -08/20 - * Added unblock command (ladmin C) [Yor] - * Added unblock command (ladmin perl) [Yor] - * Fixed: when limited time is in past, add new duration starts from actual time [Yor] - * Added chardisguise/charundisguise [Kalaspuff] - * Added default time [23:59:59] for timeset/banset ladmin (C) commands [Yor] - * Fixed sage rebirth ability at professor job change NPC. [PoW] - * Fixed pecopeco knight/crusader rebirth ability at LordKnight and Paladin job change NPCs. [PoW] - * Added default time [23:59:59] for timeset/banset ladmin (perl) commands [Yor] - * Added a check_ip_flag option in char-server [Yor] - * Added a check_ip_flag option in login-server [Yor] - * Added a display at start of login-server about IP checking configuration. [Yor] - -08/19 - * Added unban/unbanish command (ladmin c) [Yor] - * Added unban/unbanish command (ladmin perl) [Yor] - * Added parameter to choose how works timeadd (ladmin command) with unlimited time accounts [Yor] - * Fixed @option/@charoption when player is disguised. [Yor] - * Added: some information about TODO 19. [Yor] - * Added: possibility to use "" or '' to give an account name in ladmin (C) (no more problem with account name which have spaces). [Yor] - -08/18 - * Guardians were immune to skills/spells, fixed. [Valaris] - * Added custom draculax.txt script to display npcskilleffect command. [Valaris] - * Added npc/events/custom folder. [Valaris] - * Fixed Umbala Language Quest NPC bug [PoW] - * Added temporary prevention of crash caused by peco + disguise, will look into a better solution. [Valaris] - * Changed working of putting disguise on (much like Yor's setpos with undisguise) [Valaris] - * Changed disguise id check to > 23 instead of max_pc_class. [Valaris] - * Added bDisguise script command for items. [Valaris] - Syntax : bonus bDisguise,npc_id/mob_id; Example bonus bDisguise,1002; for poring disguise - * Added flag so @disguise command will override any disguise scripts. [Valaris] - * Updated @disguise description in help.txt. [Valaris] - * Added: @ignorelist/@charignorelist to know from which people a player ignore wisps [Yor] - * Renamed: @makepet -> @makeegg (@makepet will be created later to create pet, not a egg) [Yor] - * Fixed Phantom of Opera quest, fixed quests_aldebaren requirements [PoW] - * Changed: anti-freeze disconnection in char-server set from 1mn 15s to 30s [Yor] - * Fixed: free block memory on NULL pointer in char-server do_final [Yor] - * Fixed: reset server information when map-server disconnected from char-server [Yor] - * Changed: anti-freeze disconnection in login-server set from 1mn 15s to 30s [Yor] - * Improved pecopeco checks in @option/@charoption/@jobchange/@charjob [Yor] - -08/17 - * Fixed pecopeco displayings in @option/@charoption/@jobchange/@charjob [Yor] - * Correction of @rura, @where, @rurap and some other things in GM commands. [Yor] - * Correction of a parameters' errors in GM commands. [Yor] - * Correction of @charzeny Gm command (+ @zeny/@charzeny can add and remove zeny without problem). [Yor] - * Acolyte Job Quest: Fixed Marthilda, Yosuke NPC bugs. [Lupus] - * Added some comments in .conf about @gm [Yor] - * Fixed max value of level_new_gm parameter (not 100, but 99) [Yor] - * Added level_new_gm parameter in login-server to disable or set level of all GM created by @gm [Yor] - * Fixed @GM GM command [Yor] - -08/16 - * Translation of final message of @gm [Yor] - * Fixed on @GM: When login server is offline, char server sends impossible to create GM [Yor] - * Fixed: refuse @gm GM command to ... a GM :) [Yor] - * Added complete answers of /in /ex /inall /exall. [Yor] - * Added option to send information to online GM when there is a hack, a spoof name, etc. [Yor] - * Added individual ignore management, and wisp checks [Yor] - * Added TODO 33 [Yor] - * Fixed possible overflow with @ban GM command [Yor] - * Speed up a little @ban GM command [Yor] - * Added ignore all for wisps (to same map-server). Sorry, before, I was added only for not same map-server [Yor] - -08/15 - * Added a resume for 'email_creation' parameter [Yor] - * Fixed double messages when a player wisp/page itself [Yor] - * Added ignore all for wisps [Yor] - * Added better explanation for the new 'email_creation' parameter [Yor] - * Fixed: now, GM accounts are sended to all servers when auto-detect change of GM file is actived [Yor] - * Fixed: at auto-creation of e-mail, don't ask the player if login-server is offline (we need login-server to save e-mail) [Yor] - * Used config_switch instead of atoi for email_creation parameter [Yor] - * Added an option to create e-mail at connection with client [Yor] - * Added authentification with login_id2 (1040) - activated by default [Yor] - * Added partial part of authentification with login_id2 (1040) [Yor] - * Added some missing GM commands in help.txt [Yor] - * Improved search of map-server when map is not found [Yor] - * Added banish in ladmin (c) to be like of GM commands [Yor] - * Fixed Angel Helm quest, fixed Spore Doll quest exploit, Fixed Morgenstein quest bug [Lupus] - -08/14 - * Added banish in ladmin (perl) to be like of GM commands [Yor] - * Fixed some possible errors with maps management in char-server [Yor] - * Fixed bug of map searching when to few maps on map-servers [Yor] - * Changed some console displayings in char-server [Yor] - * By default, activation of player ip check [Yor] - * Added some of 1040: check of player ip between each server [Yor] - * Fixed dupes in warp scripts, reorganized, thanks to midas fro GH warp [kobra_k88] - * Added possibility to disable automatic reload of GM accounts file [Yor] - * Added log when GM accounts file can not be readed [Yor] - * Changed default of GM accounts file check for 120 sec to 15 sec [Yor] - * Added automatic reload of GM accounts file if it was modified [Yor] - * Added @mapmove, @broadcast, and @localbroadcast in help.txt [Yor] - * Fixed possible error of monster id (GM command) if monster begins by a number. [Yor] - * Added jobname in @charstats command. [Yor] - * Fixed: If a GM command uses NULL pointer as command function, there is no more crash. [Yor] - * Fixed Niflheim&Umbala guides. Fixed Niflheim city. removed 2 NPC clones. [Lupus] - * Added Archer Skills quests, fixed Thief Skill Quest [kobra_k88] - -08/13 - * Add an option to fix a ban for hacker that spoof name (to set minutes of ban) [Yor] - * Fixed incorrect mob IDs with Valaris's mob_db [Ancyker] - * Added possibility to execute GM commands when you wisp someone [Yor] - * Added a console message when a player try to spoof his name in Global message [Yor] - * Added size of packet in packet send by map-srvr to char-srvr about online players [Yor] - * Added check on individual stat at creation of a character [Yor] - * Added npcskilleffect script command. Will allow npc to show effects of certain skills on specified XY coordinate. - Syntax : npcskilleffect 21,10,148,150; skillid, skilllv, x, y. [Valaris] - * Increase maximum weight can be used with an item now, thanks to orn. [Valaris] - * Fixed mob names in Gonryun , thanks to unsul and Filougarou. [Valaris] - * Fixed muramasa curse rate, thanks to OxiMoron. [Valaris] - * Fixed Aldeabran&Comodo towns. Added Cheese quest to Comodo. Fixed Thief Job Quest [kobra_k88] - -08/12 - * Begin to add 1040 in login/char/chrif about authentification. not finished [Yor] - * @mapmove, @broadcast, and @localbroadcast can now be used. [Valaris] - * Looting mobs will not continue to item if it disappears, instead will walk away. [Valaris] - * Unitinalized nameid in script.c [Valaris] - * Added position in log when unknown packets are saved (login-server). [Yor] - * Corrected possible error to contact not good player when a wisp concerns player on an other map-server. [Yor] - * Added a function to obtain character name with index in auth structure (char.c). [Yor] - * Corrected check/test error in mapif_send. [Yor] - -08/11 - * itemdb_searchname fixed (now firstly looks for item aliases 'name', if not found looks for item name 'jname'). [Lupus] - * Optimized getitem, delitem. getweight, fixed there possible scripts exploits [Lupus] - * Thief bug's long name in mob_db.txt was Thief Bug Larva, fixed. [Valaris] - * Thief bug names were mixed around in monster.txt, fixed. [Valaris] - * Fixed incorrect parse of usable item rate. [Valaris] - * Added ban command in ladmin (C), like GM command [Yor] - * Terminated some translations about wisp/page, and control/improvement/correction of wisp/page. All 'found' bugs are corrected [Yor] - * Added translations in inter.c about wisp/page. [Yor] - * Corrected printf datas in intif_parse_WisMessage when map-srv receives wisp message from inter-srv. [Yor] - * Sended an answer when a wisp/page is supressed because of a timeout. [Yor] - * Improved: if inter-srv is asked for a wisp, verify first if the character exists. Don't ask all map-server if it not exists. [Yor] - * Changed Printf in intif_wis_message to have better information. [Yor] - * Improved: Don't ask inter-server for a whisp/page if player is on the same map-server. [Yor] - * Completed some printf and comments in char.c [Yor] - -08/10 - * Improved map_nick2sd function. Now, sensitiv case is removed when it's possible [Yor] - * Corrected split of broadcast messages in char-server [Yor] - * Message to Valaris from Yor (special file) - * Improved accounts file saving: [Yor] - - be sure that accounts file is save at least every minute. - - save accounts file at end of login-server - * Reduce displaying size on some errors about accounts file reading. [Yor] - * Created log when change sex packet give an invalid value (login-server) [Yor] - * Correction of unknow_packet displaying (in log). Separate is done after 8th char [Yor] - * Give possibility to use account name with spaces in prompt commands finished by account name in ladmin (perl). [Yor] - -08/09 - * Fixed char-server lag. 3 tests from 3 people appeared to function properly again. [Valaris] - * Basic Implementation of Basilica [AppleGirl] - * Added ban command (ladmin perl) [Yor] - * Correction of bug about auth_fifo when we block a player. Invalid value in array (login.c) [Yor] - * Correction of some tests on server_fd array in login.c [Yor] - * Improved Item_searching in all GM commands [Yor] - * Created @undisguise GM command [Yor] - * Added Umbala town&quests&guide. Some fixes in Yuno warps&shops&guides. Kafra fix. Added Valhallen quest. [kobra_k88],[Lupus] - * Corrected char_divorce (char-server) to remove ring to both partner [Yor] - * Eventual crashfix for clif_authfail_fd [Kalaspuff] - * Corrected @jump GM command. [Yor] - * Reduced size of conf/help.txt (max 200 lines in chat window). [Yor] - -08/08 - * Added NPCs to @disguise. [Valaris] - * Mob disguises will now show up to player using it as well. Attack animation and sitting do show up to them yet. [Valaris] - * Added @disguise GM command in help files [Yor] - * Added @go 16 to visit prisoners [Yor] - * Reduced number of accounts file saving when informations are not important: [Yor] - - save immediatly any modification/creation/deletion of account (like before) - - use counter before saving if only ip/time of last connection is changed (normal authentification) - because these values are already save in log file. - * Speed up account searching in login-server. [Yor] - * Speed up character searching for @(un)block/@(un)ban. [Yor] - * Created @unjail/@discharge GM command. [Yor] - * According to GM definition level in at_command.conf, set level 20 to online_gm_display_min_level for online files. [Yor] - * Speed up some sortings of online creation (strings based sortings) [Yor] - * Fixed nullpointer crash with disguise in clif_changelook [Kalaspuff] - -08/07 - * Fixed so spells will still be cast if target walks out of range. (please don't overwrite this again) [Valaris] - * Corrected a little error in online files creation (only 1 player was visible) [Yor] - * Optimized memory management of online list [Yor] - - less memory usage - - less tests and loops (more speed) - - more efficient (use directly char_dat position instead of search it) - * Added Official Assassin Job Quest. Now eAthena contains all 2-1 Job Quests! [kobra_k88] - * Fixed scripts: 32hats, warper2, platinum_skills, added/changed some mapflags and other misc script changes [Lupus] - * Added @disguise command (enter a mob_id or name, and you will appear to others as that mob/npc!) - * Fixed code for mob disguises, should not crash clients now. - * Improved online management code when we receive char_id. [Yor] - * Added code for mob disguises. Can not set yet. Atcommand needs created. [Valaris] - * Improved mmo_char_send006b function [Yor] - * Corrected: when save file of character can not be created, try backup file if flag is set to create it. [Yor] - * Added an option to create backup of characters file [Yor] - The backup_txt file was created because char deletion bug existed. - Now this bug is corrected and no character disappear. - But, create a file with a lot of characters can use CPU usage and decrease hard disk speed. - So, I create an option with default value: no create backup. - * Improved online management code and some others little codes (char.c). [Yor] - * Respawn points of prisoners set to the jail rooms. Jail.txt mapflag addeed. So imprisoned players can't escape. [Lupus] - -08/06 - * Improved/Optimized some little code (char.c/login.c). [Yor] - * Improved 0x2afa and 0x2afb (map transmissions between char and map). [Yor] - * Optimized global message nick spoof fix. [Valaris] - * Fixed crash in attacking guardians in a null guild. [Valaris] - * Capped earned exp at 1000000000. [Valaris] - * Set area size back to 20 for now, some things in path.c need to be fixed. [Valaris] - * Fixed crash in guardian search. [Valaris] - -08/05 - * Added @jail <char_name> GM command [Yor] - * Added explanation of @idsearch and @mapinfo in help.txt [Yor] - * Improved @idsearch GM command [Yor] - * Improved a little 3 loops in ladmin.c [Yor] - * Improve some codes in char.c: [Yor] - - less tests in online creation - - mmo_char_send006b: remove duplicated memset, create a char_dat structure pointer - - server_fd[] not seted/modified/checked correctly - * Set max_walk_path back to 48. [Valaris] - * Added translated Gonryun town. Fixed map names of Louyang shops. Added missing Blacksmith, - added extra Rapairmen into refine.txt. In Inns added 4 different prices based on Base Lvl.[kobra_k88] - ----------eAthena 1.0.0 RC3 TXT--------- -08/04 - * Set battle_athena.conf to more accurate settings. [Valaris] - * Decreased default damage delay (stun after being hit) by 75%. [Valaris] - * Max walk path is now correct (17). [Valaris] - * Area size is now correct (14). [Valaris] - * Improved some very little codes in char.c. [Yor] - * Remove displayings of logs on console of map-server [Yor] - use it for DEBUG, not by default, that decrease a lot the performance - * Added (commented) printf in freeze function for debug if necessary [Yor] - * Fixed melee ctrl-attack targetting. [Valaris] - * Reset attack target when equipping arrows. [Valaris] - * Improved (log and remove_control_chars functions). [Yor] - * Added 'available free bytes' in displaying when size is expanded. [Yor] - * Fixed incorrect returns in clif_authok. [Valaris] - * Added pointer checks to chrif.c [Valaris] - * Added some pointer checks to the mob ai. [Valaris] - * New (lag-free) fix for NPCs / mobs not showing up when chars walk around [Kalaspuff] - -08/03 - * Made so if exp given is less than 0, 0 is given instead of 1 (plants were giving exp) [Valaris] - * Added console displaying to have complete informations when we expand Wdata session. [Yor] - * IMPORTANT: Add a TODO 31 for Guilds' coders. [Yor] - * Old packet 0x2b16 use packet number 0x2b0e. [Yor] - * remove packets 0x2b0e and 0x2b0f. [Yor] - * on character_name ask packet: add account_id of asker. [Yor] - * Improved script code in novice.txt. [Yor] - * Fixed error in alberta.txt. [Valaris] - * Allow player placement on afm-type maps. [Valaris] - * Added afm loading. [Valaris] - * Removed useless code for mob equipment. [Valaris] - * Initial packet setup for possible playable mobs. [Valaris] - * Added check for save_clothcolor for the dyefix, and added another check to make sure player is dyed before using the fix. [Valaris] - * Improvement: Character asking of map-server to char-server is not more case sensitive. [Yor] - * Added TODO 29 & 30. [Yor] - -08/02 - * Re-added "player not attached" error reporting. [Valaris] - * Fixed errors in 32 hat quest that was causing player not attached errors. [Valaris] - * Fixed input number function: commented out negative input check by Valaris in script.c (all scripts have been revised and fixed), - made actual bug fix of buildin_input func (wrong variable type conversion (int)->(unsigned int) in clif.c - Due to the fixed bug Merchant Job Quest works fine now [Lupus] - * Fixed number input bugs/possible exploits: mage.txt IceCream.txt event_valentine.txt refine.txt - milk_trader.txt grandpa_pharmacist.txt aldebaran.txt alberta.txt juice_maker.txt [Lupus] - * Finished: offline player can be @ban/@block/@unban/@unblock by their character name. [Yor] - * Added packet between map to char to work on offline players (@ban/@block/@unban/@unblock) [Yor] - * Added check on character name with less than 4 characters [Yor] - * Added @chardelitem GM command [Yor] - * Fixed Kafras (no more buttonless msg bugs, Kafra Pass works fine) [Lupus] - * Changed input exploit, only checks for negative now instead of having an input cap. Fixed up vending exploit. [Valaris] - * Added check for src with High Wizard's soul drain. [Valaris] - * Fixed up npc_suicide and npc_selfdestruction, should fix up crashes caused by them. [Valaris] - * Added more pointer checks in the clif_authok function. [Valaris] - * Added some pointer checks to clif.c, should prevent crashes. [Valaris] - * Added some checks about writing errors of item names in GM commands (check cases). [Yor] - * Fixed Hunter Job Quest 1.6 [Lupus] - * Removed Kalaspuff's fix for mob/npc data not always being recieved. It was causing - excessive amounts of lag. [Valaris] - -08/01 - * Added ability to spawn character pets. [Valaris] - * Added show_mob_hp. [Valaris] - * @item/@item2 GM commands now work correctly with name begining by a number. [Yor] - * @spawn/@monster2 GM commands authorise spawn of guardians. [Yor] - * Fixed so guardians may be spawned outside of castles. [Valaris] - * Fixed/Improved @spawn/@monster2 GM command. [Yor] - @spawn/@monster2 GM command: you can use space in the desired name now (use "") [Yor] - * Added TODO 26 and 27. [Yor] - * Guardians if owned by a guild will display guild name and castle on name request. [Valaris] - * Added checks for null blocks in mapforeachin functions. [Valaris] - * Addition of a GM level 99 account for test of GM commands. [Yor] - * Creation of a default structure for GM levels (sub-gm, gm, admin, etc.). [Yor] - * Improved @time GM command (better code and display more informations). [Yor] - * Added informations about game time in @time command [Yor] - * Added @time command to have server time [Yor] - * Fix night at start if administrator want night and there is no duration for night and day [Yor] - * Fix for NPCs / mobs not showing up when chars walk around [Kalaspuff] - * Begin @unban/@unblock GM command (structure done). [Yor] - * It's now possible to disable Night or Day (set to 0 in battle.conf). [Yor] - * @day/@night: when already the desired cycle, display a message. [Yor] - * Fixed overlapping Ice-Cream Maker NPC, duplicated NPCs, restored duplicated Akaru's MrSmile [Lupus] - -07/31 - * Terminated: night/day cycles. [Yor] - * When a state comes back to normal, player stay in night if it's night. [Yor] - * Started to add management of day/night: [Yor] - creation of 3 parameters in battle.conf - TODO: usage of these parameters (later). - * added line '// $Id: Changelog.txt,v 1.65 2004/09/29 17:31:42 kalaspuff Exp $' in all code source files to avoid overwrite in CVS. [Yor] - * Fixed number/quantity in @item command. [Yor] - * Fixed when night and disconnect/reconnect, it's night. [Yor] - * Removed extension to check a map in char.c (less tests). [Yor] - * Added savepoint coordonates (x,y) if player is set to a new map (char.c). [Yor] - * Added izlude to check major cities. [Yor] - * Began adding developer mobs. [Valaris] - * Added dyes and fixed client crashes with player mobs. [Valaris] - -07/30 - * Added temp fix for "nullpo player not attached" error message (script.c script_rid2sd) [Lupus] - * Added checks for major cities in afm format. [Valaris] - * Added preliminary AFM(Advanced Fusion Map) support. Actual map-reading works, but rest of server needs to recognize them. - Thanks to alexkreuz [Valaris] - * Changed Map and NPC loading display. [Valaris] - * Removed unneeded 'End' and duplicate 'end' script commands. [Valaris] - * Added 'language <language>' command in ladmin (perl) to change language of displaying. [Yor] - * Fixed atcommand_gm_only parameter: [Yor] - 0: you can define level command '0' for normal players (gm level 0) - 1: even you define a level 0 for a command, normal player can not use it. Only GM level 1 or more can use command (if command level is possible for this GM) - Note: This parameter is not like atcommand_for_all (this parameter doesn't exist actually) . - * Fixed Kafras (Cart Service for Super Novice), some warps in Morroc, Aldebaran. [Lupus] - Added official shop into St.Abbey. [Lupus] - Added quests: Lutie Town Hat Quest by TonyMan, 23 new hats custom quest. [Lupus] - Fixed jobchange.txt. [Lupus] - Improved pvp.txt. [Lupus] - Rearranged and updated! (now in 2 variants) mapflags. [Lupus] - Updated map_athena.conf [Lupus] - * Fixed: battle_athena config's atcommand_gm_only; yes was no and vice versa [Kalaspuff] - -07/29 - * Added 'language <language>' command in ladmin.c to change language of displaying. [Yor] - * Re-added guardians don't attack guild members, someone must have removed it by accident. [Valaris] - * Restore correct displaying (LAN/WAN) previous was good :) (sorry... prabably tiredness). [Yor] - * Fixed some errors in novice.txt script. [Yor] - * Kashy's script fixes. [Valaris] - * Displaying of correct information in LAN/WAN test (displaying was reversed) in char.c [Yor] - * Creation of a char_unblocked directory (char directory is blocked) [Yor] - - modification of makefile - * Added a note in TODO 14: encrypted password - problem with client versions [Yor] - ----------eAthena 1.0.0 RC2 TXT--------- -07/28 - * Added metaller to equipped mobs. [Valaris] - * Added a note in TODO 19 [Yor] - * REMOVED last changelog: cvs server: [14:29:29] waiting for cvs's lock in /usr/cvsroot/athena/src/char [Yor] - * Displaying of correct information in LAN/WAN test (displaying was reversed) in char.c [Yor] - * Added "OMG" emotion to weapon/armor breaking. [Valaris] - * Removed space in a pointer in mob.c. [Valaris] - * Restored previous version of lan management in login.c, because: [Yor] - - check test was incorrect (no mask for controled ip). - - in check test, we recalculate every time the subnetwork (loss of time). - - impossible to have a name definition for the sub-network (some network administrator use a name to define the sub-network). - - no more default configuration of sub-network. - - possible errors in the reading function of the lan file. - - no more logs about sub-network. - - BUT, conserved: - new default name for lan file - - color for displaying of LAN/WAN - * Removed some memsets from chrif.c that caused segfaults. [Valaris] - * Added fix for anklesnare and spiderweb. [Valaris] - * Added Kashy's Lan Support code. [Valaris] - * Removed variables and assignment used by prevent_multi_login. [Valaris] - * Removed prevent_multi_login. (many problems reported with it) [Valaris] - * Fixed armor breaking. Was being broken when pc was attacking instead of when being attacked. [Valaris] - * Fixed checkcart, checkfalcon, checkriding (they didn't return any value) in script.c [Lupus] - * Fixed breeder.txt renter.npc, kafras NPC (added correct class check, added correct checkcart, checkfalcon, checkriding) [Lupus] - * Fixed Kafra functions_kafras.txt NPC (added correct checkcart, fixed cmall cart giving bug) [Lupus] - * Fixed Kafra functions_kafras.txt NPC (fixed Kafra Pass exploit) [Kobra_k88] - * Fixed Hunter.txt coords of the Guild entrance warp [Lupus] - -07/27 - * Improved check command in ladmin.c [Yor] - * Added map_id check in map_foreachinarea, to prevent eventual crashes [Kalaspuff] - * Added @enablenpc and @disablenpc in help files [Yor] - * Fixed Thunder Storm range (thanks midas) [Kalaspuff] - * Added Anthell NPC trigger in Morroc.txt warps/town [Lupus] - * Added missing Warps for Job Quests of Swordman, Hunter and Thief in jobquests.txt [Lupus] - * Updated atcommand_conf, missing GM-level for @enablenpc and @disablenpc [Yor] - * Removed possible overflow error in @enablenpc and @disablenpc [Yor] - * Updated atcommand_conf, missing GM-level for haircolor [Kalaspuff] - * Improved best job test in novice.txt [Yor] - * Improved @go command: [Yor] - - give list of cities if no value - - added start point (to welcome newbies) - - give possibilities to use city names (@go geffen): at least 3 characters, and some writing errors are tested - * Replaced every Job Quest Script (excluding Assassin, 2-2 and 2-2-X ). Now all 2-1 Jobs have big quests. [Kobra_k88] - * Replaced all Skill Quests (Added Sand Attack Skill Quest). [Kobra_k88] - * Added Legendary Swords quest. [Kobra_k88] - * Replaced 6 towns with new scripts: Izlude, Prontera, Morocc, Geffen, Alberta, Al De Baran. Splitted all towns quests into files. [Kobra_k88] - * Splitted and optimized Kafras & Guides. [Kobra_k88] - * Implemented Kafra Pass! [Kobra_k88] - * Removed free Breeders (replaced by the correct ones). [Kobra_k88] - * Placed all Sign Posts/Signs into a single file. [Lupus] - * Files arrangement, additional warps/scripts correction. Fixed several scripts (NPC overlapping, bad sprites, etc). [Lupus] - -07/26 - * More accurate pvp point system. It skips ranks, needs more work. [Valaris] - * Fixed crash in executioner card code. [Valaris] - * Fixed mob respawn after death bug. [Valaris] - * Fixed exp problem caused by bounds checking. [Valaris] - * Fixed pvp rank so only one person may be rank 1. [Valaris] - * Any time a person is on a pvp map, the rank will calculate, preventing bad rank packets from being sent. [Valaris] - * Added Job Agencies for Training Ground (novice.txt). [Yor] - * PVP respawn client crash fix. [Valaris] - * Fixed small error in kafra.txt [Syrus22] - * Finished adding special equipped mobs. [Valaris] - * Added 2 living statues behind the NPC 'Monster Master'. [Yor] - * Removed infinite possibilities to have items from helper (novice.txt, new_1-4.gat,60,149). [Yor] - * Added 2 living statues behind the NPC 'Monster Expert'. [Yor] - * Improved a little 1st course of novice training. [Yor] - -07/25 - * Allow mobs to be equipped with pet armor. mob_avail and clone mobs need to be created. [Valaris] - * Removed [AppleGirl]'s armor breaking code. [Valaris] - * Commented out data_dir. [Valaris] - * Finished exp bounds checking. [valaris] - * Added negative value checks to clif_updatestatus. [Valaris] - * Added exp bounds checking for those rediculously high rate servers. [Valaris] - * Added bounds checking to the @zeny and @charzeny commands. [Valaris] - * Improved and corrected some errors 1st course of novice training. [Yor] - * Removed no guild check for Guardians. Guardians SHOULD attack people with no guild. [Syrus22] - * Fixed Alliance check in mob.c [Syrus22] - * Added armor breaking to normal battle (crits will double the chance) [Valaris] - * Fixed mistake in map.c causing compile errors. [Syrus22] - * Fixed backstab bow penalty option. [Syrus22] - * Fixed Alliance check in battle.c for emp/guardian damage. [Syrus22] - -07/24 - * Added backstab bow penalty option [Akaru] - * Fixed OnGuardianDied events on prontera castles 3 to 5. [Valaris] - * Another vending fix. [Valaris] - * Fixed bugs in npc headers caused by someone using spaces and not tabs. (kafra.txt, guide.txt, yuno.txt) [Valaris] - * Fixed a vending bug. [Valaris] - ----------eAthena 1.0.0 RC1 TXT--------- -07/22 - * Fixed numerous startup errors in aldebaron castles and one geffen castle. [Valaris] - * Full Guild Wars Script Complete!!! [Akaru] - * Fixed rice ball item. [Valaris] - * Fixed problems with options and peco riding. [Valaris] - * Updated item_db with fix for Sleipnir and more translations. [Akaru] - * Translated item_violetbox, mob_poring, mob_branch, mob_boss. Fixed wizard.txt (wrong item id), headgeatquest.txt(added Zeny check) [Lupus] - -07/21 - * Updated refine.txt. Added optional features and optimized the file. [Syrus22] - * Evened out the # of columns in mob_db, filled in some blanks. [Valaris] - * Undid compilation errors caused by Akaru's removal of nullpo.o from map-server compile [Valaris] - -07/20 - * Removed Ghostring from gef_fild13.gat [rg] - -07/19 - * Fixed Graffiti [Valaris] - * Zeny Bug In Vending Fixed [Darkchild] - -07/18 - * Added a check about level of at_command when reading the file [Yor] - * Updated /help and conf/help.txt [Yor] - * Added @nuke command in conf/help.txt [Yor] - * More WoE Castles Done [Hikaru] - * Changed: inter.txt->inter.log in log directory [Yor] - * Added some char_log when character can not be created (invalid value, invalid name, etc...) [Yor] - * Changed: char.txt->char.log in log directory [Yor] - * Update features.html/changlog.html [Yor] - * Fixed compilationissue on FreeBSD [Kalaspuff] - -07/16 - * Remove limit for kami/kamib ladmin command. [Yor] - * Fixed crash in weddingtxt.txt where it was checking an invalid equip index. [Valaris] - * Added some TODO for next version. [Yor] - -07/15 - * Changed: login.txt->login.log in log directory [Yor] - * added system to choice authorised ip for remote administration [Yor] - * Added listBan/listOk commands in ladmin's. [Yor] - * Speed up a little search_mapserver function. [Yor] - * Init map strings of each servers when map-server send informations. [Yor] - * Added some TODO for next version. [Yor] - -07/14 - * Fixed another lockup with multi_level_up [Valaris] - * Added kami(yellow)/kamib(blue) commands in ladmin (terminated). [Yor] - * Fixed name of ladmin_athena.conf. [Yor] - * Fixed mvp item reading. [Valaris/Syrus22] - * Added new move packet in map (ver.13jully04) [Yor] - * Added new auth packet in map (ver.13jully04) [Yor] - * Added kami/kamib commands in ladmin. not terminated: to do: login->char [Yor] - * Updated Some Npcs [Darkchild] - * Added Gefenia Warps [Darkchild] - * Added Berzebub Quest [Darkchild] - * Removed random alchemist marine sphere code, until some other system is worked out. [Valaris] - * Fixed infinite loop caused by turning multi level off. [Valaris] - * Added display id the char-server is freezed. [Yor] - * Added debug printf about the max_connect_user in char-server. [Yor] - * Added banadd command in ladmin.c [Yor] - * Removed duplicate check in chrif.c. [Yor] - -07/13 - * Fixed GM_level code in map-server. [Yor] - problem is in the hash system of the db -> use simple db until we found solution. - note: for this db, it's not necessary to use a db system (little db, 2 values: key, value) - * Improved GM_level code in map-srv, but not solve the problem. [Yor] - * Fixed error of 'return' without value in chrif_parse (chrif.c). [Yor] - * Added character name, account id and gm level on console in map-server when auth is accepted. [Yor] - * Added gm_level of the account on console in char-server when auth is accepted. [Yor] - * Added gm_level of the account on console in login-server when auth is accepted. [Yor] - * Added timeadd command in ladmin.c [Yor] - * Added help for each command (help <command>) in ladmin (perl and c). [Yor] - * Fixed global message (normal speak) name spoof exploit. [Valaris] - * Added timeset command in ladmin.c [Yor] - * Added banset command in ladmin.c [Yor] - * Added vending and trading dupe fixes, thanks to Kinko and Kazzy [AppleGirl] - * Added multi_level_up command to battle_athena and commandline. [Valaris] - Turning it off will allow a player to only level up once from a monster. - * Added: explanations of ladmin_athena.conf keys in conf_ref.txt. [Yor] - * Fixed: init mmo_map_server structure (to 0) in char-server. [Yor] - * Added Gefenia Maps [Darkchild] - * Added @nuke command do to user request. [Valaris] - * Removed nick spoof fix code for now, it broke chat. [Valaris] - * Added some code for @nuke command. [Valaris] - * Finished adding battle_athena options to command line. Every option in battle_athena.conf - can now be passed directly through the command prompt. [Valaris] - -07/12 - * Added many battle_athena options to command line arguments. [Valaris] - * Allow battle_config_switch to be used globally in map-server. [Valaris] - * Rewrote map-server command-line code. Will now begin implemented nice commands for map-server. [Valaris] - * Added BETA version of ladmin in C. [Yor] - * Added new packet structure of authentification and move - automatic detection. [Yor] - * Added /item command. It is same as /monster. Both commands will search for mobid first, if not found will give item. [Valaris] - * Fixed a displaying error in state command (perl ladmin). [Yor] - * Added /monster command. Syntax is /monster <name/id>. [Valaris] - * Fixed chat spoofing in global messages. [Valaris] - * Prevent nick spoofing in whispers. [Valaris] - * Added check about lenght of packet 0x72 for new client version [Yor] - * Added Pet Equip Items Quest Npc - * Added Pet Taming Items Quest Npc - * Added Slotted Sunglasses Quest Npc - * Added pet_equip_required option for pet skills. [Valaris] - * Changed: create a sub-function for help command in ladmin (perl). [Yor] - -07/11 - * Added Petit pet skill. [Valaris] - * Added some code for Petite Heaven Drive, still does not work, but doesn't crash. [Valaris] - * Fixed dokebi and baby desert wolf pet skills. [Valaris] - * Added Orc Warrior, Hunter Fly, Poison Spore, Baby Desert Wolf, Baphomet Jr, and Dokebi pet skills. [Valaris] - * Added script command petskillattack.[Valaris] - * Fixed search command in ldamin (perl) ignore sensitive case now. [Yor] - * Fixed default to 0 for save_unknown_packets configuration in login. [Yor] - * Fixed the warnings about implicit declarations. [Kalaspuff] - * Added @guildrecall/@partyrecall commands. [Yor] - * Added Isis pet skill. [Valaris] - * Added petmag script command for magnificat. [Valaris] - -07/10 - * Added Banker NPC because alot of users wanted one. [Syrus22] - -07/09 - * Added Sohee pet skill. [Valaris] - * Added petheal command. [Valaris] - * Added Smokie pet skill. [Valaris] - * Added bonus bPerfectHide for Smokie pet skill. [Valaris] - * Added Spore pet skill. [Valaris] - * Created petrecovery script command. [Valaris] - * Added Poring, Drops, Poporing, and Yoyo loot skills. [Valaris] - * Added petloot script command for pet looting. [Valaris] - * Removed pet_loot config settings. [Valaris] - * If pk_mode is on, a message will show up in map-server. [Valaris] - * Fixed pk_mode extra experience and drops so will occur if monsters is 20 levels or higher than player. [Valaris] - * Fixed @killmonster crash caused by implementation of pk_mode. [Valaris] - * Finished setting up pk_mode, should be 100% complete now. [Valaris] - * Added nopvp.txt for pk_mode. [Valaris] - * Prevent novice engagement in pk_mode. [Valaris] - * Fixed up and changed the exp penalty system. [Valaris] - * Pk_mode will now give double exp loss if killed by player. [Valaris] - * Updated conf/help with new commands [Yor] - * Removed more pvp timer stuff from pk_mode [Valaris] - * Increase drop rates +25% if over level 20 on pk_mode. [Valaris] - * Changed +25% exp increase on pk_mode to 15%. [Valaris] - -07/08 - * Disabled pvp rank and timer if pk_mode is on. [Valaris] - * All maps made pvp if pk_mode is on. [Valaris] - * pk_mode additional 25% exp given over level 20 [Valaris] - * Disable @pvpon and @pvpoff commands if pk_mode is on. [Valaris] - * Added pk_mode option in battle_athena.conf (not yet implemented) [Valaris] - * Reworked prevent_multi_login, should work perfectly now. [Valaris] - * Removed need for eof=2 for prevent multilogin, will now just delete the blocks containing both sessions. [Valaris] - * Added map-servers anti-freezed connection in char-server. [Yor] - * Added char-servers anti-freezed connection in login-server. [Yor] - * Fixed spy commands so that inputting the same id/name turns off the command. [Syrus22] - * Created @partyspy command. [Syrus22] - * Renamed search_guildname function to conform with normal naming standards in guild.c. [Syrus22] - * Created @whomap/@whomap2/@whomap3 commands to show online players on a specifical map. [Yor] - * Updated and Shrunk the Kafra Script. [Syrus22] - * Create @reloadgmdb gm command. [Yor] - -07/07 - (Dated On Aegis Website) - *--Released 1.0.0 RC3--* - * Fixed crashed with prevent_multi_login. [Valaris] - * Allow infinited local logins if prevent multi_login is on. [Valaris] - * If prevent_multi_login is on, it will disconnect both clients on the same ip. [Valaris] - * Prevent_multi_login will now list the character names of both accounts when logged out, and give a message. [Valaris] - * added updated const.txt and pet_db.txt [Valaris] - * GM accounts/level updating without restarting completed (by reloadgm ladmin command). [Yor] - * Removed gm_account_filename definition from map.conf. [Yor] - * Updated GM level by reloadGM ladmin command. [Yor] - * Added a packet between char and map to send GM accounts and their level. [Yor] - * Added a GM minimum level option to display 'GM' in online files. [Yor] - * Added a warning when a GM account is defined twice in the file. [Yor] - * Check for castle before guardian searches for emblem. [Valaris] - * Prevent stealing from treasure boxes. [Valaris] - * Enable mounted classes to use pedestrian counterpart's items. [Valaris] - * Change so petskillbonus will only update stats(client-side) if need be to prevent errors. [Valaris] - * Fixed crash with putting pets with skills back into egg. [Valaris] - * Added Steel ChonChon, Rocker, and Deviruchi pet skills. [Valaris] - * Added bAllStats(SP_ALL_STATS), bAgiVit(SP_AGI_VIT), bAgiDexStr(SP_AGI_DEX_STR) bonuses for pet skills. [Valaris] - * Added ChonChon, Lunatic, Picky, and Savage Babe pet skills to pet_db.txt. [Valaris] - * Added petskillbonus command for pet skills. Added pet_skill_bonus functions in pet.c. Made pointers for pet skills. [Valaris] - * Added 'GM' display option for online files [Yor] - * Improved GM accounts file reading in login-server [Yor] - -07/06 - * Changed heal dog in prontera to a poring. [Valaris] - * NPCs with mob sprites can now be used in scripts. [Valaris] - * Removed sd->brokencounter. Made getbrokenid more scripter friendly. Updated refine.txt getbrokenid commands. [Valaris] - * Mounted classes will now use equipment of their pedestrian counterpart. [Valaris] - * Improved management of GM account structure in char-server. [Yor] - * Added packet betwen login to char to send GM accounts value. [Yor] - * Added reloadGM command in ladmin to reload GM accounts file without stop the login-server. [Yor] - * Added listGM/lsGM command in ladmin to list only GM. [Yor] - * Correct an error in loop of char_divorce function (incorrect variable). [Yor] - * Added some comments. [Yor] - * Added a check on start_point.map when configuration is readed. [Yor] - * Modified final message of login log at end of login-server. [Yor] - -07/05 - * Flamelauncher,frostweapon,lightningloader,seismicweapon, and enchant poison now check to make sure target's weapon is not already enchanted. [Valaris] - * If sage breaks another person's weapon due to enchant failure, it will tell caster. [Valaris] - * Modified venom splasher to hopefully stop crashes caused by spamming. [Valaris] - * SA_FLAMELAUNCHER,SA_FROSTWEAPON,SA_LIGHTNINGLOADER,SA_SEISMICWEAPON now check to make sure target is holding a weapon. [Valaris] - * SA_FLAMELAUNCHER,SA_FROSTWEAPON,SA_LIGHTNINGLOADER,SA_SEISMICWEAPON now will break target's weapon on failure (if one - is being held and caster met requirements) [Valaris] - * Prevent unidentified and broken items from being sold. [Valaris] - * Added buildin_repair for equipment repair npc. [Valaris] - * Added repair npc to forgery in prontera. (refine.txt) [Valaris] - * Added sd->brokencounter and buildin_getbrokenid for item repair npc. [Valaris] - * Corrected some item names [rg] - * Fixed so @repairall success message and effect will only display once. [Valaris] - * Added "No items needed to be repaired" message and added forge success effect to @repairall. [Valaris] - * Added @repairall command. [Valaris] - * Added equipment_breaking option, changed weapon_break_chance to weapon_break_rate (changed to %) [Valaris] - * Crit's will now double weapon breaking chance if turned on. [Valaris] - * Added missing commands in atcommand_athena.conf. [Yor] - * Added @warpto command (same @jumpto). [Yor] - * Added increase in chance to break weapon if using powerthrust. [Valaris] - * Added weapon_break_chance to battle_athena.conf. [Valaris] - * Modified multiple login from one ip prevention(and remove gm bypass). [Valaris] - * Broken weapons will now have their description names in red. [Valaris] - * Speed up characters saving [Yor] - * Improved logs when a character isn't readed [Yor] - -07/04 - * Completed Prontera guild castles [Akaru] - * break_weapon_chance now works, but broken weapon will not be displayed any differently than a normal weapon. - Also does not yet affect a dual dagger assassin's 2nd weapon. No way to repair yet, and no skills/stats affect breaking chances. [Valaris] - * Update int_storage to include broken column on all items (updates from old version) [Valaris] - * Added @guildspy command. [Syrus22] - * Added weapon_break_chance. (Not implemented yet) [Valaris] - * Added break column for items in athena.txt (will upgrade older versions automatically) [Valaris] - * Changed default required GM levels for GM commands (effective if corresponding directive(s) in /conf/atcommand_athena.conf is/are missing) to 1 [rg] - * Added packet_table_en.txt in doc folder. Has some translations of the client_packet.txt. [Valaris] - * Prevent @monster and @spawn of guardians/emperium. [Valaris] - * Changed killmonster so it will not destroy guardians. [Valaris] - * Added prevent_multi_login in battle_athena.conf to disable multiple logins from same ip (ignores gms, and will - display ip of offending ip if turned on) [Valaris] - * Added checks on player trading to prevent possible exploits. [Valaris] - * Make sure cart is on before vending. [Valaris] - * Cleaned up vending exploit fixes. Now checks to make sure not vending more than max items per skill level. [Valaris] - -07/03 - * Prevent use of potion pitcher on oneself, fixed potion pitcher so can be used on other targets. [Valaris] - * Fixed the damage code for Falcon Assault, so its not totally useless. [?] - * Update peco riders for people upgrading athena, fixed bug in unmounting pecos. [Valaris] - * Removed option 32 from @option, added @mountpeco command. [?] - * Removing peco will revert to proper job level, fixed so jobchanging from peco status to peco user without peco status, - will update job to peco status. (ie going from Mounted crusader to Unmounted knight, will jobchange to mounted knight) [Valaris] - * Fixed so Peco mounting will not reset job level. Set to remove peco status if jobchanging to a class that does not use them. [Valaris] - * Peco mounting will now jobchange accordingly. [Valaris] - * Added checkfalcon and checkriding script commands. [Valaris] - * Added checkcart script command (since was already being used in scripts) [Valaris] - * Re-added unix fd_setsize definitions, makefile will now pass -DFD_SETSIZE=4096 only for windows compiles. - Tested new implementation of using -DFD_SETSIZE=4096 in makefile on windows box, and got past 64 connections even. [Valaris] - * Improved messages between servers about connections. [Yor] - * Improved pc_resetlvl, fixed the bug about options being left. [?] - -07/02 - * Added optional match_test in @who/who2/who3 commands (no sensitive case) [Yor] - * If there is no map-server, send right message to client (char-server) [Yor] - * Improved counter of users (char-server) [Yor] - * Improved save of characters (char-server) [Yor] - * Improved sorting of account before save (login-server) [Yor] - * Improved map search at selection of a character (char-server) [Yor] - -07/01 - * Removed FD_SETSIZE definitions from socket.h, added -DFD_SETSIZE=4096 argument to makefiles. [Valaris] - * Changed exploit fix in chrif.c [Valaris] - * Added assassin mask view_id in item_db [Valaris] - * Added a parameter to authorise minimum GM level at connection (login) [Yor] - * Fixed crash caused by making raw connection to map-server. [Valaris] - * Corrected a possible error at check of online players [Yor] - * Improved characters names control/check [Yor] - * Improved save/load of REG2 strings and values (login) [Yor] - * When there is no char-server, login-server sends proper message instead of a void list of servers [Yor] - -06/30 - * Fixed a crash when used @charmodel,@charstpoint,@charskpoint and - @charzeny with the wrong name [Kalaspuff] - * Added possibilities for switchs in battle.conf (add some foreign language) [Yor] - * Protected char-server again disconnection of login-server [Yor] - * Added possible protection against packet exploits in chrif.c. [Valaris] - * Login-server: Added an option for the format of the date (log, etc...) [Yor] - Improved some little code. - Added log for char-server packets. - * Correction of prtg_cas03.txt that crash server AT START! [Yor] - * Added functions of mapflag noskill [Kalaspuff] - -06/29 - (Dated On Aegis Website) - *--Released 1.0.0 RC2--* - -06/28 - * Added monsters_ignore_gm option. Monster won't attack GMs if turned on unless attacked and within 1 cell. [Valaris] - * Added drops_by_luk option in battle_athena.conf. Anything higher than 0 will turn this option on, and act as a mutiplier. - Example : Setting of 10 with 50 luk would add 5 to the drop rate. So say a card has a drop rate of 2, it would become 7. [Valaris] - * Fixed range and removed skill failed message from Venom Splasher, also moved some of it's code around. [Valaris] - * When a player arrive on map-server, time limit of its account is displayed if not unlimited [Yor] - * Fixed problem where warp portals broke in npc.c [Valaris] - * Updated atcommand_heal so it works like it should [Kalaspuff] - -06/27 - * Changed Venom Splasher so it will increase damage based on level of Poison React (had it set so the player had to be - using it, but it turns out it doesn't need to be) [Valaris] - * Venom Splasher now works except for the counter part. Damage is instantly dealt if skill is successful. [Valaris] - * Improved @item command to make correctly pet eggs [Yor] - * Updated Chase Walk so you can't attack while you have it casted [?] - * Removed un-needed code for graffiti from clif.c [Valaris] - * Added @ban command (to ban a player for a limited time) [Yor] - * Added @charblock command (you have been blocked by GM team) [Yor] - * Added the mapflag nowarpto [Kalaspuff] - * Updated the function of nowarp [Kalaspuff] - -06/26 - * When a player is banned (or with a state != 0), he is disconnected [Yor] - * When sex is changed, skills of other sex are reseted (and skill points increased of the same number) [Yor] - * To avoid problem with change sex and equipement, changed sex character is unequipped of all equipment [Yor] - -06/25 - * Added @charchangesex GM command [Yor] - * Changed: Changesex is now done after that the login-server has confirmed the change [Yor]. - becuase sex is saved in account file. - -06/24 - * Added new classes in change sex script command (buildin_changesex). [Yor] - * Translated pet_db.txt again [Valaris] - * Initial implementation of Venom Splasher. Runs checks on target poison status and whether or not hp is less then 2/3. - Will display skill failed if checks do not pass. Shows effect when successful. [Valaris] - * Added administration system to change final date of a banishment. [Yor] - * Added information about banishment in admin packets about an account. [Yor] - * Updated Chase Walk so it cancels when recasted to fix it. [?] - * Initial implementation for Chase Walk skill for Stalker Class [?] - * When an account is banned, message_error_7 is not more modified [Yor]. - -06/23 - (Dated On Aegis Website) - *--Released 1.0.0 RC1--* - * Added bRandomAttackIncrease for Executioner card. Chance stacks, attack does not. [Valaris] - * Fixed magic_damage_return so it will actually work (for Maya card). [Valaris] - * Add a ban timestamp in the structure of the accounts. Management not yet make [Yor] - -06/22 - * Don't send a message when it's void (packet 0x8e) - client doesn't display it [Yor]. - * Add a refresh time parameter for the html online file (refresh time in the explorer) [Yor]. - * Create a job_name function in atcommand to have the name of the job (suppress repeated code) [Yor]. - * Added New City: Jawaii - * Fix free memory of online structure at end of char-server [Yor]. - * Remove possible duplicated online players (multiple map-servers) [Yor]. - * Add examples in state command (ladmin) [Yor]. - * Use a function to display warnings in login-server to avoid duplicated messages with import option [Yor]. - * Iinitial implementation for magicdamagereturn for Maya Card [?] - * skill_out_range_consume - If it is set 'no' the skill will still be cast (like real servers). - If it is set to yes, skill will fail and sp and items required will be lost. [Valaris] - -06/21 - * Updated Sacrifice skill code to be more flexible for user usage [?] - * Changed SC_ATTACKPOTION and SC_MATTACKPOTION to SC_ATKPOT and SC_MATKPOT, also added it in item_db.txt [?] - * Guild Territory will now display the # of castles owned or "None Taken". [Valaris] - * Changed SC_ATTACKPOTION and SC_MATTACKPOTION so the increase can be specified in itemdb.txt. - Example : sc_start SC_AtkPot,18,30; (+30 atk for 30 seconds) [Valaris] - * Added SC_ATTACKPOTION and SC_MATTACKPOTION for +30 atk for specified time period (need to get the correct id's yet, - right now giving wrong icons and wrong message). Added entries in const.txt, need more info to complete these. [Valaris] - * Fixed so players will always spawn with guild emblem if one is needed. [Valaris] - * Reduce number of tests in atcommand_character_stats_all (@charstatsall). [Yor] - * Fix memory management for online players list. [Yor] - * Party HP now updates instantly on change. [Valaris] - * Fixed crash when non-guild members are in the area of guardians in attack mode.(Will ignore them) [Valaris] - * A higher level GM is not displayed by who/who2/who3 if he uses HIDEGM. [Yor] - * When a GM with HIDEGM relogs, he is always HIDEGM (only GM). [Yor] - * Improve presentation of online.txt file. [Yor] - * In /npc/quests/magicalhatquest, corrected checking for and deletion of Mage Hat instead of Wizard Hat. [rg] - -06/20 - * Fixed problem with guardian emblems disappearing [Valaris] - * If a GM use GM HIDE, he is not counted in the number of players [Yor] - * Setup prtg_cas01 to load guardians on server startup and to spawn them when purchased. Also switched from GuardianDied - to OnGuardianDied (other way wasn't working). Changed so guardians won't be killed on agitend. [Valaris] - * Guardians cannot attack and cannot be hurt during non woe time. [Valaris] - * Switched checking of castle.txt format so it won't wipe guardian hp everytime it loads. [Valaris] - * Made it so if guardians were installed in old db, that it will set guardians to full hp based on defense and class. [Valaris] - * Autosave will save guardian HP data. [Valaris] - * Castle.txt visibleG flags will be set when guardians are killed. [Valaris] - * Moved emperium defense upgrade to mob.c. [Valaris] - * Removed guardian hp saving from agitend. [Valaris] - * Added option to choose which columns are displayed in the online files [Yor] - * Added option to choose how to sort online players in the online files [Yor] - * Correction of a new error on guild (from [Valaris]). Old castle.txt files couldn't be readed. [Yor] - * Kafra Points And Rewards fixed [Darkchild] - * Kafra file made a lot smaller with DoEvents [Darkchild] - * Fixed lotsa bugs in Kafra's [Darkchild] - * Initial implementation for paladin's skill sacrifice [?] - * Loading/Saving of guardian hp (loads on agitstart, saves on agitend) [Valaris] - * Added so guardian hp will change accordingly. Moved the guardian defense increase to mob.c [Valaris] - * Implemented guardian and guardianinfo script commands [Valaris] - -06/19 - * Added Ghp0-7 into castle database [Valaris] - * Added configuration parameters to choose online files filename [Yor] - * Added online files (txt and html) [Yor] - * Added choose of authorised letters/symbols for characters names [Yor] - * Added 3 new Dragon Boat Festival monsters with temporary stats to mob_db [Akaru] - * Translated more of item_db [Akaru] - * Added correct effects for Dragon Boat Festival items [Akaru] - * Solve problem about the change of MAX_GUILDPOSITION by [Valaris] when we load an old guild.txt file. [Yor] - * Improve allow/deny configuration. Write warnings if necessary. [Yor] - -06/18 - * Add heal_payment.txt as an alternative to heal.txt. [Yor] - * Sex change (char.C): Correct error in jobchange. Disconnect player if connected. [Yor] - * Sex change/account deletion: Change authentification to avoid that player comes back on char-server within the 5 secondes before disconnection. [Yor] - * Save configuration of login-server in log file at start. [Yor] - -06/17 - * Added fritz's vending exploit fixes. [Valaris] - * Increased max guild castle size to accomodate for novice guild castles. [Valaris] - * Fixed investment in prontera castle 1. [Valaris] - * Implemented of showing guardian hp on guardian investment in prontera castle 1 (factors in defense investment) [Valaris] - * Added strmobinfo script command. Syntax is strmobinfo(x,y). 'y' is the mob's id. x will show different values. - 1=english name, 2=jap name, 3=level, 4=max_hp, 5=max_sp,6=base_exp,7=job_exp. [Valaris] - * Disable % and / for 1st symbol of commands (party chat symbol and standard ragnarok GM commands) [Yor] - -06/16 - * Added fully functional economy for Prontera Castle 2 Guild Wars script [Akaru] - * added fix for cross-class ensemble skills. [?] - * Increased max guild member limit to accomodate for +2 member increase per extension level - and increased max position to 56 to accomodate for all members. [Valaris] - * More of fov's fixes for atcommand.c, chrif.c, and clif.c. [Valaris] - * added fixes for class checking skills like bard & dancer skills and a priest skill. [?] - * updated skill_cast_db and skill_require_db.txt [?] - * changed int_guild.c added +4 for extension skill to match kRO [?] - * remote administration: add a command/packet to change sex of an account [Yor] - * Log detailled reason of refused connection in remote administration [Yor] - * Create a mmo_auth_tostr for accounts [Yor] - * Add a message when char-server is terminated [Yor] - * Save deleted accounts (administration deletion) in log file [Yor] - * Add a message when login-server is terminated [Yor] - -06/15 - * Added in fov's fixes for socket.c, atcommand.c, npc.c and skill.c [Valaris] - * Added a char_log function. Save unreadable characters in log instead of a specific file [Yor] - * Save invalid account lines in log file. Account will be never lost [Yor] - * Sort characters of same player with the slot number in the characters file [Yor] - -06/14 - * Fix errors in prtg_cas01, prtg_cas05 and MrSmile scripts [Akaru] - * Added fully functional economy for Prontera Castle 1 Guild Wars script [Akaru] - -06/13 - * If player is on map-server when the account is deleted, player is now disconnected [Yor] - * Correction of char deletion bug when account is deleted [Yor] - * Added Prontera Castle 5 guild wars script [Akaru] - * Added Prontera Castle 4 guild wars script [Akaru] - * Add checks about duplicated character ids and names [Yor] - * Don't save a reg of a character if its string is void [Yor] - * Read a character even if a reg string is void (don't suppress the char for that) [Yor] - * Save characters in account_id order [Yor] - * Save not readed characters in a file (char file name + "not_readed.txt") [Yor] - * Display line number when a character can not be readed [Yor] - * Initialise char_num! Display number of readed characters [Yor] - * Do right initialization of char_dat [Yor] - * Add red color for ERROR displays in char.c [Yor] - -06/12 - * Change 0 to '\0' for char in login.c. Add red color for ERROR displays [Yor] - * Optimised Mr. Smile NPC script [Akaru] - * Add a configuration in atcommand.conf to set the 1st character of ALL commands (Now, you can choose @, #, !..., any char that is not control character) [Yor] - * Optimised Prontera Castle 1 and 2 guild wars scripts [Akaru] - * Added Prontera Castle 3 guild wars script [Akaru] - * Changed Graffiti placement, will allow placement of one painting at a time (old one will be replaced). [Valaris] - * Graffiti displays to other plays and remains on map for set time period. [Valaris] - -06/11 - * Initial implementation of graffiti (does not change directions yet (vertical/upsidedown) and doesn't dissappear [Valaris] - * Add config_switch (0/1, yes/no, ...) for char-server configuration [Yor] - * Add a display when a player does a connection [Yor] - * Add a display when a remote administration does a connection [Yor] - -06/10 - * Improve compiling instructions for cygwin (socket.h) (depends of the cygwin version). [Yor] with help of [Lostsoul] - * Add parameters in login.conf to display or not parse information [Yor] - * Remove some repeated codes in ladmin / add example when error of command [Yor] - * Remove delete_session error in login.c (sorry) [Yor] - * Display correct message for char-server disconnection [Yor] - * Finish translation of ladmin [Yor] - * Fixed Various Npc Bugs [Darkchild] - * Added green colour for READY displays in char-server, login-server and map-server [Akaru] - -06/09 - * Add some comments in ladmin [Yor] - * Remove displaying of packet 0x2714 from login-server [Yor] - * Correct length of password send to login-server in char-server [Yor] - * Char-server/login-server: put default lan to 127.0.0.1 instead of any hasardous value [Yor] - * Change displaying of the title [Yor] - * Optimised twin towers script to use duplicate [Akaru] - * Edited to a more user friendly error message for invalid server communication password [Akaru] - * Updated the item_db for more item name consistencies [Akaru] - * Reverted training grounds back to new_1-?.gat maps. [Valaris] - * Added added more variety to sending packets to guild members (same map, same map w/out self, ect) [Valaris] - -06/08 - * Put a HOWTO in lan_support.conf. [Yor] - * Removed extra semicolons in char.c, map.c, and pc.c. [Valaris] - * Added missing } to clif_storageitemlist in clif.c and found a couple lines ending with 2 semicolons, removed them. [Valaris] - -06/07 - * Translated refine_db.txt. [Valaris] - * Negative vending fix. [Fritz] - * Correction of mktime parameters in ladmin + some translations [Yor]. - * Add some checks on login-server configuration parameters [Yor]. - -06/06 - * Fixed error in skill_tree.txt that would crash some people's servers when changing to Professor. [Valaris] - * Added admin_state directive for enabling and disabling remote administration, instead of testing whether admin_pass == "" [rg] - * Add title to the servers. [Yor] - * Add warnings about default password usage (administration and gm passwords). [Yor] - * Modify adduser.c for the default configuration. [Yor] - * Write the complete admin_packet.txt. [Yor] - * Champion NPC was looking for a priest instead of monk, changed to correct value. [Valaris] - * Small fixes in guide.txt, kafra.txt, and swordsman.txt pointed out by StiNKy. [Valaris] - * Begin splitting monsters.txt [Akaru] - * Removed obselete monster spawn files [Akaru] - * Complete Guild Wars for Prontera Castle 2 script done [Akaru] - * Fixed prevent_logout option. [Valaris] - -06/05 - * Implemented guild castle regen.(Stackable 2x for castle owners) [Valaris] - * Fixed player logout display on map-server console. [Valaris] - * Added atcommand_spawn_quantity_limit directive to /conf/battle_athena.conf [rg] - * Fixed noskill map flag [?] - * Complete information about login configuration in conf_ref.txt [Yor] - * Add possible configuration values on/off or yes/no in login-server [Yor] - * Guardians and emp will now get +2000 hp for every defense investment within a castle [Valaris] - * Changed the login server to reject all remote administration authentication if the admin_pass directive isn't set, and commented-out the admin_pass directive in /conf/login_athena.conf [rg] - * Changed /src/common/grfio.c so it doesn't try to read GRF files with no respective directive in /conf/grf-files.txt [rg] - * Changed so no one can spawn inside castles. [Valaris] - * Updated item_db with more consistant names, fixed some unknown_items [Akaru] - * Complete Guild Wars for Prontera Castle 1 script done [Akaru] - * Disabled guild breaking, alliance breaking, and alliance making during WoE. [Valaris] - * Will not default to prontera.gat if map-server is not connected. [Valaris] - * Warp players who are not in guild out of castles when WoE starts. [Valaris] - -06/04 - * Allies now do no damage to guardians or emperium. [Valaris] - * Prevent allies from being attacked by guardians. [Valaris] - * Optimized guardian emblem code. [Valaris] - * Fixed map-server crashing with spawning guardians in untaken castles. [Valaris] - * Guardian emblems will change if castle is taken, but client needs to refresh map. [Valaris] - * Fixed problem where guild emblem would vanish from guild info screen. [Valaris] - -06/03 - * Improve e-mails checks and LAN/WAN checks on char-server. [Yor]. - * Add some explanations in front of accounts file. [Yor] - * Set a non LAN configuration for basic configuration in lan_support.conf. Explain parameters. [Yor] - * add missing parameters of char_athena.conf, and explain them. [Yor] - * Restore default admin pass and gm pass of login_athena.conf, and add missing parameters. [Yor] - * fix missing include in char.c. [Yor] - * Translation of checkversion. Add some explanations in front of file. [Yor] - * Translation of getlogincount [Yor] - * Finish translation of new login.c [Yor] - * Implemented Guardian Emblems [Valaris] - -06/02 - * Added maximum_level option in battle_athena.conf [Valaris] - * Added maximum level cap to all the level up commands. [Valaris] - * Added "Deal has been cancelled" message to Fritz's input exploit fix. [Valaris] - -06/01 - * Fixed training ground npcs and warps, removed depreceated maps, using new ones. [Valaris] - -05/30 - * Small map-server crashing fix with Leo and Guide npcs in training ground [Valaris] - -05/29 - * Removed item_value_db.txt and all references to it [Valaris] - * Removed unused class_equip_db.txt [Valaris] - * Fixed stat and level reset bug where needed status points wouldnt reset unless relogged [Valaris] - * @monster will summon monster without an amount specified [Valaris] - -05/28 - * Added heal and usable item rate modifier [Valaris] - * Added pet equipment to equipment rate modifier [Valaris] - * Added option to turn alchemist summon experience and drops on and off [Valaris] - * Alchemist Marine Spheres now randomly explode [Valaris] - * Fixed bug where if certain items lowered max hp (4 mysteltain, and 1 eddga) below 0 - would loop to server max hp value. [Valaris] - -05/26 - * Added New Hats [Darkchild] - * Added New Monsters [Darkchild] -05/23 - * Added @charstatsall, views all characters (easy for money bug scaning etc! [Fritz] - * Max to input npc command, 0 is lowest, 99999999 is max, this to prevent money bugs! [Fritz] - -05/21 - (Dated On Aegis Website) - *--Released 0.5.2--* - -05/20 - (Dated On Aegis Website) - *--Released 0.5.1--* - * got dye working again [Darkchild/fritz] - -05/19 - (Dated On Aegis Website) - *--Released 0.5.0--* - -05/09 - * added Prontera Guild Castle 3 test guild wars test script [Akaru] - * modified Prontera Guild Castle 1 and 2 guild wars test script [Akaru] - * fixed several valkyrie jobchangers [Akaru] -05/08 - (Dated On Aegis Website) - *--Released 0.4.2--* - *--Released 0.4.1--* - * added Prontera Guild Castle 2 test guild wars test script [Akaru] - -05/07 (Dated On Aegis Website) - *--Released 0.4.0--* - -05/06 - * added Prontera Guild Castle 1 test guild wars test script [Akaru] -05/04 - * removed parses and added ENGLISH! [?] - -04/29 (Dated On Aegis Website) - *--Released 953 Delta--* - -04/28 (Dated On Aegis Website) (Whose Ideas Were These?) - *--Released 953 Gamma--* -04/27 - *--Released 951 Beta--* - * fixed @jobchange crash [credits to Mugendai, commited by Akaru] - -04/25 (Dated On Aegis Website) - *--Released 947 Alpha--* -04/23 - * added more Professor Skills and added checks [?] -04/10 - * added more upper skills from moonsoul's works [?] -02/12-04/10 - * CVS Down - Not Many changes could be made...* - -02/22 (Dated On Aegis Website) - *--Released 817--* - -02/12 - * added more mob skill conditions (friendstatuseq, mysyatuseq, friendhpltmaxrate) [RoVeRT] -02/06 - * dumped @skillall for @allskill [?] -02/05 - * fixed provoke so it doesnt work on undead [RoVeRT] - * added TyrNemesis^ card removal code and min/max settings [RoVeRT] -02/04 - * added start_zeny and party_level_range to char_athena.conf [RoVeRT] -02/03 - * Improved the prontera.gat map fallback. [Sara-chan] - * Improved the way guild emblems act when logging in. [Sara-chan] - * Undead-class armor, and Undead monster themselves will never be frozen [RoVeRT] - * fixed negative values for NPC to always be 0 -01/26 - * mob_warpslave correction [RoVeRT] -01/25 - * added poison hp reduction [AppleGirl] -01/20 - * added intimidate [RoVeRT] - * added mvp checks for some skills -01/17 - * added skill check for empelium attack and removed drops from NULL kills [RoVeRT] -01/16 - * added secondary effects for when characters with appropriate elemental armor - are within area of effect of sage spells SA_VOLCANO(atk up), SA_DELUGE(max hp up), - SA_VIOLENTGALE(flee up) [moonsoul] - * removeal of @randmon as it isnt needed [RoVeRT] -01/15 - * fixed auto spell so it works the prober way [RoVeRT] -01/12 - * added mob_warpslave [RoVeRT] - * added mob_warp to check noteleport mapflag -01/07 - * added OnCommand for NPC [RoVeRT] - * added new on death method for NPC spawned mobs [RoVeRT] - * added mobcount [RoVeRT] -01/06 - * fixed icon status for spear quicken [AppleGirl] - * added quoted name support for @monster [RoVeRT] -01/05 - * added indivudal support for card and equip drop rates [RoVeRT] -01/04 - * added TF_PICKSTONE and skill check condition for TF_THROWSTONE [AppleGirl] - * added updated cast_db.txt and fixed SA_VOLCANO, SA_DELUGE, - SA_VIOLENTGALE, and SA_LANDPROTECTOR GRAPHICS [AppleGirl] - * Fixed Effects of a few bard Skills. [AppleGirl] - * added option to stop logout for 10 seconds after taking a hit [RoVeRT] -01/03 - * added inet_ip support to char and map [RoVeRT] - * added checkcart, checkfalcon and checkriding npc commands -01/02 - * added new npc timer support that is independant of a player [RoVeRT] -12/31 - * Added @refineall [Mark] -12/30 - * added support for custom_item-db.txt with battle_athena.conf option [RoVeRT] - * fixed @charzeny bug - * translated help.txt to english anong with a few other files [RoVeRT] -12/29 - * added umbala maps to map_athena.conf [RoVeRT] -12/26 - * added Skill_range based on level, and partially working AutoGuard [Moonsoul] - * added Correction of Whip and Instrument Damage Again [Sara-Chan] -12/25 - * Spear Quicken Correct Graphics,Fixed Magnum Break (Which Fixes All Other - Splash skills), and Fixed Brandish Spear [AppleGirl] - * Updated Command For @SkillAll Added Atcommand_athena.conf [RoVeRT] -12/24 - * Added Side Effects for multiple skills for 2-2 classes [AppleGirl] -12/23 - * Added GM Command Called @Skillall [RoVeRT] - * @skillall to skill-up all your current skills [RoVeRT] - * @hide does hide you from all monsters [RoVeRT] - * fire wall limited to 5 per map [RoVeRT] - * to turn on PVP without @pvpon and to disable flywing search for mapflag [RoVeRT] - * no luck with @morph at this time yet [RoVeRT] - * splash attack added but still kinda buggy [RoVeRT] - * Added in Dancing and Song Playing for Bard and Dancer [AppleGirl] - * Added Skill Arrow Check For Archer Skills [AppleGirl] - * Added Skill Status Recovery [AppleGirl] - * Added Skill Bard and Dancer Skills Last Longer [AppleGirl] - * Added Skill Grimtooth does splash damage [AppleGirl] - * Added Skill Steal Fixed and Snatcher [AppleGirl] - * Added Skill SonicBlow only works with Katars Now [AppleGirl] -12/22 - * Added Skills Shield Boomerang, Shield Charge, and Defender [AppleGirl] diff --git a/doc/Readme-jap b/doc/Readme-jap deleted file mode 100644 index ce744a9..0000000 --- a/doc/Readme-jap +++ /dev/null @@ -1,17507 +0,0 @@ --------------------- -//1032 by (凸) -・1031で何故か削除されていたbuildin_getitemname()を復活 -・バグスレなどに出た修正を反映 -・その他細かい修正 - - (map/) - clif.c - clif_disp_onlyself() NULLチェック追加 - map.c - map_nick2sd() nickがNULLだとすぐNULLを返すように変更 - mob.c - mob_setdelayspawn() NULLチェック変更 - mob_delete() 修正 - npc.c - npc_parse_warp() 修正 - script.c - buildin_getitemname() 復活 - ----------------------------------------- -//1031 by huge -・NPCのscriptに、makepetを追加。 - makepet 卵ID; で、ペットを作成します。 -・NPCのscriptに、getexpを追加。 - getexp Base,Job; で、それぞれの経験値を増やします。 -・ペットの卵をNPCのdelitemで消したりshopで売った時、ペットセーブデータから削除するよう修正。 -・ディボーション成功条件修正。(未確認) -・経験値表示を可能にしてみました。confにて設定してください。 - - (conf/) - battle_athena.conf 修正 - (doc/) - conf_ref.txt 修正 - script_ref.txt 修正 - (map/) - battle.c - battle.h - disp_experience 追加 - clif.c - clif.h - clif_disp_onlyself() 追加 - pc.c - pc_gainexp() 修正 - script.c - buildin_delitem() 修正 - buildin_makepet() 追加 - buildin_getexp() 追加 - npc.c - #include 修正 - npc_selllist() 修正 - skill.c - skill_castend_nodamage_id() 修正 - - --------------------- -//1030 by (凸) -・map_athena.confに新婚島ザワイをコメントアウトして追加 -・クローンスキルで覚えたスキルを自動セーブごとに忘れていたのでとりあえずログオフ時にのみ忘れるように変更したつもり -・mobskill_castend_posの無害nullpoチェックを変更 -・Emotionの設定がないMobがスキルを使用するときに/!を出していたのを修正 -・バグスレに投げたtrade.cを添付。とりあえず相手が所持できる種類の限界を超えた場合は渡さずに元に戻すように変更 - - (conf/) - map_athena.conf ザワイ追加 - (doc/) - client_packet.txt パケット長の更新 - (map/) - map.c - map_quit() 終了時にクローンスキルで覚えたスキルを忘れるように変更 - mob.c - mobskill_castend_pos() nullpoチェック変更 - mob_readskilldb() 修正 - pc.c - pc_makesavestatus() クローンスキルを忘れるのをmap_quitに任せた - trade.c - trade_tradecommit() 所持できる種類以上を取引した場合にアイテムが消えないように - --------------------- -//1029 by (凸) -・20040619RagexeHC_jp.rgzの0x204と0x20bパケットに対応 -・charとloginも知らないパケットが来たらパケットダンプを出力するようにclif.cからコピペ - - (doc/) - client_packet.txt 新パケット追加 - (char/) - char.c - parse_char() 0x20b対応 - (login/) - login.c - parse_login() 0x204対応 - --------------------- -//1028 by (凸) -・ウンバラ以降、Mobがスキルを使用するときにエモーションを出すようになったので、mob_skill_dbを拡張 - サンプルでオークウォーリアーが喫煙すると「/…」を出すのとオークレディが速度を使うと「/ちゅ」を出します -・アイテム682,683を使用すると30秒間ATKやMATKが増えるらしいのでそれっぽく -・job_db2.txtに謎の行が2行あったのを削除 -・範囲魔法などでスキルユニット相手にステータス変更をかけようとした場合にnullpoが出たのを修正 - - (db/) - const.txt SC_INCATK SC_INCMATK追加 - item_db.txt ↑を682,683に追加 - job_db2.txt 謎の2行を削除 - mob_skill_db.txt Emotion追加 - (map/) - mob.c - mobskill_use() スキル使用時にエモーションを出すように変更 - mob_readskilldb() Emotionを読み込むように変更 - mob.h 変更 - pc.c - pc_calcstatus() 変更 - skill.c - - skill_status_change_end() 変更 - skill_status_change_start() 変更とNULLチェック修正 - skill.h 変更 - --------------------- -//1027 by Ni+S -・getitemname関数追加 -・スクリプトにgetitemname関数を追加 -・itemidより、jnameを文字列で返します -・詳しくはscript_ref.txtで。 - - script.c - getitemname()追加 - ----------------------------------------- -//1026 by (凸) -・1023で入れてなかったclif.hを同梱 -・バイオプラントとスフィアーマインで出したmobを倒すとmob_timer_delete()でnullpoが出る問題を解決したつもり -・バグ報告スレッド part6 >>63 Destさんのscript.c修正を取り込み - - (map/) - clif.h 変更 - map.h 変更 - mob.c - mob_changestate() 変更 - skill.c - skill_castend_pos2() 変更 - mob_spawn() 変更 - do_init_mob() add_timer_func_listにmob_timer_deleteが無かったので追加してみた - script.c - script_load_mapreg() 変更 - ------------------------- -//1025 by Sel -・ロードナイトのジョブ補正が間違っていたのを修正 -・オーラブレード効果時間を修正 -・オーラブレード武器制限を素手以外全てに修正 -・コンセントレーション武器制限を両手槍のみから片手槍+両手槍へ修正 -・トゥルーサイト効果時間を修正 -・ファルコンアサルト武器制限を解除、素手を含めた全てで使用可能に - - (db/) - job_db2-2.txt 変更 - skill_cast_db.txt 変更 - skill_require_db.txt 変更 --------------------- -//1024 by mare -・ファーマシー材料の変更、製造可能薬品の追加 - 6/8日本鯖にきたものと同じにしました - - (db/) - produce_db.txt 変更 - ----------------------------------------- -//1023 by (凸) -・1022でエンバグしたnpc_parse_script()を戻し -・スパイラルピアースの重量追加ダメージ計算式をちょっと変更 -・魔法力増幅の計算式をちょっと変更 -・テンションリラックスが座って使うのではなく使うと座るという情報を見かけたので変更 -・↑に伴いskill_requireのsitting条件廃止 -・バーサークをGvGで使用できないように変更 - - (db/) - skill_cast_db.txt 変更 - skill_require_db.txt 変更 - (doc/) - db_ref.txt 修正 - (map/) - battle.c - battle_calc_pc_weapon_attack() 変更 - clif.c - clif_sitting() 追加 - clif_parse_ActionRequest() 変更 - npc.c - npc_parse_script() 修正 - pc.h 変更 - pc.c - pc_calcstatus() 変更 - pc_natural_heal_hp() 変更 - pc_setstand() 追加 - skill.c - skill_castend_nodamage_id() テンションリラックスを使うと座るように - skill_check_condition() ST_SITTING廃止 - skill_use_id() バーサークをGvGで使用できないように - skill_status_change_timer() テンションリラックスは10秒ごとにSPを12消費 - skill_status_change_start() テンションリラックス変更 - skill_readdb() sitting廃止 - skill.h 変更 - --------------------- -//1022 by (凸) -・NULLチェック変更 -・login,char,map終了時に開放されていなかったメモリを微妙に開放する努力をしてみた -・スパノビ爆裂波動実装、クリティカル+50 -・スパノビボーナスを変更、最初から一度も死んでないJobLv70にAll+15、BaseLv99にMHP+2000 - - (doc/) - client_packet.txt S 01ed追加 - (char/) - do_final() 変更 - do_init() 変更 - (login/) - do_final() 追加 - do_init() 変更 - (map/) - atcommand.c Destさんの変更を取り込み - battle.c 同上 - chat.c NULLチェック変更 - chrif.c NULLチェック変更 - clif.c NULLチェック変更 - clif_parse() 変更 - clif_parse_sn_explosionspirits() 追加 - clif_parse_sn_doridori() 名前変更 - guild.c NULLチェック変更 - intif.c NULLチェック変更 - itemdb.c NULLチェック変更 - map.c NULLチェック変更 - do_final() 変更 - mob.c NULLチェック変更 - npc.c NULLチェック変更 - npc_parse_script() buf開放忘れ?を開放 - party.c NULLチェック変更 - path.c NULLチェック変更 - pc.c NULLチェック変更 - pc_calcstatus() スパノビ変更 - pet.c NULLチェック変更 - storage.c NULLチェック変更 - trade.c NULLチェック変更 - vending.c NULLチェック変更 - --------------------- -//1021 by Kalen -・プロンテラ冠婚品NPCにてタキシード販売 -・Umbalaのワープ見直し - D2Fのワープを本鯖使用に変更。重複ポイント修正 -・UmbalaNPC修正 - ラベルを使用しなくいい場所は極力削除(-) - セーブポイント修正 - バンジージャンプ台追加 - 骸骨門追加 - 分解、合成処理追加 - カプラ、案内要員をあるべき場所へ移動。 - ※一部Emoについて、癌呆自身が逆に取り違えているみたいなので独自で変えました。 - 見てもらえば分かりますが18と28を逆にするとNPCの会話内容に合うEmoが出たので - クエストフラグの条件追加 - これによりすでに終えている場合でも途中になる可能性があります。 -・スパノビ転職NPC追加 - 凸さんのログを基に作成しました。 -・アルケミストギルドのノビの場合の対応修正(凸さんからのログより) -・結婚NPC追加 - ただし、まだテスト段階です。問題点があるため結婚不可能です。 - (/script) - (/warp) - npc_warp_umbala.txt - (/npc) - (/town) - npc_town_umbala.txt - npc_town_kafra.txt - npc_town_guide.txt - npc_town_prontera.txt - (/quest) - npc_event_marriage.txt(新・テスト) - (/job) - npc_job_alchemist.txt - npc_job_supernovice.txt(新) - --------------------- -//1020 by (凸) -・nullpoの変更に対応してmap_athena.confの設定削除&skill.c書き換え -・座っているとHPRとSPRが通常の半分で発動したのを修正 -・スパノビが一定条件(クライアント依存)で/doridoriするとSPR回復量が倍になるように変更 -・結婚式用のエフェクトをスクリプトからwedding命令で発生させることが出来るようした -・合奏を開始したPCは合奏中に終了できないようにしたつもり(未確認) - - (conf/) - map_athena.conf nullpo_check削除 - (doc/) - client_packet.txt 更新 - conf_ref.txt nullpo_check削除 - (map/) - map.c - map_config_read() nullpo_check削除 - map.h 同上 - skill.c NULLチェック再度総入れ替え - clif.c - clif_wedding_effect() 追加 - clif_parse_QuitGame() 合奏開始者は合奏中に終了できないように変更 - clif_parse_doridori() 追加 - clif_parse() doridori追加 - clif.h 変更 - pc.c - pc_authok() doridori初期化追加 - pc_natural_heal_hp() 座っているときのHPR時間修正 - pc_natural_heal_sp() 座っているときのHPR時間修正、doridori追加 - script.c - buildin_wedding_effect() 追加 - - --------------------- -//1019 by Dest -・nullpoモジュールにコーディングミス発見/修正 -・同、voidな関数から呼ばれた時のnullpo_retv_f()を追加 -・同、条件コンパイルに対応 - - (common/) - nullpo.c - nullpo_info_core() コーディングミス修正 - nullpo.h - NULLPO_CHECKフラグによる条件コンパイル追加 - nullpo_retv_f() 追加 - --------------------- -//1018 by chloe -・ウンバラモンスターを追加 - - (script/mob/) - npc_monster.txt 変更 - 各ウンバラマップにMob配置 - (db/) - mob_db.txt 変更 - 1495,STONE_SHOOTER,フレイムシューター 修正 - 1511,AMON_RA,アモンラー 修正 - --------------------- -//1017 by (凸) -・バグ報告スレッド part6 >>46 Destさんのnullpoモジュールを追加&voidな関数から呼ばれた時のnullpo_retv()を追加(とりあえずskill.cのNULLチェックだけ入れ替え) -・同>>39 Selさんから報告があったコンセントレーションを修正 -・仕様について語り合うスレッド >>33 Kalenさんの情報をclient_packet.txtに反映 -・本鯖相違スレッド part3 >>24 M @zqcM6jBwさんの情報を↑ -・同>>30 はちさんの修正を反映 - - (conf/) - map_athena.conf nullpo_check追加 - (db/) - item_db.txt 結婚指輪を武器-アクセサリに変更&最新版 - (doc/) - client_packet.txt 更新 - conf_ref.txt nullpo_check追加 - (common/) - Makefile 変更 - nullpo.c 追加 - nullpo.h 追加 - (map/) - Makefile 変更 - map.c - map_config_read() nullpo_check追加 - map.h 同上 - skill.c NULLチェック総入れ替え - skill_status_change_start() コンセントレーション修正 - skill_castend_nodamage_id() テレポート修正 - clif.c - clif_skill_setunit() コメント修正 - pc.c - pc_calcstatus() コンセントレーション修正 - --------------------- -//1016 by な。 -・Athena雑談スレッドPart4 42 かる氏作のウンバラNPCを追加 - - (script/npc/town/) - npc_town_umbala.txt追加 - イベントデバッグ様(230〜256行目)はコメントアウト - (conf/) - map_athena.conf town に npc: script/npc/town/npc_town_umbala.txt 追加 - --------------------- -//1015 by (凸) -・リムーブトラップを本鯖仕様とAthena仕様で選べるようにした -・スパノビにAll+10する条件が良く分からなかったけど最初から+10じゃないのは確かなのでとりあえずBase99で一度も死んでなければという条件に変更 -・ダンス中に吹き飛ばされてもエフェクトは移動しないそうなので変更 -・@go 13微調整 - - - (conf/) - battle_athena.conf skill_removetrap_type追加 - (doc/) - client_packet.txt 本鯖相違スレッド part3 23 M @zqcM6jBwさんの情報を追加 - conf_ref.txt skill_removetrap_type追加 - (map/) - atcommand.c - atcommand_go() ウンバラの出現位置微調整 - battle.c - battle_config_read() skill_removetrap_type追加 - battle.h 同上 - pc.c - pc_calcstatus() スパノビAll+10条件変更 - skill.c - skill_blown() ダンス中の吹き飛ばしを元に戻した - skill_castend_nodamage_id() リムーブトラップ仕様変更 - - -------------------- -//1014 by (Pepermint) -I fixed again the problem if you put minus sign(-) in front of digits, -the error comes up when you puchase a item. -When you put a minus sign(-), the error sign will be changed shrotage of -amount as original server dose. - -I tested with it in ver. 1013, it was working - --------------------- -//1012 by (凸) -・help.txtにある@goの説明から13と14を削除 - 機能は消えてないので使えることは使えますが、helpに載せるのはjROに来てからということで -・cast_db.txtをskill_cast_db.txtに改名 -・ついでにmake cleanでGNUmakefileも消してみることにする -・u-0さんの検証などを総合してダンスユニット関連を変更 - 演奏・ダンス中のハエはユニット付きで飛ぶそうです - 演奏・ダンス中にワープポイントに乗ったら状態が解除されるようです - 合奏中に片方がハエ飛びしたらエフェクトは元の場所に残り、飛んだ先では合奏状態が継続して動けない&時間ごとにSP消費するようです -・PC_DIE_COUNTERがスクリプトから変更された時にすぐに反映されるように変更 - - (conf/) - help.txt @go説明変更 - (db/) - skill_cast_db.txt 改名 - (map/) - pc.c - pc_setpos() ダンス中断のタイミング変更 - pc_setglobalreg() PC_DIE_COUNTER特別処理追加 - skill.c - skill_castend_id() NULLチェック変更 - skill_stop_dancing() マップ移動などでの挙動を変更 - skill_readdb() skill_cast_dbに改名 - skill_blown() 飛ばされたらダンス移動 - npc.c - npc_touch_areanpc() ワープポイントに乗ったらダンス解除 - --------------------- -//1011 by パイン -・パーティ要請やギルド要請を出しているときに他の要請を拒否る処理を追加 - battle_athena.confで切り替えが出来るようになっています。 -・make clean で事が足りるので、objectdel.batを消去 - - (map) - clif.c - clif_party_invite()変更(nullpoの文言違ってました) - guild.c - guild_invite()変更 - party.c - party_invite()変更 - battle.c - battle_config_read()変更 - battle.h変更 - trade.c - trade_traderequest()変更 - --------------------- -//1010 by (凸) -・gcc 2.95対策 -・スパノビの1度死ぬまでAll+10をスクリプト変数で実装してみる試み - PC_DIE_COUNTER 死ぬと+1、転職すると0になります - ↑はキャラクタ永続なスクリプト変数なのでNPCで参照&再設定とか比較的楽かも - - (map/) - chrif.c - chrif_divorce() gcc2.95対策 - skill.c - skill_attack() gcc2.95対策 - skill_unit_move_unit_group() gcc2.95対策 - map.h map_session_dataにdie_counterを追加 - npc.c - npc_click() nullpoメッセージを修正 - pc.c - pc_setrestartvalue() nullpoメッセージを修正 - pc_authok() die_counter初期化の追加 - pc_calcstatus() die_counter=0のスパノビはAll+10 - pc_damage() PC_DIE_COUNTER設定 - pc_jobchange() PC_DIE_COUNTER設定 - pc_readparam() gcc2.95対策 - pc_divorce() gcc2.95対策 - pc_get_partner() gcc2.95対策 - --------------------- -//1009 by ぴざまん -・ダンス移動軽量化実装 - battle_athena.confで切り替え可能です。詳しくはconf_refを - オリジナルアップデートの為、デフォルトではoffにしています - また、この軽量化モードは回線負荷を大幅に削減できる(つもり)ですが、 - その分サーバー側の処理が重たくなります(といってもある程度のCPUがあれば全然問題にならない程度の負荷ですが) -・結婚システム/結婚スキル実装 - 結婚指輪の特別扱いが未実装です(落とせたり取引に出せたりします) - 離婚のみ未テストです。 -・結婚用スクリプト(marriage、divorce)追加。 - ・marriage <partner_name> - <partner_name>: 結婚相手の名前 - 戻り値: 成功:1 失敗:0 - 結婚処理を行います。対象は話し掛けたプレイヤーと<partner_name>のキャラクターで、どちらかが既婚の場合は失敗します。 - 1回のmarriageスクリプトで新郎→新婦と新婦→新郎の結婚処理を同時に行います。 - また、このスクリプトで結婚指輪は与えられません。 - ・devorce - 引数無し - 戻り値: 成功:1 失敗:0 - 離婚処理を行います。対象は話し掛けたプレイヤーで、未婚の場合は失敗します。 - marriageスクリプトと同様に互いの離婚処理を同時に行います。 - また、このスクリプトが成功すると自動的に対象キャラクターの結婚指輪は剥奪されます。 - - どちらのスクリプトの処理も、2人共ログインしていないと成功しません。 - - (map/) - pc.c - pc_ismarried()、pc_marriage()、pc_divorce()、pc_authok()変更 - pc_get_partner() 追加 - map.c - map_quit() 変更 - skill.c - skill_use_id()、skill_castend_nodamage_id() 変更 - skill_unitsetting()、skill_unit_onlimit() 変更 - script.c - buildin_marriage()、buildin_devorce() 追加 - pc.h 変更 - battle.h 変更 - --------------------- -//1008 by ぴざまん -・GMセッション隠し実装(未テスト) - GMアカウントのキャラクターを@who等で表示するかどうか設定できます。 - 詳しくはconf_ref.txtを参照してください。 -・結婚システム仮実装 - char-map間通信のみ実装です。まだ結婚することは出来ません。 - 尚、このパッチからathena.txtのバージョンが変わります。 - データの互換性は保ったつもりですが、念の為バックアップを取っておく事を強く推奨します。 - - (map/) - clif.c - clif_countusers() 変更 - battle.c - battle_config_read() 変更 - atcommand.c - atcommand_who() 変更 - pc.c - pc_ismarried()、pc_marriage()、pc_divorce() 追加 - chrif.c - chrif_divorce() 追加 - chrif_parse() 変更 - (char/) - char.c - char_divorce() 追加 - char_delete()、mmo_char_fromstr()、mmo_char_tostr() 変更 - --------------------- -//1007 by (凸) -・NULLチェックの見直し - - (map/) - clif.c - clif_send() 変更 - skill.c - skill_delunit() 変更 - --------------------- -//1006 by (ruhu) -・@goに洛陽とニフルヘイム追加 - - (conf/) - help.txt ニフルヘイム、洛陽追加 - (map/) - atcommand.c - atcommand go() ニフルヘイム、洛陽追加 --------------------- -//1005 by (凸) -・NULLチェックの見直しと追加、大量に変更したので問題が出る可能性が大です -・ウンバラ分割パッチが配布されたので@go 12にウンバラを追加 -・ロードナイト バーサークをちょっとそれっぽく(ASPD増加などは未実装) -・クラウン・ジプシー 月明りの泉に落ちる花びらの使用条件を合奏と同じに変更(効果等は未実装) -・ブレッシングが本鯖ではステータスアップ→エフェクトだったのでそのように変更 -・本鯖相違スレッド part2 >>145 zzzさんの報告を反映 -・同スレ >>143 plalaさんの報告を反映 - - (db/) - skill_require_db.txt 変更 - (conf/) - help.txt ウンバラ追加 - map_athena.conf ウンバラ関連のコメントアウトを解除 - (map/) - atcommand.c NULLチェック強化 - atcommand() @mapmoveなどで落ちる問題を修正 - atcommand_go() ウンバラ追加 - battle.c NULLチェック強化 - battle_calc_mob_weapon_attack() バーサーク時ダメージ150% - battle_calc_pc_weapon_attack() バーサーク時ダメージ150% - chat.c NULLチェック強化 - chrif.c NULLチェック強化 - clif.c NULLチェック強化 - clif_parse_ActionRequest() ダンス時の処理を若干変更 - clif_parse_GlobalMessage() バーサーク時は会話が出来ないように変更 - clif_parse_Wis() バーサーク時は会話が出来ないように変更 - clif_parse_PartyMessage() 同上 - clif_parse_GuildMessage() 同上 - clif_parse_TakeItem() バーサーク時はアイテムを取れないように変更 - clif_parse_DropItem() バーサーク時はアイテムを落とせないように変更 - clif_parse_UseItem() バーサーク時はアイテムを使えないように変更 - clif_parse_EquipItem() バーサーク時は装備できないように変更 - clif_parse_UnequipItem() バーサーク時は装備解除できないように変更 - clif_parse_UseSkillToId() バーサーク時はスキル使用ができないように変更 - clif_parse_UseSkillToPos() 同上 - clif_parse_UseSkillMap() 同上 - guild.c NULLチェック強化 - intif.c NULLチェック強化 - itemdb.c NULLチェック強化 - map.c NULLチェック強化 - map_quit() バーサーク時にログアウトするとHP 100/SP 0になるように変更 - mob.c - mob_attack() clif_fixmobpos()を送信しないように変更 - mob_timer() NULLチェック条件を変更 - mobskill_castend_id() 同上、バーサーク時スキルを使えないように変更 - mobskill_castend_pos() バーサーク時スキルを使えないように変更 - mobskill_use_id() 同上 - mobskill_use_pos() 同上 - npc.c NULLチェック強化 - party.c NULLチェック強化 - path.c NULLチェック強化 - pc.c NULLチェック強化 - pc_calcstatus() バーサーク時は速度UP&MHP3倍、メディテイティオのSP回復増加をSPRではなく通常回復にかかるようにした - pc_heal() バーサーク時は回復しない - pc_jobchange() 転職直後1歩動かないと服の色が反映されなかったのを修正 - pc_natural_heal_sub() バーサーク中はSPが自然回復しないように変更(HPは良く分からなかったので回復するようにしてある) - pet.c NULLチェック強化 - skill.c - skill_castend_nodamage_id() ブレッシング等のパケット順を変更、ストーンカースを不死には無効にした - skill_castend_map() しつこいくらいにバーサーク時にスキルを使えないように変更 - skill_check_condition() 同上 - skill_use_pos() 同上 - skill_use_id() 同上&月明りの泉に落ちる花びら追加 - skill_status_change_end() バーサーク時にはIAアイコンを消去するように変更 - skill_status_change_timer() NULLチェック条件を変更、月明りの泉に落ちる花びら時SP消費、バーサーク時HP100以上なら10秒あたり1%減らすように変更 - skill_status_change_start() バーサーク時にはIAアイコンを表示するように変更 - skill_delunit() NULLチェック条件を変更 - skill_check_condition_char_sub() 月明りの泉に落ちる花びら追加 - skill_check_condition_use_sub() 同上 - skill_is_danceskill() 同上 - skill_initunitgroup() 同上 - trade.c NULLチェック強化 - vending.c NULLチェック強化 - --------------------- -//1004 by (凸) -・NULLチェックでエンバグしていたところをいくつか修正と他のNULLチェック強化 -・skill.cでもnullpoを表示するように変更 - - (map/) - battle.c - battle_damage() NULLチェック強化 - battle_heal() 同上 - clif.c - clif_damage() 同上 - map.c - map_addflooritem() NULLチェック強化 - mob.c - mob_once_spawn() 余計なNULLチェックを削除 - mob_once_spawn_area() 同上 - mob_damage() 同上 - mob_counttargeted() 同上 - mobskill_castend_id() 同上 - mob_summonslave() メッセージ間違いを修正 - pc.c - pc_damage() NULLチェック強化 - skill.c ほぼ全部 NULL関連修正 - --------------------- -//1003 by (凸) -・jROクライアントで/account使用時に繋がらない原因の0x200パケット問題を修正 -・0x1c9パケットの穴埋めを引き続き継続中 -・一人で聖体や合奏を使用できる設定(player_skill_partner_check)を追加 - 一人で合奏を実行した場合には通常のダンスと挙動が同じになります -・プロボックは不死に対して発動しないように変更 -・FWの吹き飛ばし判定を変更 -・デリュージに水場判定を追加、聖水を作れるのを確認 -・ハイディングの有効時間が正しく機能するように修正 -・アスペルシオを不死に使用した場合、聖属性の40ダメージを与えるように変更 -・アスペルシオを不死以外のMOBに使用しても効果が無いように変更 -・合奏、ダンス、演奏中の経過時間によるSP消費を実装 -・報告のあったガーディアンがギルド未加入PCをターゲットしたらmapが落ちる問題の修正(ガーディアン実装当時からずっと落ちてた?) -・mob.c、storage.cのnullチェックを強化 - エラーで落ちるべきところを無理やり通常処理に戻しているので他で問題がでるかもしれません - その場合、コンソールに「関数名 nullpo」と表示されるので表示された場合は報告をお願いします - もしかしたら正常な処理でも表示されるかもしれませんが、その際も報告をお願いします - 本来エラー、実は正常、どちらにしてもこれが表示されるのはバグです - - (conf/) - battle_athena.conf player_skill_partner_check追加 - (db/) - skill_db.txt アスペルシオの属性を聖に変更 - (doc/) - conf_ref.txt player_skill_partner_check説明追加 - (login/) - login.c - parse_login() 0x200パケット対応 - (map/) - mob.c NULLチェックでほぼ全部 - storage.c NULLチェックでほぼ全部 - battle.h 変更 - battle.c - battle_calc_magic_attack() アスペルシオを追加、FWを変更 - battle_config_read() 設定追加 - clif.c - clif_getareachar_skillunit() 調査結果の反映 - clif_skill_setunit() 同上 - [1001と1002の間の変更点] - skill.c NULLチェックを沢山 - skill_castend_damage_id() アスペルシオ追加 - skill_castend_nodamage_id() アスペルシオ、プロボック処理変更 - skill_castend_id() アスペルシオ処理変更 - skill_check_condition_char_sub() player_skill_partner_checkに対応 - skill_check_condition_use_sub() 同上 - skill_use_id() 同上 - skill_check_condition() 同上&デリュージ対応 - skill_status_change_timer() ハイディング修正、ダンス演奏合奏中のSP消費実装 - skill_initunitgroup() ダンスSP消費用変更 - skill_status_change_start() 同上&プロボックをボスに効かないように(でもbattle.cで止めてるから通常ここまで来ない) - --------------------- -//1002 by ぴざまん -・ポータルバグ修正 -・スキル関係のNullチェック強化(by(凸)) - (map/) - skill.c - skill_castend_map() 修正 - --------------------- -//1001 by (凸) -・0x1c9でいくつかパケットを見比べて変化のないところを固定値で埋め込み(今後情報が集まると変わる可能性大) -・ダンス中はSPだけ回復しないように変更 -・聖体で相方のSPが10以下だと使用失敗にして使用したらSPを10減らしてみる(未確認) -・合奏のスキル使用パケットを若干変更 - - (map/) - clif.c - clif_getareachar_skillunit() 0x1c9の穴埋め開始 - clif_skill_setunit() 0x1c9の穴埋め開始 - pc.c - pc_natural_heal_sub() ダンス中はSPのみ回復しないように変更 - skill.c - skill_check_condition() 変更 - skill_check_condition_char_sub() 聖体は相方のSPチェックするように変更 - skill_check_condition_use_sub() 聖体は相方のSPを減らすように変更 - --------------------- -//1000 by ぴざまん -・0999の変更取り戻し -・トラップの巻き込み実装 -・イドゥンの林檎でNPCまで回復した(ように見える)問題修正(未テスト) -・デモンストレーションのエフェクト変更(こちらに明記) - (map/) - skill.c - skill_count_target() 追加 - skill_unit_onplace()、skill_trap_splash() 変更 --------------------- -//0999 by eAthena Dev Team (Yor's Fixes) -(login/) - added email for accounts -(char/) - added email for character deletion --------------------- -//0998 by (凸) -・battle.cで引数の存在を確認せずに値を見に行ってる関数をいくつか修正 -・ダンス中は座れないようにした(本鯖相違スレッド part2 >>114 DoTさん) -・ダンス中はHP、SPが回復しないように変更(同上) -・ダンス中は通常攻撃できないようにした(本鯖相違スレッド part2 >>116 ・・・さん) -・合奏中片方が落ちた場合、残ったほうで演奏を継続するようにした(同上) -・合奏中はアドリブ以外できないように変更(同上) -・合奏発動条件にダンス中じゃない&座っていないを追加(本鯖相違スレッド part2 >>118 ろろさん) -・阿修羅使用後にHPも回復しなかったのを修正 - - (map/) - battle.c - battle_counttargeted() 修正 - battle_get系 たぶん全部修正 - clif.c - clif_parse_WalkToXY() 合奏の判断方法の変更 - clif_parse_ActionRequest() ダンス中は殴らない座らないように変更 - map.c - map_quit() ダンス中断追加 - mob.c - mob_damage() skill_stop_dancingの引数増加による変更 - pc.c - pc_setpos() 同上 - pc_damage() 同上 - pc_equipitem() 同上 - pc_natural_heal_sub() ダンス中は自然回復しないように&阿修羅時はSPのみ回復しないように - skill.c - skill_castend_nodamage_id() skill_stop_dancingの引数増加による変更 - skill_status_change_start() 同上 - skill_check_condition_char_sub() 相手がダンス中や座っていても合奏できないように変更 - skill_check_condition_use_sub() 同上 - skill_use_id() 合奏の判断方法の変更&合奏中はアドリブ以外禁止に - skill_status_change_end() 合奏のダンス状態解除は相手のval4を0にするようにした - skill_is_danceskill() 戻り値変更 - skill_stop_dancing() 引数増加、合奏で片方だけ落ちたときの処理追加 - skill_delunitgroup() 合奏時のステータス変更処理を↑に移した - skill_clear_unitgroup() 自分のbl->idとユニットグループのgroup->src_idが違うときは削除しないように変更 - skill.h 変更 - --------------------- -//0997 by (凸) -・二人で合奏、三人で聖体を実装 - 合奏 バード・ダンサーが隣接したセルにいて同じスキルを持っている時に発動 - スキルレベルは両者のスキルレベルの中間 - 本鯖仕様が分からないけど斜め隣接もOK - 聖体 使用者のX軸で-1と+1の場所に一人ずつアコライトかプリーストがいる時に発動すると思う(未テスト) - 使用者 ○ アコプリ ● - OK ●○● - - NG ● - ○● -・トーキーボックスを使って設置時に座っていた時はスキル使用失敗にしてみた - - (db/) - item_db.txt 村正の呪い率を5%に(by e2さん) - (map/) - skill.c - skill_check_condition_char_sub() 追加 - skill_check_condition_use_sub() 追加 - skill_check_condition() 変更 - skill_use_id() 変更 - skill_initunitgroup() 変更 - skill_delunitgroup() 変更 - clif.c - clif_parse_UseSkillToPos() 変更 - --------------------- -//0996 by (凸) -・アドリブの5秒制限をcast_db.txtのupkeep_time2で制御できるように変更 -・村正で自分を呪わせるためにbonus2 bAddEff2を追加 -・呪われていて終了できない時にも「今は終了できません」が表示されるようにした -・ダンスエフェクト等移動時に効果の適用判断が移動前に行われていたのを移動後に変更&使わなくていい変数を廃止 - - (db/) - cast_db.txt - const.txt - item_db.txt - (doc/) - item_bonus.txt - (src/) - clif.c - clif_parse_QuitGame() 変更 - map.h addeff2,arrow_addeff2 追加 - pc.c - pc_calcstatus() 変更 - pc_bonus2() 変更 - skill.c - skill_additional_effect() 変更 - skill_check_condition() 変更 - skill_unit_move_unit_group() 変更 - --------------------- -//0995 by (凸) -・battle.pet_lootitemのデフォルトがyesになっていたのを修正 -・battle.pet_lootitemの適用をforeach前でやるように修正 -・ペットの初期化でpd->lootitemがある時しか初期化されていなかったのを修正 -・領域が移動して対象が領域から抜けても効果が解除されない問題を修正 -・アドリブはダンス発動から5秒以上経たないと使用できないようにした - - (map/) - pet.c - pet_data_init() 修正 - pet_ai_sub_hard() 修正 - pet_ai_sub_hard_lootsearch() 修正 - skill.c - skill_blown() 変更 - skill_unit_onlimit() エラーメッセージ修正 - skill_check_condition() 変更 - skill_initunitgroup() sd_data[SC_DANCING].val3にgettick() - skill_unit_move_unit_group_sub() 追加 - skill_unit_move_unit_group() 変更 - skill.h skill_unit_move_unit_group() 引数変更 - battle.c - battle_config_read() pet_lootitem=0に修正 - pc.c - pc_walk() 変更 - --------------------- -//0994 by huge -・battle.pet_lootitemが適応されていなかったのを修正。 -・ペットにパフォーマンスをさせた後、10秒間くらいは拾わせないように。 - - (map/) - map.h pet_dataにlootitem_timer追加。 - pet.c - pet_ai_sub_hard_lootsearch() 修正。 - pet_lootitem_drop() 修正。 - --------------------- -//0993 by (凸) -・一人で合奏だけど合奏スキル中は動けないように -・アンコール実装。直前に使ったダンススキルを半分のSPで使えます -・ダンス中に移動するとエフェクトも移動するようにした -・未実装のスキルが使われるとUnknown skillと表示されることがあるかもしれません -・Sageのキャストキャンセルで実は前のスキルを覚えていなかった問題の修正 - - (map/) - clif.c - clif_parse_WalkToXY() 変更 - map.h アンコール用変数の追加 - pc.c - pc_walk() - skill.c - skill_blown - skill_castend_nodamage_id - skill_unitsetting() 変更 - skill_unit_onplace() 罠で同じ処理をしているcaseをまとめた - skill_unit_onout() 使われてないunit2を削除 - skill_check_condition() 変更 - skill_use_id - skill_initunitgroup() 使ったダンススキルを変数に入れるようにした - skill_unit_move_unit_group() 追加 - skill.h 変更 - --------------------- -//0992 by nokia - -map_quitを修正してメモリを釈放する時何度もを釈放するためメモリの間違いが起こる問題を招く - - (map/) - map.c - map_quit() - --------------------- -//0991 by (凸) -・トーキーボックスを自分が踏んでも発動しない本鯖仕様に変更 -・スキル詠唱中とディレイ中はクライアントを終了できないようにしたけど、敵に攻撃されているときは終了できます(ごめんなさいっ!!) - - (map/) - clif.c - clif_parse_QuitGame() 変更 - skill.c - skill_unitsetting() 変更 - --------------------- -//0990 by ぴざまん -・一部のトラップを範囲攻撃に変更(巻き込みは未実装)。 -・mapflagにpvp_nocalcrankとpvp_nightmaredrop追加。 - ・<gatname><tab>mapflag<tab>pvp_nocalcrank<tab>dummy - PvPによるランキング計算をしないようにします。 - ・<gatname><tab>mapflag<tab>pvp_nightmaredrop<tab><item>,<type>,<per> - PvPにて死亡した場合、<per>の確率でアイテムをドロップします。 - <item>: ドロップするアイテムIDを指定します。randomと記述すると所持品からランダムにドロップします。 - <type>: ドロップするアイテムのタイプを指定します。inventory:所持品 equip:装備品 all:全部 - <per>: ドロップする確率です。万分率で指定します。 - (map/) - skill.c - skill_unit_onplace() 変更 - skill_trap_splash() 追加 - pc.c - pc_damage() 変更 - npc.c - npc_parse_mapflag() 変更 - map.h - map_dataにメンバ追加 - (conf/) - mapflag.txt - ナイトメアモードにドロップ設定追加 - --------------------- -//0989 by (凸) -・スプリングトラップを某所で見たSSを元に実装してみた。違ったら相違スレへ -・ディテクティングを某所で見た解説文を元に実装してみた。違ったら相違スレへ -・キャストキャンセル時のdelete_timerエラーに追加でスキルIDを表示するようにした。あわせて報告するとエラーの原因が分かるかも - - (map/) - skill.c - skill_castend_nodamage_id() 変更 - skill_castend_pos2() 変更 - skill_castcancel() 変更 - --------------------- -//0988 by (凸) -・トーキーボックスは常に足元に置けるように変更とKalenさんに貰った情報等を元にパケットを本鯖にあわせてみた -・ショックウェーブトラップに効果を追加したつもり(未確認) -・ブラストマインとクレイモアトラップを殴ると吹き飛ぶようにした -・リムーブトラップで罠(skill_require_dbで指定したアイテム)を回収できるようにした -・↑の実装により罠の時間切れで罠が出るオリジナル仕様はコメントアウト -・ブラストマインの効果時間が長いのを修正 - - (db/) - cast_db.txt - (map/) - battle.c - battle_check_target() 変更 - mob.c - mobskill_castend_pos() 変更 - skill.c - skill_additional_effect() 変更 - skill_blown() 変更 - skill_castend_nodamage_id() 変更 - skill_castend_pos2() 変更 - skill_unitsetting() 変更 - skill_unit_onplace() 変更 - skill_unit_ondamaged() 変更 - skill_castend_pos() 変更 - skill_unit_timer_sub() 変更 - --------------------- -//0987 by 胡蝶蘭 - -・ユーザー定義関数/サブルーティンに引数を指定可能に - 詳しくは script_ref.txt を参照 - - (map/) - scirpt.c - buildin_getarg()追加 - buildin_callsub(),buildin_callfunc(),run_func()修正 - (doc/) - script_ref.txt - 引数についての説明追加 - -・getguildname,getpartyname,getcastlename,strcharinfo修正 - C_STRで定数文字列(C_CONSTSTR)を返していた問題修正 - strcharinfoでギルド名などを所得する際、未所属だったときの問題 - - (map/) - script.c - buildin_getguildname(),buildin_getpartyname() - buildin_getcastlename(),buildin_strcharinfo() - --------------------- -//0986 by (凸) -・client_packetの記述から推察してトーキーボックスを実装してみたつもり - - (db/) - skill_db.txt - (map/) - clif.c - clif_talkiebox() 追加 - clif_parse_UseSkillToPos() 変更 - clif_parse() 変更 - clif.h 変更 - map.h 変更 - skill.c - skill_castend_pos2() 変更 - skill_unitsetting() 変更 - skill_unit_onplace() 変更 - --------------------- -//0985 by (凸) -・サーバーsnapshot -・/script/extensionに語り部を追加したり -・0984でAthena雑談スレッド part3>>92 Michaelさんの修正を取り込んでた -・バグ報告スレッド part5 >>45に転載されてた あやねさんの修正を取り込み -・バグ報告スレッド part5 >>54 rariさんのたぬき帽修正を取り込み - - (script/extension/) - npc_event_kataribe6.txt 追加 - npc_event_kataribe7.txt 追加 - (script/npc/) - quest/npc_event_hat.txt 修正 - job/npc_job_magician.txt 修正 - --------------------- -//0984 by (凸) -・セージのフリーキャストというスキルの存在を知らなかったので0983の変更を一部戻し -・アイテム更新したけど垂れ猫とインディアンバンダナが装備できない? -・マップフラグとモンスター配置を最新版に - - (db/) - item_db.txt - (conf/) - mapflag.txt - (script/mob/) - npc_monster.txt - (map/) - clif.c - clif_parse_WalkToXY() 修正 - --------------------- -//0983 by (凸) -・長い詠唱中に歩きまわれた気がするので修正 -・ペットルーレット回転中に対象が叩き殺されたらmap-serverが困るのを修正 -・プロフェッサー ライフ置き換えの手抜き処理をちょっとマシにした - - (map/) - clif.c - clif_parse_WalkToXY() 修正 - pet.c - pet_catch_process2() 修正 - skill.c - skill_castend_nodamage_id() 修正 - --------------------- -//0982 by (凸) -・転生スキルの〜 - ストーカー リジェクトソード 相手がPCの場合は剣じゃなければ跳ね返さない予定 - プロフェッサー メモライズ 12秒の固定キャストタイム、その後スキル使用のキャストタイムが3回だけ1/3になる - プロフェッサー ライフ置き換え HPを10%減らしてSPを増やす。減ったHPのエフェクトは無しにしてみた -・見切りと回避率増加のFlee上昇がステータス変化時にしか反映されていなかったのを修正 -・0981で自分以外は歩いたら服の色が戻ってしまうのをなんとかしたつもり - - (db/) - skill_require_db.txt - (map/) - battle.c - battle_calc_damage() 修正 - clif.c - clif_movechar() 修正 - clif_getareachar_pc() 修正 - pc.c - pc_calcstatus() 修正 - skill.c - SkillStatusChangeTable 変更 - skill_castend_nodamage_id() 変更 - skill_use_id() 変更 - skill_use_pos() 変更 - skill_status_change_timer() 変更 - skill_status_change_start() 変更 - skill.h 変更 - --------------------- -//0981 by (凸) -・転生スキルの〜 - ストーカー リジェクトソード 一定確率でダメージを半分にして減らした分を相手に跳ね返すようにした…が、跳ね返したダメージのエフェクト出ません -・服の色を変更&保存している場合にリログすると元の色に戻ってるように見える問題の修正 - - (db/) - skill_db.txt - (map/) - clif.c - clif_parse_LoadEndAck() 修正 - battle.c - battle_calc_damage() 修正 - skill.c - skill_status_change_timer() 修正 - skill_status_change_start() 修正 - --------------------- -//0980 by (凸) -・例によって転生スキルとモンク関連 - スナイパー シャープシューティング クリティカル率調整? - ハイウィザード ソウルドレイン MSP増量とMobを倒したときにSP(mobLv*(65+15*SkillLv)/100)回復。でも本当は範囲攻撃の場合は回復しないらしい? - ハイウィザード 魔法力増幅 使ったらMATKがSkillLv%増量。次のスキル使用時に元に戻る - モンク 気奪 ちょっと先取りして20%の確率で敵のLv*2のSPを吸収。成功したときはターゲットを取得するようにしてみた -・アイテム名をjROウンバラに準拠させてみたつもり - - (db/) - cast_db.txt - item_db.txt - (map/) - battle.c - battle_calc_pc_weapon_attack() 変更 - mob.c - mob_damage() 変更 - pc.c - pc_calcstatus() 変更 - skill.c - skill_castend_nodamage_id() 変更 - skill_use_id() 変更 - skill_use_pos() 変更 - skill_status_change_end() 変更 - skill_status_change_timer() 変更 - skill_status_change_start() 変更 - --------------------- -//0979 by (凸) -・転生スキルをちょっと調整 - ハイウィザード マジッククラッシャー 武器攻撃でBaseATK計算をMATK2でしてみる -・息吹を本鯖仕様風にHPとSPの回復タイマーを分けて座っていなくても動かなければタイマーが進むようにした -・阿修羅使用後にHPとSPが5分間自然回復しない本鯖使用風にした(csat_db.txtのupkeep_time2で調整可能) -・古いgccでskill_unit_timer_sub_onplace()あたりでコンパイルエラーになったのを修正 - - (db/) - cast_db.txt - (map/) - battle.c - battle_calc_pet_weapon_attack() 変更 - battle_calc_mob_weapon_attack() 変更 - battle_calc_pc_weapon_attack() 変更 - map.h - pc.c - pc_authok() 変更 - pc_walk() 変更 - pc_spirit_heal() 削除 - pc_spirit_heal_hp() 追加 - pc_spirit_heal_sp() 追加 - pc_natural_heal_sub() 変更 - skill.c - skill_additional_effect() 変更 - skill_castend_damage_id() 変更 - skill_status_change_start() 変更 - skill_unit_timer_sub_onplace() 修正 - --------------------- -//0978 by (凸) -・転生スキルを修正したり色々 - スナイパー ファルコンアサルト とりあえず飛ぶだけだと思ってください - スナイパー シャープシューティング ダメージ増加だけど1体だけ - クラウン・ジプシー アローバルカン ダメージ増加と9回攻撃 - ハイウィザード マジッククラッシャー エフェクトだけ - -・アイテム交換で重量の計算が違っていたのを修正 - (doc/) - client_packet.txt パケット長テーブル更新 - (map/) - battle.c - battle_calc_misc_attack() 変更 - battle_calc_pet_weapon_attack() 変更 - battle_calc_mob_weapon_attack() 変更 - battle_calc_pc_weapon_attack() 変更 - clif.c パケット長の定義を更新 - skill.c - skill_castend_damage_id() 変更 - trade.c - trade_tradeadditem() 修正 - --------------------- -//0977 by (凸) -・転生スキルを修正したり色々 - アサシンクロス メテオアサルト エフェクトが違う? - ロードナイト プレッシャー 必中ダメージにしてみた - ロードナイト オーラブレードの必中damage2が他でも適用されていたのを修正 - ロードナイト ゴスペル エフェクト出現位置の調整 - ハイプリースト アシャンプティオ 効果実装 - ハイプリースト メディテイティオ 効果実装 - ハイプリースト バジリカ SGみたいにMobが侵入しようとすると吹き飛ばされるようにした - ホワイトスミス カートブースト 効果実装 - ホワイトスミス メルトダウン エフェクトと状態異常時間だけ(実際の状態変化は無し) - ホワイトスミス クリエイトコイン 名前入りの金貨とか作れるだけ - ストーカー リジェクトソード エフェクトと状態異常時間だけ(実際の状態変化は無し) - クラウン・ジプシー マリオネットコントロール エフェクトと状態異常時間だけ(実際の状態変化は無し) - プロフェッサー フォグウォール エフェクトと有効時間だけ - スナイパー ウインドウォーク 速度上昇とQM、私を忘れないでがかかると解除されるようにした - スナイパー トゥルーサイト QM、私を忘れないでで解除されるようにしてみた -・トゥルーサイトの綴り間違いを修正 -・storage.cでコンパイル警告が出ないようにしたつもり - - (db/) - cast_db.txt - skill_db.txt - skill_require_db.txt - produce_db.txt - (map/) - battle.c - battle_get_str() 修正 - battle_get_agi() 修正 - battle_get_vit() 修正 - battle_get_int() 修正 - battle_get_dex() 修正 - battle_get_luk() 修正 - battle_get_flee() 修正 - battle_get_hit() 修正 - battle_get_critical() 修正 - battle_get_baseatk() 修正 - battle_get_atk() 修正 - battle_get_atk2() 修正 - battle_get_def() 修正 - battle_get_def2() 修正 - battle_get_speed() 修正 - battle_calc_damage() 修正 - battle_calc_pet_weapon_attack() 変更 - battle_calc_mob_weapon_attack() 変更 - battle_calc_pc_weapon_attack() 変更 - pc.c - pc_calcstatus() 修正 - skill.c - skill_get_unit_id() 修正 - skill_additional_effect() 修正 - skill_castend_nodamage_id() 修正 - skill_castend_pos2() 修正 - skill_unit_group() 修正 - skill_unit_onplace() 修正 - skill_unit_onout() 修正 - skill_castend_pos() 修正 - skill_check_condition() 修正 - skill_status_change_end() 修正 - skill_status_change_start() 修正 - skill_can_produce_mix() 修正 - skill_produce_mix() 修正 - skill.h 修正 - storage.c - storage_comp_item() 修正 - storage.h 修正 - --------------------- -//0976 by (凸) -・転生スキルを修正したり色々 -・準備だけして実装できてないスキルもあります - ロードナイト オーラブレード 多分こんな感じ? - ロードナイト パリイング 跳ね返すけど攻撃を1回止めるのは未実装 - ロードナイト コンセントレーション インデュア〜は良く分からないので放置 - ロードナイト スパイラルピアース 通常ダメージ増加と重量ダメージ増加と一応5回攻撃(なんか違う気がする) - ロードナイト ヘッドクラッシュ ダメージ増加とステータス変更? - ロードナイト ジョイントビート ダメージ増加とステータス変更? - アサシンクロス アドバンスドカタール研究 たぶんこんな感じ? - スナイパー トゥルーサイト たぶんこんな感じ? - スナイパー ウィンドウォーク たぶんこんな感じ?でも速度上昇とかと競合した時の処理は未実装 - スパイダーウェッブ とりあえずアンクルスネアと同じような感じ&回避率半減 - チャンピオン 狂気功 適当に増やしていたのをちゃんと増やすようにした -・出血状態と骨折状態の取り扱いがよくわかりませんっ!! - - (db/) - cast_db.txt - skill_db.txt - skill_require_db.txt - (doc/) - db_ref.txt - (map/) - battle.c - battle_get_str() 修正 - battle_get_agi() 修正 - battle_get_vit() 修正 - battle_get_int() 修正 - battle_get_dex() 修正 - battle_get_luk() 修正 - battle_get_flee() 修正 - battle_get_hit() 修正 - battle_get_critical() 修正 - battle_get_baseatk() 修正 - battle_get_atk() 修正 - battle_get_atk2() 修正 - battle_get_def() 修正 - battle_get_def2() 修正 - battle_get_speed() 修正 - battle_calc_damage() 修正 - clif.c - clif_parse_WalkToXY() 修正 - mob.c - mob_can_move() 修正 - mobskill_castend_pos() 修正 - pc.c - pc_calcstatus() 修正 - pc_checkallowskill() 修正 - skill.c - skill_get_unit_id() 修正 - skill_additional_effect() 修正 - skill_castend_nodamage_id() 修正 - skill_castend_pos2() 修正 - skill_unit_group() 修正 - skill_unit_onplace() 修正 - skill_unit_onout() 修正 - skill_castend_pos() 修正 - skill_check_condition() 修正 - skill_status_change_end() 修正 - skill_status_change_start() 修正 - skill_readdb() 修正 - skill.h 修正 --------------------- -//0975 by Sin -・0973で実装されたスクリプトによるBaseLv, JobLvの変更時に、 - ステータスポイントやスキルポイントを取得できるように修正。 - ※質問スレpart5 >>115 悩める人 さんのpc.cを参考にさせて頂きました。多謝。 - - (map/) - pc.c - pc_setparam() - case SP_BASELEVEL: 修正 - case SP_JOBLEVEL: 修正 --------------------- -//0974 by latte -・グランドクロスを本鯖に基づき修正 - アンデッド悪魔強制暗闇付与 - 反動ダメージ半減、モーションなし - MOB(PC)が重なったときのHIT数 - %UP系武器カード効果なし - 属性相性二重計算 - MOBダメージ表示白 - - 後半4項目は設定可 - -・戦闘基本計算を本鯖に基づき微修正(DEXサイズ補正、弓最低ダメ、PCサイズ補正) - -・完全回避 - スタン等で完全回避が発生しなかったのを修正 - AGIVITペナルティが完全回避の敵もカウントして計算されていたのを修正 設定可 - オートカウンターは未修正 - -・倉庫を閉じるとき、アイテムIDでソートするようにした - -・kalenさんのプロ1執事NPCスクリプトを改造して - 商業防衛値、投資金額、宝箱の数を本鯖に準拠(商業値は1~100) - 全砦に設置 - - (/script/npc) - aldeg_cas01.txt ... prtg_cas05.txt 修正 - (/script/npc/gvg) - aldeg_cas01.txt ... prtg_cas05.txt 追加 - tbox.txt 追加 - - (/conf) - battle_athena.conf - 6項目追加 - - (/map) - mob.c/mob.h - mob_attack() 修正 - mob_counttargeted_sub(),mob_counttargeted() 修正 - mobskill_use() 修正(↑の引数だけ) - pc.c/pc.h - pc_counttargeted_sub(),pc_counttargeted() 修正 - pc_attack_timer() 修正 - pet.c - pet_attack() 修正 - - map.h - pc_data, mob_data, map_data 変数1つ追加 - enum1つ追加 - map.c/map.h - map_count_oncell() 追加 skill.cでよかったかも・・・ - - skill.c - GX関連修正(skill_additional_effect(), skill_attack(), skill_castend_damage_id(), skill_unit_onplace()) - - battle.c 修正 - battle.h 修正 - - storage.c/storage.h - storage_comp_item() 追加 - sortage_sortitem(), sortage_gsortitem() 追加 - storage_storageclose(), storage_guild_storageclose() 修正 --------------------- -//0973 by 獅子o^.^o -・スクリプトのBASELEVEL,JOBLEVEL命令追加 - 例: set BASELEVEL,1; - 例: set JOBLEVEL,1; - (map/) - pc.c - pc_setparam() - case SP_BASELEVEL: 項目追加 - case SP_JOBLEVEL: 項目追加 - --------------------- -//0972 by (凸) -・転生スキルをエフェクトだけいくつか追加したり -・状態変化はそのうち誰かが - エフェクト(ステータス変化アイコン含む)のみ - SC_AURABLADE: /* オーラブレード */ - SC_PARRYING: /* パリイング */ - SC_CONCENTRATION: /* コンセントレーション */ - SC_TENSIONRELAX: /* テンションリラックス */ - SC_BERSERK: /* バーサーク */ - SC_ASSUMPTIO: /* */ - SC_TURESIGHT: /* トゥルーサイト */ - SC_CARTBOOST: /* カートブースト */ - SC_WINDWALK: /* ウインドウォーク */ - - (db/) - cast_db.txt - (map/) - skill.h - skill.c - SkillStatusChangeTable[] 項目追加 - skill_castend_nodamage_id() 項目追加 - skill_status_change_end() 項目追加 - skill_status_change_start() 項目追加 - --------------------- -//0971 by (凸) -・atcommand.hに残っていたjobchange2とかの残骸を削除 -・転生スキルをエフェクトだけいくつか追加したりチャンピオンはそれなりに追加したり - エフェクトのみ - ハイプリースト バジリカ(HP_BASILICA) - ホワイトスミス カートブースト(WS_CARTBOOST) - スナイパー トゥルーサイト(SN_SIGHT) - ジプシー 月明りの泉に落ちる花びら(CG_MOONLIT) - パラディン ゴスペル(PA_GOSPEL) - 追加ダメージ等なし - ロードナイト ヘッドクラッシュ(LK_HEADCRUSH) - ロードナイト ジョイントビート(LK_JOINTBEAT) - ロードナイト スパイラルピアース(LK_SPIRALPIERCE) - パラディン プレッシャー(PA_PRESSURE) - パラディン サクリファイス(PA_SACRIFICE) - それなり(コンボは繋がりますがディレイは適当、ダメージ追加はあるけどそれ以外の追加効果は無し) - チャンピオン 猛虎硬派山(CH_PALMSTRIKE) - チャンピオン 伏虎拳(CH_TIGERFIST) - チャンピオン 連柱崩撃(CH_CHAINCRUSH) - チャンピオン 狂気功(CH_SOULCOLLECT) - - (db/) - cast_db.txt - skill_db.txt - skill_require_db.txt - (map/) - atcommand.h ゴミ削除 - battle.c - battle_calc_pet_weapon_attack() 変更 - battle_calc_mob_weapon_attack() 変更 - battle_calc_pc_weapon_attack() 変更 - clif.c - clif_parse_UseSkillToId() 変更 - skill.c - skill_get_unit_id() 項目追加 - skill_attack() チャンピオンコンボ処理追加 - skill_castend_damage_id() 変更 - skill_castend_nodamage_id() 変更 - skill_castend_id() 変更 - skill_unitsetting() 変更 - skill_check_condition() 変更 - skill_use_id() 変更 - --------------------- -//0970 by (凸) -・ドレイクのウォーターボールが異常に痛い(121発食らう)のでLv5以上の場合は25発に制限 -・シグナムクルシスの計算式を14+SkillLvから10+SkillLv*2変更 -・ソースの気が向いたところに落書き -・DB関係をまとめて同梱 - - (map/) - battle.c コメント_〆(。。)カキカキ - skill.c skill_status_change_start() - (db/) - cast_db.txt - item_db.txt - mob_skill_db.txt - skill_db.txt - skill_require_db.txt - skill_tree.txt - --------------------- -//0969 by ぴざまん - -・白刃取り状態で片方が死亡した場合、片方の白刃取りが解除されない問題修正 -・battle_athena.confに項目追加 - ペット・プレイヤー・モンスターの無属性通常攻撃を属性無しにするか否かを設定できます - 詳しくはconf_refを。 -・@コマンド@idsearch実装 - ロードしたitem_dbから検索語句にマッチするアイテムとIDを羅列するコマンドです - 例えば「@idsearch レイ」と入力した場合、ブレイドやレイドリックカード等が引っかかります -・アシッドテラーとデモンストレーション実装 - 装備破壊は未実装です -・イドゥンの林檎の回復仕様を丸ごと変更。 - (map/) - battle.c - battle.h - 属性補正の修正やアシッドテラー・デモンストレーションのダメージ算出式追加等。 - battle_configに項目追加 - skill.c - skill_idun_heal()追加。foreachinareaで処理するように変更 - アシッドテラーとデモンストレーションの処理追加。 - atcommand.c - atcommand.h - @idsearch追加。 - --------------------- -//0968 by 胡蝶蘭 - -・キャラクターIDが使いまわされないように修正 -・キャラクター削除時、パーティー、ギルドを脱退するように修正 -・アカウント削除時、キャラクターと倉庫を削除するように修正 -・倉庫/ギルド倉庫削除時、倉庫内のペットを削除するように修正 - ・注意:ログインしているアカウントを削除した場合の動作は不明 - - (char/) - char.c - パケット2730の処理、char_delete()追加、削除処理修正など - int_storage.c/int_party.c/int_guild.c/int_party.h/int_guild.h - inter_party_leave(),inter_guild_leave()追加、 - inter_storage_delete(),inter_guild_storage_delete()修正など - (login/) - login.c - parse_admin()をアカウント削除時にパケット2730を送るように修正 - -・athena-start stop で停止させた場合、データが保存されない問題を修正 - killで送るシグナルをSIGKILLからSIGTERMに変更。 - どうしてもSIGKILLを送りたい場合は athena-start kill を使ってください。 - - athena-start - stop修正、kill追加 - --------------------- -//0967 by Asong -・モンスターの残影を実装。 - 通常モンスターはスキルによるフィルターがかからないので残像が出ません。 - PC型モンスターには残像が出ます。 -・モンスタースキル使用対象を追加。 - around5〜around8はターゲットの周辺セルを対象にします。 - - (map) - mob.c - mobskill_use() 修正 - mob_readskill() 修正 - mob.h 修正 - skill.c - skill_castend_pos2() 修正 - --------------------- -//0966 by (凸) -・サーバーsnapshot -・ディレクトリ構造を変更(common,login,char,mapは/src以下に移転) - それに伴うMakefile等のパス書き換え -・npc_turtle.txtをnpc_town_alberta.txtに統合 -・モンクのコンボに関するディレイを変更 -・battle_config.enemy_criticalのデフォルトをnoに変更 -・転生職等を無効にするenable_upper_classの追加 -・@joblvup,@charjlvlでJobレベルが最高のときに負数を指定してもレベルを下げられなかった問題を修正 - - (conf) - battle_athena.conf 修正 - (doc) - conf_ref.txt 修正 - (map) - atcommand.c - atcommand_joblevelup() 修正 - atcommand_character_joblevel() 修正 - battle.c - battle_calc_attack() 修正 - battle_config_read() 修正 - battle.h 修正 - pc.c - pc_calc_skilltree() 修正 - pc_calc_base_job() 修正 - pc_jobchange() 修正 - pc_readdb() 修正 - skill.c - skill_attack() 修正 --------------------- -//0965 by ぴざまん -・@mapexit実行時全セッションをkickするように変更。 -・白刃取り時に片方が倒れても、もう片方の白刃が解除されない問題修正。(未テスト) -・スティール情報公開機能実装。(未テスト) - スティールに成功すると、何をスティールしたのか - 画面内のPTメンバー全員に知らせる機能です。 - battle_athena.confのshow_steal_in_same_partyで設定できます。 - オリジナルアップデートの為、デフォルトはnoにしています。 -・イドゥンの林檎の回復効果実装。 - - (conf/) - battle_athena.confに項目追加。 - (map/) - atcommand.c - atcommand_mapexit() 修正。 - pc.c - pc_steal_item() 修正。 - pc_show_steal() 追加。 - skill.c - skill_unitsetting()、skill_unit_onplace() 修正。 - battle.c - battle_config_read() 修正。 - battle.h 修正。 - (doc/) - conf_ref.txt 抜けてたのを色々追加。 - --------------------- -//0964 by (凸) - -・この前追加したskill_tree2.txtを廃止したので削除してください -・skill_tree.txtのフォーマットを変更&Kalenさんなどの情報を元に転生ツリーの見直し -・それにともなってpc.cのファイル読み出し部分などを変更 -・Athena雑談スレッド part3 >>14 miyaさんの指摘があるまですっかり忘れていたatcommand_athena.confの修正を同梱 - - (conf/) - atcommand_athena.conf 修正 - (db/) - skill_tree.txt 修正 - skill_tree2.txt 廃止 - (map/) - map.h PC_CLASS_BASE等追加 - pc.c - pc_calc_skilltree() 修正 - pc_allskillup() 修正 - pc_readdb() 修正 - --------------------- -//0963 by (凸) - -・@jobchange2, @jobchange3廃止 @jobchangeに引数追加 @help参照 - 例: @jobchange2 10 → @jobchange 10 1 -・同様に@charjob2, @charjob3廃止 @charjobに引数追加 @help参照 - 例: @charjob2 10 ほげほげ → @charjob 10 1 ほげほげ -・同様にスクリプトのjobchange2, jobchange3命令廃止 jobchangeに引数追加 script_ref.txt参照 - 例: jobchange2 10; → jobchange 10,1; -・↑どれも追加された引数は省略可能です。なので、転生ノービスは現状のスクリプトで転生一次職に転職できます。 - 例: Novice High → @jobchange 10 → Whitesmith - Novice → @jobchange 10 → Blacksmith -・スクリプトから転生しているか判定するためにUpperを追加しました。Upper 0=通常, 1=転生, 2=養子 - Upper=0の時にBaseLevel=99なら転生させる〜とかそういうスクリプト誰か書いてください - その時に元の職業は記憶していないので永続変数とかで覚えさせて判定させないと転生後何にでも転職できちゃう? -・バイオプラントとスフィアマインで呼び出されるMobの名前を--ja--にしてmob_db.txtから読むようにした - - (conf/) - help.txt 修正 - (db/) - const.txt - (doc/) - help.txt 修正 - script_ref.txt 修正 - (map/) - atcommand.c - atcommand_jobchange() 修正 - atcommand_jobchange2() 削除 - atcommand_jobchange3() 削除 - atcommand_character_job() 修正 - atcommand_character_job2() 削除 - atcommand_character_job3() 削除 - map.h 修正 - pc.c - pc_readparam() 修正 - pc_jobchange() 修正 - pc.h 修正 - script.c - buildin_jobchange() 修正 - buildin_jobchange2() 削除 - buildin_jobchange3() 削除 - skill.c - skill_castend_pos2() 修正 - --------------------- -//0962 by (凸) - -・職業は0〜23で処理したいので転生職用のスキルツリー追加、eAthenaを参考に拡張 - っていうか韓国本サーバでの実装の資料が見当たらないので適当 -・sakexe.exeを解析してskill_db.txt変更、これもeAthenaを参考に拡張 - どれが本サーバで実装されているスキルか分かりませんっ!! -※スキルツリーが表示されたからといって使えるわけじゃありませんっ!! - - (common/) - mmo.h 定数修正 - (db/) - skill_db.txt 変更 - skill_require_db.txt 変更 - skill_tree2.txt 追加 - (map/) - skill.h 定数修正 - pc.c - pc_calcstatus() 修正 - pc_allskillup() 修正 - pc_calc_skilltree() 修正 - pc_readdb() 修正 - --------------------- -//0961 by 胡蝶蘭 - -・スクリプトにサブルーチン/ユーザー定義関数機能追加 - 詳しくはサンプルとscript_ref.txtを読んでください。 - 地味に大改造なので、スクリプト関係でバグがあるかもしれません。 - - (map/) - map.h/map.c - struct map_session_data にスクリプト情報退避用のメンバ追加 - map_quit()修正 - script.h/script.c - 色々修正(run_script(),run_func()が主) - npc.c - npc_parse_function()追加他 - (conf/sample) - npc_test_func.txt - ユーザー定義関数/サブルーティンのテストスクリプト - (doc/) - script_ref.txt - サブルーティンなどの説明追加 - --------------------- -//0960 by (凸) -・本鯖相違スレッド part2 >>62 KKさんのアンクルスネア修正を同梱 -・バグ報告スレッド part5 >>14-16 rbさんのバグ修正を同梱 -・For English User Forum >>15 Mugendaiさんの指摘で0x1d7を使うのはVal>255に修正(0xc3のValは1バイトだから0x1d7を使うのかと納得) -・pc_calc_base_job()を変更して元jobだけでなくノビか一次職か二次職(type)、通常か転生か養子(upper)を返すようにした - - (map/) - atcommand.c - atcommand_joblevelup() 修正 - atcommand_character_joblevel() 修正 - clif.c - clif_changelook() 修正 - pc.h 修正 - pc.c - pc_setrestartvalue() 修正 - pc_equippoint() 修正 - pc_isequip() 修正 - pc_calc_skilltree() 修正 - pc_calcstatus() 修正 - pc_isUseitem() 修正 - pc_calc_base_job() 修正 - pc_allskillup() 修正 - pc_damage() 修正 - pc_jobchange() 修正 - pc_equipitem() 修正 - script.c - buildin_changesex() 修正 - skill.c - skill_castend_nodamage_id() 修正 - skill_unit_onplace() 修正 - --------------------- -//0959 by (凸) -・help.txtがdocじゃなくてconfのが読み出されてた_| ̄|○ -・gamejokeを参考に転生二次職のステータス加重値をjob_db2-2.txtに記述 -・スクリプトにjobchange2とjobchange3を追加それぞれ転生職と養子職へ転職させる命令です - - (conf/) - help.txt 修正 - (db/) - job_db2.txt 修正 - job_db2-2.txt 追加 - (doc/) - help.txt 修正 - script_ref.txt 修正 - (map/) - pc.c - pc_calcstatus() 修正 - pc_readdb() 修正 - script.c - buildin_jobchange() 修正 - buildin_jobchange2() 追加 - buildin_jobchange3() 追加 - --------------------- -//0958 by (凸) -・転生職方面の実装を色々 -・重量制限は良く分からないので元の職業の値をそのまま使っています(モンク=チャンピオン等) -・装備品も同上、HPやSPのテーブルも同上なので、転生してもHPなどが増えないガッカリ仕様です - - (map/) - atcommand.c - atcommand_joblevelup() 修正 - atcommand_character_joblevel() 修正 - pc.c - pc_setrestartvalue() 修正 - pc_equippoint() 修正 - pc_isequip() 修正 - pc_calcstatus() 修正 - pc_isUseitem() 修正 - pc_calc_base_job() 追加 - pc_damage() 修正 - pc_jobchange() 修正 - pc_equipitem() 修正 - pc.h 修正 - script.c - buildin_changesex() 修正 - skill.c - skill_castend_nodamage_id() 修正 - --------------------- -//0957 by (凸) -・@charjob2と@charjob3を追加、関係としては@charjob⇔@jobchange、@charjob2⇔@jobchange2、(ry -・@mapexitを追加、map-serverを落とすコマンドですatcommand_athena.confでは99設定にされてますので使用には十分注意してください。 - - (map/) - atcommand.c - atcommand_character_job2() 追加 - atcommand_character_job3() 追加 - atcommand.h 修正 - (conf/) - atcommand_athena.conf 修正 - (doc/) - help.txt 修正 - --------------------- -//0956 by (凸) -・転生職仮実装(@jobchange2)、見た目と経験値テーブルだけです -・養子職仮実装(@jobchange3)、見た目だけです現状では経験値は転生二次職と同じというマゾ仕様 -※上記2点は転生職が実装されているクライアントでなければ実行するとエラー落ちするので注意!! - その後直接セーブデータを弄らないとキャラセレにも行けなくなります!! -・Athena雑談スレッド part2 >>149 稀枝さんの報告を元にガーディアンを修正 -・砦以外でガーディアンとかエンペリウムを殴るとmap-serverが落ちていたのも修正(未確認) -・スパノビのJobテーブルはFor English User Forum >>13 kingboさんのデータを元に修正 -・転生職の経験値テーブルはOWNを参照してBase99の経験値は不明だったので適当に設定 - - (map/) - atcommand.c - atcommand_jobchange() 修正 - atcommand_jobchange2() 追加 - atcommand_jobchange3() 追加 - atcommand.h 修正 - clif.c - clif_changelook() 修正 - pc.c - pc_nextbaseexp() 修正 - pc_nextjobexp() 修正 - pc_jobchange() 修正 - pc_readdb() 修正 - battle.c - battle_calc_damage() 修正 - mob_can_reach() 修正 - --------------------- -//0955 by huge -・ペットのルート機能。 - ・仕様はmobのルートに近い感じですが、射程を短くしてます。 - ・拾ったアイテムは、パフォーマンスをすると床に落とします。 - ・卵に戻したり、ログオフしたときはPCの手元に入るようにしました。(重量超過はドロップ) - ・拾える個数はルートmob同様の10個ですが、11個目は拾いに行きません。 - ・ルート権の問題から、アイテムにfirst_idが入っていて、それが飼い主以外だったら、何秒経とうと拾いません。(未確認) - ・それと、荷物持ちにされると可哀想なので、重量制限もつけました。これはconfで設定可能です。 -・atcommandで、@whereがうまく働いてなかったので修正(またウチだけかなぁ・・・) -・@memoでmemoする時は、mapflagを無視するように。 -・スフィアマインの名前だけ修正。 - - (conf/) - battle_athena.conf - pet_lootitem,pet_weight 追加 - (doc/) - conf_ref.txt 修正 - (map/) - atcommand.c - atcommand_memo() 修正 - atcommand_where() 修正 - battle.c - battle_config_read() 修正 - battle.h 修正 - map.c - map_quit() 修正 - map.h - pet_data{} 修正 - pc.c - pc_memo() 修正 - pet.c - pet_performance() 修正 - pet_return_egg() 修正 - pet_data_init() 修正 - pet_ai_sub_hard() 修正 - pet_lootitem_drop() 追加 - pet_delay_item_drop2() 追加 - pet_ai_sub_hard_lootsearch() 追加 - pet.h 修正 - skill.c - skill_castend_pos2() 修正 - --------------------- -//0954 by (凸) -・object_del.batで各server.exeも削除するようにした -・For English User Forum >>11 kingboさんの修正を取り込み -・バグ報告スレッド part5 >>10 Sinさんの修正を取り込み -・ついでに見かけたatcommand_character_joblevelの不具合を修正 -・@コマンドでジョブレベルを上げるときにスパノビはJob70まで対応(未確認) - - (/) - object_del.bat 修正 - (map/) - atcommand.c - atcommand_joblevelup() 修正 - atcommand_character_joblevel() 修正 - atcommand_character_baselevel() 修正 - - code by kingbo 2004/4/29 PM 06:15 - base on 0953 - now i sure it works well - (map/) - mob.c - mob_can_reach() fix - --------------------- -//0953 by (凸) -・mob_skill_db.txtの条件値に0以外入っていなかったのを訂正 -・gcc 2.95でコンパイルできるように訂正(by バグスレpart5 >>2 茜さん) -・↑やLinuxなどを考慮してstartやMakefileなどの改行をLFに変更 -・0952で出たコンパイル警告を出ないように修正 -・0952で更新されなかったconf_ref.txtを修正 - - (/) - start 改行コード変更 - athena-start 改行コード変更 - (db/) - mob_skill_db.txt 修正 - (doc/) - conf_ref.txt 修正 - (login/) - Makefile 改行コード変更 - (map/) - Makefile 改行コード変更 - atcommand.c - atcommand() 宣言位置修正 - atcommand_where() 宣言位置修正 - battle.c - battle_calc_pet_weapon_attack() 修正 - battle_calc_mob_weapon_attack() 修正 - battle_calc_pc_weapon_attack() 修正 - battle_calc_magic_attack() 修正 - clif.c - clif_skill_fail() 宣言位置修正 - guild.c - guild_gvg_eliminate_timer() 宣言位置修正 - mob.c - mob_damage() 宣言位置修正 - script.c - buildin_deletearray() 宣言位置修正 - buildin_getequipcardcnt() 宣言位置修正 - buildin_successremovecards() 宣言位置修正 - --------------------- -//0952 by CG -・confでDEFとMDEFの計算方法を選択できるように。 - - (conf/) - battle_athena.conf 変更 - (map/) - battle.c - battle_calc_pet_weapon_attack() 修正 - battle_calc_mob_weapon_attack() 修正 - battle_calc_pc_weapon_attack() 修正 - battle_calc_magic_attack() 修正 - battle.h 修正 - --------------------- -//0951 by (凸) -・サーバーsnapshot -・バグ報告スレッド part4 >>95 KAJIKENさんの修正を同梱 -・同 >>138 バグかな?さんの修正を同梱 -・Athena雑談スレッド part2 >>112 名無しさんのPVPナイトメアモードのアンダークロスマップワープポイントを同梱 -・同 >>96 稀枝さんのnpc_gldcheck.txtを同梱 -・スナップショットにsave/を入れるのをやめました。無い場合はathena-startが作ってくれます -・athena-startでlog/が無い場合に作るように変更 -・その他? - - (/) - athena-start 変更 - (db/) - mob_db.txt 変更 - (conf/) - map_athena.conf 変更 - (conf/extension/) - npc_gldcheck.txt 追加 - (conf/npc/) - npc_event_ice.txt 変更 - npc_job_alchemist.txt 変更 - npc_event_valentine.txt 変更 - npc_town_geffen.txt 変更 - npc_event_whiteday.txt 変更 - npc_event_potion.txt 変更 - npc_town_comodo.txt 変更 - (conf/warp/) - npc_warp_pvp.txt 追加 - --------------------- -//0950 by (凸) -・mob_dbのModeフラグに以下の物を追加 - 0x40(64) ダメージを1に固定(草やクリスタルなど) - 0x80(128) 攻撃を受けたときに反撃をする -・上記の変更のためmob_db.txtほぼ全部変更、mob_db2.txtを作っている人は - 草など1ダメ固定にはModeに64を足さないと普通にダメージ - その他MobはModeに128を足さないと反撃してこなくなるので注意 - - (db/) - mob_db.txt 修正 - (map/) - battle.c - battle_calc_pet_weapon_attack() - battle_calc_mob_weapon_attack() - battle_calc_pc_weapon_attack() - battle_calc_magic_attack() - mob.c - mob_once_spawn() - mob_attack() - mob_target() - mob_ai_sub_hard() - --------------------- -//0949 by ぴざまん - -・ステータス異常耐性全面修正。 - 耐性算出式全面修正。 - ステータス異常耐性100%のキャラクターには状態異常を行わないように修正。 -・ディスペルの仕様変更。 - 解除したらシステム上問題のあるステータス変化以外片っ端から解除するように修正。 -・フロストダイバーの仕様変更。 - 凍結率修正(マジスレテンプレ準拠)。 -・リカバリーの仕様変更。 - ノンアクティブモンスターに使用するとターゲットがリセットされるように修正。 -・クァグマイアの仕様がアレだったので修正。 - 演奏や属性場と同様にrangeで処理するように修正。 - DEX/AGI半減の影響が詠唱以外にも及ぶ様に修正。 -・スキルターゲット中に死んだ振りを使用してもスキルが回避できない問題修正。 -・白刃取りが動作しない問題修正(cast_dbが抜けてました)。 - (map/) - pc.c - pc_calcstatus()修正 - skill.c - skill_additional_effect()、skill_attack() 修正 - skill_status_change_start()、skill_unitsetting() 修正 - (db/) - cast_db.txt 修正。 - --------------------- -//0948 by 胡蝶蘭 - -・warpwaitingpcが正しくPCを転送できない問題を修正 -・スクリプトの読み込み時にエラーまたは警告が出る場合、警告音を鳴らすように。 - (流れたログを見ない人対策です) - - (map/) - script.c - buildin_warpwaitingpc()修正 - disp_error_message()修正 - -・atcommand.c修正 - ・atcommand_athena.confのmapmoveを読むように - ・@strなどの省略時の必須レベルを0に。 - ・@paramは使わないのでコメント化 - - (map/) - atcommand.c - 該当個所修正 - -・mobが最大15秒ほど移動しない場合がある問題修正 - ・手抜きでないmob処理で、移動しない時間が7秒以上続かないように修正 - - (map/) - mob.c - mob_ai_sub_hard()修正 - -・快速船員の伊豆港行きの判別式修正 (by ID:F8nKKuY) - (conf/npc/) - npc_town_comodo.txt - --------------------- -//0947 by (凸) -・取り巻きは取り巻きを召喚しないように修正 -・露天の販売価格の上限をbattle_athena.confで設定できるように修正 - - (conf/) - battle_athena.conf - vending_max_value追加 - (doc/) - conf_ref.txt 修正 - (map/) - skill.c - skill_castend_nodamage_id() 修正 - battle.c - battle_config_read() 修正 - battle.h 修正。 - vending.c - vending_openvending() 修正。 - --------------------- -//0946 by Kalen -・プロ北Warp見直し -参考:本鯖(1F,2F)らぐなの何か(3F) - (conf/warp/) - npc_warp.txt - -・語り部の2週3週追加(どうせ見ないと思いますが…) - (conf/npc/) - npc_event_kataribe.txt - --------------------- -//0945 by 胡蝶蘭 - -・NPCタイマーラベルデータが正しくインポートされない問題を修正 -・NPCタイマー初期値やタイマーIDが正しく初期化されない問題を修正 -・NPCのduplicateを行うとアクセス違反が起こる場合がある問題を修正 - - (map/) - npc.c - npc_parse_script修正 - -・パッチアップスレ4の87のpc.cとりこみ - (map/) - pc.c - カード重量制限を元に戻したもの - --------------------- -//0944 by huge -・ギルドの上納経験値の上限を、confで制限できるように。 -・露店の販売価格を10Mまでに制限。 -・カートの重量制限が一桁下がってたんですが、ウチだけですか?修正してみましたが。 - - (conf/) - battle_athena.conf - guild_exp_limit追加 - (doc/) - conf_ref.txt 修正 - (map/) - atcommand.c - 蘇生時のSP回復で、細かい修正。 - battle.c - battle_config_read() 修正 - battle.h 修正。 - guild.c - guild_change_position() 修正。 - pc.c - pc_calcstatus() 修正。 - vending.c - vending_openvending() 修正。 - --------------------- -//0943 by (凸) -・battle_athena.confでdead_branch_activeをyesにすると古木の枝で召喚されるモンスターがアクティブになるように変更 -・微妙に変更したclient_packet.txtを同梱 - - (conf/) - battle_athena.conf - dead_branch_active追加 - (doc/) - client_packet.txt 修正 - conf_ref.txt 修正 - (map/) - battle.c - battle_config_read() 修正 - battle.h 修正 - map.h 修正 - mob.c - mob_once_spawn() 修正 - mob_attack() 修正 - mob_target() 修正 - mob_ai_sub_hard_lootsearch() 修正 - mob_ai_sub_hard() 修正 - -・英語スレのkingboさんの変更を同梱 - code by kingbo 2004/4/16 PM 09:47 - - support guildcastle guardian - maybe still have problems..need to try - Good Luck Q^^Q - P.S: sorry my poor english ^^a - - (map/) - mob.c - mob_can_reach() fix - battle.c - battle_calc_damage() fix - - (conf/gvg/) - prtg_cas01_guardian.txt - --------------------- -//0942 by 胡蝶蘭 - -・アクセスコントロールで不正なメモリにアクセスする場合があるバグを修正 - (login/) - login.c - check_ipmask()修正 - -・スクリプトリファレンス少し追加と修正 - (doc/) - script_ref.txt - 修正 - --------------------- -//0941 by (凸) - -・e2さんの報告を元に召喚された手下のスピードを召喚主と同じにしてみる - - (map/) - battle.c - battle_get_speed() 修正 - mob.c - mob_spawn() 修正 - mob_summonslave() 修正 - --------------------- -//0940 by End_of_exam - -・ヒールやポーションピッチャーを使用しても回復しないバグを修正(0938〜)。 - - Thanks for Pepermint, reporting the bug that using PotionPitcher with - BluePotion was no effective. - (=ポーションピッチャー+青Pで効果がない事を報告してくれたPepermint氏に感謝) - - (map/) - battle.c - battle_heal() 修正 - --------------------- -//0939 by (凸) -・cutinパケットを0x145(ファイル名16文字)から0x1b3(64文字)に変更 -・ついでに雑談スレに上げたathena-startを同梱 - - (/) - athena-start saveファイルが無いときに作るように - (map/) - clif.c - clif_cutin() 本鯖パケット準拠に変更 - (doc/) - client_packet.txt 修正 - --------------------- -//0938 by ぴざまん - -・ポーションピッチャーで青ポを投げてもエフェクトだけだったバグ修正。 -・露店開設が特定のアイテム配置で失敗するバグ修正。 -・スクリプト関数getareadropitem実装。 - 指定エリア内のドロップアイテムをカウントする関数です - - 書式:getareadropitem <mapname>,<x0>,<y0>,<x1>,<y1>,<item>; - mapname:対象マップ名(例:prontera.gat) - x0とx1:対象X座標範囲 - y0とy1:対象Y座標範囲 - item:カウントする対象アイテム - - 戻り値:mapname内座標(x0,y0)-(x1,y1)の範囲内に落ちているitemの総個数 - 取得失敗時には-1を返します。 - ・itemの値はIDでもアイテム名("Red_Jemstone"とか)でもいいです。 - - (map/) - battle.c - battle_heal() 修正。 - vending.c - vending_openvending() 修正。 - script.c - ローカルプロトタイプ宣言修正。 - struct buildin_func[] 修正。 - buildin_getareadropitem()、buildin_getareadropitem_sub() 追加。 - --------------------- -//0937 by netwarrior - -- Fix Japanese remarks problem in 0936 -- Fix minor problem in battle_heal() - --------------------- -//0936 by Pepermint - -Retouch about problem of increase in quantity at the CART, -when enter the an minus quantity in the CLIENT. - -Retouch about problem of not recovery,use POTIONPITCHER skill. - - (map/) - battle.c - battle_heal() - - vending.c - vending_purchasereq() - --------------------- -//0935 by 胡蝶蘭 - -・内容の同じスクリプトNPCを何度も記述しなくても言いように修正 - ・NPC定義の"script"と書く部分を"duplicate(NPC名)"とすると、 - 該当のNPCとスクリプトを共有するように。NPC名は表示名ではなく - エクスポートされる名前を指定します。 - <例> -prontera.gat,165,195,1 duplicate(カプラ職員) カプラ職員2 112 - - ・共有元のNPCは同じマップサーバーに存在する必要があるため、 - 同じマップでない場合はduplicateすべきではない。 - ただし、NPCの位置を"-"にすることで、マップ上には存在しないが、 - マップサーバー内には存在するNPCを作成できるので、 - そのNPCを共有元にするのであればどのマップへも共有できる。 - <例> - -- script テスト::test1 112,{ // このNPCグラフィックIDは使用しない -// (略) -} -prontera.gat,165,195,1 duplicate(test1) テスト2 112 -geffen.gat,99,99,1 duplicate(test1) テスト3 112 - - ・上のマップに存在しないNPCはイベントにもすることができる。 - (どのマップサーバーからでも必ず呼び出せるイベントになる) - - (map/) - map.h - struct npc_label_list追加,struct npc_data修正 - npc.c - npc_parse_script()修正 - 不要になったラベルデータベース関連の関数を削除 - --------------------- -//0934 by ぴざまん - -・MOBの状態異常耐性がやたら高かったのを修正。 -・速度減少の仕様変更(成功率計算式変更・失敗時にはエフェクト無し)。 -・何時の間にか状態異常の継ぎ足し禁止がコメントアウトされていたので戻し。 -・ポイズンリアクトのアイコン表示が無くなっていたので修正(でも出るだけ…) -・白刃取り実装。 - - (map/) - battle.c - battle_weapon_attack() 修正。 - clif.c - clif_parse_WalkToXY()、clif_parse_ActionRequest() 修正。 - clif_parse_TakeItem()、clif_parse_UseItem() 修正。 - clif_parse_DropItem()、clif_parse_EquipItem() 修正。 - clif_parse_UnequipItem() 修正。 - mob.c - mob_can_move()、mob_attack()、mob_ai_sub_hard() 修正。 - mobskill_use_id()、mobskill_use_pos() 修正。 - mobskill_castend_id()、mobskill_castend_pos() 修正。 - pc.c - pc_attack_timer()、pc_setpos() 修正。 - skill.c - SkillStatusChangeTable[] 修正。 - skill_additional_effect()、skill_castend_damage_id() 修正。 - skill_castend_nodamage_id()、skill_check_condition() 修正。 - skill_status_change_start()、skill_status_change_end() 修正。 - skill_use_id() 修正。 - skill.h 修正。 - (db/) - cast_db.txt 修正。 - --------------------- -//0933 by 胡蝶蘭 - -・ウィザード転職所NPC仮実装 - ・eathenaのデータの翻訳、および某所の昔のデータを元に作ったので - 癌鯖とは微妙に異なってると思います。 - 「古い巻物」とか使えませんし。 - ・現行のjob_2nd.txtと一緒に読み込むと、NPCが重なるので、 - job_2nd.txtの該当スクリプトをコメント化してください。 - ただし、その場合はセージに転職させてもらえないので注意してください。 - - (conf/npc/) - npc_job_wizard.txt - 追加 - (conf/warp/) - npc_warp_job.txt - ウィザード転職所のワープをコメント化 - -・バグ修正 - ・gotoやmenuでラベルが見つからないときスクリプトの実行を中断するように. - ・1回のスクリプトの実行において、実行命令数が約8000を超えるか、 - gotoやmenuの実行回数が約500回を超えると実行を中断するように。 - ・関数/命令実行時にもエラーチェックを入れた - ・ギルド/パーティ/ペットの名前に日本語が使えない問題修正 - - - (char/) - int_guild.c/int_party.c - 名前問題修正 - (map/) - pet.c - 名前問題修正 - script.c - 修正 - --------------------- -//0932 by End_of_exam - -・0930でギルド倉庫の中身が消えるバグを修正。 - - (char/) - int_storage.c guild_storage_tostr() 修正。 - --------------------- -//0931 by (凸) -・サーバーsnapshot -・AthenaDB計画から更新のあった物を反映 -・atcommand_athena.confにstr等を追加 -・ワープポータルの本鯖相違点を修正 -・霧さんのaldeg_cas03〜05を同梱 -・pさんのnpc_event_kataribe.txt同梱 -・KAJIKENさんのnpc_warp_louyang.txt同梱 - - (db/) - item_db.txt 変更 - (conf/) - atcommand_athena.conf 変更 - map_athena.conf 変更 - (conf/gvg/) - aldeg_cas03.txt 変更 - aldeg_cas04.txt 変更 - aldeg_cas05.txt 変更 - (conf/mob/) - npc_monster.txt 変更 - (conf/npc/) - npc_event_kataribe.txt 追加 - (conf/warp/) - npc_warp_louyang.txt 追加 - (map/) - pc.c pc_memo() 変更 - --------------------- -//0930 by 胡蝶蘭 - - 既存の char/ にあるlock.cとlock.hは削除してください。 - これらは common/ に移動されます。 - -・スクリプト追加修正 - ・setarray(配列へリスト代入)追加 - ・cleararray(配列を指定値でクリア)追加 - ・copyarray(配列をコピー)追加 - ・getarraysize(配列の有効な要素数を求める)追加 - ・deletearray(配列の要素を削除してつめる)追加 - ・warpwaitingpc:人数やアカウントIDをマップ変数にセットするように修正 - - (map/) - script.c - 色々 - (doc/) - script_ref.txt - 命令追加など - (npc/sample/) - npc_test_array.txt - 配列系テスト用NPCスクリプト - -・バグ修正など - ・キャラクター名/アカウント名/パーティ名/ギルド名/ペット名に - コントロールコードを使えないように修正。 - ・char.cなどの保存の効率を更にアップ。 - ・倉庫ファイル/ギルド倉庫ファイルに空行が残らないように修正 - ・lock.*をcommon/に移動、ファイルが保存できなくなるバグ修正、 - アカウントとマップ変数の保存にもlock_fopenを使うように。 - - (common/) - lock.c/lock.h - フォルダ移動、lock_fopen修正 - (login/) - login.c - mmo_auth_new()修正 - (char/) - char.c - mmo_char_tostr(),make_new_char()修正 - int_storage.c - storage_tostr(),guild_storage_tostr(), - inter_storage_save_sub(),inter_guild_storage_save_sub()修正 - int_party.c - int_guild.c - 名前問題修正 - (map/) - pet.c - 名前問題修正 - --------------------- -//0929 by ぴざまん - -・ランドプロテクター完全実装。 -・プロボックのスキル仕様変更(詠唱妨害・凍結、石化、睡眠解除)。 -・リカバリーのスキル仕様変更(アンデッドに使用すると一定確率で暗闇効果)。 -・状態異常中でも装備の切り替えが出来るように変更。 -・アイテム自動取得中に@killmonsterを使用すると落ちるバグ修正。 -・胡蝶蘭さんが上げていたnpc.cを同梱しました。 -・skill_dbで気になってたとこをちょこっと修正。 - - (map/) - clif.c - clif_parse_EquipItem() 修正。 - skill.c - skill_castend_nodamage_id() 修正。 - skill_unitsetting()、skill_unit_onplace() 修正。 - skill_landprotector() 追加。 - mob.c - mob_delay_item_drop()、mob_delay_item_drop2() 修正。 - npc.c 修正 - - (db/) - skill_db.txt 修正。 - --------------------- -//0928 by End_of_exam - -・キャラや倉庫内アイテムが消える問題に暫定対処(キャラ鯖の改良)。 - - 1.キャラデータ・倉庫データのデータ変換処理を改良。 - (char/char.c , char/int_storage.c) - - 2.ファイル書き出しが終わるまで、旧ファイルを残すように修正。 - (char/lock.c, char/lock.h の追加。メイクファイルの修正。 - char/int_storage.c,int_guild.c,int_party.c,int_pet.c,char.c,inter.c - 内にある、データ書き出し処理を変更。) - --------------------- -//0927 by ぴざまん - -・武器攻撃以外に種族補正が入っていなかったのを修正。 -・演奏中に楽器・鞭以外の武器に持ち変えると演奏が止まる様に修正。 -・演奏の効果が演奏者自身にはかからないように修正。 -・アイテム自動取得機能実装 - 敵を倒した時に、アイテムがドロップされるのではなく、その敵に一番多くのダメージを - 与えた人(ルート権1位の人)にドロップアイテムが自動で与えられる機能です。 - battle_athena.confのitem_auto_getで設定できます。 - オリジナルアップデートの為、battle_athena.confでのデフォルトではnoにしています。 -・属性場(デリュージ・バイオレントゲイル・ボルケーノ・ランドプロテクター)仮実装 - 一部の機能が未実装です - デリュージ:水場を用いたウォーターボール - バイオレントゲイル:ファイアーウォールの持続時間補正 - ボルケーノ:アイスウォール禁止 - ランドプロテクター:オブジェクト設置系スキル禁止(つまり出るだけのLPです) - - (map/) - battle.c - battle_calc_damage()、battle_calc_magic_attack() 修正。 - battle_calc_misc_attack()、battle_config_read() 修正。 - mob.c - mob_delay_item_drop()、mob_delay_item_drop2() 修正。 - pc.c - pc_calcstatus()、pc_equipitem() 修正。 - skill.c - ローカルプロトタイプ宣言修正。 - SkillStatusChangeTable[] 修正。 - skill_castend_nodamage_id()、skill_castend_pos2() 修正。 - skill_unitsetting()、skill_unit_onplace() 修正。 - skill_unit_onout()、skill_unit_ondelete() 修正。 - skill_status_change_start()、skill_status_change_end() 修正。 - skill_clear_element_field() 追加。 - battle.h 修正。 - skill.h 修正。 - (conf/) - battle_athena.conf - item_auto_get項目を追加。 - (db/) - cast_db.txt 修正。 - --------------------- -//0926 by 胡蝶蘭 - -・ギルド城の初期化方法変更 - ・全てのギルド城(+占拠ギルド情報)を所得したときにOnAgitInitが - よばれるように。GetCastleDataやRequestGuildInfoの必要がなくなります。 - 従って、現在のgvgスクリプトのOnInterIfInitやOnRecvCastleXXXは - 必要なくなります。(おそらく現行のスクリプトも動作は可能です) - 初期化が必要なNPCは変わりにOnAgitInitを使ってください。 - なお、不要になった命令などを削除する予定はありません。 - - (char/) - inter.c/inter.h/char.c/int_guild.c/int_guild.h - マップサーバー接続時に処理を行えるように修正 - 接続時にギルド城データを送信するように - (map/) - intif.c/guild.c/guild.h - 接続時のギルド城データ一括受信処理&ギルド情報要求、 - OnAgitInitの呼び出しなど - chrif.c - 旧OnAgitInitの呼び出し削除 - (doc/) - inter_server_packet.txt - ギルド城データ一括送信パケット0x3842追加 - -・スクリプトにNPC主体イベント実行命令追加 - ・donpcevent(NPC主体イベント実行)追加 - こちらはdoeventと違いブロードキャスト可能です。詳細はscript_ref。 - ・isloggedinのコンパイル警告がでないように修正 - (map/) - script.c - buildin_donpcevent()追加など - (doc/) - script_ref.txt - doevent,donpcevent,OnAgitInit追加など - -・その他修正 - (map/) - clif.c - clif_parse_GMReqNoChat()追加 - - --------------------- -//0925 by 胡蝶蘭 - -・スクリプトのバグ修正 - ・monster,areamonsterの問題修正 - これらはscript_rid2sdを使用しないようにしました。 - sdがNULLのとき、レベルチェックを行わないようにしました。 - - (map/) - script.c/mob.c - buildin_monster(),buildin_areamonster(),mob_once_spawn()他 - -・スクリプトの機能追加 - ・detachrid命令(プレイヤーのデタッチ)追加 - ・isloggedin関数(プレイヤーのログインチェック)追加 - ・getitem,getitem2命令,countitem,checkweight関数で - nameidにアイテムの名前を指定可能に。 - (item_dbなどに依存するため、使用すべきではありませんが、一応) - - (map/) - script.c - 色々 - (doc/) - script_ref.txt - 変更部分とエラー説明修正 - -・athena-startとstartを修正 - ・athena-start stopでプロセスが終了するまで待つように - ・startで再起動させるときathena-start restartを呼ぶように。 - --------------------- -//0924 by (凸) - -・バグ報告スレッド part4 >>66のnpcを取り込み -・同 >>51のguild.cを反映 -・同 >>38のatcommand_athena.confへの変更を取り込み -・なぜかnpcフォルダにあってmap_athena.confないファイルを一覧に追加。ついでにギルドフラッグのコメントアウトを解除 -・conf/npc/npc_job_1st.txt npc_script2.txt npc_shop3.txtはスナップショットから削除してください - - (map/) - guild.c 修正 - (conf/) - map_athena.conf 修正 - atcommand_athena.conf 修正 - (conf/npc/) - npc_event_hat.txt 修正 - npc_event_oni.txt 修正 - npc_job_1st.txt 削除 - npc_script2.txt 削除 - npc_shop3.txt 削除 - --------------------- -//0923 by 胡蝶蘭 - -・スクリプトのバグ修正 -・script_rid2sdが失敗してもサーバーを終了しないように変更 - ・monster,areamonsterなどが実行できない問題修正 - - (map/) - script.c/mob.c - buildin_monster()など修正 - - (doc/) - script_ref.txt - ラベルとエラーの説明修正 - --------------------- -//0922 by 胡蝶蘭 - -・スクリプトエラーの行番号が正しく表示されるように - - (map/) - itemdb.c / npc.c - itemdb_readdb(),npc_parse_script()修正 - -・キャラクター情報にアクセスできない状態でアクセスするとエラーを出すように修正 -・goto/menuでラベルが指定される場所にラベル以外が指定されると警告を出すように -・script_refにエラーメッセージの説明追加 -・イベント起動されたスクリプトでキャラクターを使用できるようにする関数追加 - ・attachrid(指定したIDの情報を使用できるようにする)追加 - ・getcharid(3でアカウントIDを所得できるように)修正 - (map/) - script.c - script_rid2sd(),buildin_attachrid()追加 - 多々修正。 - (doc/) - script_ref.txt - エラーメッセージの説明追加、変数/ラベルの説明修正 - 他修正 - --------------------- -//0921 by RR -・スクリプトバグ修正(ご迷惑をおかけしました) - (conf/npc/) - npc_event_tougijou.txt - -・steal率修正(自DEX - 敵DEX + SLv*3 +10の部分で一度判定をしていたので) -・0918で0914以前に巻き戻ってしまっていた部分を元に戻した - (map/) - pc.c - pc_steal_item() 修正 - itemdb.c - pet.c - skill.c 修正 - --------------------- -//0920 by 獅子o^.^o -・ Steal率 = Drop率 * (自DEX - 敵DEX + SLv*3 +10) /100 - (map/) - pc.c - int pc_steal_item()修正 - --------------------- -//0919 by RR -・atcommandのlvupを使うと取得ステータスポイントがおかしい問題の修正 -・バグ修正(バグ報告スレで修正の出たものの取り込み 胡蝶蘭さん、pさん、共にお疲れ様です) - (map/) - atcommand.c - atcommand_baselevelup()修正 - guild.c - guild_gvg_eliminate_timer()修正 - pc.c - pc_setreg(),pc_setregstr()修正 - (login/) - login.c - parse_login()修正 --------------------- -//0918 by 聖 -・item_db自体がオーバーライド可能になったので、class_equip_db.txtの廃止。 -・pet_db.txt、produce_db.txtもオーバーライド可能に修正。 - (map/) - itemdb.c - do_init_itemdb() 修正。 - pet.c - read_petdb() 修正。 - skill.c - skill_readdb() 修正。 - --------------------- -//0917 by RR -・スクリプト修正 - 桃太郎イベントと闘技場イベントをNPCタイマーに変更 - (conf/npc/) - npc_event_momotarou.txt - npc_event_tougijou.txt 修正 -・スキルツリー修正(バグ報告スレ25より) - (db/) - skill_db.txt 修正 - --------------------- -//0916 by (凸) -・npc_monsterにnpc_mob_jobを統合。npc_mob_job.txtは削除してかまいません - - (conf/) - map_athena.conf npc_mob_jobを削除 - (conf/mob/) - npc_monster.txt 更新 - --------------------- -//0915 by 胡蝶蘭 - -・NPCタイマー関係の命令追加&修正他 - ・delwaitingroom(NPCチャット終了)引数を見てなかったので修正 - ・initnpctimer(NPCタイマー初期化)追加 - ・stopnpctimer(NPCタイマー停止)追加 - ・startnpctimer(NPCタイマー開始)追加 - ・getnpctimer(NPCタイマー情報所得)追加 - ・setnpctimer(NPCタイマー値設定)追加 - - 既存のaddtimerなどはプレイヤー単位のため、NPC単位のタイマーを作りました。 - こちらは、addtimerなどとは違い、OnTimerXXXという風にラベルを指定します。 - 詳しくはサンプルとscrit_ref.txtを参照。 - - (map/) - map.h - struct npc_data 修正、struct npc_timerevent_list追加 - npc.c / npc.h - npc_timerevent(),npc_timerevent_start(),npc_timerevent_stop(), - npc_gettimerevent_tick(),npc_settimerevent_tick()追加 - npc_parse_script()修正 - script.c - buildin_*npctimer()追加など - (conf/sample/) - npc_test_npctimer.txt - NPCタイマー使用サンプル - (doc/) - script_ref.txt - NPCタイマー関係の命令/関数追加、定数ラベルの説明修正 - -・Sageのアーススパイクの所得条件修正 - (db/) - skill_tree.txt - アーススパイクの行(サイズミックウェポンをLv1に) - --------------------- -//0914 by p -・範囲スキル使用時に解放済みメモリを参照していた問題に対応 -・メモリを初期化せずに使用していた領域を、初期化してから使用するように変更 - (common/) - db.c - grfio.c - socket.c - timer.c - (char/) - char.c - int_guild.c - int_party.c - int_pet.c - int_storage.c - inter.c - (login/) - login.c - (map/) - ほとんど.c - --------------------- -//0913 by Kalen - -・GVGScriptの修正 - 911対応 - フラグからアジトへ戻る機能追加 - 戻るときに聞かれるように修正(TESTscript) - 砦取得時::OnRecvCastleXXXを発動するように修正 - (conf/gvg/) - ほとんど.txt - --------------------- -//0912 by (凸) -・このファイルの文字化けとTEST_prtg_cas01_AbraiJの文字化けを修正 -・バグ報告スレの>>19-20を取り込み -・昔やっちまったbattle_athena.confの誤字の訂正 - - (common) - mmo.h - #define MAX_STAR 3に修正 - (conf) - battle_athena.conf - (conf/gvg/) - TEST_prtg_cas01_AbraiJ.txt - (map) - atcommand.c - get_atcommandinfo_byname() 修正 - - --------------------- -//0911 by Michael_Huang - - Mounting Emblem of the Flag-NPC. - (Added Script Command: FlagEmblem). - -(conf/gvg/) - TEST_prtg_cas01_AbraiJ.txt (FlagEmblem Test) - - (map/) - map.h struct npc_data{} - clif.c clif_npc0078() - script.c buildin_flagemblem() - --------------------- -//0910 by RR -・スクリプトの間違いを修正 -(conf/gvg/) - ev_agit_payg.txt - ev_agit_gefg.txt - -・ひな祭りに一度入ったらマップ変数が残ったままになるので、マップ変数を使わないよう変更 -(一時的マップ変数にすれば問題ないとも言えますが、 -town_guideとtown_kafraに時期限定の物が常駐してしまうのが気になったので、 -それらをevent_hinamatsuriへ移動し、普段のをdisableしています) - (conf/npc/) - npc_event_hinamatsuri - npc_town_guide - npc_town_kafra - -・スキルリセット時のスキル取得制限判定をスキルポイント48以上消費から、 - スキルポイント58以上消費か残りスキルポイントがJOBLEVELより小さくなったときに変更 -・@model時の服色染色制限を緩和(男アサ、ローグのみへ) - (map/) - pc.c pc_calc_skilltree() - atcommand.c atcommand_model() - - --------------------- -//0909 by 胡蝶蘭 - -・NPCチャット関係の命令追加 - ・waitingroom(NPCチャット作成)修正(イベントを起こす人数を指定可能) - ・delwaitingroom(NPCチャット終了)追加 - ・enablewaitingroomevent(NPCチャットイベント有効化)追加 - ・disablewaitingroomevent(NPCチャットイベント無効化)追加 - ・getwaitingroomstate(NPCチャット状態所得)追加 - ・warpwaitingpc(NPCチャットメンバーワープ)修正 - 詳しくはscript_ref.txtを参照 - - (map/) - script.c/npc.c/npc.h/chat.c/chat.h/clif.c - 多々修正 - (doc/) - script_ref.txt - 修正 - (conf/sample/) - npc_test_chat.txt - 追加命令のテストスクリプト - -・スクリプトの間違いを修正 - (conf/npc/) - npc_event_skillget.txt - npc_event_yuno.txt - npc_town_lutie.txt - npc_turtle.txt - 謎命令additemをgetitemに置換 - npc_town_guide.txt - 謎命令scriptlabelをコメント化 - npc_event_momotaro.txt - npc_job_swordman.txt - npc_job_magician.txt - ';'付け忘れ修正 - (conf/gvg/) - ev_agit_aldeg.txt - @GID4を@GIDa4に置換 - ev_agit_gefg.txt - ev_agit_payg.txt - Annouceに色指定と';'の付け忘れを習性 - - -・AthenaDB計画のデータとりこみ、その他修正 - 安定しているデータかどうかわかりませんが。 - - (db/) - item_db.txt/mob_db.txt/mob_skill_db.txt - AthenaDB計画のデータとりこみ - mob_skill_db.txt.orig - 以前のデータ(コメント部分などの参考に) - (conf/) - water_height.txt/mapflag.txt - AthenaDB計画のデータとりこみ - map_athena.conf - npc_monster3*.txtを削除 - 追加マップデータ (by ID:UVsq5AE) - (conf/mob/) - npc_monster.txt - AthenaDB計画のデータとりこみ - --------------------- -//0908 by 胡蝶蘭 - -・スクリプトのエラーチェック処理を増やした - ・文字列の途中で改行があるとエラーを出すように。 - ・関数呼び出し演算子'('の直前に関数名以外があるとエラーを出すように。 - ・命令があるべきところに関数名以外があるとエラーを出すように。 - ・命令および関数の引数区切りの','を省略すると警告を出すように。 - ・命令および関数の引数の数が異なると警告を出すように。 - - (map/) - script.c - 色々修正 - -・NPCスクリプト修正 - (conf/npc/) - npc_town_guide.txt - 4行目はいらないようなのでエラーが出ないようにコメント化 - npc_event_hat.txt - コモドの仮面職人とフェイヨンの青年 (by ID:dS8kRnc) - (conf/sample/) - npc_card_remover.txt - @menuを使って短くした&文章少し修正 - -・その他 - (db/) - skill_tree.txt - Sage応急手当 - --------------------- -//0907 by p -・atcommand() の肥大化がひどいのでリファクタリング - @ コマンドを追加する場合は、atcommand.h 内で定数を、atcommand.c 内で - 関数定義マクロとマッピングテーブル、処理用の関数を記述してください。 -・global 変数の atcommand_config を消去。 - @ コマンド毎のレベルは get_atcommand_level() で取得してください。 -・一部のキャラ名を取る @ コマンドで、半角スペースを含む名前のキャラを - 正常に処理できていなかった問題を修正。 - この影響により、@rura+ など、キャラ名がパラメータの途中にあったものは - 全て最後に回されています。 -・@ コマンドの文字列を正常に取得できなかった場合に、バッファの内容を - チェックせずに処理を行おうとしていた部分を修正しました。 - - (common/) - mmo.h - (map/) - atcommand.h - atcommand.c - clif.h - clif.c - --------------------- -//0906 by Selena -・胡蝶蘭さんの修正にあわせて、バルキリーレルム1以外のスクリプトの修正。 -・@コマンド入力ミスの際にエラーメッセージを表示。 - (conf/gvg/) - ev_agit_aldeg.txt - ev_agit_gefg.txt - ev_agit_payg.txt - ev_agit_prtg.txt - aldeg_cas01〜05.txt - gefg_cas01〜05.txt - payg_cas01〜05.txt - prtg_cas02〜05.txt - (map/) - atcommand.c - --------------------- -//0905 by 管理人 - -・サーバーsnapshot -・前スレのファイル取り忘れた人がいるかもしれないので - --------------------- -//0904 by 胡蝶蘭 - -・スクリプト処理修正 - ・char/interサーバーに接続した時にOnCharIfInit/OnInterIfInitイベントが - 呼ばれるようになりました。 - OnAgitInitはOnInterIfInitに変更すべきです。 - ・getcastledata命令で第2パラメータが0のとき、第3パラメータに - イベント名を設定できます。このイベントはギルド城のデータを - Interサーバーから所得完了したときに実行されます。 - ・起こすNPCイベント名を"::"で始めると、同名ラベルを持つ全NPCのイベント - を実行できます。 - たとえば、getcastledata "prtg_cas01.gat",0,"::OnRecvCastleP01"; - とすると全てのNPCの OnRecvCastleP01ラベルが実行されます。 - ・requestguildinfo命令追加。特定ギルドの情報をInterサーバーに - 要求できます。第1パラメータはギルドID、第2パラメータはイベント名で - このイベントはギルド情報をInterサーバーから所得完了したときに - 実行されます。 - - (map/) - guild.c/guild.h/npc.c/npc.h/script.c/intif.c/chrif.c - 色々修正 - -・ギルド城関連NPC修正 - (バルキリーレルム1のみ修正。他の城のスクリプトは各自で弄ってください。 - というか、むしろ弄ったらあっぷしましょう) - ・初期化処理をOnAgitInitでなくOnInterIfInitに変更。 - ・城データ所得完了処理としてOnRecvCastleP01を追加。 - ・鯖再起動時、ギルド専属カプラが正しく表示されるように。 - ・ギルド専属カプラの名前を"カプラ職員::kapra_prtg01"に変更。 - ("::"以降はエクスポートされる名前で、"::"以前が表示名) - "カプラ職員#prt"より名前を長くして競合しにくくするためです。 - この関係で、disablenpcなどのパラメータを"kapra_prtg01"に修正。 - (conf/gvg/) - prtg_cas01.txt - ギルド専属カプラ修正 - ev_agit_prtg.txt - 初期化処理修正(バルキリーレルム1のみ) - TEST_prtg_cas01_AbraiJ.txt - ギルド専属カプラ雇用/城破棄修正 - -・NPCの修正 - (conf/npc/) - npc_job_swordman.txt - npc_event_hat.txt - 修正 - -・アカウントを削除してもアカウントIDを再利用しないように修正 -・ギルド/パーティについても一応同等の処理追加(コメント化されています。 - ギルドやパーティはIDを再利用してもおそらく問題ないため) - - (login/) - login.c - 読み込み/保存処理修正 - (char/) - int_guild.c/int_party.c - 読み込み/保存処理修正 - --------------------- -//0903 by 胡蝶蘭 - -・l14/l15およびプレフィックスlを"推奨されない(deprecated)"機能としました。 - ・まだ使用できますが、今後の動作が保障されないので、速やかに代替機能を - 使用するように移行してください。 - ・プレフィックス'l'は代替機能のプレフィックス'@'を使用してください。 - ・l15は代替機能の@menuを使用してください。 - ・l14は代替機能はありません。input命令の引数を省略しないで下さい。 - ・これらの推奨されない機能を使用すると警告メッセージがでます。 - - (map/) - script.c - parse_simpleexpr()修正 - (conf/warp/) - npc_warp.txt/npc_warp25.txt/npc_warp30.txt - 変数名l0を@warp0に修正 - (conf/npc/) - npc_event_hat.txt - 変数名l15を@menuに修正 - (doc/) - script_ref.txt - 配列変数の説明追加 - 変数のプレフィックス'l'、input命令のl14、menu命令のl15の - 説明を修正 - --------------------- -//0902 by 胡蝶蘭 - -・スクリプトが配列変数に対応。 - ・array[number]のように使います。数値型、文字列型両方使えます。 - ・使えるプレフィックスは @, $, $@ です。 - (一時的キャラクター変数、一時的/永続的マップサーバー変数) - ・number==0は配列じゃない変数と値を共有します。 - (@hoge[0]と@hogeは同じ変数を表す) - ・まだ仮実装段階なのでバグ報告よろしくお願いします。 -・マップサーバー変数の読込中にCtrl+Cをするとデータ破損の可能性がある問題を修正. -・マップファイル読み込み画面がさびしいのでせめてファイル名を表示するように。 - - (conf/sample/) - npc_test_array.txt - 配列変数テストスクリプト - (map/) - script.c - buildin_set(),buildin_input(),get_val(), - parse_simpleexpr()修正 - buildin_getelementofarray()追加 - do_final_script()修正など - map.c - map_readmap(),map_readallmap()修正 - --------------------- -//0901 by ぴざまん - -・露店バグの修正 - - (map/) - pc.c - pc_cartitem_amount() 追加。 - vending.c - vending_openvending() 修正。 - clif.c - clif_parse_NpcClicked() 修正。 - pc.h 修正。 - --------------------- -//0900 by ぴざまん - -・アブラカダブラのランダムスキル発動率をabra_db.txtで設定できるように。 -・スフィアーマインとバイオプラントの微修正。 -・Noreturnマップで蝶が消費だけされるバグ修正。 -・一部のアブラ固有スキルが正しく動作しなかったバグ修正。 - (map/) - mob.c - mob_damage()、mobskill_use() 修正。 - mob_skillid2skillidx() 追加。 - skill.c - skill_readdb()、skill_abra_dataset() 修正。 - skill_castend_nodamage_id()、skill_castend_pos2() 修正。 - script.c - buildin_warp() 修正。 - - skill.h 修正。 - map.h 修正。 - (db/) - abra_db.txt 追加。 - skill_db.txt 修正。 - --------------------- -//0899 by 胡蝶蘭 - -・取り巻きMOBの処理修正 - ・取り巻き召喚でコアを吐くバグ修正 - ・主が別マップに飛ぶと、テレポートで追いかけるように修正 - ・取り巻き処理をより軽く変更 - - (map/) - mob.c - mob_ai_sub_hard_mastersearch()をmob_ai_sub_hard_slavemob() - に名前を変えて処理修正。 - mob_summonslave()修正 - --------------------- -//0898 by 胡蝶蘭 - -・eathenaからCardRemoverNPCの取り込み - NPCデータも日本語訳してますが、かなり適当です。 - - (map/) - script.c - buildin_getequipcardcnt(),buildin_successremovecards() - buildin_failedremovecards()追加 - (conf/sample/) - npc_card_remover.txt - カード取り外しNPCの日本語訳 - プロンテラの精錬所の中の左下の部屋にいます - -・ポータルで別マップに飛ばしたMOBがそのマップに沸き直すバグ修正 - (map/) - map.h - struct mob_dataにmメンバ追加 - mob.c - mob_spawn(),mob_once_spawn()修正 - npc.c - npc_parse_mob()修正 - - --------------------- -//0897 by ぴざまん - -・細かい調整 -・ストリップ系とケミカルプロテクション系スキルの全実装 - 本鯖での細かい仕様が分ったので実装しました。 - 確率は暫定です。 - - (map/) - pc.c - pc_isequip() 修正 - skill.c - skill_status_change_start()、skill_castend_nodamage_id() 修正。 - skill_abra_dataset() 修正。 - battle.c - battle_get_def()、battle_get_atk2() 修正。 - battle_get_vit()、battle_get_int() 修正。 - (db/) - const.txt 修正。 - skill_db.txt 修正。 - cast_db.txt 修正。 - --------------------- -//0896 by 胡蝶蘭 - -・永続的マップ変数機能追加 -・マップ変数を文字列型変数としても使用できるようにした - ・今までのプレフィックス $ は永続的になります。 - 一時的マップ変数を使用する場合はプレフィックス $@ を指定してください. - - ・永続的/一時的ともに文字列型に対応しています。 - 文字列型のポストフィックスは$です。 - - <例> $@hoge 数値型一時マップ変数、$hoge$ 文字列型永続マップ変数 - ・永続マップ変数はデフォルトでは save/mapreg.txt に保存されます。 - これはmap_athena.confのmapreg_txtで設定できます。 - -・str_dataが再割り当てされるとマップ変数が正常に使用できないバグ修正 - ・strdbからnumdbにして、変数名はstr_bufに入れるように。 - -・map_athena.confのdelnpc,npc:clearが正しく働かないバグ修正 - - (map/) - npc.c - npc_delsrcfile(),npc_clearsrcfile()修正 - script.c / script.h - マップ変数系かなり修正 - map.c - map_read_config()修正など - (conf/) - map_athena.conf - mapreg_txt追加 - (doc/) - conf_ref.txt - mapreg_txt,help_txt,motd_txt追加 - script_ref.txt - 文字列型変数の説明修正 - --------------------- -//0895 by Selena - -・mapflagにnozenypenaltyを追加。 - GVGや街中のテロなどで死亡した際に、Zenyペナルティー発生を外す用。 - - (map/) - pc.c - pc_setrestartvalue() 修正 - script.c - buildin_setmapflag()、buildin_removemapflag() 修正 - npc.c - npc_parse_mapflag() 修正 - map.h - map_data() 修正 - (db/) - const.txt 修正。 - --------------------- -//0894 by ぴざまん - -・コーマ以外のアブラカダブラ固有スキル全実装。 - オートスペルにはレベルアップ以外多分全部乗せれます。(オートスペルレベルアップは未テスト) -・アブラカダブラ仮実装 - 発動スキルがレベル依存じゃありません。 - 全ての発動率が理論上均一です。 - アイテムスキルを使って実装しているので一部の使用条件を無視します(ジェム罠気球等) -・アイテムスキルがキャスト・ディレイ無しだったのを修正。 - - (map/) - skill.c - skill_castend_nodamage_id()、skill_use_id()、skill_use_pos() 修正。 - skill_abra_dataset() 追加。 - (db/) - skill_db.txt 修正。 - --------------------- -//0893 by 胡蝶蘭 - -・他マップからポータルの上にワープしてきたPCがワープしない問題を修正 -・チャット中のPCをワープポータルで飛ばすかどうか設定可能に -・MOBをワープポータルで飛ばすかどうか設定可能に - MOBのワープポータルを許可すると、テロが簡単にできるので注意。 - -・アカウント変数変更と同時にファイルに書き出すように修正 -・マップデータのロード部分のログ表示はあまり重要じゃないと思うので変更。 - - (char/) - inter.c - mapif_parse_AccReg()でinter_accreg_save()を呼ぶように修正 - (map/) - mob.c/mob.h - mob_warp()の引数変更と修正 - battle.c/battle.h - mob_warp()呼び出しの引数修正 - battle_config関連 - map.c - map_readallmap(),map_readmap()修正 - pc.c - pc_setpos()修正 - skill.c - mob_warp()呼び出しの引数修正 - skill_unit_onplace()修正 - (conf/) - battle_athena.conf - chat_warpportal,mob_warpportalの追加 - (doc/) - conf_ref.txt - chat_warpportal,mob_warpportalの追加 - --------------------- -//0892 by 胡蝶蘭 - -・各種confファイルで別ファイルをインポートできるようにした - ・自分のサーバー用の設定を別ファイルに記述できるようになります。 - ・全て「import: ファイル名」形式で記述します。 - ・各種confファイル(login,char,map,inter,atcommand,battle)の最後に - conf/import/*_conf を読むように指定したので、そこに自分用の設定を - 書いておけば、変更部分のみオーバーライドします。 - msg,scriptのconfについては、この限りではありませんが、import命令の - 処理は追加されているので、自分でimport命令を書けば動きます。 - ・新しいスナップショットが出た場合などに、このconf/importフォルダを - 昔のAthenaからコピーするだけで自分用の設定を適用できるようになります. - -・map_athena.confのmapとnpcで追加したファイルを削除できるようにした - ・上に関連する変更です。 - ・delmap,delnpc命令を使用すれば、map,npc命令で追加したファイルを - 読み込まないように指定できます。ここでファイル名ではなく、 - all と指定するとそれまでに指定されたファイルを全て読み込まなくします. - ・map,npc命令で、ファイル名にclearを指定すると、 - delmap,delnpcのallと同等の動作をするようになりました。 - -・login_athena.confのallowとdenyをクリアできるようにsた - ・allowおよびdeny命令でclearを指定すると以前のホスト情報を全削除します. - - (conf/) - 各種confファイルの最後にimport命令追加 - (conf/import) - *.txt - インポートされるファイル。これらに自分用の設定を書くとよい。 - (login/) - login.c - login_read_config()修正 - (char/) - char.c/inter.c - char_read_config(),inter_read_config()修正 - (map/) - map.c - map_read_config(),map_addmap()修正、map_delmap()追加 - npc.c - npc_addsrcfile()修正,npc_delsrcfile(),npc_clearsrcfile()追加 - battle.c/atcommand.c/script.c - battle_read_config(),atcommand_read_config(), - msg_read_config(),script_read_config()修正 - (doc/) - conf_ref.txt - 修正 - --------------------- -//0891 by (凸) - -・「スキル使用の後は、しばらくお待ちください」を表示するかどうか設定できるようにした。 - ・本鯖相違スレッド 其のU>>5さんのコードをパクリました。 - (doc/) - conf_ref.txt 修正。 - (conf/) - battle_athena.conf 修正。 - (map/) - battle.h 修正。 - battle.c - battle_config_read() 修正。 - clif.c - clif_skill_fail() 修正。 - --------------------- -//0890 by 死神 - -・ギルド倉庫を一度に一人だけが使用するように変更。(未テスト) -・battle_athena.confからplayer_undead_nofreeze 削除。 -・@コマンド@gstorage 追加。 -・スクリプトguildstorageをguildopenstorageに変更。 -・その他細かいバグ修正。 - (doc/) - conf_ref.txt 修正。 - script_ref.txt 修正。 - (conf/) - atcommand_athena.conf 修正。 - battle_athena.conf 修正。 - help.txt 修正。 - (conf/sample/) - gstorage_test.txt 追加。 - (char/) - makefile 修正。 - int_storage.h 修正。 - int_storage.c - inter_storage_delete()、inter_guild_storage_delete() 追加。 - int_guild.c - guild_check_empty()、mapif_parse_BreakGuild() 修正。 - (map/) - makefile 修正。 - battle.h 修正。 - battle.c - battle_config_read() 修正。 - guild.c - guild_broken() 修正。 - storage.h 修正。 - storage.c - storage_guild_storageopen() 修正。 - storage_delete()、guild_storage_delete() 追加。 - script.c - buildin_guildstorage() を buildin_guildopenstorage()に変更。 - intif.c - intif_parse_LoadGuildStorage() 修正。 - mob.c - mob_summonslave()、mob_damage()、mob_delete() 修正。 - mob_catch_delete()、mob_readdb() 修正。 - skill.c - skill_castend_nodamage_id()、skill_status_change_start() 修正。 - clif.c - clif_parse_ActionRequest() 修正。 - atcommand.h 修正。 - atcommand.c - atcommand() 修正。 - --------------------- -//0889 by 胡蝶蘭 - -・文字列型一時的キャラクター変数機能追加。 - ・プレフィックス@,ポストフィックス$を使用します。(@hoge$など) - ・inputで文字列変数を指定すると文字列入力になります。 - ・関係演算子(比較演算子)で文字列どうしを指定すると文字列の比較が - できます。数値と文字列を混ぜて比較することはできません。 - ・とりあえずサンプル付けてます。 - - (map/) - map.h - struct map_session_dataにnpc_str,regstr,regstr_numメンバ追加 - script.c - buildin_set(),get_val(),buildin_input(),op_2num()など修正 - op_2str(),op_2()追加 - clif.c / clif.h - 01d5パケット長修正 - clif_parse_NpcStringInput(),clif_scriptinputstr()追加 - pc.c / pc.h - pc_readregstr(),pc_setregstr()追加 - (doc/) - script_ref.txt - 演算子の説明追加、変数の説明修正、input,menu修正 - (conf/sample/) - npc_test_str.txt - 文字列変数を使用したスクリプトの例。 - 文字列の代入、結合、比較、入力などのテストを行うもの。 - --------------------- -//0888 by 死神 - -・設計から間違っていたギルド倉庫修正。(ただ複数人の使用によるバグがある可能性はまだあります。) -・細かいバグ修正。 - (doc/) - inter_server_packet.txt 修正。 - conf_ref.txt 修正。 - (conf/) - inter_athena.conf 修正。 - help.txt 修正。 - (common/) - mmo.h 修正。 - (char/) - makefile 修正。 - int_storage.h 修正。 - int_storage.c - account2storage()、inter_storage_init()、storage_fromstr() 修正。 - inter_storage_save()、mapif_load_storage() 修正。 - mapif_parse_SaveStorage() 修正。 - guild_storage_fromstr()、guild_storage_tostr() 追加。 - inter_storage_save_sub()、inter_guild_storage_save_sub() 追加。 - inter_guild_storage_save()、mapif_parse_LoadGuildStorage() 追加。 - mapif_parse_SaveGuildStorage()、mapif_load_guild_storage() 追加。 - mapif_save_guild_storage_ack()、guild2storage() 追加。 - int_party.c - inter_party_init() 修正。 - int_guild.h 修正。 - int_guild.c - inter_guild_init() 修正。 - inter_guild_search() 追加。 - int_pet.c - inter_pet_init() 修正。 - inter.c - inter_init()、inter_save()、inter_config_read() 修正。 - (map/) - makefile 修正。 - map.h 修正。 - map.c - map_quit()、do_init() 修正。 - pc.c - pc_setpos() 修正。 - storage.h 修正。 - storage.c - do_init_storage()、do_final_storage()、account2storage() 修正。 - storage_storageopen()、storage_storageadd()、storage_storageget() 修正。 - storage_storageaddfromcart()、storage_storagegettocart() 修正。 - storage_storageclose()、storage_storage_quit() 修正。 - storage_storage_save() 修正。 - guild2storage()、storage_guild_storageopen() 追加。 - guild_storage_additem() 、guild_storage_delitem() 追加。 - storage_guild_storageadd()、storage_guild_storageget() 追加。 - storage_guild_storageaddfromcart()、storage_guild_storagegettocart() 追加。 - storage_guild_storageclose()、storage_guild_storage_quit() 追加。 - intif.h 修正。 - intif.c - intif_send_storage()、intif_parse_LoadStorage()、intif_parse() 修正。 - intif_request_guild_storage()、intif_send_guild_storage() 追加。 - intif_parse_SaveGuildStorage()、intif_parse_LoadGuildStorage() 追加。 - clif.h 修正。 - clif.c - clif_additem()、clif_parse_MoveToKafra() 修正。 - clif_parse_MoveFromKafra()、clif_parse_MoveToKafraFromCart() 修正。 - clif_parse_MoveFromKafraToCart()、clif_parse_CloseKafra() 修正。 - clif_parse_LoadEndAck() 修正。 - clif_guildstorageitemlist()、clif_guildstorageequiplist() 追加。 - clif_updateguildstorageamount()、clif_guildstorageitemadded() 追加。 - guild.c - guild_broken() 修正。 - script.c - buildin_openstorage()、buildin_guildstorage() 修正。 - skill.c - skill_castend_nodamage_id() 修正。 - mob.c - mob_summonslave()、mob_damage() 修正。 - atcommand.c - atkillmonster_sub()、atcommand() 修正。 - --------------------- -//0887 by 獅子o^.^o - -・(db/) - skill_tree.txt 修正 - --------------------- -//0886 by ぴざまん - -・サーバーsnapshot -・ファイル調整 - --------------------- -//0885 by huge - -・ギルド共有倉庫の実装。guildstorageで開けます。 - 自分の鯖で実験はしてみましたが、過疎地なので多人数ギルドになるとどう動くか分かりません。 - (念のためバックアップは必ず取っておいて下さい) -・areawarpで、対象マップ名を"Random"にすると、同マップ内でランダムに飛ぶように修正。 -・GMコマンドで生き返したときにSPも全回復するように修正。 -・ディボーションの条件をちょっと修正。 - - (char/) - int_storage.c - mapif_load_storage() 修正。 - mapif_parse_SaveStorage() 修正。 - inter.c - inter_send_packet_length[] 修正。 - inter_recv_packet_length[] 修正。 - (map/) - atcommand.c - @alive,@raise,@raisemap 修正。 - intif.c - packet_len_table[] 修正。 - intif_request_storage() 修正。 - intif_send_storage() 修正。 - intif_parse_LoadStorage() 修正。 - - map.h - map_session_data stateにstorage_flag 追加。 - script.c - buildin_areawarp_sub() 修正。 - buildin_openstorage() 修正。 - buildin_guildstorage() 追加。 - skill.c - skill_castend_nodamage_id() 修正。 - storage.c - account2storage() 修正。 - storage_storageopen() 修正。 - storage_storage_save() 修正。 - --------------------- -//0884 by 死神 - -・細かいバグ修正。 -・battle_athena.confにpet_str、zeny_penalty、resurrection_exp 追加。 -・0878の銀行関係のコードはもういらないので全て削除。 -・zeny_penaltyを設定して使う場合は手数料はなくした方がいいかも。 -・ポーションピッチャーでpercenthealにもPPとLPによる回復ボーナスが付くように変更。(ただvitやint、HPR、MPRによる回復ボーナスが付きません。) -・ほとんど未テスト。 - (common/) - mmo.h 修正。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (map/) - map.c - do_init()、do_final() 修正。 - script.c - buildin_openbank() 削除。 - buildin_failedrefitem() 修正。 - storage.h 修正。 - storage.c - do_init_bank()、do_final_bank()、account2bank() 削除。 - storage_bank()、storage_readbank() 削除。 - skill.c - skill_castend_nodamage_id()、skill_attack() 修正。 - battle.h 修正。 - battle.c - battle_calc_pet_weapon_attack()、battle_config_read() 修正。 - pc.c - pc_setrestartvalue() 修正。 - clif.c - clif_skill_nodamage()、clif_refine() 修正。 - itemdb.c - itemdb_isequip3() 修正。 - atcommand.c - atcommand() 修正。 - --------------------- -//0883 by Kalen - -・Warp色々修正 - ・アサシンギルド周り修正(昔のままのリンクだったので現在の状態に修正。) - ・YunoのWarp全面見直し(YumilLoop修正、SageCastleRandomWarp追加、女医さんの家追加) - ・モンクギルド周り追加 -・NPC色々修正 - ・帽子作成NPCを別ファイルへ。一部追加(ep2.5追加分) - 参考Data(R.O.M776): ttp://green.sakura.ne.jp/~youc/ro/data/itemmaking.html#04 - ・アサシンギルド修正 - ・二次職転職関係NPC一部追加(これでコモド小劇場へ行けます) - ・マスターアルケミストの台詞修正 - ・アルデバランの案内要員を移動&台詞修正&イメージ追加 - ・BBSにあがっていたコモドスクリプト追加(event_hat等へ分散) - ・コンロンクエスト関係NPC一部追加(女医[yuno]、ネル[prontera]) - (conf/warp/) - npc_warp.txt - npc_warp30.txt - npc_warp_job.txt - (conf/npc/) - npc_event_hat.txt(新規) - npc_job_2nd.txt - npc_job_alchemist.txt - npc_town_aldebaran.txt - npc_town_comodo.txt - npc_town_gonryun.txt - npc_town_guide.txt - npc_town_yuno.txt - npc_town_lutie.txt - --------------------- -//0882 by 胡蝶蘭 - -・スクリプトに0881相当のアカウント共有変数機能のプレフィックス変更 - ・0881のアカウント変数はプレフィックス##になりました。 - ・0881のアカウント変数は全ワールドで共有されます。 - ・変数の個数はmmo.hのACCOUNT_REG2_NUMで定義されています(16)。 -・ワールド内のアカウント共有変数機能追加 - ・変数名のプレフィックスは#です。 - ・変数の個数はmmo.hのACCOUNT_REG_NUMで定義されています(16)。 - ・0881の銀行スクリプトはこちらを使用するようになります。 - よって以前のデータがつかえないのであらかじめ引き出しておいてください. - ・変数データは save/accreg.txt に保存されます。 - このファイル名は inter_athena.conf で変更可能です。conf_ref.txt参照。 - - (common/) - mmo.h - ACCOUNT_REG_NUMを16に、ACCOUNT_REG_NUM2追加 - struct mmo_charstatusにaccount_reg2_num,account_reg2メンバ追加 - (login/) - login.c - account_regを全てaccount_reg2に置き換え - (char/) - char.c - account_regを全てaccount_reg2に置き換え - inter.c - ワールド内アカウント変数機能追加。 - inter_accreg*()追加、accreg_db追加など。 - (map/) - chrif.c/chrif.h - account_regを全てaccount_reg2に置き換え - 0881でのバグを修正 - intif.c/intif.h - ワールド内アカウント変数機能追加。 - pc.c/pc.h - pc_*accountreg()=>pc_*accountreg2()に。 - pc_setaccountreg(),pc_readaccountreg()追加。 - script.c - buildin_set(),buildin_get_val(),buildin_input()修正 - (doc/) - inter_server_packet.txt - ワールド内アカウント変数関係 - conf_ref.txt - accreg_txt追加 - --------------------- -//0881 by 胡蝶蘭 - -・スクリプトにアカウント共有変数機能追加 - ・変数名にプレフィックス#を付けることでアカウント共有変数になります。 - ・アカウント変数は変更した時点で全サーバーにポストされるので - 頻繁に書き換えるとサーバー間通信が肥大化します。 - ・アカウント変数は変更した時点(そしてそれがlogin鯖に届いた時点)で - account.txtに書き出されます。 - ・グローバル変数(永続変数)の個数を96に減らし、減った32個分を - アカウント変数にしていますが、mmo_charstatusのサイズが - 16000byteを超えない限り増やすことができます。<0879の変更を参照 - 変数の個数はmmo.hのACCOUNT_REG_NUMで定義されています。 - ・0878の銀行をアカウント変数を使用するように修正 - bank.txtのデータが使えなくなるのであらかじめ引き出しておいて下さい。 - - (common/) - mmo.h - GLOBAL_REG_NUMを96に、ACCOUNT_REG_NUMを追加 - struct mmo_charstatusにaccount_reg_num,account_regメンバ追加 - (login/) - login.c - パケット2728処理追加 - (char/) - char.c - パケット2729,2b10処理追加 - (map/) - chrif.c - chrif_saveaccountreg(),chrif_accountreg() - (パケット2b10,2b11処理)追加。 - pc.c/pc.h - pc_readaccountreg(),pc_setaccountreg()追加 - script.c - buildin_set(),buildin_get_val(),buildin_input()修正 - (conf/sample/) - bank_test.txt - アカウント変数使用版の銀行スクリプト - --------------------- -//0880 by 死神 - -・ポーションピッチャーを正しく実装とちょっと機能拡張。 -・ポーションピッチャーでレベル別に使えるアイテムをskill_require_db.txtに設定できるようにしました。ただポーションピッチャーで使えるアイテムはitemheal、percentheal、sc_start、sc_end以外の物が入っていると正しく動作しません。 -レベル5までは本鯖に合わせていますが最大レベルを10まで拡張するとレベル6 - マステラの実、7 - ローヤルゼリー、8 - イグドラシルの種、9 - イグドラシルの実、10 - バーサークポーションに設定しています。skill_db.txtを修正すればこれが有効になります。(どこを修正するかもわからない人は諦めることです。) ポーションピッチャーによるアイテム使用は使用条件を無視します。少しはアルケミストに希望ができたかも...(多分無理...) -・battle_athane.confにproduce_item_name_input、produce_potion_name_input、making_arrow_name_input、holywater_name_input 追加。 -・パーティ員にだけ使うスキルとギルド員にだけ使うスキルを設定できるように修正。 -・その他細かい修正。 - (conf/) - battle_athane.conf 修正。 - (doc/) - conf_ref.txt 修正。 - db_ref.txt 修正。 - (db/) - skill_db.txt 修正。 - skill_require_db.txt 修正。 - (map/) - map.h 修正。 - skill.h 修正。 - skill.c - skill_status_change_timer()、skill_attack()、skill_use_id() 修正。 - skill_castend_nodamage_id()、skill_castend_damage_id() 修正。 - skill_castend_id()、skill_castend_pos()、skill_produce_mix() 修正。 - skill_arrow_create()、skill_check_condition() 修正。 - skill_status_change_clear()、skill_readdb() 修正。 - mob.c - mobskill_use_id()、mob_changestate() 修正。 - pc.c - pc_itemheal()、pc_percentheal()、pc_calcstatus() 修正。 - battle.h 修正。 - battle.c - battle_delay_damage()、battle_damage()、battle_heal() 修正。 - battle_get_adelay()、battle_get_amotion() 修正。 - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_weapon_attack()、battle_config_read() 修正。 - clif.c - clif_skill_fail() 修正。 - script.c - buildin_sc_start()、buildin_sc_end() 修正。 - makefile 修正。 - --------------------- -//0879 by 胡蝶蘭 - -・送信FIFOのバッファオーバーフローの脆弱性の修正 - ・2048バイト以上のパケットを送るとき、FIFOが満杯に近ければ - バッファオーバーフローによる不正アクセスが起こっていた問題修正。 - ・FIFOが満杯に近いときWFIFOSETされたパケットが捨てられていた問題修正。 - ・FIFOがオーバーフローする場合、自動的にFIFOを拡張するようにした。 - (ただし、一度にWFIFOSETするパケットが16384バイト以下と仮定している) - ・「socket: ? wdata expanded to ???? bytes」はFIFOが拡張されたときに - でるログだが、エラーではなく、パケットは正しく送信される。 - ・「socket: ? wdata lost !!」はパケットが喪失したことを表すログで、 - エラーであるが64KBを超える超巨大なパケットをWFIFOSETしないと出ない。 - ・16384バイトを超えるパケットをWFIFOSETするとエラーメッセージなしに、 - 不正アクセスが起こる可能性があるので、超えないようにすること。 - - (common/) - socket.c /socket.h - WFIFOSET()をマクロから関数に変更 - realloc_fifo()追加 - -・サーバー間通信FIFOのバッファサイズを大きくした - ・大量のデータが通信されたときにデータ処理遅延が起きにくくするため。 - ・メモリ使用量が増えた。(ぎりぎりの人は65536に設定すると元通りになる) - ・サーバー間通信のFIFOサイズは mmo.h で定義されている。 - 変更する場合は64KB(65536)以上の値にすること。 - 大きくすると巨大データ受信時の遅延が減るがメモリを多く使う。 - ・@kickall時などにデータ送信が激しくなるので変更したが、 - 同時ログイン人数が少ないと増やしても意味は無い。 - - (common/) - mmo.h - FIFOSIZE_SERVERLINKマクロ追加。 - (login/) - login.c - 2710パケットでrealloc_fifo()を呼ぶように - (char/) - char.c - 2af8パケットでrealloc_fifo()を呼ぶように - check_connect_login_server()でrealloc_fifo()を呼ぶように - (map/) - chrif.c - check_connect_char_server()でrealloc_fifo()を呼ぶように - --------------------- -//0878 by huge - -・カプラ銀行サービス。 - 自分の鯖で実装してたんですが、意外と好感触だったので出してみます。 - NPCscriptで、openbank(0);で預金額を返して、中に数字を入れると出し入れします。 - 詳しくはサンプルを同封したので、それを参照。 - - (common/) - mmo.h - struct bank 追加。 - (map/) - map.c - do_final(),do_init() 修正。 - script.c - buildin_openbank() 追加。 - storage.c - storage.h - グローバル変数追加。 - do_init_bank(),do_final_bank(),account2bank() 追加。 - storage_bank(),storage_readbank() 追加。 - --------------------- -//0877 by 胡蝶蘭 - -・login鯖のアクセスコントロールがネットマスク表記に対応 - 192.168.0.0/24 や 192.168.0.0/255.255.0.0 といった表記に対応。 -・battle_athena.confにGMが無条件で装備品を装備できる& - 無条件でスキルを使用できる設定追加 - これらはデバグ用なので動作に不都合があるかもしれません。 - - (login/) - login.c - check_ip()修正,check_ipmask()追加 - (map/) - battle.c/battle.h - battle_configにgm_allequip,gm_skilluncond追加 - battle_config_read()修正更 - skill.c - skill_check_conditio()修正 - pc.c - pc_isequp()修正 - (doc/) - conf_ref.txt - allow変更、gm_all_equipment、gm_skill_unconditional追加 - --------------------- -//0876 by 死神 - -・細かいバグ修正。 -・@コマンドにテストの為に入れていた物が入っていたので修正。 -・ハンマーフォールの射程を5から4に修正(本鯖射程は不明)とリザレクションが無属性だったのを聖属性に修正。 - (db/) - skill_db.txt 修正。 - (map/) - mob.c - mob_catch_delete()、mob_stop_walking() 修正。 - storage.c - storage_additem() 修正。 - pc.c - pc_damage()、pc_stop_walking() 修正。 - clif.c - clif_parse_UseSkillToId()、clif_parse_UseSkillToPos() 修正。 - battle.c - battle_calc_magic_attack() 修正。 - skill.c - skill_check_condition() 修正。 - atcommand.c 修正。 - --------------------- -//0875 by 胡蝶蘭 - -・party_share_levelをinter_athena.confに移した - (パーティ関連の処理の管轄がinter鯖のため) -・inter_athena.confにinter_log_file項目追加 -・ギルド作成/解散/城占領/城破棄がログに残るように -・ギルド解散時にメモリリークしていた問題を修正 - (char/) - char.c/char.h - party_share_level関連 - (inter/) - inter.c/inter.h - party_share_level / inter_log_file 関連 - ログ出力用にinter_log()追加 - int_guild.c - 作成/解散/城占領/城破棄をログに出力 - メモリリーク修正 - (doc/) - conf_ref.txt - 修正 - -・サーバー状態確認用CGIスクリプト添付など - ・自己責任&詳細な解説無し、質問されてもスルーする可能性有り - ・エディタで開いたら少し説明有り - ・CGI設置の基本さえわかれば問題ないはず - - (tool/cgi/) - serverstatus.cgi - サーバー状態確認用CGIスクリプト - addaccount.cgi - 説明修正 - --------------------- -//0874 by Kalen -・WhiteDayイベント追加 - conf/npc/npc_event_whiteday.txt(新規) - ただ、お菓子売ってるだけみたい…GMがなにやるのかは知りませんが。 - sakROのほうではホワイトチョコらしきものが追加されたのに - jROで追加されたのは雛壇撤去パッチのみ(*´д`;)… - -・Alchemistギルドで乳鉢、製造書を変えるように - conf/npc/npc_job_alchemist.txt(新規) - 転職クエストが分からなかったので温めていましたが - 買えないと不便と聞いたので、追加 - -・染色NPC実装 - conf/npc/npc_event_dye.txt(更新) - 髪型変更がsakROに来たらしいので - なんとなーく更新 - --------------------- -//0873 by 死神 - -・@コマンドitem2とkillmonster 追加。 -・スクリプトgetitem2とkillmonsterall 追加。 -・矢作成で作られた矢も製造者の名前が付くように修正。 -・battle_athena.confにmonster_class_change_full_recover追加。 -・装備スクリプトにbWeaponComaEleとbWeaponComaRace 追加。 -・少し間違いがあったダメージ計算式修正。 -・bInfiniteEndureの処理をインデュア表示なしで内部処理するように変更。 -・オートスペルでcastend_nodamage_id()を呼ぶスキルも使用できるように修正。 -・その他細かい修正とバグ修正。 -・ほとんど未テストなのでバグがあったら報告お願いします。 - (conf/) - help.txt 修正。 - atcommand_athena.conf 修正。 - battle_athena.conf 修正。 - char_athena.conf 修正。 - (db/) - const.txt 修正。 - item_db.txt 修正。 - (doc/) - item_bonus.txt 修正。 - script_ref.txt 修正。 - conf_ref.txt 修正。 - (map/) - map.h 修正。 - map.c - map_quit() 修正。 - skill.h 修正。 - skill.c - skill_castend_nodamage_id()、skill_status_change_clear() 修正。 - skill_castend_id()、skill_castend_pos()、skill_arrow_create() 修正。 - skill_status_change_timer() 修正。 - pc.c - pc_calcstatus()、pc_bonus2()、pc_equipitem() 修正。 - pc_unequipitem()、pc_damage() 修正。 - battle.h 修正。 - battle.c - battle_get_dmotion()、battle_weapon_attack() 修正。 - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_calc_magic_attack()、battle_config_read() 修正。 - clif.c - clif_parse_LoadEndAck()、clif_damage()、clif_skill_damage() 修正。 - clif_skill_damage2() 修正。 - itemdb.h 修正。 - itemdb.c - itemdb_isequip3() 追加。 - mob.h 修正。 - mob.c - mob_delay_item_drop()、mob_damage()、mob_changestate() 修正。 - mob_class_change()、mob_delete()、mob_catch_delete() 修正。 - script.c - buildin_getitem() 修正。 - buildin_killmonsterall_sub()、buildin_killmonsterall() 追加。 - atcommand.h 修正。 - atcommand.c - atcommand() 修正。 - atkillmonster_sub() 追加。 - --------------------- -//0872 by ElFinLazz - -・スキルポーションピッチャー修正 -・スキルギムソバングドンボルオッネ具現 -・スキルアブラカダブなら義コーマ具現 -・コーマの武器オプション追加(種族, 千分率) -・オプション説明追加 - (db/) - const.txt 修正. - (doc/) - item_bonus.txt 修正. - (map/) - map.h 修正. - skill.c - skill_castend_nodamage_id(), skill_unit_group(), skill_status_change_start() 修正. - pc.c - pc_calcstatus(), pc_bonus2(), pc_gainexp() 修正. - battle.c - battle_weapon_attack() 修正. - --------------------- -//0871 by 死神 - -・0869のバグ修正。 -・char_athena.confとlogin_athena.confに項目追加。(キャラ鯖とログイン鯖のログファイルを変えることができるようにしました。デフォルトでlog/フォルダーに入るのでlogフォルダーを作る必要があります。) -・エナジーコートの処理を少し修正。モンスターが使った場合はスキルレベル*6%の物理ダメージを減らすように変更。 -・武器以外の物でも製造者の名前を表示するように変更。(本鯖ではプレゼントボックスと手作りチョコレット以外は表示されませんがパケットはあることだし入れてみました。) -・その他スキル関係の細かい修正。 -・@コマンド一つとスクリプト一つを追加しましたが説明は後のパッチで書きます。 - (conf/) - char_athena.conf 修正。 - login_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (login/) - login.c - parse_login()、login_config_read()、login_log() 修正。 - (char/) - char.h 修正。 - char.c - char_config_read()、make_new_char()、parse_char() 修正。 - int_party.c 修正。 - int_storage.c 修正。 - int_guild.c 修正。 - int_pet.c 修正。 - (map/) - map.h 修正。 - skill.c - skill_status_change_start()、skill_additional_effect() 修正。 - skill_castend_nodamage_id()、skill_check_condition() 修正。 - skill_status_change_clear()、skill_produce_mix() 修正。 - skill_status_change_timer() 修正。 - pc.c - pc_calcstatus()、pc_insert_card()、pc_additem()、pc_cart_additem() 修正。 - storage.c - storage_additem() 修正。 - battle.c - battle_get_adelay()、battle_get_amotion()、battle_calc_damage() 修正。 - clif.c - clif_additem()、clif_equiplist()、clif_storageequiplist() 修正。 - clif_tradeadditem()、clif_storageitemadded()、clif_use_card() 修正。 - clif_cart_additem()、clif_cart_equiplist()、clif_vendinglist() 修正。 - clif_openvending()、clif_arrow_create_list() 修正。 - clif_skill_produce_mix_list()、clif_parse_SelectArrow() 修正。 - clif_parse_ProduceMix() 修正。 - script.c - buildin_produce() 修正。 - buildin_getitem2() 追加。 - atcommand.c - atcommand() 修正。 - --------------------- -//0870 by shuto - -・mapflagの攻城戦MAPにnomemo追加 -・ギルド宝箱で、宝箱出現と同時にMAP鯖が落ちる問題修正(by ぴざまん) - --------------------- -//0869 by 死神 - -・battle_athena.confにplayer_land_skill_limit、monster_land_skill_limit、party_skill_penaly 追加。 -・char_athena.confにparty_share_level 追加。 -・その他細かい修正。 - (conf/) - char_athena.conf 修正。 - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (char/) - char.h 修正。 - char.c - char_config_read() 修正。 - int_party.c - party_check_exp_share() 修正。 - (map/) - map.h 修正。 - skill.c - skill_attack()、skill_castend_damage_id() 修正。 - skill_castend_nodamage_id()、skill_status_change_start() 修正。 - skill_castend_pos() 修正。 - pc.c - pc_calcstatus() 修正。 - mob.c - mobskill_castend_pos() 修正。 - battle.h - battle.c - battle_get_adelay()、battle_get_amotion()、battle_calc_damage() 修正。 - battle_config_read() 修正。 - pet.c - pet_data_init() 修正。 - --------------------- -//0868 by 死神 - -・マジックロッド実装とスペルブレイカー修正。 -・マジックロッドの場合本鯖で使ってもなんの表示もなく発動の前には使ったかどうかの確認ができないのでスキル詠唱パケット(0x13e)を利用して使用する時スキル名が出るようにしています。(本鯖と違うぞとかで文句がこないように) -・スペルブレイカー詠唱キャンセルに関係なくskill_db.txtに設定されてるskill_typeがmagicのスキルのみ破ることができます。(ラグナゲートの説明を適用) -・skill_db.txtの書式が変わったので注意してください。ノックバック距離の設定もできますが念の為にいっておきますがA鯖でのテストでFWのノックバック距離は2でサンクも2であることを確認しています。韓国の2003年11月19日パッチ前の鯖ではありますが2-2は適用されている所なので本鯖の違いはないと思います。 -・その他スキル関係の細かい修正。 -・0867で書き忘れ。モンスターのヒールでアンデッドモンスターが攻撃されて自滅するのでヒールやリザの場合mob_skill_db.txtのval1(値1)に1を入れるとアンデッドモンスターも攻撃を受けず回復するようになります。本鯖ではモンスターのヒールはアンデッドに関係なく回復するようです。ただ個人的にはゾンビがヒールして自滅する方が正しいと思うのでmob_skill_db.txtで設定できるようにしております。 - (doc/) - db_ref.txt 修正。 - (db/) - cast_db.txt 修正。 - skill_db.txt 修正。 - (map/) - skill.h 修正。 - skill.c - skill_status_change_start()、skill_status_change_end() 修正。 - skill_castend_damage_id()、skill_castend_nodamage_id() 修正。 - skill_attack()、skill_status_change_timer()、skill_castcancel() 修正。 - skill_unit_onplace()、skill_use_id()、skill_castend_id() 修正。 - skill_readdb() 修正。 - skill_get_blewcount() 追加。 - mob.c - mobskill_use_id()、mob_spawn()、mob_attack() 修正。 - battle.c - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack()、battle_calc_magic_attack() 修正。 - battle_calc_misc_attack()、battle_weapon_attack() 修正。 - clif.c - clif_damage() 修正。 - pet.c - pet_attack() 修正。 - pc.c - pc_attack_timer()、pc_authok() 修正。 - pc_spirit_heal()、pc_natural_heal_sub() 修正。 - --------------------- -//0867 by 死神 - -・スキル関係の細かい修正。 -・battle_athena.confにplayer_undead_nofreeze追加。 -・新しいアイテムパケットに対応。(PACKETVERを5以上にする必要があります。) -・mob_avail.txtでプレイヤーの姿を指定した時ペコペコや鷹を付けることができるように変更。頭下段次にオプションを設定できます。(ただハイディングとクローキングは指定できないようになっています。) - makefile 修正。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - client_packet.txt 修正。 - (map/) - battle.h 修正。 - battle.c - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack()、battle_config_read() 修正。 - clif.c - clif_mob_class_change()、clif_spawnmob()、clif_spawnpet() 修正。 - clif_damage()、clif_skill_damage()、clif_skill_damage2() 修正。 - clif_itemlist()、clif_cart_itemlist()、clif_storageitemlist() 修正。 - clif_mob0078()、clif_mob007b()、clif_pet0078()、clif_pet007b() 修正。 - pc.c - pc_attack_timer() 修正。 - skill.c - skill_castend_nodamage_id()、skill_additional_effect() 修正。 - skill_status_change_start() 修正。 - mob.h 修正。 - mob.c - mobskill_castend_id()、mob_getfriendstatus_sub() 修正。 - mob_readdb_mobavail() 修正。 - --------------------- -//0866 by ぴざまん - -・MOTDのメッセージを全て編集できるように変更。 -・クローンスキル実装。 - ドル服のヒールアタックによるヒール習得は未テストです。 -・ギルド宝箱仮実装。 - ヴァルキリー1のみです。 - 商業投資による宝箱個数の算出式は適当です(初期個数4個としか知らないので)。 - Onclockイベントで動作させています。任意の時刻に変更してください。 -・AthenaDB計画のmob_db.txtとmapflag.txtを入れておきました。 - - (map/) - pc.c - pc_makesavestatus()、pc_calc_skilltree() 修正。 - pc_allskillup()、pc_calc_skillpoint() 修正。 - pc_resetskill()、pc_authok() 修正。 - skill.c - skill_attack() 修正。 - map.h 修正。 - (conf/) - gvg/TEST_prtg_cas01_AbraiJ.txt 修正。 - motd.txt 修正。 - mapflag.txt 修正。 - (db/) - mob_db.txt 修正。 - --------------------- -//0865 by ぴざまん - -・自分が占領しているアジトのエンペリウムを攻撃できたバグ修正。 -・アブライが占領ギルドメンバー全員をマスターとみなしていたバグ修正。 - この修正に伴ってスクリプトリファレンスに改変があります。 - ・getcharid(0)で、自分のcharIDを返すように。 - ・getguildmasterid(<n>)追加。 - <n>=ギルドID - 該当ギルドのマスターのcharIDを返します。 - - (map/) - guild.c - guild_mapname2gc() 追加。 - battle.c - battle_calc_damage() 修正。 - script.c - buildin_getcharid() 修正。 - buildin_getguildmasterid() 追加。 - ローカルプロトタイプ宣言の一部を修正、追加。 - guild.h 修正。 - --------------------- -//0864 by 胡蝶蘭 - -・inter鯖のwisの処理変更 - ・自前リンクリストからdb.hで提供されているデータベースを使用するように - ・WISのIDを16ビットから32ビットに増やした(パケットも修正) - ・メッセージのサイズチェックを入れた - ・パケットスキップが二回行われる可能性があるバグ修正 - - (char/) - inter.c - wis関係大幅変更 - (map/) - intif.c - wis関係の修正。主にパケット処理。 - (doc/) - inter_server_packet.txt - パケット3002,3801を変更 - --------------------- -//0863 by 死神 - -・細かい修正。 -・battle_athena.confにplayer_attack_direction_change追加。 -・mob_skill_db.txtを修正する時挑発の修正を間違って修正。 -・モンスターのスキル自爆問題修正。(未テスト) - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (db/) - mob_skill_db.txt 修正。 - (map/) - mob.c - mobskill_use_id()、mobskill_use()、mobskill_castend_id() 修正。 - pc.c - pc_skill()、pc_attack_timer() 修正。 - skill.c - skill_castend_damage_id() 修正。 - battle.h 修正。 - battle.c - battle_weapon_attack()、battle_config_read() 修正。 - --------------------- -//0862 by 胡蝶蘭 - -・mobスキル使用条件追加 - ・friendhpltmaxrate : 味方のHPが指定%未満のとき(テスト済み) - ・friendstatuson : 味方が指定したステータス異常になっているとき - ・friendstatusoff : 味方が指定したステータス異常になっていないとき - ・mystatuson : 自分が指定したステータス異常になっているとき - ・mystatusoff : 自分が指定したステータス異常になっていないとき - ステータス系は未テストです。mob_skill_db.txtに指定方法を書いています。 - たとえば自分が毒かどうかは mystatus,poison で、 - ハイディング中かどうかは mystatuson,hiding で指定します。 -・mobスキル使用ターゲット追加 - ・friend : 味方 - ・around : 自分の周囲(現在の仕様では周囲81マス)のどれか - ・around1〜around4 : 自分の周囲9,25,49,81マスのどれか(範囲を明示) - friendは条件がfriend系(friendhpltmaxrateなど)のときに使用可能。 - around系は場所指定スキルで使用可能。 - - (map/) - mob.c / mob.h - mob_getfriend*()追加、mobskill_use()修正など - (db/) - mob_skill_db.txt - 最初の説明のみ修正。データは修正していません。 - --------------------- -//0861 by いど - -・サーバーsnapshot - --------------------- -//0860 by J - -・死神さんの手下召喚の修正に合わせてMOBスキルDBを修正 -(/conf) - mob_skill_db.txt 修正。 - --------------------- -//0859 by 獅子o^.^o -Alchemist warp 修正(Aegis参考) -(/conf) - (/warp) - npc_warp_job.txt 修正 - --------------------- -//0858 by 死神 - -・細かい修正。 -・MAX_MOBSKILLを24から32に変更。(ただ少しですがまたメモリー使用量が増えます。) -・プロボケーションで取る行動をmob_skill_db.txtのval1(値1)で設定できるように修正。 -・手下召喚で複数の種類を設定出切るように修正。(最大5つまで) -・メタモルフォーシスとトランスフォーメーションも複数の種類を設定できるように修正。 - (db/) - skill_db.txt 修正。 - mob_skill_db.txt 修正。 - (map/) - skill.c - skill_castend_damage_id()、skill_castend_nodamage_id() 修正。 - map.h 修正。 - mob.h 修正。 - mob.c - mob_readskilldb()、mob_summonslave()、mob_class_change() 修正。 - --------------------- -//0857 by J - -・OWN Ragnarokにのっていた情報を元にMOBスキルを修正。 -・chase(突撃)が実装されているとのことなので突撃(?)をchaseにかえて -コメントアウトをはずしました。 -・死神さんが実装したMOBスキルを使用するモンスターを狩場情報に載ってる情報を元に実装。 - (/conf) - mob_skill_db.txt - --------------------- -//0856 by 死神 - -・バグ修正と細かい修正。 -・battle_athena.confにmonster_attack_direction_change追加。 -・battle_athena.confのbasic_skill_checkとカプラの倉庫利用を合わせていましたがいつのまにかなくなったので取り戻し。(basic_skill_checkがnoなら基本機能スキルレベルに関係なく倉庫を使えます。) -・ピアーシングアタックの射程を3セルに変更して近接攻撃として認識するように修正。 -・A鯖でのテストでアンデッドの認識を属性によってすることがわかったのでundead_detect_typeのデフォルトを0に変更。 -・メタモルフォーシスやトランスフォーメーションで見た目がプレイヤーなら0x1b0パケットを送らないように変更。 -・ニューマバグは修正してみましたがスキルユニットの時間による作動仕様はまだ分析が完全じゃないので他の不具合が出てくるかも... - (conf/) - battle_athena.conf 修正。 - mapflag.txt 修正。(普通のダンジョンがシーズモードであるはずがないので) - (conf/npc/) - npc_town_kafra.txt 修正。 - (db/) - skill_db.txt 修正。 - (doc/) - conf_ref.txt 修正。 - script_ref.txt 修正。 - (map/) - pc.c - pc_modifybuyvalue()、pc_modifysellvalue() 修正。 - battle.h - battle.c - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack()、battle_weapon_attack() 修正。 - battle_config_read() 修正。 - skill.c - skill_unitsetting()、skill_castend_damage_id() 修正。 - skill_castend_nodamage_id() 修正。 - mob.c - mob_attack() 修正。 - pet.c - pet_attack() 修正。 - clif.c - mob_class_change() 修正。 - --------------------- -//0855 by asong - -・メタモルフォーシスでPCとして表示するMOBを指定した場合倉落ちするバグを「暫定」修正。 -・0x1b0パケでは無く0x7bを使うことで何とかしています。 -・使い分けをしたいところですが当方Cの知識が無く条件分岐が上手くいきませんでした。 -・もしかしたらプパの孵化(羽化?)がおかしくなってるかもしれません。 - (/map) - clif.c - mob_class_change() 修正。 - --------------------- -//0854 by Kalen - -・不足していた一次職転職クエスト追加及び、それに伴うWarp、Mob修正) - (/conf) - (/npc) - npc_job_archer.txt - npc_job_swordman.txt - npc_job_thief.txt(台詞修正、点数処理変更) - npc_job_magician.txt - (/warp) - npc_warp25.txt(一部移動) - npc_warp.txt(一部移動) - npc_warp_job.txt(新設) - (/mob) - npc_mob_job.txt -・雛祭りQuest追加及び、それに伴うNPC修正。アマツ行き船で料金を取らなかった問題修正 - (/conf) - npc_event_hinamatsuri.txt - npc_town_amatsu.txt - npc_town_guide.txt - npc_town_kafra.txt - 雛祭りを有効にするとアマツカプラをWに、 - アルベルタ南カプラを削除にするようにしています。 - --------------------- -//0853 by 死神 - -・バグ修正とNPCスキル関係の修正。 -・ダークブレスをMISC攻撃に変更。(ただ命中判定有り) -・クリティカルスラッシュ、コンボアタック、ガイデッドアタック、スプラッシュアタック、ブラインドアタック、カースアタック、ペトリファイアタック、ポイズンアタック、サイレンスアタック、スリープアタック、スタンアタック、ランダムアタック、ダークネスアタック、ファイアアタック、グラウンドアタック、ホーリーアタック、ポイズンアタック、テレキネスアタック、ウォーターアタック、ウィンドアタック、マジカルアタック、ブラッドドレイン、メンタルブレイカーはモンスターの武器射程に変更。そしてこれらのスキルをモンスターの攻撃射程によって遠距離攻撃と近距離攻撃になるように変更。 -・ピアーシングアタックは武器射程+2に変更。 -・エナジードレイン、ハルシネーションは魔法射程に変更。 -・ダークブレッシングの射程を4に変更とかかる確率を50+スキルレベル*5%に変更。(一応これも魔法なので少し射程を広くしました。基本魔法射程である8に変えるべきなのかどうかは微妙...) -・ガイデッドアタックはセイフティウォールとニューマを無効にする報告がありましたのでセイフティウォールとニューマが効かないように修正。 -・ディフェンダーはエフェクトだけ出るように修正。(スキルの仕様等をわかる方は情報をお願いします。) -・トランスフォーメーション実装。(メタモーフォシスと同じ物だそうです。ただこれは全然関係ない別のモンスターになる物らしいです。ニフルヘイムに使うやつがいるみたいです。) -・Athena雑談スレッド 其の弐の80をscript_ref.txtとして追加とちょっと修正。 - (db/) - skill_db.txt 修正。 - (doc/) - script_ref.txt 追加。 - (map/) - battle.c - battle_calc_damage()、battle_calc_pet_weapon_attack() 修正。 - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_calc_magic_attack()、battle_calc_misc_attack() 修正。 - skill.c - castend_damage_id()、castend_nodamage_id()、skill_use_pos() 修正。 - clif.c - clif_spawnnpc()、clif_parse_Restart()、clif_parse_QuitGame() 修正。 - mob.c - mobskill_castend_id()、mobskill_castend_pos() 修正。 - mobskill_use_id()、mobskill_use_pos() 修正。 - --------------------- -//0852 by ぴざまん - -・亀島4F・蟻D2F・アマツD1Fをテレポ不可、シーズモードに変更。 -・nosaveの引数にSavePointが指定できてなかったので追加。 -・PVPのmapflagをmapflag.txtに統合。 - (map/) - npc.c - npc_parse_mapflag() 修正。 - (conf/) - mapflag.txt 修正。 - npc/npc_pvp.txt 修正。 - --------------------- -//0851 by 胡蝶蘭 - -・ログイン時の暗号化keyが常に同じという大きな問題があったので修正 -・ログイン管理者ログイン(ladminで使用)でパスワードの暗号化に対応 - (login/) - login.c - login_session_data作成、暗号化keyをクライアントごとに作成など - (tool/) - ladmin - ver.1.05に。デフォルトでパスワードを暗号化するように。 - 暗号化のためにDigest::MD5モジュールを使用します。 - Digest::MD5が無い場合はパスワードの暗号化を行いません。 - (doc/) - admin_packet.txt - ログインサーバー管理ログイン部分変更 - --------------------- -//0850 by 死神 - -・NPCスキル実装。(ハルシネーション、キーピング、リック、メンタルブレイカー、プロボケーション、バリヤー、ダークブレッシング、ダークブレス) -・スキル自爆の制限はmob_skill_db.txtでやればいいものなので取り戻し。 -・battle_athena.confにpet_hungry_friendly_decrease追加。 -・ペットの腹が完全に減ると支援攻撃を中止するように変更。 -・属性変更スキルが作動しなかった問題修正。 -・メンタルブレイカーは10+スキルレベル*5%のSPを減らす。(攻撃は通常武器スキル攻撃) -・リックは必中でSP-100、スタン確率スキルレベル*5%。(ダメージは無し、bNoWeaponDamageで無効) -・プロボケーションはモーションが準備されてないモンスターは入れてもなんの効果もなし。 -・ダークブレッシングはかかるとHPが1になる。耐性は魔法防御で適用。 -・ダークブレスは500+(スキルレベル-1)*1000+rand(0,1000)のダメージ。回避できるが防御無視で近距離物理攻撃だがセイフティウォールは無視して闇属性攻撃。(本鯖の計算式にあっている可能性はないかも。ただダメージ量と命中補正以外は本鯖合わせ) -・NPCスキルの維持時間は適度に設定。 -・モンスターの属性攻撃とガイデッドアタックがセイフティウォールを無視するとの報告を受けたのですが修正するかどうかはちょっと微妙。(スプラッシュアタックもセイフティウォール無視かも) - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (db/) - cast_db.txt 修正。 - skill_db.txt 修正。 - (map/) - mob.c - mob_damage() 修正。 - clif.h 修正。 - clif.c - clif_skill_estimation()、clif_damage()、clif_skill_damage() 修正。 - clif_skill_damage2()、clif_pet_performance() 修正。 - pet.c - pet_performance()、pet_target_check()、pet_hungry() 修正。 - skill.h 修正。 - skill.c - skill_additional_effect()、skill_castend_damage_id() 修正。 - skill_castend_nodamage_id()、skill_status_change_start() 修正。 - battle.h 修正。 - battle.c - battle_get_def()、battle_get_mdef()、battle_calc_damage() 修正。 - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack()、battle_config_read() 修正。 - --------------------- -//0849 by lapis - -・街中のテストギルドフラグの表示がおかしかったのを修正。 -・ギルドメンバーは旗からアジトに飛べるように修正。 - (conf/gvg) - TEST_prtg_cas01_AbraiJ.txt 修正。 - --------------------- -//0848 by huge - -・スキル自爆を、HPが全回復している時は使えないよう修正。 -・スフィアマイン・バイオプラント・・・ターゲット変更できない...。 -・mobにターゲット無視IDを設定できるようにしました。(Gv用mobに使える?) - (map/) - map.h 修正。 - mob_dataに int exclusion_src,exclusion_party,exclusion_guild 追加。 - mob.h 修正。 - mob.c - mob_exclusion_add() 追加。 - mob_exclusion_check() 追加。 - mob_timer_delete() 追加。 - mob_attack() 修正。 - mob_target() 修正。 - mob_ai_sub_hard_activesearch() 修正。 - mob_ai_sub_hard_mastersearch() 修正。 - mob_ai_sub_hard() 修正。 - skill.c - skill_castend_damage_id() 修正。 - skill_castend_pos2() 修正。 - --------------------- -//0847 by 死神 - -・露店バグ修正。 - (map/) - clif.c - clif_vendinglist()、clif_openvending() 修正。 - vending.c - vending_openvending() 修正。 - skill.c - skill_castend_nodamage_id() 修正。 - --------------------- -//0846 by 死神 - -・バグ修正と細かい修正。 -・battle_athena.confのenemy_strがペットにも適用するように変更。 -・bHPDrainRateとbSPDrainRateでxがマイナスでも作動するように変更。 -・PCやNPCの姿をしたモンスターも死ぬと5秒後マップから消えるように変更。 - (map/) - battle.c - battle_calc_pet_weapon_attack()、battle_weapon_attack() 修正。 - skill.c - skill_attack()、skill_castend_damage_id() 修正。 - pc.c - pc_allskillup() 修正。 - clif.h 修正。 - clif.c - clif_openvending()、do_init_clif() 修正。 - clif_clearchar_delay()、clif_clearchar_delay_sub() 追加。 - mob.c - mob_damage() 修正。 - --------------------- -//0845 by ぽぽぽ - -・mob_avail.txtでPCグラフィック(0〜23)を指定したペットが出現したときクライアントエラーがでるのを暫定修正。 -・mob_avail.txtでペットにもPCキャラの性別・髪型&色・武器・盾・頭装備を指定できるようにしました。 -・MOBのATK計算にSTRを適用するかどうか設定可能にした。 - (map/) - clif.c - clif_pet0078()、clif_pet007b()、clif_spawnpet()修正。 - battle.h修正。 - battle.c - battle_config_read()、battle_calc_mob_weapon_attack()修正。 - --------------------- -//0844 by ぽぽぽ - -・mob_avail.txtでPCグラフィック(0〜23)を指定したMOBが出現したときクライアントエラーがでるのを暫定修正。 -・mob_avail.txtでPCキャラの性別・髪型&色・武器・盾・頭装備を指定できるようにしました。 - グラフィックすり替え先IDが0〜23の時だけ有効で、指定方法は - MOB-ID,グラフィックすり替え先ID,性別(0=female,1=male),髪型,髪色,武器,盾,上段頭装備,中段頭装備,下段頭装備 - となります。装備はitem_dbのView欄参照のこと。 - (map/) - clif.c - clif_mob_0078()、clif_mob007b()、clif_spawnmob()修正。 - mob.h修正。 - mob.c - mob_get_sex()、mob_get_hair()、mob_get_hair_color()、ob_get_weapon()、 - mob_get_shield()、mob_get_head_top()、mob_get_head_mid()、mob_get_head_buttom()追加。 - mob_readdb()、mob_readdb_mobavail()修正。 - --------------------- -//0843 by 死神 - -・リフレクトシールド実装。 -・アイテムスクリプトにbShortWeaponDamageReturnと -bLongWeaponDamageReturn 追加。 -・その他スキル関係や他の所修正。 - (db/) - item_db.txt 修正。 - skill_db.txt 修正。 - cast_db.txt 修正。 - const.txt 修正。 - (doc/) - item_bonus.txt 修正。 - (map/) - map.h 修正。 - battle.c - battle_get_def()、battle_get_def2()、battle_calc_pet_weapon_attack() 修正。 - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_weapon_attack()、battle_calc_magic_attack() 修正。 - pc.c - pc_calcstatus()、pc_bonus()、pc_bonus2()、pc_equipitem() 修正。 - pc_unequipitem()、pc_checkallowskill() 修正。 - skill.c - skill_attack()、skill_unit_onplace()、skill_status_change_start() 修正。 - skill_status_change_end()、skill_status_change_timer() 修正。 - skill_castend_nodamage_id() 修正。 - clif.c - clif_additem()、clif_equiplist()、clif_storageequiplist() 修正。 - clif_tradeadditem()、clif_storageitemadded()、clif_cart_additem() 修正。 - clif_cart_equiplist()、clif_vendinglist()、clif_openvending() 修正。 - clif_damage()、clif_skill_damage()、clif_parse_LoadEndAck() 修正。 - --------------------- -//0842 by 死神 - -・スキル関係の修正と細かい修正。 -・aegis鯖で色々と検証した物を適用。 -・メテオの範囲を7*7、LoV13*13、SG11*11、FN5*5に修正。 -・シグナム実装。(ただPVPでプレイヤーにかかるかどうかがわからなかったので -かかる方向で実装。)これで1次職業のスキルはクリアかも... -・装備スクリプトにbHPDrainRateとbSPDrainRate追加。 -・その他細かい修正少し。 - (doc/) - item_bonus.txt 修正。 - (db/) - cast_db.txt 修正。 - item_db.txt 修正。 - const.txt 修正。 - (map/) - map.h 修正。 - skill.c - skill_castend_damage_id()、skill_castend_nodamage_id() 修正。 - skill_unitsetting()、skill_castend_pos2()、skill_castend_id() 修正。 - skill_status_change_start()、skill_status_change_timer() 修正。 - skill_status_change_end()、skill_unit_onplace() 修正。 - skill_frostjoke_scream()、skill_attack() 修正。 - skill_attack_area() 追加。 - battle.c - battle_calc_magic_attack()、battle_get_element()、battle_get_def() 修正。 - battle_get_def2()、battle_get_mdef()、battle_damage() 修正。 - battle_calc_damage()、battle_calc_pet_weapon_attack() 修正。 - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_weapon_attack() 修正。 - mob.c - mobskill_castend_id() 修正。 - pc.c - pc_calcstatus()、pc_bonus2()、pc_attack_timer() 修正。 - clif.c - clif_spawnmob()、clif_spawnpet()、clif_spawnnpc() 修正。 - clif_parse_ActionRequest() 修正。 - --------------------- -//0841 by Kalen - -・水溶液が作れなかったので追加 - conf/npc/npc_job_magician.txt - --------------------- -//0840 by Kalen - -・鬼イベント追加 - conf/npc/npc_event_oni.txt - -・map_athena.conf修正(バレンタインコメントアウト。鬼追加) - conf/map_athena.conf - --------------------- -//0839 by shuto - -・コンロンNPC追加(カン ソンソンが抜けてた) - --------------------- -//0838 by 死神 - -・スキルサイトラッシャー実装。 -・モンスターのクローキングとマキシマイズパワーは持続時間をレベル*5秒に変更。 -・その他細かいバグ修正。 - (db/) - skill_db.txt 修正。 - (map/) - skill.c - skill_castend_damage_id()、skill_castend_nodamage_id() 修正。 - skill_castend_pos2()、skill_unitsetting()、skill_get_unit_id() 修正。 - skill_status_change_start() 修正。 - battle.c - battle_calc_magic_attack() 修正。 - --------------------- -//0837 by 死神 - -・スキル関係の細かい修正。 -・フロストノヴァをユニット設置式に変更。 -・ロードオブヴァーミリオンの範囲を11*11に修正と40ヒットするように変更。(ラグナゲートの情報。 -13*13説もありますが...) -・ユピテルサンダーのノックバックを2~7に変更。 -・ストームガストの攻撃回数をレベル依存から10回に固定。 -・サンクチュアリのノックバックを3から2に変更。(aegis鯖でノックバックがあることは確認しましたがどれぐらいなのかが不明だったので少し減らしてみました。) -・モンスターの詠唱時間が早くなっていた問題修正。(dex補正が入ってしまったせいです。) -・その他オートスペル当たりの細かい修正。 - (db/) - skill_db.txt 修正。 - (map/) - skill.c - skill_castfix()、skill_delayfix()、skill_timerskill() 修正。 - skill_castend_pos2()、skill_unitsetting()、skill_castend_damage_id() 修正。 - skill_castend_nodamage_id()、skill_get_unit_id()、skill_attack() 修正。 - battle.c - battle_calc_magic_attack()、battle_weapon_attack() 修正。 - --------------------- -//0836 by 釈尊 - -・モンスターの取り巻き召還の間隔を中ボス以外完全修正。 - (db/) - mob_skill_db.txt 修正。 - --------------------- -//0835 by (凸) - -・白刃取りでポーズをとるようにした。 -(ポーズだけなので、実際に攻撃を受け止めたりはできません) -clif_bladestop()を呼ぶことで白刃取り状態のON、OFFのパケットが送れます。 - - (map/) - clif.h 修正。 - clif,c - clif_bladestop() 追加 - skill.c - skill_castend_nodamage_id() 修正。 - --------------------- -//0834 by 釈尊 - -・モンスター取り巻き召還の間隔が短すぎるとの事で応急処置。(今回は黄金蟲のみ) - (db/) - mob_skill_db.txt 修正。 - --------------------- -//0833 by (凸) - -・memo禁止地域で/memo時の修正。 -・ついでにitem_dbを更新。 - - (doc/) - client_packet.txt - R 0189 更新。 - (db/) - item_db.txt 最新版へ更新。 - (map/) - pc.c - pc_memo() 修正。 - --------------------- -//0832 by 死神 - -・コード最適化と細かい修正。 -・オートスペルを地面魔法に対応。 -・サンダーストームとヘヴンズドライブをユニット設置式に変更。 -・ディフェンダーの攻撃速度低下を本鯖にあわせ。 -・その他細かい修正。 - (doc/) - item_bonus.txt 修正。 - (db/) - skill_require_db.txt 修正。 - cast_db.txt 修正。 - (map/) - map.h 修正。 - path.c - calc_index()、path_search() 修正。 - skill.c - skill_unitsetting()、skill_castend_pos2()、skill_get_unit_id() 修正。 - skill_status_change_timer_sub()、skill_castend_nodamage_id() 修正。 - skill_additional_effect()、skill_frostjoke_scream() 修正。 - pc.c - pc_calcstatus()、pc_skill()、pc_allskillup() 修正。 - battle.c - battle_get_speed()、battle_get_adelay()、battle_get_amotion() 修正。 - battle_weapon_attack() 修正。 - --------------------- -//0831 by 死神 - -・少し修正。 -・オートスペル修正。装備による物とスキルによる物を別々に適用、発動確率修正。 -・装備によるオートスペルは指定したレベルより2つ下まで判定をします。つまりレベル5を設定するとレベル3から5まで発動します。 -・battle_athana.confのplayer_cloak_check_wall、monster_cloak_check_wallをplayer_cloak_check_type、monster_cloak_check_typeに変更。 -・アイテムルート権限時間を本鯖に合わせて修正。 -・その他スキル関係の細かい修正。 - (doc/) - conf_ref.txt 修正。 - db_ref.txt 修正。 - item_bonus.txt 修正。 - (conf/) - battle_athana.conf 修正。 - (db/) - item_db.txt 修正。 - (map/) - map.h - map.c - block_free_max、BL_LIST_MAX 修正。 - skill.h 修正。 - skill.c - skill_additional_effect()、skill_attack()、skill_castend_damage_id() 修正。 - skill_castend_nodamage_id()、skill_unit_onplace() 修正。 - skill_status_change_end()、skill_status_change_start() 修正。 - skill_initunitgroup()、skill_unitsetting()、skill_castfix() 修正。 - skill_delayfix()、skill_autospell()、skill_use_id()、skill_use_pos() 修正。 - skill_check_cloaking()、skill_unit_timer_sub()、skill_check_condition() 修正。 - battle.h 修正。 - battle.c - battle_damage()、battle_get_agi()、battle_get_speed() 修正。 - battle_get_adelay()、battle_get_amotion()、battle_get_flee() 修正。 - battle_weapon_attack()、battle_calc_magic_attack() 修正。 - battle_config_read() 修正。 - mob.c - mob_attack()、mob_damage()、mobskill_use_id() 修正。 - mobskill_use_pos()、mob_spawn()、mob_class_change() 修正。 - mob_can_move() 修正。 - pc.c - pc_attack_timer()、pc_checkweighticon()、pc_calcstatus() 修正。 - pc_damage()、pc_equipitem()、pc_unequipitem() 修正。 - pc_bonus2()、pc_bonus3()、pc_memo()、pc_authok() 修正。 - pc_isUseitem() 修正。 - clif.h 修正。 - clif.c - clif_changeoption()、clif_parse_LoadEndAck()、clif_autospell() 修正。 - clif_skill_memo() 修正。 - clif_skill_teleportmessage() 追加。 - script.c - buildin_sc_start() 修正。 - atcommnad.c - atcommand() 修正。 - --------------------- -//0830 by huge - -・オートスペルで、自分の習得してるレベルよりも高いレベルで - 魔法が発動していたであろう問題を修正。 -・オートスペルでも、ちゃんとSPが減るように修正(ど忘れ) - (map/) - battle.c - battle_weapon_attack() 修正。 - skill.c - skill_autospell() 修正。 - --------------------- -//0829 by Kalen - -・mob_db修正 - 自鯖用のと間違ってUPしてしまったようです。 - 本来のものに直しました。 - --------------------- -//0828 by 聖 - -・サーバのSnapshot -・MVPボス系からバカンスチケットが大量に出ていた問題を修正。 - (common/) - version.h 修正。 - (db/) - mob_db.txt 修正。 - --------------------- -//0827 by J - -・固定MOBのはずのメガリスと人面桃樹が歩いていたのを修正。 -・闘技場のMOBにスキルを実装。 -・パサナとファラオがスキルが設定されていなかったのを実装。 - (db/) - mob_db.txt 修正。 - mob_skill_db.txt 修正。 - --------------------- -//0826 by ぴざまん - -・一部の演奏スキルを使うと鯖が落ちるバグ修正。 -・クローキング中にスキルを使用でき、 - 使用するとクローキングが解除されるように修正。 -・Kalenさんのmob_db.txtをまとめました。 - (map/) - skill.c - skill_unit_onplace()、skill_unit_onout() 修正。 - skill_status_change_start()、skill_status_change_timer() 修正。 - skill_use_id()、skill_use_pos() 修正。 - (db/) - mob_db.txt 修正。 - --------------------- -//0825 by 死神 - -・細かい修正。(細かいことのわりには修正した所が多いけど...) -・ワープポータルの中に止まった時以外はワープしないように修正。 -・battle_athena.confにplayer_skill_nofootset、monster_skill_nofootset 追加。 -・NPCをクリックした後露店をクリックして露店を閉じると動けなくなるバグ修正。 -ただ露店を閉じる時何のパケットも転送してこないので露店をクリックするとNPCの処理から抜けるようにしました。(本鯖ではNPCの処理が抜けないらしいですがそれ以外方法がなかったのっで。) -・killmonsterのAllで召喚されたモンスターだけ消すように変更。 -・ソース最適化やスキル関係の細かい修正多数。 - (doc/) - conf_ref.txt 修正。 - db_ref.txt 修正。 - (conf/) - battle_athana.conf 修正。 - atcommnad_athena.conf 修正。 - (db/) - item_db.txt 修正。 - skill_db.txt 修正。 - (login/) - parse_fromchar() 修正。 - (map/) - map.h 修正。 - clif.c - clif_closevendingboard()、clif_parse_VendingListReq() 修正。 - clif_mob0078()、clif_mob007b()、clif_pet0078()、clif_pet007b() 修正。 - skill.h 修正。 - skill.c - skill_check_condition()、skill_castend_pos2() 修正。 - skill_castend_damage_id()、skill_castend_nodamage_id() 修正。 - skill_castend_id()、skill_status_change_start()、skill_castfix() 修正。 - skill_delayfix()、skill_check_unit_range_sub() 修正。 - skill_check_unit_range()、skill_castend_pos()、skill_stop_dancing() 修正。 - skill_unit_onplace()、skill_readdb()、skill_timerskill()、skill_blown() 修正。 - skill_check_unit_range2_sub()、skill_check_unit_range2() 追加。 - skill_get_maxcount() 追加。 - mob.c - mobskill_castend_id()、mobskill_castend_pos()、mob_deleteslave() 修正。 - mob_stop_walking()、mob_walk()、mob_damage() 修正。 - pc.c - pc_calcstatus()、pc_checkskill()、pc_stop_walking() 修正。 - pc_walk()、pc_damage() 修正。 - npc.c - npc_touch_areanpc() 修正。 - pet.c - pet_stop_walking() 修正。 - script.c - buildin_killmonster()、buildin_killmonster_sub() 修正。 - battle.h - battle.c - battle_calc_magic_attack()、battle_get_flee()、battle_get_flee2() 修正。 - battle_get_adelay()、battle_get_amotion()、battle_get_max_hp() 修正。 - battle_get_hit()、battle_get_critical()、battle_get_atk2() 修正。 - battle_damage()、battle_config_read() 修正。 - atcommand.h 修正。 - atcommand.c 修正。 - --------------------- -//0824 by ぴざまん - -・セイフティウォール・ニューマの足元置きができなかった問題修正。 -・エンペリウムにヒール等の支援スキルが効いていた問題修正。 -・闘技場でモンスターリセットができなかった問題修正。 - killmonsterは"killmonster <mapname>,<eventname>"と記述して - 該当eventnameを持つモンスターを削除しますが - eventnameにAllと入れると該当MAPの全モンスターを消去するようにしました。 - - (map/) - skill.c - skill_check_unit_range_sub()、skill_castend_nodamage_id() 修正。 - script.c - buildin_killmonster()、buildin_killmonster_sub() 修正。 - (conf/npc/) - npc_event_tougijou.txt 修正。 - --------------------- -//0823 by Kalen - -・闘技場データ揃ったので、完成 - conf/npc/npc_event_tougijou.txt - ただし、こちらでチェックしたところkillmonsterがうまくいかず、 - 失敗、時間切れした場合モンスターリセットが出来ません。 - イベントが設定されているモンスターは処理できないのかと思いましたが - AgitのほうのエンペのKillmonsterはちゃんと動いてますし… - 原因分かる方お願いします<(_ _)> - -・gon_testのmapflag追加 - conf/mapflag.txt - -・mob_db更新 - 1419〜1491が既存のMobの定義ばかりなので追加しませんでしたが、 - 調べた所闘技場のMobのデータであることが分かりました(Dropを弄ったもの) - 本鯖では闇りんごが報告されています。が、こちらはDrop空白で処理しました。 - クライアント上では同名でしたが、区別のため接頭にG_をつけて区別してます。 - mob_skill_dbありがとうございました↓ - --------------------- -//0822 by ぴざまん - -・演奏スキルでの補正をダンサーにも適用。 -・サンクチュアリバグ修正。 -・KalenさんのMOBスキルデータベースをまとめときました。 - - (map/) - skill.c - skill_status_change_start()、skill_unit_onplace() 修正。 - battle.c - battle_get_critical()、battle_get_hit() 修正。 - pc.c - pc_calcstatus() 修正。 - --------------------- -//0821 by huge - -・オートスペル仮実装。 -・timerで判定しようかとも思いましたが、装備の無限オートスペルの為にsc_[].val1で見てマス。 -・bonus2 bAutoSpell追加。一応どんなスキルでも指定できるようにしてますが(番号はskill_tree参照) - skill_castend_damage_idのタイプ以外のスキルを指定しないでください。 - 発動確率は、Lv1:50%、Lv2:35%、Lv3:15%、それ以上は 5%固定です。 - あと、スキルレベルも指定できますが、限界を超えた数字を入れると墜ちるかもしれません。 -■書き方例:(ファイアボルトLv3の時)bonus2 bAutoSpell 19,3; - - (db/) - const.txt 修正。 - (map/) - battle.c - battle_weapon_attack() 修正。 - clif.h - clif.c - packet_len_table 修正。 - clif_autospell() 追加。 - clif_parse_AutoSpell() 追加。 - map.h 修正。 - pc.c - pc_bonus2() 修正。 - pc_equipitem() 修正。 - pc_unequipitem() 修正。 - skill.h - skill.c - skill_castend_nodamage_id() 修正。 - skill_autospell() 追加。 - skill_status_change_end() 修正。 - skill_status_change_start() 修正。 - status_changeの番号テーブル修正。 - --------------------- -//0820 by ぴざまん - -・アドリブのメッセージが入ってなかったので修正 -・バードの演奏スキルで楽器の練習や自ステータスの補正が入ってなかったのを修正。 - struct status_changeのvalが3つ必要だったので(val4は予約されてたっぽいので)val5を追加しました - (map/) - map.h 修正。 - skill.c - skill_status_change_start()、skill_castend_nodamage_id() 修正。 - skill_castfix()、skill_delayfix() 修正。 - battle.c - battle_get_flee()、battle_get_max_hp() 修正。 - battle_get_adelay()、battle_get_amotion() 修正。 - battle_calc_misc_attack() 修正。 - pc.c - pc_calcstatus() 修正。 - --------------------- -//0819 by Kalen - -・コンロン(NPC、Warp)修正 - conf/npc/npc_town_gonryun.txt(案内員補充) - conf/npc/npc_event_tougijou.txt - conf/warp/npc_warp_gonryun.txt(宿2FとD2Fなど) - -・MOB修正 - conf/mob/npc_monster30.txt(一反木綿不足追加) - conf/mob/npc_monster35.txt(コンロンMob追加) - -・DB修正 - db/mob_db.txt(コンロン[全て]+ウンバラ[定義]追加。Aspeed等適当です。まぁ無いよりましということで) - db/mob_skill_db.txt(情報を元にコンロンのMob分追加) - db/item_db.txt(Athena DB Project 2/19 21:10DL分) - --------------------- -//0818 by あゆみ - -・テレポートスキルLv1で、選択ウインドウが出てこないバグを修正。 -・重量が90%以上の場合でも、一部のスキルが使用可能だったバグを修正。 -・@allskillコマンドの修正とか。 - - (conf/) - msg_athena.conf 修正。 - (map/) - atcommand.c - atcommand() 修正。 - pc.c - pc_allskillup() 修正。 - skill.c - skill_castend_nodamage_id() 修正。 - skill_check_condition() 修正。 - --------------------- -//0817 by huge - -・ディボーションの処理修正 - ・糸の出し方はパケを貰ったのでできましたが、アイコンの方はまだ分からないです。 - ・あと、自分の環境で2人以上に同時に掛けれなかったので、複数人にかけた場合 - 多分0の羅列の所に2人目、3人目・・・のIDが入るんじゃないかなぁという予測でやってます。 -・ハイディング中、及びクローキング中にダメージを受けると解けるよう修正。 - - (map/) - battle.c - battle_damage() 修正。 - clif.c - clif_devotion() 修正。 - pc.c - pc_walk() 修正。 - skill.c - skill.h - skill_castend_nodamage_id() 修正。 - skill_devotion() skill_devotion2() 修正。 - skill_devotion3()skill_devotion_end() 修正。 - --------------------- -//0816 by ぴざまん -・ファイアーウォール3枚制限実装。 -・重ね置き禁止をプレイヤー・モンスターにも適用するように修正。 -・寒いジョーク・スクリームのPvP・GvGで、効果が自分にも及ぶバグ修正。 - ついでにPTメンバーには低確率でかかるのも実装。 -・寒いジョーク・スクリーム・スピアブーメランのディレイ修正。 - ミュージカルストライク・矢撃ちの詠唱時間修正。 - (map/) - skill.c - skill_check_condition()、skill_check_unit_range_sub() 修正。 - skill_check_unit_range()、skill_delunitgroup() 修正。 - skill_castend_pos2()、skill_frostjoke_scream() 修正。 - map.h 修正。 - (db/) - cast_db.txt 修正。 - --------------------- -//0815 by 死神 - -・0814のバグ修正と細かい修正。 -・mapflag monster_noteleport、noreturn追加とnoteleportの仕様変更。 -noteleportはプレイヤーのハエとテレポート、ワープスキルの制限をするが蝶は制限しないように変更、monster_noteleportはモンスターのテレポートを制限する物でnoreturnは蝶の使用を制限する物です。ただmapflag.txtは修正していません。(noreturnを設定する必要があります。) -・battle_athena.confのplayer_auto_counter_typeとmonster_auto_counter_typeが説明通りに機能しなかった問題修正。 -・battle_athena.confにplayer_cloak_check_wall とmonster_cloak_check_wall 追加。 -・ボスモンスターの認識をMVP経験とmodeの0x20で行なっていた物をmodeだけにするように変更。(本鯖のイベントモンスターでMVP経験をくれるが状態異常に掛かるやつがあったらしく修正。HPが1億もあって毒じゃないと倒せなかったらしいので...) つまりMVP経験があってもボス扱いではないモンスターを作ることも可能です。 -・状態異常に掛かった状態で接続切断ができないように修正。(ただタイマーチェックではなくopt1とopt2をチェックするだけなので見た目が変わる状態異常だけに適用されます。) -・今さらですが昔のyareCVS(2003年9月バージョン)で適用されていたラグを減らす為の処理を入れてみました。どんな効果があるかは自分でもわかりません。(ただ入れてみただけ...) -・シーズモードとPVPで禁止装備が外されても効果が消えないバグ修正。 -・その他細かい修正。 -・未テストの物もかなりあります。 - (common/) - socket.c - connect_client()、make_listen_port()、make_connection() 修正。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (map/) - battle.h 修正。 - battle.c - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_calc_magic_attack()、battle_config_read() 修正。 - skill.c - skill_unit_onplace()、skill_status_change_timer() 修正。 - skill_castend_nodamage_id()、skill_use_id() 修正。 - skill_check_unit_range_sub()、skill_timerskill() 修正。 - skill_additional_effect()、skill_attack()、skill_status_change_start() 修正。 - skill_check_cloaking() 修正。 - clif.c - clif_item_identify_list()、clif_parse_QuitGame()、clif_GM_kick() 修正。 - pc.c - pc_attack_timer()、pc_isUseitem()、pc_checkitem 修正。 - mob.c - mob_warp()、mob_walk()、mob_attack()、mob_target() 修正。 - mob_ai_sub_hard_activesearch()、mob_ai_sub_hard_mastersearch() 修正。 - mob_ai_sub_lazy()、mob_damage() 修正。 - npc.c - npc_parse_mapflag() 修正。 - map.h 修正。 - --------------------- -//0814 by 死神 - -・バグ修正と細かい修正。 -・battle_athena.confのplayer_auto_counter_typeとmonster_auto_counter_typeの仕様を変更。(本鯖ではスキル反撃はできないみたいなので設定できるように変更。) -・毒と石化によるHP減少を本鯖に合わせて修正と完全石化の前では動けるように変更。(毒は1秒に3+最大HPの1.5%(モンスターは0.5%)、石化は5秒に1%) 未テスト -・MVP経験値は本鯖でいつも入るようになったので修正。 -・スティールの確率を少し下げ。 -・モンスターのハイディング、クローキング、マキシマイズパワーがすぐに解除される問題修正。(モンスターにはSPがないせいです。取り敢えずクローキングはハイディングの時間を適用してマキシマイズパワーはウエポンパーフェクションの時間を適用します。) 未テスト -・サンクチュアリを人数から回数に変更。 -・PVPで自分のトラップに攻撃対象になるように変更。 -・vitペナルティの適用で乗算防御も減るように変更。(未テスト) -・その他細かいバグ修正。 - (conf/) - battle_athena.conf - (doc/) - conf_ref.txt - (db/) - skill_db.txt - (map/) - map.h 修正。 - script.c - buildin_itemskill() 修正。 - mob.c - mob_can_move()、mob_ai_sub_hard()、mob_damage() 修正。 - skill.c - skill_unitsetting()、skill_unit_onplace()、skill_castend_nodamage_id() 修正。 - skill_attack()、skill_status_change_start() 修正。 - skill_status_change_timer()、skill_status_change_timer_sub() 修正。 - skill_addtimerskill()、skill_cleartimerskill() 修正。 - skill_check_unit_range_sub() 修正。 - battle.c - battle_calc_damage()、battle_check_target() 修正。 - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack() 修正。 - pc.c - pc_steal_item() 修正。 - clif.c - clif_parse_WalkToXY()、clif_closevendingboard() 修正。 - --------------------- -//0813 by Kalen -・コンロンNPC追加 - conf/npc/npc_town_gonryun.txt(クエストは不明 - conf/npc/npc_town_kafra.txt - conf/npc/npc_town_guide.txt - (conf/npc/npc_event_tougijou.txt)データ不足 - -・全GvGMAPのMobデータ追加 - conf/mob/npc_monster_gvg.txt - -・TESTmobからテストギルドフラグ移動 - conf/gvg/TEST_prtg_cas01_AbraiJ.txt - --------------------- -//0812 by huge - -・ディボーションの仮実装 - ・パケットが全然分かりませんでしたので、 - 青い糸も出ないし、アイコンすら表示できません。 - ・ダメ移動だけで、ノックバック・オートガードは適応されません。 - - (map/) - clif.c - clif.h - clif_devotion() 追加。 - skill.c - skill_castend_nodamage_id() 修正。 - skill_devotion() skill_devotion2() 追加。 - skill_devotion3() skill_devotion_end() 追加。 - skill_status_change_end() 修正。 - skill_status_change_start() 修正。 - skill_brandishspear_first() 修正。 - skill_brandishspear_dir() 修正。 - pc.c - pc_authok() 修正。 - pc_walk() 修正。 - pc_damage() 修正。 - battle.c - battle_damage() 修正。 - map.h - map_session_data{} - struct square dev 追加。 - skill.h のbrandishをsquareに改名し、 - (common/) mmo.h に移動 - --------------------- -//0811 by ぴざまん - -・攻城中は蝶が使えるように修正 -・寒いジョーク・スクリーム実装(PTメンバーに低確率で云々は未実装です) -・GVGスクリプトを修正(試行錯誤しすぎてどこをどうしたか覚えてません…) - GVGスクリプトに関してですが、既知のバグがあります - それは、占領ギルドマスター以外のPCが、占領ギルドマスターより先にNPCに話し掛けると - マップサーバが落ちるというものです。 - これは、getguildmaster・getguildnameを使用しているスクリプトすべてに起こり得ることであり - 先に占領ギルドマスター以外で話し掛けると、guild_searchが何故か(該当IDのギルドがあるにも関わらず) - NULLを返す事に起因します。 - 正直スクリプト関係はよくわかっていないので、これは私の技術では修正のしようがありません。 - 暫定的な対処としてNULLを返してMAP鯖が落ちるくらいなら文字列「null」を返すようにしました。 - - (map/) - skill.c - skill_frostjoke_scream() 追加。 - skill_additional_effect()、skill_timerskill() 修正。 - skill_castend_nodamage_id() 修正。 - pc.c - pc_isUseitem() 修正。 - script.c - buildin_getpartyname()、buildin_getguildname() 修正。 - buildin_getguildmaster() 修正。 - (db/) - cast_db.txt 修正。 - (conf/gvg/) - ev_*.txt以外のtxt全てを修正。 - --------------------- -//0810 by 聖 - -・MVPの処理を変更。(確率で10000があっても、他のアイテムも出るようにしました) -・MVPで装備を入手した場合、鑑定済みで入手していた問題を修正。 -・スキル詠唱中にイグ葉や拡大鏡を使うとプレーヤーの使用可能な - 全スキルのLVが1に固定されてしまう問題を修正。 -・オークアーチャー等、モンスターによる罠スキルの有効期限が切れたときに、 - 設置用トラップが出る問題を修正。 -・ログインエラー(パスワード入力ミスやBAN等)のエラーメッセージが - 正しくクライアントに通知されない問題を修正。 -・その他細かな修正。 - (common/) - version.h 修正。 - (login/) - login.c - parse_login() 修正。 - parse_fromchar() 修正。 - (char/) - int_guild.c - mapif_parse_GuildLeave() 修正。 - (map/) - itemdb.c - itemdb_read_itemnametable() 修正。 - atcommand.c - atcommand() 修正。 - skill.c - skill_unit_timer_sub() 修正。 - script.c - buildin_itemskill() 修正。 - mob.c - mob_damage() 修正。 - --------------------- -//0809 by Kalen - -・東湖城ワープポイント修正 -・アマツ寿司屋修正 -・バグスレ129の問題修正? - - --------------------- -//0808 by ぴざまん - -・装備制限が上手く動作していなかったのを修正。 -・モンハウギルドはGvG開始時に作られるように変更。 -・GvG開始時に該当マップにいる全PC(占領ギルド員以外)をセーブポイントに戻すように修正。 -・モンハウギルドアジトでエンペを壊すと、モンハウが消えるように修正。 - この修正に伴ってmaprespawnguildidの引数のflagの仕様を変更しました - flagはビットフラグになり、 - 1ビット目:占領ギルド員をセーブポイントに戻すか - 2ビット目:占領ギルド員以外をセーブポイントに戻すか - 3ビット目:エンペ・ガーディアン以外のMOBを消すか - いずれも、0=NO、1=YESになります - - (conf/gvg/) - ev_agit_aldeg.txt 修正。 - ev_agit_gefg.txt 修正。 - ev_agit_payg.txt 修正。 - ev_agit_prtg.txt 修正。 - TEST_prtg_cas01_AbraiJ.txt 修正。 - TEST_prtg_cas01_mob.txt 修正。 - (map/) - pc.c - pc_checkitem() 修正。 - script.c - buildin_maprespawnguildid_sub() 修正。 - buildin_maprespawnguildid() 修正。 - --------------------- -//0807 by 死神 - -・0805でFD_SETSIZEを修正する所を間違ったので修正しました。56名止まりが治ると言う保証はありませんが... -・一度に転送するパケットの長さを32768bytesから65536bytesに変更。 - (common/) - mmo.h 修正。 - socket.h 修正。 - socket.c 修正。 - --------------------- -//0806 by Kalen - -・agitフォルダ→gvgフォルダへ移行 - 諸意見あると思いますが、jROでは攻城戦をgvgと呼ぶことが一般的なのでこちらに統合します。 - conf/gvg/ - ###agitフォルダを削除してください### (Please delete the "agit" folder.) - getmaster対応 - -・アマツの寿司屋バグ修正と項目追加(thx 114 - conf/npc/npc_town_amatsu.txt - -・map_flag再修正 - conf/map_flag.txt - [GVGMAP]確かに常にシーズモードなら問題ないですが、削除されましたので - 常にシーズモードではありません。従って解除時(時間外)には枝、テレポが使えます - 時間前に枝撒き、まだ実装してませんが宝箱奪取も可能になるので枝、テレポは常に使用不可で問題ないと思います。 - -後前回書き忘れましたが、momotaroイベントですが、ちょっと不安定な可能性があります。 -原因がわからないのですが、ループしてるかもしれません。一応コメントアウトしてあります - --------------------- -//0805 by 死神 - -・文字化け修正。 -・シーズモードでのテレポート禁止や古木の枝使用禁止はソースレベルで -処理しているのでmapflag.txtから削除。(因みにnopenaltyもソースレベルで -処理しています。) -・battle_athena.confのagit_eliminate_timeをgvg_eliminate_timeに変更。 -・@コマンド@GM削除。 -・FD_SETSIZEかcygwinで64に設定されていたのせいで最大接続人数が56名を -越えるとマップ鯖が無限ループする問題修正。(ただテストができなかった物なので本当に大丈夫になったかどうかは不明です。あくまでも自分の予測にすぎない物ですが...) -・文字化けのせいでどこをどう修正したか覚えてないので修正したファイルだけ。 - (conf/) - atcommand_athena.conf - battle_athena.conf - mapflag.txt - (db/) - castle_db.txt - (doc/) - conf_ref.txt - (common/) - mmo.h - (login/) - login.c - (char/) - inter.c - int_guild.c - (map/) - atcommand.h - atcommand.c - battle.h - battle.c - chrif.c - guild.h - guild.c - intif.h - intif.c - map.h - map.c - mob.c - npc.c - npc.h - script.c - skill.c - pc.c - makefile - --------------------- -//0804 by 釈尊 - -・アルベルタのぬいぐるみイベントでうさぎのぬいぐるみをあげるとサーバーが落ちるバグ修正 - - (conf/npc/) - npc_event_doll.txt 修正。 - --------------------- -//0803 by ぴざまん - - GvGでエンペリウム崩壊時gvg_eliminate_timeの値に関わらず即座に退去させられていたバグ修正 - GvGのセリフを一部修正 - inter鯖でcastle.txtがないと起こる色々なエラーを修正 - help.txtを修正(@gvgstart→@agitstart云々) - - (conf/) - gvg/TEST_prtg_cas01_AbraiJ.txt 修正。 - agit/ev_agit_prtgJ.txt 修正。 - help.txt 修正。 - (map/) - int_guild.c - inter_guild_init() 修正。 - --------------------- -//0802 by Michael_Huang - - Added NPC Script - 'GetGuildMaster' Command. - (common/) - version.h - Mod_Version 0802 - (map/) - script.c - buildin_getguildmaster_sub() buildin_getguildmaster() - --------------------- -//0801 by Kalen -・アマツ修正 - 実装前のデータ、抜けてるデータなどを調査し修正 - conf/npc/npc_town_guide.txt - conf/npc/npc_town_amatsu.txt - conf/npc/npc_event_momotaro.txt - conf/npc/npc_event_alchemist.txt - conf/mob/npc_monster35.txt - conf/warp/npc_warp_amatsu.txt -・map_flag修正 - [GVGMAP]枝、テレポは常に使用不可 -・GVG関係 - 0800のコマンドに対応 - --------------------- -//0800 by Michael_Huang - - Added Agit NPC Script & Command. - Fix FreeBSD GCC compatibility. - Attachment Agit Demo NPCs. - - (char/) - int_guild.c - mapif_guild_castle_dataload() mapif_guild_castle_datasave() - int mapif_parse_GuildCastleDataLoad() int mapif_parse_GuildCastleDataSave() - inter_guild_parse_frommap() inter_guildcastle_tostr() inter_guildcastle_fromstr() - inter.c - inter_send_packet_length[] inter_recv_packet_length[] - (common/) - mmo.h - GLOBAL_REG_NUM, struct global_reg {} - version.h - Mod_Version 0799. - (conf/) - atcommand_athena.conf - agitstart: 1,agitend: 1 - battle_athena.conf - agit_eliminate_time: 7000 - map_athena.conf - conf/agit/ev_agit_*.txt - (doc/) - conf_ref.txt - battle_athena.cnf - agitdb_ref.txt - (login/) - login.c - parse_login() - (map/) - atcommand.h - agitster, agitend - - atcommand.c - @agitstart, @agitend - battle.h - battle_config.agit_eliminate_time - battle.c - battle_config_read() - chrif.c - chrif_changedsex() chrif_connectack() - guild.h - guild_agit_start() guild_agit_end() guild_agit_break() - guild.c - guild_read_castledb() do_init_guild() - guild_agit_start() guild_agit_end() guild_agit_eliminate_timer() guild_agit_break() - intif.h - intif_guild_castle_dataload() intif_guild_castle_datasave() - intif.c - packet_len_table[] intif_guild_castle_dataload() intif_guild_castle_datasave() - intif_parse_GuildCastleDataLoad() intif_parse_GuildCastleDataSave() intif_parse() - map.h - agit_flag - map.c - agit_flag - npc.h - npc_event_doall() npc_event_do() - npc.c - npc_event_do_sub() npc_event_do() - script.c - buildin_maprespawnguildid() buildin_agitstart() buildin_agitend() - buildin_getcastlename() buildin_getcastledata() buildin_setcastledata() - skill.c - skill_unit_onplace() - skill_gangster_count() - --------------------- -//0799 by ぴざまん - -・GvG実装の為にinter-map間の通信仕様変更 -・0798のコンパイルエラー修正(byバグ報告スレ82氏) - (login/) - login.c - parse_login() 修正。 - (map/) - intif.c - packet_len_table[] 修正。 - intif_parse_GuildCastleInfo() 修正。 - intif_parse_GuildCastleChange()をintif_parse_GuildCastleChangeErr()に改名・修正。 - intif_parse() 修正。 - guild.c - guild_read_castledb() 修正。 - - (char/) - inter.c - inter_send_packet_length[] 修正。 - int_guild.c - inter_guildcastle_tostr() 修正。 - inter_guildcastle_fromstr() 修正。 - mapif_parse_GuildChangeCastle() 修正。 - mapif_parse_GuildCastleInfo() 修正。 - mapif_guild_castle_info() 修正。 - mapif_guild_change_castle()をmapif_guild_change_castle_err()に改名・修正。 - (common/) - mmo.h 修正。 - version.h 修正。 - --------------------- -//0798 by 胡蝶蘭 - -・login-serverのログイン失敗パケットの長さがおかしかったのを修正 -・login-serverにアクセスコントロール機能追加 - ・login_athena.cnfにorder,allow,denyを記述することで、 - IP単位(前方一致)でアクセスを禁止する機能。 - ・指定方法は doc/conf_ref.txt を参照 - - (doc/) - conf_ref.txt - login_athena.cnfの部分修正 - (login/) - login.c - グローバル変数 access_* 追加 - parse_login()修正,check_ip()追加 - -・アカウント作成用CGIスクリプト追加 - ・自己責任&詳細な解説無し、質問されてもスルーする可能性有り - ・エディタで開いたら少し説明有り - ・CGI設置の基本さえわかれば問題ないはず - ・メッセージは英語、日本語両対応 - (Accept-Languageがjaなら日本語に変換します) - ・管理者パスワードなしで動くのでセキュリティには注意(.htaccessなど推奨) - - (tool/cgi/) - addaccount.cgi - アカウント作成用CGI。 - -・その他 - (tool/) - backup - castle.txtもバックアップするように - --------------------- -//0797 by 死神 - -・少し修正。 -・battle_athena.confの項目変更。(lootitem_time 削除、item_first_get_time、 -item_second_get_time、item_third_get_time、mvp_item_first_get_time、 -mvp_item_second_get_time、mvp_item_third_get_time 追加。) -・アイテムルート権限を正しく実装。最初攻撃ではなく与えたダメージの -量によって収得権限を与えるように変更。(最初収得権限のみテスト) -パーティの場合パーティの設定に合わせる必要がありますがまだパケットが -不明な所がある為同じパーティなら収得できるようになっています。 -・ボウリングバッシュのバグ修正。(多分修正されたはず...) -・装備スクリプトbonusにbSplashRangeとbSplashAddRange追加。 -bSplashRangeとbSplashAddRangeは武器でダメージを与えた時のみ発動、通常の武器攻撃扱いなので避けられるが(Flee2による完全回避は不可能)クリは出ないようになっていて武器による状態異常は発生しません。本鯖仕様なんて知りません。 -・スキルの重ね置き処理を本鯖に合わせて修正。 -・mapflagのgvgはいつもなっているわけじゃないので削除。 -・その他細かい修正。 - athena-start 修正。 - (common/) - mmo.h 修正。 - (conf/) - mapflag.txt 修正。 - battle_athena.conf 修正。 - (db/) - const.txt 修正。 - item_db.txt 修正。 - (doc/) - conf_ref.txt 修正。 - item_bonus.txt 修正。 - (map/) - mob.c - mob_spawn()、mob_damage()、mob_class_change()、mob_warp() 修正。 - mob_delay_item_drop()、mob_delay_item_drop2() 修正。 - mobskill_castend_pos() 修正。 - pc.c - pc_takeitem()、pc_dropitem()、pc_equipitem() 修正。 - pc_calcstatus()、pc_bonus() 修正。 - skill.c - skill_attack()、skill_additional_effect()、skill_castend_damage_id() 修正。 - skill_castend_nodamage_id()、skill_produce_mix() 修正。 - skill_arrow_create()、skill_unit_timer_sub()、skill_castend_pos() 修正。 - map.h 修正。 - map.c - map_addflooritem() 修正。 - script.c - buildin_getitem() 修正。 - pet.c - pet_return_egg()、pet_get_egg()、pet_unequipitem() 修正。 - battle.h 修正。 - battle.c - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack() 修正。 - battle_weapon_attack()、battle_config_read() 修正。 - --------------------- -//0796 by huge - -・細かい修正 - (conf/npc/) - npc_event_valentine.txt 修正。 - - (map/) - pc.c - pc_takeitem() 修正。 - skill.c - skill_unit_timer_sub() 修正。 - --------------------- -//0795 by Kalen - -・雑談341のnpc_warp_niflheim.txt追加 - conf/warp/npc_warp_niflheim.txt - -・mapflag.txt修正(GVGMAP設定) - nosaveはしていません - -・map_athena.confの修正 - umbala niflheim等の追加 - コメントアウトしてあります。 - -・バレンタインスクリプト追加 - conf/npc/npc_event_valentine.txt - チョコ達のDropは弄っていません。お好みでどうぞ - 尚、手作りチョコを食べたときのエフェクトは - 最新クライアントにすれば見えます。 - -・GVGScript追加 - conf/gvg/以下 - Weiss時代に作成したものをAthena用にコンバート&台詞修正 - prtg_cas01以外は旗のみです。 - GVGDATAは鯖再起動で消滅します。 - エラーが出るようならコメントアウトしてください。 - MobData、執事Scriptもprtg_cas01のみです。(TestScript) - あくまでテストスクリプトです。GVG実装の参考にどうぞ - --------------------- -//0794 by DRG - -・skillusedで指定したIW,QMなどにのってる間MOBスキルを使用するように変更 -・アップスレ3の7のathena-startを一応含めときました - - athena-start - (map/) - skill.c - skill_unit_onplace() 修正。 - --------------------- -//0793 by huge - -・サーバーsnapshot -・サーバーがクラッシュするバグを修正 -・発動せずに罠が消えたら、設置用トラップが返ってくるように修正。 -・ルート権限で、同じパーティーのキャラはすぐ拾えるように修正。 -・バグ報告スレ3 >>54 のバグ修正。 -・ログイン時にサーバー側にIDを表示するようにしました。 - (login/) - login.c - parse_login() 修正。 - (conf/npc/) - npc_event_doll.txt 修正。 - (map/) - skill.c - skill_unit_timer_sub() 修正。 - mob.c - mob_spawn_dataset() 修正。 - mob_damage() 修正。 - pc.c - pc_additem() 修正。 - --------------------- -//0791 by 聖 - -・マップサーバがクラッシュするバグ修正。 -・イグ葉を使ってもジェムが必要になる問題を修正。 -・PvP強制送還実装。 -・PvPでリザレクションが出来なかった問題を修正。 -・その他細かな修正。 - (map/) - guild.c - mob.c - pc.c - skill.c - --------------------- -//0790 by 死神 - -・バグ修正。 - (conf/) - battle_athena.conf 誤字修正。 - (doc/) - conf_ref.txt 誤字修正。 - (common/) - mmo.h 修正。 - (map/) - itemdb.h 修正。 - map.h 修正。 - skill.c - skill_check_condition()、skill_use_pos()、skill_unit_onplace() 修正。 - --------------------- -//0789 by huge - -・ドロップアイテムにルート権限を実装。 -・最初に攻撃した人以外がドロップアイテムを拾えるまでの時間を設定できるように。 - (/conf) - battle_athena.conf 項目追加。 - - (/doc) - conf_doc.txt 説明追加。 - - (/map) - battle.h - Battle_Config{} 修正。 - battle.c - battle_config_read() 修正。 - itemdb.h - item_data {} 修正。 - map.h - flooritem_data {} 修正。 - mob_data {} 修正。 - map.c - map_addflooritem() 修正。 - mob.c - delay_item_drop{} 修正。 - mob_spawn() 修正。 - mob_damage() 修正。 - mob_delay_item_drop() 修正。 - mob_warp() 修正。 - pc.c - pc_takeitem() 修正。 - --------------------- -//0788 by あゆみ - -・cardスキルの処理?を修正。 -・@allskillコマンドの再修正。 - - (map/) - pc.c - pc_skill() 修正。 - pc_allskillup() 修正。 - --------------------- -//0787 by ぽぽぽ - -・ペットにもmob_avail.txtの設定を適用するようにした。 -・MOBスキルのskillusedでval1に0を入れるとあらゆるスキルに対して発動するようにした。 -・skillusedで発動したスキルの対象を、発動させたPCにするかどうか設定できるようにした(対IWハメなど?)。 - (/map) - clif.c - clif_pet0078()、clif_pet007b()修正。 - mob.c - mobskill_use()修正。 - skill.c - skill_attack() 、skill_castend_damage_id()修正。 - battle.h - battle.c - battle_config_read()修正。 - --------------------- -//0786 by huge - -・BDS修正 - 前から吹き飛ばして行くと良くないかもしれないので、後ろから処理 - 有効範囲の修正 - - (/map) - - skill.h - skill.c - skill_castend_damage_id() 修正。 - skill_castend_nodamage_id() 修正。 - skill_brandishspear_first() 修正。 - skill_brandishspear_dir() 修正。 - --------------------- -//0785 by 死神 - -・本鯖に合わせて修正。(韓国鞍のパッチnoticeを参考して修正しました。) -・BBとBSのキャスティング時間を0.7秒にしてディレイは0に変更。 -・ghostの変わりにマップ移動後の無敵時間を設定。この時間の間はどんな攻撃も受けないが移動や攻撃、スキル使用、アイテム使用でこの時間はなくなります。シーズモードではこの無敵時間を2倍として適用。 -・シーズモードで死んでも経験が減らないように修正。(mapflagのnopenaltyを設定する必要はありません。) -・スキッドで滑べる距離増加。 -・既に沈黙にかかってる対象にレックスディビーナを使うと沈黙が解除されるように変更。 -・呪いにかかると移動速度も減るように修正。 -・battle_athena.confに項目変更。 -・スキルの重ね置きを判断処理を少し変更。 -・HPの自然回復時間が4秒ではなく6秒だとわかったのでデフォルト修正とbattle_athena.conf修正。 -・その他細かい修正やバグ修正。 -・殆どテストしてません。 - (conf/) - atcommand_athena.conf 修正。 - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (db/) - cast_db.txt 修正。 - (map/) - atcommand.c 修正。 - clif.c - clif_mob0078()、clif_mob007b()、clif_skill_estimation() 修正。 - clif_mob_class_change()、clif_parse_WalkToXY() 修正。 - clif_parse_ActionRequest()、clif_parse_LoadEndAck() 修正。 - clif_parse_UseItem()、clif_parse_UseSkillToId() 修正。 - clif_parse_UseSkillToPos()、clif_parse_UseSkillMap() 修正。 - mob.h 修正。 - mob.c - mob_get_viewclass()、mob_attack()、mob_target() 修正。 - mob_ai_sub_hard_activesearch()、mob_ai_sub_hard() 修正。 - mobskill_castend_id()、mobskill_castend_pos() 修正。 - skill.h 修正。 - skill.c - skill_can_produce_mix()、skill_castend_damage_id() 修正。 - skill_castend_nodamage_id()、skill_castend_id() 修正。 - skill_castend_pos()、skill_use_id()、skill_readdb() 修正。 - skill_check_condition()、skill_unit_onplace()、skill_unitsetting() 修正。 - skill_additional_effect()、skill_check_unit_range() 修正。 - skill_check_unit_range_sub()、skill_status_change_end() 修正。 - skill_status_change_start() 修正。 - pc.h - pc.c - pc_ghost_timer()、pc_setghosttimer()、pc_delghosttimer() 削除。 - pc_gvg_invincible_timer() -> pc_invincible_timer()に変更。 - pc_setgvginvincibletimer() -> pc_setinvincibletimer()に変更。 - pc_delgvginvincibletimer() -> pc_delinvincibletimer()に変更。 - pc_authok()、pc_attack_timer()、pc_calcstatus() 修正。 - pc_setrestartvalue()、pc_damage()、pc_allskillup() 修正。 - do_init_pc() 修正。 - battle.h 修正。 - battle.c - battle_config_read()、battle_weapon_attack()、battle_check_target() 修正。 - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack()、battle_get_speed() 修正。 - map.h 修正。 - map.c - map_quit() 修正。 - --------------------- -//0784 by あゆみ - -・カードスキルを覚えている状態で@allskillコマンドを使用するとmap-serverが暴走する問題を修正。 - - (map/) - pc.c - pc_allskillup() 修正。 - --------------------- -//0783 by huge - -・ブランディッシュスピアの修正 - 範囲指定、斜めの際の格子範囲、攻撃力計算 - 多分合ってると思うんですけど、イマイチ自信が持てない・・・ - (参考)みすとれ巣 -スキル関連豆情報 -・スペルブレイカーをちょっと修正 -・プロボックをMVPmobに効かないよう修正 -・バグ報告スレ3 >>8 で報告されたものの取り込み - - (/db) - create_arrow.txt 修正。 - skill_db.txt 修正。 - - (/map) - battle.c - battle_calc_pet_weapon_attack() 修正。 - battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack() 修正。 - - skill.h - skill.c - skill_brandishspear_first() 追加。 - skill_brandishspear_dir() 追加。 - skill_castend_nodamage_id() 修正。 - skill_castend_damage_id() 修正。 - skill_unit_group() 修正。 - --------------------- -//0782 by ぴざまん -・@allskillコマンドの使用条件が参照されていなかったバグ修正 - (/map) - atcommand.c - atcommand() 修正。 - --------------------- -//0781 by Chunglyeng -・バド, ダンサー音楽具現 - (/map) - skill.c 修正。 - --------------------- -//0780 by reia -・ペコペコの卵などが孵化するとノビになってしまう問題修正。 -・GMコマンド「@kickall」が何時の間にか無効になっていたので修正。 - - (/conf) - atcommand_athena.conf 修正。 - (db/) - mob_skill_db.txt 修正。 - (map/) - atcommand.c - atcommand_config_read() 修正。 - --------------------- -//0779 by あゆみ - -・全スキル取得コマンドの追加。 - ・GMで全スキルを覚えられるようにしている場合や、スキルの数が多い職業は一部のスキル表示がおかしくなります。その場合はリログして下さい。 - @allskill : 現在の職業で取得可能な全スキルを取得する。(クエストスキル含む) - - (conf/) - battle_athena.conf 修正。 - help.txt 修正。 - (map/) - atcommand.h 修正。 - atcommand.c - atcommand() 修正。 - pc.h 修正。 - pc.c - pc_allskillup() 追加。 - (doc/) - conf_ref.txt 修正。 - help.txt 修正。 - --------------------- -//0778 by huge - -・スペルブレイカーの修正 - ・キャスティングタイムの無いスキルには効かないように修正。 - ・使用された相手の消費SPの修正。 - - (map/) - skill.c - skill_castend_nodamage_id() 修正。 - --------------------- -//0777 by ぴざまん - -・ギルド攻城戦仮実装 - ・基本的な部分だけしか実装してない上、いくつかの点で本鯖と相違があります。 - ・攻城戦開始と終了は@コマンドで行います - @gvgstart : 攻城戦開始 - @gvgend : 攻城戦終了 - ・battle_athena.confに項目追加。 - (char/) - int_guild.c - inter_guild_init()、inter_guild_readdb()、inter_guild_save() 修正。 - inter_castle_save_sub()、mapif_guild_castle_info() 追加。 - mapif_guild_change_castle()、mapif_parse_GuildCastleInfo() 追加。 - mapif_parse_GuildChangeCastle() 追加。 - inter.c - inter_config_read() 修正。 - inter_send_packet_length[]、inter_recv_packet_length[] 修正。 - int_guild.h 修正。 - (map/) - atcommand.c - atcommand()、atcommand_config_read() 修正。 - battle.c - battle_config_read() 修正。 - guild.c - guild_castle_search()、guild_read_castledb()追加。 - do_init_guild() 修正。 - guild_gvg_init()、guild_gvg_final()、guild_gvg_final_sub() 追加。 - guild_gvg_eliminate()、guild_gvg_eliminate_sub() 追加。 - guild_gvg_eliminate_timer()、guild_gvg_empelium_pos() 追加。 - guild_gvg_break_empelium() 追加。 - intif.c - intif_parse()、packet_len_table[] 修正。 - intif_parse_GuildCastleInfo()、intif_parse_GuildCastleChange() 追加。 - intif_guild_castle_info()、intif_guild_castle_change() 追加。 - mob.c - mob_damage() 修正。 - atcommand.h 修正。 - battle.h 修正。 - guild.h 修正。 - intif.h 修正。 - mob.h 修正。 - (common/) - mmo.h 修正。 - (conf/) - battle_athena.conf 修正。 - inter_athena.conf 修正。 - msg_athena.conf 修正。 - atcommand_athena.conf 修正。 - (db/) - castle_db.txt 追加。 --------------------- -//0776 by 死神 - -・NPCスキル孵化実装。(mob_skill_db.txtのval1を使います。) -・mob_skill_db.txtの確率を千分率から万分率に変更。(ただmob_skill_db.txtの修正はしてません。) -・モンスターがダブルアタックする問題修正。(修正されたかどうかの自信はありませんが...) -・その他細かい修正。 - (db/) - mob_skill_db.txt 修正。 - skill_db.txt 修正。 - (map/) - map.h 修正。 - mob.h 修正。 - mob.c - mob_spawn_dataset()、mob_spawn() 修正。 - mob_changestate()、mobskill_use() 修正。 - mob_class_change() 追加。 - npc.c - npc_parse_mob() 修正。 - battle.c - battle_check_target() 修正。 - clif.h 修正。 - clif.c - clif_mob_class_change() 追加。 - skill.c - skill_castend_nodamage_id() 修正。 - --------------------- -//0775 by 死神 - -・シーズモードの処理修正。 -・シーズモードの無敵時間の間はどんな攻撃も受けないように修正。 -・シーズモードの無敵時間が時間切れになる前には解除されないように修正。 -・battle_athena.confに項目追加。 -・@hideや/hideによるGMハイディング中は自分に自動使用されるスキル以外のスキル使用や攻撃を受けないように修正。 -・ハイディング中地属性スキル以外の攻撃を受けないように修正。(トラップやクァグマイア等のスキルは影響を受けるかどうか不明なので今までと同じように影響を受けるように処理。) -・トンネルドライブの移動速度を本鯖に合わせました。 -・その他バグ修正や細かい修正。(殆ど未テスト) - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (map/) - battle.h 修正。 - battle.c - battle_check_target()、battle_calc_damage() 修正。 - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack()、battle_calc_magic_attack() 修正。 - battle_calc_misc_attack() 修正。 - battle_config_read()、battle_weapon_attack() 修正。 - pc.h 修正。 - pc.c - do_init_pc()、pc_authok() 修正。 - pc_attack()、pc_attack_timer() 修正。 - pc_setgvg_ghosttimer()、pc_delgvg_ghosttimer()を - pc_setgvginvincibletimer()、pc_delgvginvincibletimer()に修正。 - pc_gvg_invincible_timer() 追加。 - pc_attack_timer()、pc_steal_item()、pc_calcstatus() 修正。 - clif.c - clif_parse_ActionRequest()、clif_parse_UseItem() 修正。 - clif_parse_UseSkillToId()、clif_parse_UseSkillToPos() 修正。 - clif_parse_UseSkillMap()、clif_parse_WalkToXY() 修正。 - map.h 修正。 - map.c - map_quit() 修正。 - mob.c - mob_attack()、mob_target()、mob_ai_sub_hard_activesearch() 修正。 - mob_ai_sub_hard_mastersearch()、mob_ai_sub_hard() 修正。 - mob_damage()、mobskill_castend_id()、mobskill_castend_pos() 修正。 - skill.c - skill_castend_damage_id()、skill_attack() 修正。 - skill_castend_id()、skill_castend_pos()、skill_castend_map() 修正。 - --------------------- -//0774 by 獅子o^.^o -・Monk job bouns 修正 -・ドケビ 修正 -(db/) - job_db2.txt 修正 - pet_db.txt 修正 - --------------------- -//0773 by 聖 - -・細かいバグ修正 - (map/) - skill.c 修正。 - battle.c 修正。 - --------------------- -//0772 by ぴざまん - -・シーズモード下で以下の点を修正 - ・連続して攻撃できなくなっていたバグ修正 - ・ダメージ軽減率が正しく設定できなかったバグ修正 - ・無敵時間実装。battle_athena.confのgvg_ghost_timeで設定できます - -・ハイディングで魔法攻撃等を回避できなかったバグ修正 - - (map/) - skill.c - skill_attack()、skill_unit_onplace()、skill_check_condition() 修正。 - clif.c - clif_parse_ActionRequest()、clif_parse_UseItem() 修正。 - clif_parse_UseSkillToId()、clif_parse_UseSkillToPos() 修正。 - clif_parse_UseSkillMap()、clif_parse_WalkToXY() 修正。 - pc.c - do_init_pc()、pc_authok() 修正。 - pc_attack()、pc_attack_timer() 修正。 - pc_setgvg_ghosttimer()、pc_delgvg_ghosttimer() 追加。 - pc_gvg_ghost_timer() 追加。 - map.c - map_quit() 修正 - battle.c - battle_config_read()、battle_weapon_attack() 修正。 - battle.h 修正。 - pc.h 修正。 - --------------------- -//0771 by huge - -・スペルブレイカー実装 - (map/) - skill.c - skill_castend_nodamage_id() 修正。 - (db/) - skill_db.txt 修正。 - --------------------- -//0770 by 聖 - -・青箱系の処理変更 -・その他バグ修正 - (map/) - battle.c 修正。 - itemdb.c 修正。 - mob.c 修正。 - script.c 修正。 - --------------------- -//0769 by 死神 - -・シーズモード修正。 -・無敵時間の方はghost_timer以外の方法で実装するつもりなので今は削除しています。 -・スクリプトviewpointが正しく動作しない問題修正。 -・produce_db.txtを修正。(乳鉢はskill_require_db.txtで処理しています。そしてアイテムの数を0にすれば消耗はされないけど作る時必要なアイテムになります。) -・その他細かい修正。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (db/) - produce_db.txt 修正。 - (map/) - battle.h 修正。 - battle.c - battle_calc_damage()、battle_calc_weapon_attack() 修正。 - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack()、battle_calc_magic_attack() 修正。 - battle_calc_misc_attack()、battle_check_target()、battle_config_read() 修正。 - skill.c - skill_unit_onplace()、skill_castend_damage_id()、skill_castend_id() 修正。 - skill_use_id()、skill_use_pos()、skill_check_condition() 修正。 - skill_can_produce_mix() 修正。 - pc.c - pc_attack_timer()、pc_attack()、pc_isUseitem()、pc_delitem() 修正。 - pc_damage() 修正。 - mob.c - mob_damage()、mobskill_use_id()、mobskill_use_pos() 修正。 - script.c - buildin_viewpoint()、buildin_emotion() 修正。 - makefile 修正。 - --------------------- -//0768 by ぴざまん - -・シーズモード下で、以下の点を修正 - ・死亡したらセーブポイントに強制送還するように修正 - ・特定のアイテムが使用できないように修正(アンティペインメント・ハエの羽) - ・特定のスキルが使用できないように修正(ワープポータル・バックステップ・インティミデイト・テレポート・インデュア) - ・同盟ギルドには無条件で攻撃できないように修正 - ・敵対ギルドには無条件で攻撃できるように修正 - ・無敵時間中は両者とも攻撃できないように修正 - -ソースレベルでテレポ、ハエの使用を禁じているため攻城戦MAPのmapflagにnoteleportは必要ありません -また、無敵時間はghost_timer依存です。つまりbattle_athena.conf内のghost_timeが無敵時間になります - - (map/) - skill.c - skill_castend_damage_id()、skill_castend_id() 修正 - skill_check_condition() 修正 - pc.c - pc_damage() 修正 - battle.c - battle_weapon_attack() 修正 - --------------------- -//0767 by huge - -・ファーマシーで、製造の書が減る問題を修正 -・武器製造DBで、いくつか抜けていたのを修正 - - (map/) - skill.c 修正。 - (db/) - produce_db.txt 修正。 - --------------------- -//0766 by ぴざまん - -・シーズモード下で、以下の点を修正 - ・正規ギルド承認がないとエンペリウムに攻撃が効かないように修正 - ・エンペリウムに対するスキル攻撃が効かないように修正 - ・魔法攻撃、遠距離攻撃、罠のダメージ補正を実装 - 魔法攻撃:50% 遠距離攻撃:75% 罠:60% - これは人にもエンペリウムにも適用されます - (map/) - battle.c - #include "guild.h" 追加 - battle_calc_damage()、battle_calc_weapon_attack() 修正 - --------------------- -//0765 by ぴざまん - -・装備制限実装 -・装備制限がかかった装備品は該当マップに移動した際に自動的に装備が外れ、 - 再装備もできなくなります -・制限できるのは装備品のみです。カード類は制限できません - (db/) - item_noequip.txt 追加 - (map/) - itemdb.h 修正 - itemdb.c - do_init_itemdb()、itemdb_search() 修正 - itemdb_read_noequip 追加 - pc.c - pc_checkitem()、pc_isequip() 修正 - --------------------- -//0764 by 死神 - -・全てのダメージが1になる防御を10000から1000000に変更。 -・battle_athena.confに項目追加。 -・モンスターから経験値を貰う処理を本鯖のように修正。 -・スキルスローポイズン実装。 -・交換バグ修正。 -・その他細かい修正。 -・テストは殆どしてません。 - (db/) - mob_db.txt 修正。 - skill_db.txt 修正。 - (doc/) - conf_ref.txt 修正。 - db_ref.txt 修正。 - (conf/) - battle_athena.conf 修正。 - (map/) - makefile 修正。 - battle.h 修正。 - battle.c - battle_get_def()、battle_get_mdef() 修正。 - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack()、battle_calc_magic_attack() 修正。 - battle_calc_misc_attack()、battle_config_read() 修正。 - skill.h 修正。 - skill.c - skill_castend_nodamage_id()、skill_castend_damage_id() 修正。 - skill_check_condition()、skill_status_change_timer() 修正。 - skill_status_change_end()、skill_status_change_start() 修正。 - skill_additional_effect()、skill_produce_mix()、skill_unit_timer_sub() 修正。 - skill_check_unit_sub()を skill_check_unit_range_sub()に変更。 - skill_check_unit_range() 追加。 - skill_castend_pos()、skill_area_sub_count() 修正。 - mob.c - mobskill_castend_pos()、mob_damage() 修正。 - clif.c - clif_parse_TradeRequest()、clif_parse_TradeAck() 修正。 - clif_parse_TradeAddItem()、clif_parse_TradeOk() 修正。 - clif_parse_TradeCansel()、clif_parse_TradeCommit() 修正。 - map.h 修正。 - map.c - do_init() 修正。 - pc.c - pc_calc_skilltree()、pc_calcstatus() 修正。 - tarde.c - trade_tradeack() 修正。 - --------------------- -//0763 by 胡蝶蘭 - -・サーバーsnapshot - フォルダを整理したので注意してください。 - 以前のセーブデータ(account.txtなど)はsaveフォルダに置いてください - cnfファイルは各種ファイルのパスが変わってるので、 - この古いものをコピーではなく、新しく書き換えなおしてください。 - -・フォルダ整理 - confフォルダ - NPC関連をconf/npc/、MOB配置関連をconf/mob/、WARP関連をconf/warp/ - テストやサンプルをconf/sample/に移動しました。 - dbフォルダ - sampleフォルダのうちdb関係を db/sampleに移動しました。 - help.txt/motd.txt - confフォルダに移動しました - account.txt/athena.txt/guild.txt/party.txt/pet.txt/storage.txt - saveフォルダに移動しました - tool/backup - パス修正 - -・motd.txt/help.txtのパスをmap_athena.cnfで指定できるように - map.h/map.c/atcommand.c/atcommand.h修正 - -・athena-startにrestartオプション追加 - ./athena-start restartでAthenaを再起動します - --------------- -//0761 by ぽぽぽ - -・MOBのMDEFに10000以上指定してもファイアピラーで普通にダメージを与えてしまうのを修正。 - (map/) - battle.c - --------------- -//0760 by ll3y - -・文字化け修正 - (map/) - script.c - --------------- -//0759 by 獅子o^.^o -・スピアクイッケン 修正 -・Dancer skill tree 修正 -(db/) - cast_db.txt 修正 - skill_tree.txt 修正 - --------------- -//0758 by hack -・Put GM messages into msg_table which is loaded from msg_athena.conf. -(Easy to translate into other language) - (map/) - atcommand.h - atcommand.c - msg_conf_read() Read conf/msg_athena.conf - Put messages into msg_table which is loaded from msg_athena.conf. - map.c - do_init() - (conf/) - msg_athena.conf Store the message of atcommand, easy to translate into other language. - --------------- -//0757 by Michael - (map/) - script.c - buildin_viewpoint() - Fix packet sequence of viewpoint command. - --------------- -//0756 by ll3y - -・Interix(Windows Services for Unix 3.5)でコンパイルが通るように修正 - Interop Systems(http://www.interopsystems.com/)よりgmakeとzlibを取ってくるか、 - 自前でInterix用を用意する必要があります。 - (common/) - socket.h 修正。 - --------------- -//0755 by 死神 - -・バグ修正と説明追加。(報告されたのは多分全て修正されたのかと...) -・0751でスキルの最大レベルを100まで設定できるようにしました。 -・cast_db.txtに入っている状態異常の維持時間は自分が適度に入れた物です。本鯖の仕様なんて知りませんので。 - (doc/) - db_ref.txt 修正。 - (db/) - cast_db.txt 修正。 - skill_db.txt 修正。 - (map/) - skill.h 修正。 - skill.c - skill_check_unit_sub()、skill_castend_id()、skill_use_id() 修正。 - skill_status_change_end()、skill_status_change_start() 修正。 - skill_castend_map() 修正。 - mob.c - mobskill_castend_id()、mobskill_castend_pos() 修正。 - pc.c - pc_calcstatus() 修正。 - battle.c - battle_calc_pc_weapon_attack() - battle_calc_mob_weapon_attack() - battle_calc_magic_attack() - --------------- -//0754 by 獅子o^.^o -(db/) - cast_db.txt 修正 - --------------- -//0753 by 聖 - -・IWの発生ポイントを指定するとメテオのエフェクトが一切出なくなる - 問題が復活していたので修正。 -・warningを出ないようにコード修正。 - (map/) - skill.c - skill_castend_pos2() 修正。 - chrif.h - --------------- -//0752 by ぴざまん - -・changesexスクリプト実装。性別を反転させることができます - 性別反転成功後は、そのプレイヤーは強制的に接続を切断されます - また、ダンサー・バードの互換性はかなり怪しいです - ダンサー・バードがスロット内どこかに居るアカウントでの反転は、以下の点に注意して下さい - ・必ず反転させる前にそのキャラクターをスキルリセットしてください - そのまま反転させると、共通するスキル(楽器の練習等)しか残らなくなってしまいます - ・ダンサー・バード専用武器を装備している場合は、外してから反転させてください - そのまま反転させると、そのキャラクターの開始時に - クライアントエラーが出ます(出るだけで、落ちることはないのですが…) -・データベース修正 by 獅子o^.^o - (map/) - chrif.c - packet_len_table[]、chrif_parse()修正 - chrif_changesex()、chrif_changedsex()追加 - chrif.h 修正 - (char/) - char.c - parse_frommap()、parse_tologin()修正 - (login/) - login.c - parse_fromchar()修正 - (db/) - cast_db.txt 修正 - skill_require_db.txt 修正 - --------------- -//0751 by 死神 - -・skill_db.txtとcast_db.txtの変更とskill_require_db.txtの追加。 -・毒にかかるとHPが減るように変更。HPは1秒に最大HPの1%減ります。(未テスト) -・石化を進行中の物と完全な物に分けてHPが減るように変更。(1秒に最大HPの1%)ブレッシングで完全石化だけ治せるように修正。(未テスト) -・ハンターのトラップにエフェクト実装。ただランドマインとショックウェーブは爆発エフェクトが出ないようです。ランドマインはファイアピラーの爆発エフェクトが出るように変えています。 -・オートカウンターの方向チェックをするように変更と本鯖仕様に合わせました。 -・バックスタブも方向チェックをするように変更。 -・インティミデイトの処理変更。 -・ディフェンダーの移動速度減少を本鯖に合わせました。ASPDは勝手ながら -(30 - (skilllv*5))%が減るようにしましたが本鯖でいくら程減るのかの情報をお願いします。 -・トンネルドライブLV1で移動速度が150から312になるのが確認されて計算を変更しましたがレベルによってどれぐらい増加するかは不明です。情報を求めます。(今の計算式は適度に作った物です。) -・ポーション製造の計算式変更とちょっと修正。 -・一部地面スキルの重ね置きを禁止。 -・bNoMagicDamageで魔法による異常やステータスアップ効果が出ないように修正。(リザレクション以外の魔法は無効になります。) -・battle_athena.confに項目追加。 -・その他色々と修正。 -・変更されたskill_db.txt、castdb.txtと追加されたskill_require_db.txtの構造は今の所自分しか知らないのでdb_ref.txtに説明を追加する予定なのでそれまではこれらの変更は控えてください。 - (char/) - int_guild.c 修正。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (db/) - skill_db.txt 修正。 - skill_require_db.txt 修正。 - cast_db.txt 修正。 - (map/) - battle.h 修正。 - battle.c - battle_counttargeted()、battle_calc_pet_weapon_attack() 修正。 - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_weapon_attack()、battle_config_read() 修正。 - skill.h 修正。 - skill.c - skill_attack()、skill_castend_damage_id() 修正。 - skill_castend_nodamage_id()、skill_status_change_start() 修正。 - skill_check_condition()、skill_castend_pos() 修正。 - skill_use_id()、skill_use_pos() 修正。 - skill_status_change_timer()、skill_status_change_start() 修正。 - skill_check_unit_sub() 追加。 - pc.h 修正。 - pc.c - pc_damage()、pc_counttargeted()、pc_counttargeted_sub() 修正。 - mob.h 修正。 - mob.c - mob_countslave()、mob_counttargeted()、mob_counttargeted_sub() 修正。 - mobskill_use()、mob_can_move()、mob_damage() 修正。 - mobskill_use_id()、mobskill_use_pos()、mobskill_castend_id() 修正。 - mobskill_castend_pos() 修正。 - map.c - map_quit() 修正。 - --------------- -//0750 by CHRIS - -・スキル関係のDBを調整 - (db/) - skill_db.txt - cast_db.txt - skill_require_db.txt - --------------- -//0749 by 死神 - -・色々と変更と修正。 -・スキルの仕様変更や実装、状態異常の仕様変更や実装。 -・スキルの使用条件をdbに設定できるように変更。 -・skill_db.txtとcast_db.txtの仕様変更。 -・マップ鯖の無限ループ可能性がある部分を修正。(あくまでも可能性が -あっただけの物です。無限ループの原因とは断言できません。) -・トラップの発動実装。(ただ実際に動作はまだ修正していません。 -見た目が変わっただけです。) -・battle_athena.confに項目追加を削除。 -・0748の修正削除と文字化け修正。 -・skill_db.txt、cast_db.txt、skill_require_db.txtの方がまだ完成されていないので -かなりの量のスキルが正しく動作しません。(db_ref.txtに設定方法を入れないと - けないのですが時間がなかったので...) そして修正はしましたがテストは -殆んどしてませんので注意してください。 - (char/) - char.c 修正。 - int_party.h 修正。 - int_party.c 修正。 - int_guild.h 修正。 - int_guild.c 修正。 - int_pet.h 修正。 - int_pet.c 修正。 - int_storage.h 修正。 - int_storage.c 修正。 - charの方は大した修正はしてません。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (db/) - skill_db.txt 修正。 - cast_db.txt 修正。 - skill_require_db.txt 追加。 - produce_db.txt 修正。 - (map/) - map.h 修正。 - map.c - map_check_dir() 追加。 - map_readmap()、map_addblock()、map_delblock() 修正。 - map_foreachinarea()、map_foreachinmovearea() 修正。 - map_addflooritem() 修正。 - pc.h 修正。 - pc.c - pc_spiritball_timer()、pc_addspiritball()、pc_delspiritball() 修正。 - pc_steal_item()、pc_steal_coin()、pc_calcstatus() 修正。 - pc_checkallowskill()、pc_jobchange()、pc_checkweighticon() 修正。 - pc_damage()、pc_equipitem()、pc_walk()、pc_stop_walking() 修正。 - pc_authok()、pc_counttargeted()、pc_counttargeted_sub() 修正。 - pc_damage()、pc_setpos() 修正。 - skill.h 修正。 - skill.c - skill_get_range()、skill_get_sp()、skill_get_num() 修正。 - skill_get_cast()、skill_get_delay() 修正。 - skill_get_hp()、skill_get_zeny()、skill_get_time() 追加。 - skill_get_time2()、skill_get_weapontype() 追加。 - skill_get_unit_id()、skill_blown()、skill_additional_effect() 修正。 - skill_attack()、skill_castend_damage_id() 修正。 - skill_castend_nodamage_id()、skill_castend_id() 修正。 - skill_castend_pos()、skill_unit_onplace() 修正。 - skill_unit_timer_sub_onplace()、skill_unitsetting() 修正。 - skill_use_id()、skill_use_pos()、skill_check_condition() 修正。 - skill_status_change_end()、skill_status_change_timer() 修正。 - skill_status_change_start()、skill_can_produce_mix() 修正。 - skill_produce_mix()、skill_gangsterparadise() 修正。 - skill_gangster_out()、skill_gangster_in() 修正。 - skill_gangster_count() 追加。 - skill_readdb() 修正。 - battle.h 修正。 - battle.c - distance()、battle_counttargeted()、battle_get_range() 追加。 - battle_get_dir() 追加。 - battle_get_maxhp()、battle_get_str()、battle_get_agi() 修正。 - battle_get_vit()、battle_get_dex()、battle_get_int() 修正。 - battle_get_luk()、battle_get_flee()、battle_get_hit() 修正。 - battle_get_flee2()、battle_get_critical()、battle_get_baseatk() 修正。 - battle_get_atk()、battle_get_atk2()、battle_get_def() 修正。 - battle_get_def2()、battle_get_mdef()、battle_get_speed() 修正。 - battle_get_adelay()、battle_get_amotion()、battle_get_party_id() 修正。 - battle_get_guild_id()、battle_get_size() 修正。 - battle_check_undead() 追加。 - battle_check_target()、battle_addmastery() 修正。 - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack()、battle_weapon_attack() 修正。 - clif.h 修正。 - clif.c - clif_skillinfo()、clif_skillinfoblock()、clif_skillup() 修正。 - clif_item_skill()、clif_changeoption()、clif_parse_LoadEndAck() 修正。 - clif_01ac() 追加。 - clif_parse_WalkToXY()、clif_parse_ActionRequest() 修正。 - clif_parse_TakeItem()、clif_parse_DropItem() 修正。 - mob.h 修正。 - mob.c - mobskill_castend_id()、mobskill_castend_pos() 修正。 - mobskill_use_id()、mobskill_use_pos()、mob_heal() 修正。 - mob_spawn()、mob_damage()、mob_walk() 修正。 - mob_stop_walking()、mob_warp()、mob_counttargeted() 修正。 - mob_counttargeted_sub()、mob_countslave() 修正。 - mob_attack()、mob_target()、mob_ai_sub_hard_activesearch() 修正。 - mob_ai_sub_hard_mastersearch()、mob_ai_sub_hard() 修正。 - script.c - buildin_sc_start() 修正。 - path.c - can_move() 修正。 - pet.c - pet_data_init()、pet_stop_walking() 修正。 - npc.c - npc_parse_warp()、npc_parse_shop()、npc_parse_script() 修正。 - --------------- -//0748 by Michael - (map/) - pc.c - pc_walk(); - Fix Player cannot move in ICEWALL but have Path. - mob.c - mob_walk(); - Fix Monster cannot move in ICEWALL but have Path. - path.c - can_move(); - Fix Player&Monster cannot move in ICEWALL. - --------------- -//0747 by 聖 -・ペットがエモを出すとmap-serverが落ちることがあった問題を修正。 - (map/) - clif_parse_SendEmotion() 修正。 - --------------- -//0746 by Michael - (map/) - script.c - Add Script command - checkoption(type); - Attach a npc_testchkoption.txt npc script! - --------------- -//0745 by ぴざまん -・ギャングスターパラダイス実装 -・PvPエリアのmapflagを修正(同士討ちが無くなったかと思います) -・シーズモードでノックバックがあったバグを修正 -・インティミの遅延時間を少し調整 - (map/) - skill.c - skill_attack()、skill_additional_effect()修正 - skill_gangsterparadise()、skill_gangster_in()、skill_gangster_out()追加 - clif.c - clif_parse_ActionRequest()修正 - mob.c - mob_target()、mob_attack()修正 - mob_ai_sub_hard()、mob_ai_sub_hard_mastersearch()修正 - mob_ai_sub_hard_activesearch()修正 - map.h 修正 - skill.h 修正 - (conf/) - npc_pvp.txt 修正 - --------------- -//0744 by 聖 - -・アイスウォール、メテオストームのコンボでメテオストームのエフェクトが表示されなくなる問題を修正。 -・HP吸収スキルのエフェクト修正。 -・battle_athena.confに項目追加。 -・パケ周りの細かい修正。 - (conf/) - battle_athena.conf - (doc/) - conf_ref.txt - (map/) - battle.c - battle.h - clif.c - pc.c - pet.c - skill.c - --------------- -//0743 by J - -・取り巻き召喚などを本鯖に似せる為の修正。 - あと本鯖相違スレにあったゴスリンの取り巻きを修正。 - デリーターの空と地のスキルが逆になっていたのを修正。 - (db/) - mob_skill_db.txt 修正 - --------------- -//0742 by ぴざまん - -・インティミデイトを実装 - 攻撃とワープの分別がうまくいかなかったので - SC_INTIMIDATEを使って遅延処理をしました -・skill_dbの誤字等を修正 - (map/) - skill.c - skill_additional_effect()、skill_castend_map()修正 - skill_castend_nodamage_id()、修正 - skill_status_change_start()、skill_status_change_end()修正 - map.h 修正 - skill.h 修正 - (db/) - skill_db.txt 修正 - --------------------- -//0741 by whitedog - -snapshot - --------------- -//0740 by ぽぽぽ -・PCがMOBにタゲられたとき3匹目から防御と回避が減るようにした。 - 1匹につき回避は10%、防御は5%減ります。 - (map/) - pc.h - pc.c - pc_counttargeted()、pc_counttargeted_sub()追加 - battle.c - battle_get_flee()、battle_get_def()、battle_get_def2()修正。 - --------------- -//0739 by 聖 -・ファイアーウォール等の設置系スキルが正しく表示されない問題を修正。 -・マリンスフィアが自爆するとサンダーストーム等のダメージが表示されなくなる問題を修正。 -・HP吸収系スキルで敵が回復してるエフェクトが出るよう修正。 - (map/) - skill.c - skill_castend_damage_id() 修正。 - battle.c - battle_calc_misc_attack() 修正。 - clif.c - clif_getareachar_skillunit() 修正。 - clif_skill_setunit() 修正。 - --------------- -//0738 by ぴざまん -・ストームガストを完全に本鯖仕様に修正(3回で絶対凍結&凍結状態の敵はSGをくらわない) -・サフラギウムが自分にかけられるバグ修正 - (map/) - skill.c - skill_additional_effect()、skill_attack()修正 - skill_castend_nodamage_id()修正 - map.h 修正 - --------------- -//0737 by ぽぽぽ -・アンクルが歩いている敵に効かない&複数の敵に効くのを修正。 - (map/) - skill.c - skill_unit_onplace()、skill_unit_onout()修正 - mob.c - mob_stop_walking()修正 - --------------- -//0736 by ぴざまん -・状態異常耐性が効果時間にも及ぶ様に修正。発動率と同率で効果時間が割り引かれます -・ストーンカースの効果時間を永久からマジスレテンプレ準拠に -・攻撃を受けた時にペットの支援攻撃を受けられないよう修正(コメントアウトしただけ) - これはVIT型にペットを付けて放置するだけで自動でレベル上げができるのを - 防ぐための暫定的な処置です - (map/) - skill.c - skill_castend_nodamage_id()、skill_addisional_effect()修正 - skill_status_change_start()修正 - pc.c - pc_damage() 修正 - --------------- -//0735 by ぽぽぽ - -・敵を倒してレベルが上がったときPT公平範囲のチェックをするようにした。 -・オートカウンター仮実装。 - 向きや射程チェックはしていません。またタイミングがおかしいかもしれません。 - MOBスキルとして使うときはターゲットをselfにしてください。 - (conf/) - battle_athena.conf項目追加 - (doc/) - conf_ref修正 - (map/) - battle.h - battle.c - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() - battle_config_read()修正 - pc.c - pc_checkbaselevelup()、pc_attack_timer()修正 - skill.c - skill_castend_nodamage_id()、skill_status_change_start()修正 - clif.c - clif_parse_WalkToXY()修正 - mob.c - mob_attack()修正 - --------------- -//0734 by 死神 - -・player_skillup_limitの処理修正と細かい修正。 -・player_skillup_limitがyesの場合skill_tree.txtで設定されてるその下位職業の -スキルツリーを使いますのでその職業では無くなるはずのスキルが出ることが -ありますがこれは仕様でありバグではありません。バグ報告されても無視します。 - (doc/) - conf_ref.txt 修正。 - (char/) - char.c - mmo_char_sync_timer()、do_init() 修正。 - inter.c - inter_init() 修正。 - inter_save_timer() 削除。 - (map/) - pc.c - pc_calc_skilltree() 修正。 - pc_resetskill() 修正。 - --------------- -//0733 by 死神 - -・バグ修正と細かい修正。 -・死んだ後にすぐにセーブポイントに戻らずにしばらく放置してると、 -放置してる時間によって経験値が減少するバグ修正。(未テスト) -・mob_availe.txtで設定したモンスターにモンスター情報を使うち鞍落ちする問題修正。 -・battle_athena.confに項目追加。 -・その他細かい修正。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (map/) - clif.c - clif_skill_estimation()、clif_parse_Restart() 修正。 - pc.c - pc_setrestartvalue()、pc_makesavestatus() 修正。 - pc_read_gm_account()、pc_calc_skilltree() 修正。 - pc_calc_skillpoint() 追加。 - map.c - map_quit() 修正。 - mob.c - mob_damage() 修正。 - skill.c - skill_unit_timer_sub()、skill_unit_timer() 修正。 - battle.h 修正。 - battle.c - battle_config_read() 修正。 - --------------- -//0732 by Kalen - -・npc_town_kafra.txtの全面見直し - カプラ利用券の廃止 - 倉庫利用料を本鯖(jRO)と同一価格に調整 - カート使用料を本鯖(jRO)と同一価格に調整 - ポイント参照変更 - ジュノーのセーブポイント修正 - アマツのセーブポイント修正 - --------------- -//0731 by ぽぽぽ - -・服の色を保存するかbattle_athena.confで選択できるように。 - 弊害があるので保存しないようにと書いてあったのでデフォルトでは保存しません。 -・スクリプト追加 - strcharinfo(1) 自分のパーティー名を取得します。 - strcharinfo(2) 自分のギルド名を取得します。 - getcharid(1) 自分のパーティーIDを取得します。 - getcharid(2) 自分のギルドIDを取得します。 - getpartyname(ID) IDで指定したパーティーの名前を取得します。 - getguildname(ID) IDで指定したギルドの名前を取得します。 - (map/) - battle.h - battle.c - battle_config_read()修正 - pc.c - pc_makesavestatus()修正 - script.c - buildin_strcharinfo()修正 - buildin_getcharid()、buildin_getpartyname()、buildin_getpartyname_sub() - buildin_getguildname()、buildin_getguildname_sub()追加 - --------------- -//0730 by ぴざまん - -・ストームガストの凍結時間を本鯖にあわせて修正(スキルレベルに関係なく一定の凍結時間(10秒)になります) -・スタン、暗闇、沈黙、毒の状態異常時間の「継ぎ足し」ができないように修正 -・状態異常が掛かりにくすぎてたのでMOBの状態異常耐性を緩和(また調整するかも) - (map/) - skill.c - skill_castend_nodamage_id()、skill_addisional_effect()修正 - skill_status_change_start()修正 - --------------- -//0729 by DRG - -・カートレボリューションがカートなしで使えた不具合の修正 -・カートレボリューションがJOBLV30で覚えれたのを修正 - (conf/) - npc_event_skillget.txt - カートレボリューション項修正 - (map/) - skill.c - skill_check_condition()修正 - --------------- -//0728 by ぽぽぽ - -・職が変わってもギルドの職業欄が更新されない不具合の修正。 - - (char/) - inter.c - パケット長リスト修正。 - int_guild.c - mapif_guild_memberinfoshort()、mapif_parse_GuildChangeMemberInfoShort()、 - inter_guild_parse_frommap()修正 - (map/) - intif.h - intif.c - intif_guild_memberinfoshort()、intif_parse_GuildMemberInfoShort() - intif_parse()修正 - guild.h - guild_send_memberinfoshort()、guild_recv_memberinfoshort()修正 - - --------------- -//0727 by 聖 - -・武器研究スキルによってホルグレンなどの精錬NPCが - 正常に動作しない問題を修正。 - - (map/) - pc.c - pc_percentrefinery() 修正。 - --------------- -//0726 by 胡蝶蘭 - -・mob_skill_db2.txtがあればmob_skill_db.txtをオーバーライドするように修正 - オリジナルのMOB使用時や、現行MOBの使用スキルを変更したい場合に。 - -・mob_skill_db.txtでmob_idの次のダミー文字列が"clear"だった場合、 - そのMOBのスキルを初期化する機能追加。 - ・mob_skill_db2.txtであるMOBのスキルを完全に書き換えるときに使用して - ください。 - ・clearしなかった場合はmob_skill_db.txtのものに追加されます。 - - mob.c - mob_readskilldb()修正 - - -・アイテム名/MOB名が全角12文字(24バイト)あるアイテム/MOBが、 - @コマンドで取り寄せ/召喚できない問題修正。 - mob.c - mobdb_searchname()修正 - itemdb.c - itemdb_searchname_sub()修正 - -・現在時刻でイベントを起こす「時計イベント」機能を追加 - ・OnInitと同じようにそれぞれのNPCで、On〜で始まるラベルを定義します。 - OnMinute?? :毎時、??分にイベントを起こします。(0-59) - OnHour?? :毎日、??時にイベントを起こします。(0-23) - OnClock???? :毎日、??時??分にイベントを起こします。 - OnDate???? :毎年、??月??日にイベントを起こします。 - ・詳しくは npc_test_ev.txt を参照 - - (conf/) - npc_test_ev.txt - 内容追加 - (map/) - npc.c - 色々修正 - -・その他 - clif.c - コンパイル警告が出ないように修正 - --------------- -//0725 by 死神 - -・鯖落ちバグ修正。 -・モンスターにイベントが設定されていて自殺やなにかでダメージを与えた -物がない場合鯖落ち確定なのでそのマップにあるプレイヤーを利用して -イベントスクリプトを実行するように変更。 - (map/) - makefile 修正。 - mob.c - mob_timer()、mob_damage() 修正。 - --------------- -//0724 by 死神 - -・バグ修正と安定化の為の修正。 -・ペットの攻撃でイベントが処理されず鯖落ちになる問題修正。(未テスト) -・モンスターの大量発生で鯖が落ちる問題修正。(モンスターを10000匹を呼んで -魔法で倒すことを5回程テスト。ただ動かないやつのみ。) -・取り巻きがボスと一緒に死ぬ時アイテムを落とさないように変更。(未テスト) -・battle_athena.confのpc_skillfleeをplayer_skillfreeに変更して処理を変更。 -・アイスウォールにskill_unit_settingを使うスキルで攻撃できないように修正。 -・その他細かい修正少し。安定化されたかどうかはまだわかりませんがXP1800+、512M、モンスター配置50%で10000匹召喚して異常なかったので大丈夫になったと思います。大丈夫じゃなくても責任はとれませんが... - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (map/) - mob.h 修正。 - mob.c - mob_timer()、mob_deleteslave_sub()、mob_damage() 修正。 - npc.c - npc_event() 修正。 - skill.c - skill_area_sub()、skill_unit_onplace()、skill_castend_nodamage_id() 修正。 - clif.c - clif_parse_GMKick() 修正。 - battle.h - battle.c - battle_damage()、battle_check_target()、battle_config_read() 修正。 - pc.c - pc_calc_skilltree()、pc_checkskill() 修正。 - map.h 修正。 - map.c - map_foreachinarea()、map_foreachinmovearea() 修正。 - map_foreachobject() 修正。 - --------------- -//0723 by DRG - -・0719の修正 - (map/) - pc.c pc_calc_skilltree()修正 - --------------- -//0722 by パイン - -・gcc 2.29系列でもコンパイルが通るように修正。 - これは以前にも直したはずなのですが、なぜか元に戻っていましたので - 皆さん注意をお願いします。 - あと、gcc3系列なら定数はどこに書いても問題ないのですが、 - gcc2.29系列では「必ずブロック要素の一番最初」に書かないとコンパイルが - 通りませんのでこちらもご注意願います。 - -コンパイルが通る例 -void hoge() { - const char booboo = 1; - … - -コンパイルが通らない例 -void hoge() { - … - const char booboo = 1; - … - - (map/) - skill.h マクロを修正 - skill.c skill_addisional_effect()修正 - --------------- -//0721 by 聖 - -・ボスにレックスデビーナが効いた問題を修正。 -・ボスにカードによる状態異常が効かなかった問題を修正。 - 本鯖ではマリナカード等でオークヒーローなどを殴ると時々凍結します。 - (結構微妙な実装方法なので、何か問題があった場合 - その辺詳しい方おりましたら修正してやってください(^^; )) - --------------- -//0720 by 胡蝶蘭 - -・PCにIWを重ねるとMOBが攻撃してこない問題を修正 - ・IWに重なっていても、隣接可能ならMOBが近寄ってきます - ・どんな地形にいても、隣接しているなら攻撃可能になります - ・ただし、MOBが遠距離攻撃可能で、攻撃範囲内にPCがいても、 - 隣接不可能なら攻撃してきません。これの解決はかなり面倒なので。 - - mob.c - mob_can_reach()修正 - battle.c - battle_check_range()修正 - --------------- -//0719 by DRG - -・下位スキルがない場合は上位スキルがふれないようにしました。 - battle_athena.confのskillfleeで設定可能です。 - 下位スキルがないまま上位スキルをふった状態で、このオプションを使う場合はスキルリセットする必要があります。 - 一般アカにスキルリセットを解放したいときに使ってやって下さい。 - (conf/) - battle_athena.conf - (map/) - battle.c - battle.h - pc.c pc_calc_skilltree(),pc_checkskill()修正 - --------------- -//0718 by 死神 - -・色々と修正。 -・毒によって防御が減るように変更。(HPはまだ減りません。) -・アイスウォールに攻撃できるように変更。(今は全ての攻撃に当たります。) -ただ鞍のバグらしくアイスウォールをクリックすると鞍から0x89パケットが30回以上連続で送ってくることが起こりますが原因は不明です。多分鞍のバグだと思いますが...) -・戦闘に関わる計算等を修正。 -・ゼニが増えるバグ修正。(多分これでこのバグはなくなると思いますがどうなのか報告をお願いします。) -・二刀流の左手武器の種族、属性、Sizeのダメージ補正を右手武器に適用するかどうかを設定できるように変更。 -・その他修正はしたはずですが覚えてません。(修正してない物もありますがdiff当ての途中でどれを作業したのかを忘れたので...) - (common/) - mmo.h 修正。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (map/) - battle.h 修正。 - battle.c - battle_get_baseatk()、battle_get_speed()、battle_get_adelay() 追加。 - battle_get_amotion() 、battle_calc_pet_weapon_attack() 修正。 - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_get_atk()、battle_get_atk_()、battle_get_atk2() 修正。 - battle_get_attack_element()、battle_get_attack_element2() 修正。 - battle_get_str()、battle_get_agi()、battle_get_vit()、battle_get_int() 修正。 - battle_get_dex()、battle_get_luk()、battle_get_flee() 修正。 - battle_get_flee2()、battle_get_hit()、battle_get_critical() 修正。 - battle_get_def()、battle_get_def2()、battle_get_mdef() 修正。 - battle_get_element()、battle_check_target()、battle_check_range() 修正。 - battle_weapon_attack()、battle_config_read() 修正。 - clif.c - clif_skill_estimation()、clif_mob0078()、clif_mob007b() 修正。 - pc.c - pc_attack_timer()、pc_attack()、pc_calcstatus()、pc_payzeny() 修正。 - pc_getzeny() 修正。 - npc.c - npc_buylist()、npc_selllist() 修正。 - pet.c - pet_attack()、pet_randomwalk()、pet_ai_sub_hard() 修正。 - mob.h 修正。 - mob.c - calc_next_walk_step()、mob_attack()、mobskill_castend_id() 修正。 - mobskill_use_id()、mobskill_use_pos()、mob_ai_sub_hard() 修正。 - mob_damage()、mob_changestate() 修正。 - mob_get_adelay()、mob_get_speed() 削除。 - skill.h 修正。 - skill.c - skill_unitsetting()、skill_unit_ondamaged()、skill_unit_timer_sub() 修正。 - skill_unit_timer()、skill_area_sub()、skill_unit_onplace() 修正。 - skill_status_change_start() 修正。 - chat.c 修正。 - makefile 修正。 - chrif.c 修正。 - guild.c 修正。 - itemdb.c 修正。 - map.c 修正。 - party.c 修正。 - script.c 修正。 - path.c 修正。 - --------------- -//0717 by 聖 - -・大量にモンスターを召還して一度に倒すとmap-serverが落ちる問題を修正。 - (カホを100体ずつ召還して50回テストをしたので恐らく大丈夫だと思います。) -・その他結構細かい修正 - (common/) - mmo.h - (map/) - chat.c - chrif.c - clif.c - guild.c - itemdb.c - map.c - mob.c - npc.c - party.c - path.c - pc.c - pet.c - script.c - skill.c - skill.h - --------------- -//0716 by 聖 - -・精錬成功率に対してBSの武器研究が正しく適用されていなかった問題を修正。 - (map/) - pc.c - pc_percentrefinery() 修正。 - --------------- -//0715 by 死神 - -・マップサーバーから表示される物を表示するかどうかの設定ができるようにしました。スキル表示だけでもなくしてやるとサーバーがかなり楽になったりもします。 -開発やバグトレースの時は表示することをお勧めします。 -・その他細かい修正。 -・修正した所を全て書けないのでファイルだけ。 - (doc/) - conf_ref.txt - (conf/) - battle_athena.conf - (map/) - makefile - skill.c - script.c - pet.c - pc.c - path.c - party.c - npc.c - itemdb.c - intif.c - guild.c - chat.c - battle.h - battle.c - chrif.c - atcommand.c - clif.c - mob.c - map.c - --------------- -//0714 by 死神 - -・細かい修正。 -・シールドブーメランで盾の重量と精錬によってダメージが増えるように修正。精錬ダメージを足す時適用でダメージ+重量+盾精錬*4(この4はrefine_db.txtの防具の過剰精錬ボーナスを使ってるので変更可能です。)になります。 -・スキルによる吹き飛ばし処理で0x88パケットを使っていましたがそのパケットの優先順位がかなり低いらしく後で来るパケットによって無視されることもあるようなのでプレイヤーだけに適用してモンスターには0x78を使うように変更しました。 -でも位置ずれは完全になくならないようです。(恐らく鞍のバグだと思います。鯖の -座標を確認してみましたが鯖の方は問題がありませんでした。) -プレイヤーの場合0x78(PACKETVERが4以上なら0x1d8)が使えません。分身を作ってしまうので... -・バグ報告スレッド2 の47を取り込みました。 -・その他修正した所少しあり。 - (db/) - refine_db.txt 修正。 - item_db.txt 修正。 - (map/) - battle.c - battle_stopattack()、battle_stopwalking() 修正。 - battle_get_attack_element2()、battle_calc_pc_weapon_attack() 修正。 - battle_weapon_attack() 修正。 - path.c - path_blownpos() 修正。 - pc.h 修正。 - pc.c - pc_stop_walking()、pc_damage() 修正。 - pc_getrefinebonus() 追加。 - mob.c - mob_damage() 修正。 - pet.c - pet_target_check()、pet_stop_walking()、pet_performance() 修正。 - skill.c - skill_attack()、skill_blown()、skill_status_change_start() 修正。 - skill_castend_damage_id() 修正。 - makefile 修正。 - --------------- -//0713 by ぽぽぽ - -・mob_avail.txt追加。item_avail.txtと同様の指定でモンスターの見た目を他のIDのものに変更します。 - モンスターのID以外を指定したりするとPCやNPCの姿をしたMOBに一方的に攻撃される場合があるので注意。 - (db/) - mob_avail.txt 追加。 - (map/) - clif.c - clif_mob0078()、clif_mob007b() 修正。 - mob.h 修正。 - mob.c - mob_readdb_mobavail()、mob_get_viewclass()追加。 - do_init_mob()、mob_readdb() 修正。 - --------------- -//0712 by 死神 - -・シールドチャージ、シールドブーメラン実装。 -・オートガードはとりあえずエフェクトが出るように変更しました。 -・0708で書き忘れ。ディフェンダーを使った時ASPDと移動速度は20%低下します。 -本鯖で低下するのは確かのようですがどれぐらい下がるのかはさっぱりわかりまんので... -・その他細かい修正。 - (db/) - cast_db.txt 修正。 - skill_db.txt 修正。 - (map/) - battle.h 修正。 - battle.c - battle_calc_damage()、battle_calc_pet_weapon_attack() 修正。 - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_calc_magic_attack()、battle_calc_misc_attack() 修正。 - skill.c - skill_additional_effect()、skill_attack()、skill_castend_nodamage_id() 修正。 - skill_check_condition()、skill_status_change_start() 修正。 - skill_castend_damage_id() 修正。 - pc.h 修正。 - pc.c - pc_calcstatus()、pc_checkallowskill()、pc_unequipitem() 修正。 - --------------- -//0711 by npc - -・鉱石製造エフェクトの修正 -・スクリプト埋め込み変数にHp,MaxHp,Sp,MaxSpを追加(読み込みのみ) - (map/) - skill.c - skill_produce_mix()修正。 - pc.c - pc_readparam()修正。 - (db/) - const.txt 修正。 - --------------- -//0710 by 胡蝶蘭 - -・名前に半角スペースが入ったパーティーを作成したとき、および、 - 半角スペースが入った名前のPCをパーティメンバにしたとき、 - party.txtが正しく読み込めなくなる問題を修正 - - (char/) - int_party.c - inter_party_fromstr()修正 - -・Message of the Day 機能追加 - ・ログインしたユーザーにMOTDを表示させることが出来ます。 - ・map-server.exe実行時のカレントディレクトリ(help.txtと同じ - ディレクトリ)にmotd.txtを作ると表示します。 - ・MOTDが表示されるタイミングは、 - 「マップサーバーにログインした直後の、マップロード完了時」です。 - つまり、ログイン直後、キャラセレ直後および、 - マップサーバー間移動の時(マップサーバーの分散を行っている場合のみ) - のマップロードが終わった時に表示されます。 - ・表示方法はhelp.txtと同じで普通のメッセージとして送信します。 - (ギルド告知メッセージは文字数制限があり、GMアナウンスは長時間 - 画面の上部に表示されてしまうため) - ・会話と区別がつくように、"< Message of the Day >"、"< End of MOTD >" - の文で上下を囲います。 - - (map/) - pc.c - pc_authok()修正 - - --------------- -//0709 by ぽぽぽ - -・スクリプトにemotion追加 - emotion n;と使うとNPCがエモを出します。nは0〜33が使用可能。 -・精錬と街ガイドのNPCを本鯖の台詞に合わせて修正。 - (conf/) - npc_town_refine.txt、npc_town_guide.txt 修正。 - (map/) - script.c - buildin_emotion() 追加。 - --------------- -//0708 by 死神 - -・スキルキャストキャンセル、ディフェンダー、オートガード実装。 -・オートガードの場合ガードしてもエフェクトは出ません。ミスになるだけです。本鯖の方は表示されるかどうかもわからないしパケット情報もないので... -・ディフェンダーは未テスト。bLongAtkDefを使ってるのでホルンカードのようにbLongAtkDefを上げる物を装備して使うと遠距離物理攻撃を全て無効にできます。(これも本鯖の仕様がどうなのかはわかりません。) -・その他細かい修正。 - (db/) - cast_db.txt 修正。 - (map/) - map.h 修正。 - map.c - map_quit() 修正。 - skill.h 修正。 - skill.c - skill_castend_nodamage_id()、skill_use_id()、skill_check_condition() 修正。 - skill_castend_id()、skill_castend_nodamage_id()、skill_castcancel() 修正。 - pc.c - pc_calcstatus()、pc_setpos()、pc_damage() 修正。 - battle.c - battle_calc_damage()、battle_damage() 修正。 - clif.c - clif_parse_UseSkillToId()、clif_parse_UseSkillToPos() 修正。 - mob.c - mob_damage() 修正。 - itemdb.c - itemdb_searchrandomid() 修正。 - --------------- -//0707 by 死神 - -・0705の阿修羅覇鳳拳のバグ修正。 - (db/) - skill_db.txt - (map/) - skill.c - skill_castend_id() - skill_castend_pos() - battle.c - battle_calc_pc_weapon_attack() - clif.c - clif_parse_UseSkillToId() - --------------- -//0706 by kalen -・修正 - conf/npc_warp_umbala.txt - --------------- -//0705 by 死神 - -・色々と修正。 -・プレイヤーのクリティカル計算にバグがあったので修正。 -・爆裂波動の処理修正。 -・モンクのコンボを修正。 -・阿修羅覇鳳拳の使用によってマップ鯖の無限ループバグ修正。(これかなり致命的な物だったようです。) -・コンボで使う阿修羅覇鳳拳は敵をクリックする必要がないように修正。 -・猛龍拳で敵を吹き飛ばす距離を5セルに変更。よってコンボで使う阿修羅覇鳳拳は距離チェックをしません。5セル飛ばされた敵は阿修羅覇鳳拳の射程から離れたわけなので距離チェックなしで発動します。(本鯖の仕様なんて知りません。) -・マップの名前を16byteから24bytesに変更。(大した意味はありませんが安全の為の物です。) -・ウェディングキャラによる鞍落ちを防ぐ為に修正。 -・その他少し修正。(テストは殆んどしてません。) - (conf/) - battle_athena.conf 修正。 - (db/) - skill_db.txt 修正。 - (common/) - mmo.h 修正。 - (doc/) - conf_ref.txt 修正。 - item_bonus.txt 修正。 - (map/) - battle.h 修正。 - battle.c - battle_get_flee2()、battle_calc_pet_weapon_attack() 修正。 - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_weapon_attack()、battle_calc_magic_attack() 修正。 - battle_config_read() 修正。 - skill.h 修正。 - skill.c - skill_status_change_start()、skill_castend_damage_id() 修正。 - skill_check_condition()、skill_use_id()、skill_blown() 修正。 - skill_castend_map()、skill_unit_onlimit()、skill_attack() 修正。 - pc.c - pc_attack_timer()、pc_setpos()、pc_setsavepoint() 修正。 - pc_movepos()、pc_calcstatus()、pc_bonus() 修正。 - clif.h 修正。 - clif.c - clif_set0078()、clif_set007b() 修正。 - clif_updatestatus()、clif_initialstatus()、clif_parse_UseSkillToId() 修正。 - clif_skillinfo() 追加。 - map.h 修正。 - map.c - map_setipport()、map_addmap() 修正。 - その他抜けた所少しあり。 - --------------------- -//0704 by kalen - -・Umbala Warp追加 - conf/npc_warp_umbala.txt - --------------------- -//0703 by いど - -・サーバーsnapshot - --------------- -//0702 by ぽぽぽ - -・ファーマシーのエフェクトを本来のものに変更 -・スクリプトでの埋め込み変数にBaseExp,JobExp,NextBaseExp,NextJobExp追加 - (map/) - skill.c - skill_produce_mix() 修正。 - pc.c - pc_readparam()、pc_setparam() 修正。 - (db/) - const.txt 修正。 - --------------- -//0701 by ぴざまん - -・ステータス異常判別式導入。各ステータス異常の発動率がVIT/INT/MDEFに影響するようになります。持続時間短縮はまた今度で_| ̄|○ -・不死に凍結が効いたバグ修正。 - (map/) - skill.c - skill_additional_effect()、skill_castend_nodamage_id() 修正。 - --------------- -//0700 by 南 - -・697のバグ修正。 - (db/) - mob_db.txt - --------------- -//0699 by 死神 - -・装備のボーナスクリティカルは自分の間違いだったのでbCriticalRateをbCriticalに変更。それと0695で書き忘れですがASPDを上げるカードや装備の一部をbAspdAddRateからbAspdRateに変更しました。みすとれ巣のシミュレーターによるとドッペルカードは複数でも一つしか適用されないみたいだったので。 - (db/) - item_db.txt - --------------- -//0698 by 死神 - -・一部のキャラに重量が0になってカプラなど何もPC,NCPが表示されなくなるバグ修正。(それだけ) - (common/) - mmo.h 修正。 - (map/) - clif.c - clif_updatestatus() 修正。 - pc.c - pc_calcstatus() 修正。 - --------------- -//0697 by 南 - -・mob_db修正 - ドロップを中心に修正。 - (db/) - mob_db.txt - --------------- -//0696 by 死神 - -・バグ修正。 -・テレポートやワープ等の時スキルユニットから抜ける処理が入って -なかったのでSAFETYWALL等によって鯖落ちが起こったようです。(確か報告も -あったと思いますが...) よって修正はしましたが確認はしてません。報告を -お願いします。 -・スキルによる吹き飛ばし処理をちょっと修正とモンスターのコードを少し修正。 -多分変になったことはないと思いますが変だったら報告してください。 -・その他細かい修正。 - (map/) - skill.h 修正。 - skill.c - skill_blown()、skill_attack()、skill_unit_move() 修正。 - skill_castend_nodamage_id()、skill_castend_damage_id() 修正。 - skill_unit_out_all()、skill_unit_out_all_sub() 追加。 - mob.c - mob_stop_walking()、mob_spawn()、mob_warp() 修正。 - mob_can_move()、mob_changestate() 修正。 - map.h 修正。 - pc.c - pc_setpos() 修正。 - battle.c - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack() 修正。 - --------------- -//0695 by 死神 - -・少し修正。 -・プレイヤーの基本パラメータを2byteに拡張。 -・item_db.txtをラグナゲートの説明に合わせて修正。 -・bAddEffとbResEffの確率を百分率から万分率に変更。 -・スクリプトstatusupとstatusup2追加。 -statusup bStr; のように使って機能はステータスポイントを減らして -基本パラメータを1上げる。 -statusup2 bInt,n; のように使って機能はステータスポイントを減らさずに -基本パラメータをn上げる。 -・その他細かい修正。 - (conf/) - battle_athena.conf 修正。 - (db/) - item_db.txt 修正。 - const.txt 修正。 - (doc/) - item_bonus.txt 修正。 - conf_ref.txt 修正。 - (common/) - mmo.h 修正。 - (char/) - char.c - mmo_char_send006b()、parse_char() 修正。 - (map/) - map.h 修正。 - clif.h 修正。 - clif.c - clif_initialstatus()、clif_updatestatus() 修正。 - pc.h 修正。 - pc.c - pc_bonus()、pc_calcstatus()、pc_equippoint()、pc_equipitem() 修正。 - pc_jobchange()、pc_checkbaselevelup()、pc_statusup() 修正。 - pc_statusup2() 追加。 - battle.h 修正。 - battle.c - battle_calc_pet_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pc_weapon_attack()、battle_config_read() 修正。 - skill.c - skill_additional_effect()、skill_status_change_start() 修正。 - script.c - buildin_statusup()、buildin_statusup2() 追加。 - atcommnad.c 修正。 - --------------- -//0694 by 死神 - -・バグ修正と細かい修正。 -・bCriticalRateが正しく適用されなかった問題修正。 -・ペットによるステータスボーナス追加。ステータスボーナスは装備の -スクリプトによって設定します。ただペットによるボーナスはカードによる物と同じ扱いをします。そして属性の適用は一番優先順位低いです。今は何も入ってませんが... - (conf/) - battle_athena.conf 修正。 - (db/) - const.txt 修正。 - pet_db.txt 修正。 - (doc/) - item_bonus.txt 修正。 - conf_ref.txt 修正。 - db_ref.txt 修正。 - (map/) - map.h 修正。 - map.c - map_quit() 修正。 - battle.h 修正。 - battle.c - battle_calc_pc_weapon_attack()、battle_weapon_attack() 修正。 - battle_calc_magic_attack()、battle_calc_misc_attack() 修正。 - battle_config_read() 修正。 - pc.c - pc_calcstatus()、pc_bonus()、pc_setpos()、pc_authok() 修正。 - pc_damage()、pc_autosave_sub() 修正。 - pet.h 修正。 - pet.c - pet_hungry()、pet_birth_process()、pet_recv_petdata()、pet_food() 修正。 - pet_return_egg()、pet_ai_sub_hard()、read_petdb() 修正。 - clif.c - clif_sendegg()、clif_parse_LoadEndAck() 修正。 - atcommand.c 修正。 - makefile 修正。 - --------------- -//0693 by 胡蝶蘭 - -・SC_*の列挙表をリナンバリング - クライアントに通知するのを64未満から128未満に増やした - パケット情報に合うようにリナンバー - StatusChangeの配列を128から192に増やしたのでメモリ使用量が増えます。 - - (db/) - const.txt - SC_* の数値を変更 - (map/) - skill.h - SC_* の列挙の数値を変更 - map.h - MAX_STATUSCHANGEを128から192に増やした - skill.c - skill_status_change_start(),skill_status_change_end(), - skill_status_change_clear()の通知処理を変更 - -・演奏/ダンスの処理を変更 - 演奏/ダンス中かどうかをSC_DANCINGで判定するように変更 - (判定処理が多少高速化されたはず) - ワープ(マップ移動や蝿など)すると演奏/ダンスを中断するように変更 - - skill.h/skill.c - skill_check_dancing()削除、skill_stop_dancing()追加 - skill_delunitgroup(),skill_initunitgroup()変更 - skill_status_change_start()変更 - skill_castend_nodamage_id()変更 - 書き損じがあるかも・・ - pc.c - pc_calcstatus(),pc_setpos(),pc_damage()変更 - -・不協和音スキルの修正 - (db/) - skill_db.txt - 不協和音スキルのHIT数修正 - (map/) - skill.c - skill_status_change_timer()変更 - battle.c - battle_calc_misc_attack()修正 - --------------- -//0692 by 胡蝶蘭 - -・アドリブスキルが使用できない問題修正(skill_dbの添付し忘れ) - (db/) - skill_db.txt - アドリブの消費SPを1に修正 - -・mob_db2.txtがあればmob_db.txtにオーバーライドするように - オリジナルmobを作ってる人は使うと便利かもしれません。 - - mob.c - mob_readdb() - -・鯖落ちバグ報告時のためのスタックバックトレースログ所得方法を紹介 - 鯖落ちバグの報告時に、この情報をコピペすると開発者が喜びます。 - Cygwinでcoreの吐かせる方法も紹介してます。 - - (doc/) - coredump_report.txt - --------------- -//0691 by 胡蝶蘭 - -・item_db2.txtがあればitem_db.txtにオーバーライドするように - オリジナルアイテムを作ってる人は使うと便利かもしれません。 - - itemdb.c - itemdb_readdb()修正 - -・演奏/ダンス系スキル仮実装 - ・演奏/ダンス中は移動が遅く、スキルも使えないようになりました - ・アドリブスキルで演奏/ダンスを中断できるようになりました - ・演奏/ダンスは石化などの異常、MHPの1/4以上のダメージで中断します - ・キャラクターグラフィックは演奏/ダンスしません - ・演奏/ダンス中のSP消費は未実装です - ・移動しても効果範囲はついてきません - ・重複しても不協和音などに変化しません - ・エフェクトが出ても効果は未実装のものがあります - ・ほとんど未テストなので多数の不都合があると思います - - skill.h - SC_* の列挙表を修正 - skill.c - skill_check_dancing()追加 - SkillStatusChangeTable[]修正 - skill_unit_onout(), skill_status_change_start(), - skill_status_change_timer(),skill_unitsetting(), - skill_castend_id(),skill_castend_pos(),skill_castend_map(), - skill_castend_nodamage_id()修正 - その他は忘れました - pc.c - pc_calcstatus(),pc_damage()修正 - --------------- -//0690 by 波浪 - -・細かい修正 - (db/) - item_db.txt 錐とメギンギョルドのbonusを修正。 - (doc/) - item_bonus.txt 修正。 - --------------- -//0689 by 死神 - -・倉庫バグ修正と細かい修正。 - (map/) - pc.c - pc_modifybuyvalue()、pc_modifysellvalue() 修正。 - storage.c - storage_storageopen() 修正。 - storage_storage_quit()、storage_storage_save() 修正。 - --------------- -//0688 by 聖 - -・ディスカウント、コムパルションディスカウント、オーバーチャージが適用されなかった問題を修正。 - (map/) - pc.c - pc_modifybuyvalue() 修正。 - pc_modifysellvalue() 修正。 - --------------- -//0687 by 死神 - -・少し修正。 -・battle_athena.confに項目追加。(詳しいことはconf_ref.txtで) -・item_avail.txtの処理を変更。アイテムIDの後に0を入れると今まで通りに使用不可能になるが0以外の数値を入れると使用不可能ではなくその数値をアイテムのIDとして見た目だけをそれに変更します。よって鞍落ちアイテムを別の物に表示して鞍落ちを防ぐことができます。(表示だけ変えて鯖の処理は本当のアイテムIDの物として認識します。修正は全てしたと思いますが抜けた所があるかも知りませので見た目変更したアイテムで鞍落ちが起こったら報告してください。) 鯖の処理はこれが限界です。(少なくとも自分には) アイテムが同じ物が二つ表示されて間違い安いとかどうこうとかの文句を言いたい人は鞍作れよ。以上。 -・ジルタスとアリスのコマントアウト解除。item_avail.txtで卵をルビーとアクアマリンで表示して捕獲アイテムも他の物に表示するように変更しています。 -・ダメージ計算のバグ修正。(大した物じゃありませんが弓だけちょっと問題があったようです。) -・青箱等のアイテムで得た装備品は未鑑定になるように変更。 -・装備ボーナスの内部処理修正と少し変更。(詳しいことはitem_bonus.txtで) -・キャラ鯖にテータを送る時キャラ、倉庫、ペットのテータを同時に送るように変更。(キャラ鯖とマップ鯖の間の転送量が増えるかも知りれませんがデータを同期化の為です。) -・FWの動作間隔を0.25秒から0.1秒に変更。(これで摺り抜は少し減るはずです。) -・カートレボリュションでどんな状態異常もかからないように変更。 - (conf/) - battle_athena.conf 修正。 - (db/) - const.txt 修正。 - item_avail.txt 修正。 - pet_db.txt 修正。 - (doc/) - conf_ref.txt 修正。 - item_bonus.txt 修正。 - (map/) - map.h 修正。 - map.c - map_quit() 修正。 - battle.h 修正。 - battle.c - battle_calc_pc_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pet_weapon_attack()、battle_calc_magic_attack() 修正。 - battle_get_dmotion()、battle_config_read() 修正。 - pc.c - pc_calcstatus()、pc_bonus()、pc_bonus3()、pc_setpos() 修正。 - pc_makesavestatus()、pc_autosave_sub()、pc_modifybuyvalue() 修正。 - pc_modifysellvalue()、pc_stop_walking() 修正。 - skill.c - skill_additional_effect()、skill_unitsetting() 修正。 - clif.c - clif_buylist()、clif_selllist()、clif_set009e()、clif_set0078() 修正。 - clif_set007b()、clif_additem()、clif_itemlist()、clif_equiplist() 修正。 - clif_storageitemlist()、clif_storageequiplist()、clif_changelook() 修正。 - clif_arrow_create_list()、clif_useitemack()、clif_tradeadditem() 修正。 - clif_storageitemadded()、clif_getareachar_item() 修正。 - clif_skill_produce_mix_list()、clif_cart_additem()、clif_cart_itemlist() 修正。 - clif_cart_equiplist()、clif_vendinglist()、clif_openvending() 修正。 - clif_produceeffect()、clif_sendegg()、clif_pet_equip()、clif_mvp_item() 修正。 - clif_pet0078()、clif_pet007b() 修正。 - itemdb.h 修正。 - itemdb.c - itemdb_searchrandomid()、itemdb_search()、itemdb_readdb() 修正。 - itemdb_read_itemavail()、itemdb_read_itemvaluedb() 修正。 - itemdb_equippoint() 削除。 - storage.h 修正。 - storage.c - storage_storage_quitsave() ->storage_storage_quit()に変更と修正。 - storage_storageclose() 修正。 - atcommand.c 修正。 - pet.c - pet_change_name()、pet_equipitem()、pet_unequipitem() 修正。 - pet_birth_process()、pet_return_egg() 修正。 - script.c - buildin_getitem() 修正。 - mob.c - mob_stop_walking() 修正。 - makefile 修正。 - --------------- -//0686 by 聖 - -・細かい修正。 - (map/) - pc.h 修正。 - --------------- -//0685 by 波浪 - -・0683、0684でのbonusの追加にともなってitem_db.txtを修正 -・他色々修正 - (db/) - item_db.txt 修正。 - (doc/) - item_bonus.txt 修正。 - --------------- -//0684 by 死神 - -・細かい修正。 -・死んだふりの時スキルとアイテムが使えないように変更。 -・bInfiniteEndure追加。機能は無限インデュア。 -・ダメージ表示の処理少し変更。 - (db/) - const.txt 修正。 - (doc/) - item_bonus.txt 修正。 - (map/) - map.h 修正。 - pc.c - pc_calcstatus() 修正。 - pc_equipitem()、pc_unequipitem() 修正。 - clif.c - clif_parse_UseItem()、clif_parse_UseSkillToId() 修正。 - clif_parse_UseSkillToPos()、clif_parse_UseSkillMap() 修正。 - clif_damage()、clif_skill_damage()、clif_skill_damage2() 修正。 - clif_parse_LoadEndAck() 修正。 - skill.c - skill_status_change_timer() 修正。 - --------------- -//0683 by 死神 - -・バグ修正とbonus追加。 -・倉庫バグ、属性バグ修正とその他のバグ修正。 -・スクリプトbonus3追加。今はbAddMonsterDropItemだけが対応になっています。 -・bonus bRestartFullRecover;n;等でnは無意味だけど消すのはちょっとまずいですので0にして入れた方がいいです。bonusは2つの数値が必要なスクリプトなので。 -・bDefRatioAtkを防御無視に変更。 -・0677で書き忘れ。 -・武器の属性適用優先順位を製造>カード>武器に変更。製造が最優先です。(属性がある時に話です。属性がない場合属性ある物に上書きされたりはしません。) -・装備で適用される効果の優先順位を右手>左手>体>頭上>頭中>頭下>ローブ>靴>アクセサリー1>アクセサリー2>矢に設定。(本鯖仕様がどうなのか分かることができそうな物でもないのでアテナの仕様と言うことで。) 右手が最優先です。 -・武器の射程を右手と左手の武器の中で長い物を適用するように変更。 - (db/) - const.txt 修正。 - (doc/) - item_bonus.txt 修正。 - (map/) - map.h 修正。 - battle.c - battle_calc_pc_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_calc_pet_weapon_attack()、battle_calc_magic_attack() 修正。 - battle_damage() 修正。 - pc.c - pc_autosave_sub()、pc_calcstatus() 修正。 - pc_bonus()、pc_bonus2() 修正。 - pc_bonus3() 追加。 - script.c - buildin_bonus3() 追加。 - mob.c - mob_once_spawn()、mob_damage() 修正。 - storage.h 修正。 - storage.c - storage_storage_save() 追加 - atcommand.c 修正。 - --------------- -//0682 by 聖 - -・スピードアップポーション系のバグ修正 - (map/) - pc.c - pc_calcstatus() 修正。 - --------------- -//0681 by 死神 - -・装備バグ修正。 - (map/) - pc.c - pc_equipitem() 修正。 - --------------- -//0680 by 聖 - -・細かい修正。 -・「@monster」コマンドでモンスターIDの指定に「-1」、「-2」等を指定すると - モンスターをランダムで召還できる機能を追加。 - (map/) - mob.c - atcommand.c - --------------- -//0679 by 波浪 - -・0676で新しいアイテム効果が実装されたので、item_db.txtを修正(bonus bAddMonsterDropItem,n,x; は、種族判定ができないのでとりあえず保留しました。) -・他色々修正 - (db/) - item_db.txt - job_db1.txt - (doc/) - item_bonus.txt - --------------- -//0678 by 聖 - -・召還関連の細かい修正。 - (map/) - mob.c - mob_once_spawn_area() 修正。 - --------------- -//0677 by 死神 - -・細かい修正。 -・アイテム売買によって得られる経験値をカードによるスキルでは得られないように修正。 -・毒に掛かると自然回復できないように修正。 -・0676で書き忘れ。製造武器の場合製造によって与えた属性が武器の属性より優先して適用されるように変更。(製造武器が無属性の場合は適用されません。) - (doc/) - item_bonus.txt 誤字修正。 - (map/) - npc.c - npc_buylist()、npc_selllist() 修正。 - pc.c - pc_calcstatus()、pc_natural_heal_sub() 修正。 - --------------- -//0676 by 死神 - -・色々と修正。 -・battle_athena.confに項目追加。(詳しいことはconf_ref.txtで) -・みすとれ巣を参考してダメージ計算を少し修正。 -・装備bonusに色々と追加。(詳しいことはitem_bonus.txtで) -・自動セーブする時(キャラ鯖にデータを送る時)倉庫のデータも送るように変更。 -・0667で言い忘れ。カートを外してもアイテムが消えないように変更。(本鯖で消えるのが仕様だと思っていたけど修正されたみたいなので。) -・取引要請を受ける側は基本スキルをチェックしないように修正。(受ける側の基本スキルチェックは自分が入れた物ではないです。いつの間にか入っていたので削除しました。) -・防具の精錬ボーナスを端数無視に変更。(これが本鯖の仕様みたいなので) -・アンクルの処理少し変更。(かからないと言う報告がありましたので...) -・プレイヤーのステータス計算で問題ありそうな所修正。 -・カードのIDで機能が決まっていたカードもスクリプトによって変えることができるように変更。(詳しいことはitem_bonus.txtで) -・aspd計算方法少し変更。 -・矢にbCritical、bAtkEle、bHit、bAddEle、bAddRace、bAddSize、bAddEffを適用できるように変更。矢を使うスキルや弓による攻撃だけに矢のbCritical、bAtkEle、bHit、bAddEle、bAddRace、bAddSize、bAddEffが適用されるように修正。 -・キリの実装に為に修正はしましたがキリが防御無視なのかどうかがわからなかったので防御無視はしないようになっています。 -・テストした物はbAddMonsterDropItemとbGetZenyNumだけなので正常に動作するかどうかの報告が欲しい所です。(ついでにitem_dbの修正も...これで吸収系とオートスペル系以外は殆ど実装できるはずです。多分...) -・その他は覚えてないけど修正した所が少しあるかも... - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - item_bonus.txt 修正。 - (db/) - const.txt 修正。 - (char/) - inter.c - inter_init() 修正。 - int_storage.c - mapif_parse_SaveStorage() 修正。 - (map/) - trade.c - trade_traderequest() 修正。 - pc.h 修正。 - pc.c - pc_autosave_sub()、pc_calcstatus() 修正。 - pc_bonus()、pc_bonus2() 修正。 - pc_setrestartvalue()、pc_setequipindex() 修正。 - pc_check_equip_wcard()、pc_check_equip_dcard()、pc_check_equip_card() 削除 - その他修正。 - skill.h 修正。 - skill.c 修正。 - skill_castend_nodamage_id()、skill_unit_onplace() 修正。 - skill_check_condition()、skill_additional_effect() 修正。 - skill_attack()、skill_status_change_start() 修正。 - map.h 修正。 - battle.h 修正。 - battle.c - battle_get_def()、battle_get_mdef2() 修正。 - battle_weapon_attack()、battle_damage() 修正。 - battle_calc_magic_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_calc_mob_weapon_attack()、battle_calc_pet_weapon_attack() 修正。 - battle_calc_misc_attack()、battle_config_read() 修正。 - mob.c - mob_damage() 修正。 - pet.c - pet_target_check() 修正。 - clif.c - clif_set0078()、clif_set007b()、clif_changelook() 修正。 - atcommand.c 修正。 - --------------- -//0675 by 波浪 - -・韓鯖で村正の効果が変更されたので報告を元にitem_db.txtを修正 -・job_db1.txtを修正 - (db/) - item_db.txt - job_db1.txt - --------------- -//0674 by npc - -・ファーマシーの仮実装。 - (db/) - produce_db.txt - (map/) - skill.c - --------------- -//0673 by 南 - -・集中力向上に装備品の補正が入っていなかったのを修正。 - (map/) - pc.c - --------------- -//0672 by 南 - -・集中力向上に装備品の補正が入っていなかったのを修正。 - (map/) - pc.c - --------------- -//0672 by 聖 - -・モンスター系のバグ修正(すみません、まだ残ってました(^^; ) - (map/) - mob.c - --------------- -//0671 by 聖 - -・IDチェック範囲の修正他。 -・@monsterで数を指定しなくても召還できるように修正。 - (map/) - atcommand.c - battle.c - battle.h - mob.c - pet.c - (conf/) - battle_athena.conf - (doc/) - conf_ref.txt - --------------- -//0670 by RR - -・モンスタードロップ率を修正(本鯖準拠、DBでの設定+1/10000)。 -・落下率0に設定したアイテムを落とすかどうかをbattle_athena.confで設定可能に。 - (map/) - mob.c - mob_damage() 修正。 - battle.c - battle.h - (conf/) - battle_athena.conf - --------------- -//0669 by 聖 - -・モンスタードロップの修正。 - (map/) - mob.c - mob_damage() 修正。 - --------------- -//0668 by 聖 - -・モンスターIDの範囲チェックを修正。 - (map/) - mob.c - mob_db、mob_once_spawn()、mob_once_spawn_area()、 - mob_summonslave()、mob_read_randommonster()、mob_readdb() 修正。 - --------------- -//0667 by 死神 - -・最大HP計算式をミストレ巣を参考して修正。(多分これで本鯖にあっていると思います。) -・防具の精錬ボーナスを0.7に変更。(今は端数を四捨五入していますが本鯖が端数無視なら修正しておきます。) -・@refineコマンドで装備場所IDに0を入れると装備している全ての装備を精錬するように変更。 -・その他細かい修正。 - (db/) - item_db.txt - 7140、7142を元に戻して0666の物はコマントアウトしました。 - job_db1.txt 修正。 - refine_db.txt 修正。 - (map/) - mob.c - mob_once_spawn() 修正。 - itemdb.c - itemdb_read_randomitem() 修正。 - pet.c - pet_food() 修正。 - pc.c - pc_readdb()、do_init_pc()、pc_calcstatus()、pc_setoption() 修正。 - pc_calc_sigma() 追加。 - その他修正。 - map.h 修正。 - battle.c - battle_calc_magic_attack()、battle_calc_misc_attack() 修正。 - atcommand.c 修正。 - --------------- -//0666 by 聖 - -・ランダムアイテムの細かい修正。 -・battle_athena.confの項目追加。 -・古木の枝で召還するモンスターの確率を設定出来るようにしました。 -・モンスター召還アイテムを複数作る事が出来るようにしました。 -・召還アイテムのサンプルとして - 生命の種子をポリン系召還、 - エンブリオをMVPボス系召還にしてみました。 - あまりいいサンプルを思いつかなかったので、 - 何かいい案を思いついた人は書き換えてやってください(^^; - (conf/) - battle_athena.conf - (doc/) - conf_ref.txt - (map/) - mob.h - mob_db 修正。 - mob.c - mob_once_spawn()、mob_makedummymobdb()、mob_readdb() 修正。 - mob_readbranch() -> mob_read_randommonster()に変更。 - battle.h - battle_config 修正。 - battle.c - battle_config_read() 修正。 - itemdb.c - itemdb_read_randomitem() 修正。 - (db/) - item_db.txt - item_bluebox.txt - item_cardalbum.txt - item_giftbox.txt - item_scroll.txt - item_violetbox.txt - mob_branch.txt - mob_poring.txt 追加。 - mob_boss.txt 追加。 - --------------- -//0665 by J - -・怨霊武士の取り巻きがカブキ忍者になっていたのを酒天狗に修正。 -・オットーにフェイクエンジェルが出すはずの取り巻きがついてたのを修正。 - (db/) - mob_skill_db.txt - --------------- -//0664 by 聖 - -・精錬失敗時他のプレーヤーにもエフェクトが表示されるように修正。 - (map/) - script.c - buildin_failedrefitem() 修正。 - --------------- -//0663 by lide - -・ブランディッシュスピア修正 - (map/) - battle.c - skill.c - --------------- -//0662 by 死神 - -・細かい修正とバグ修正。 -・プロボックによってモンスターは乗算防御と減算防御が減るように修正してプレイヤーは減算防御だけ減るように修正。 -・スクリプトgetgmlevel追加。機能はそのNPCと話しているプレイヤーのGMレベルを返します。 -・0659の書き忘れですがペットのパフォマンスの種類が親密度によって増えるように変更しました。 - (map/) - clif.c - pc.c - script.c - --------------- -//0661 by 死神 - -・細かい修正。 -・接続した時のペットのメッセージを親密度がきわめて親しいの時のみに出るように変更。 -・0659で書き忘れですがペットの支援攻撃は親密度がきわめて親しいの時のみに発生します。(それと親密度によって支援攻撃確率が少し変化します。) -・ジルタスとアリスの卵のIDをitem_db.txtに合わせました。(自分が作ったpet_db.txtの方が自分勝手に設定していた物でしたので。て言うか未実装アイテムだから番号がわからなかっただけですが...) -・pet_db.txtのattack_rateが正しく適用されなかったバグ修正。 - (db/) - pet_db.txt - (map/) - clif.c - clif_parse_LoadEndAck() 修正。 - pc.c - pc_attack_timer() 修正。 - --------------------- -//0660 by いど - -・サーバーsnapshot - --------------- -//0659 by 死神 - -・ペットを色々と修正。(ペットのコードをほとんど変えました。) -・手動的だったペットの動きをモンスターのようにAIとして処理。 -・接続した時のペットのメッセージ実装。(本鯖はどうなのかわかりませんが -Athenaは接続すると100%話すようになっています。) -・ペットのスペシャルパフォマンス実装。(ただ台詞がちょっと変です。いくら探しても該当するパケットが見つからなかったので。) -・ペットの台詞を他のペットの物に変更する機能追加。(詳しいことはdb_ref.txtとpet_db.txtで。) -・ペットによる支援攻撃変更。pet_db.txtで攻撃する時と攻撃を受けた時の支援攻撃 -確率を別々に設定できます。攻撃する時の場合攻撃する度にチェックをしますので -攻撃速度が速いと支援攻撃を受けやすくなります。攻撃を受けた時も同じです。(こちらはダメージを喰らう度になりますが。) 支援攻撃確率はソヒー、ジルタス、アリスだけ自分勝手に設定しています。(他のは全部1%に。ペットの支援攻撃は同じモンスターにはできないようになっています。そしてペットの戦闘能力はモンスターと同じです。) -・/hideコマンド実装。 -・プロボックによって乗算防御も減るように修正。 -・フリーキャストのバグ修正。 -・ノービスのステータスボーナス削除。 -・battle_athena.confの項目追加と削除。 -・修正したファイルだけ。未テストした物もかなりありますので問題があったら報告をお願いします。 - (conf/) - battle_athena.conf - (doc/) - conf_ref.txt - db_ref.txt 追加。(今説明が入っているのはpet_db.txtのみです。 ) - client_packet.txt - (db/) - pet_db.txt - job_db2.txt - (map) - clif.h - clif.c - map.h - map.c - pet.h - pet.c - pc.c - mob.h - mob.c - npc.c - atcommand.c - skill.c - battle.h - battle.c - --------------- -//0658 by huge - -・ペットがとどめをさすと、飼い主に経験値が入るようにしました。 -・固定値ダメージじゃ味が無いのでATK1〜ATK2の間で乱数を取るようにしました。 -・あと、ペットがとどめをさすかどうかの設定を、battle_athena.confに加えました。 - - (conf/) - battle_athena.conf pet_finish追加。 - (map/) - battle.c - battle_config_read() 修正。 - battle.h 修正。 - pet.c - pet_attack() 修正。 - (doc/) - conf_ref.txt 説明追記。 - --------------- -//0657 by huge - -・ペットによる攻撃を実装。 -・ペットを持っていて、ペットが装備品をつけてて、さらにランダムによる判定で発動します。 -・ただの遊び心ですw -・battle_athena.confで頻度を設定できます。詳細はdocで。 - - (conf/) - battle_athena.conf pet_attack追加。 - - (map/) - battle.c - battle_config_read() 修正。 - battle.h 修正。 - pc.c - pc_attack_timer() 修正。 - pet.c - pet.h - pet_attack() 追加。 - (doc/) - conf_ref.txt 説明追記。 - - とりあえず、ペットが動いてるなぁって感じと、ダメ回数を増やした程度です。 - --------------- -//0656 by 死神 - -・グランドクロスの修正。(おいおい何度目だ...) -・グランドクロス計算式間違いで修正。(÷3がまずかったみたいです。) -でもまだ反射ダメージがみすとれ巣よりちょっと高いです。(10ぐらいだから -関係ないかも) -・モンクの気球を必中に修正。(自分の間違いのようですので...) - (map/) - skill.c 修正。 - battle.c 修正。 - --------------- -//0655 by 死神 - -・グランドクロスの修正。 -・自分なりに情報を収集してみた結果グランドクロス反射ダメージは -プレイヤーキャラがそのキャラ自身にグランドクロスを使った時の -ダメージだそうなので修正しました。(みすとれ巣の計算とはかなり違うような -気もしますが...) -・魔法とトラップ、鷹の攻撃にも属性耐性と種族耐性を適用するように修正。 -(本鯖の仕様にあっているかどうかは不明ですが適用した方が正しいと思ったので -修正しました。) - (map/) - skill.c 修正。 - map.h 修正。 - battle.c 修正。 - --------------- -//0654 by 死神 - -・グランドクロスの修正と細かい修正。(計算式間違いで修正。) -・0653で書き忘れ。気功による追加ダメージは必中ではないらしいので -修練の加算と同じ所に計算するように変更しました。 -・カートにバグがありそうだったのでちょっと修正。 -・ダメージ計算をほんの少し修正。(ダメージ量が変わったりはしません。) - (map/) - battle.c - battle_calc_magic_attack() 修正。 - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - skill.c - pc_damage_feedback() -> skill_damage_feedback()に変更。 - skill_unit_timer() 修正。 - pc.c - pc_setoption() 修正。 - atcommand.c 修正。 - --------------- -//0653 by 死神 - -・0652の修正と細かい修正。今まで通り未テストも多いです。 -・グランドクロスの処理修正。(本鯖にあっているかどうかの自身はありません。) -ラグナーゲートの説明によると始めに現在HPの20%が消耗されてその後敵に与えた -ダメージの中で一番高い物が戻ってくるようです。そしてその戻ってきた -ダメージは聖の属性を持ちトラストによって聖の耐性が50%になっているので -半分を喰らうことになるようです。(聖の耐性上がる装備をしていれば戻ってくる -ダメージは受けないようです。) -問題なのはプレイヤーの防御属性を計算するかどうかです。今は防御属性計算の -後で聖の属性を計算しています。そして戻ってくるダメージはHPバーは減るけど -表示はされません。本鯖の方がどうなのか不明なので... -それと一応モンスターもグランドクロスの使用が可能です。ただモンスターの場合 -現在HPの20%消耗の後のダメージは受けません。(モンスターが使う -グランドクロスのテストはしてません。) -・ダメージによるディレイ中にまたディレイがかからないように修正。(大した意味はないかも...) -・値段がゼロのアイテムも売れるように変更。 -・@コマンドhealの処理少し修正。 -・移動コード少し修正。 - (map/) - clif.c - clif_selllist() 修正。 - battle.c - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_calc_magic_attack()、battle_calc_misc_attack() 修正。 - skill.c - skill_additional_effect()、skill_unit_onplace() 修正。 - skill_status_change_start()、skill_unit_onplace() 修正。 - skill_castend_damage_id()、skill_castend_id()、skill_attack() 修正。 - skill_unitsetting()、skill_check_condition() 修正。 - skill_use_id()、skill_use_pos() 修正。 - npc.c - npc_parse_script() 修正。 - pc.h 修正。 - pc.c - pc_walk()、pc_walktoxy_sub()、pc_stop_walking() 修正。 - map.h 修正。 - mob.h 修正。 - mob.c - mob_stop_walking()、mob_changestate()、mob_walk() 修正。 - pet.c - pet_changestate() 修正。 - atcommand.c 修正。 - (db/) - skill_db.txt グランドクロス修正。 - cast_db.txt グランドクロス修正。 - --------------- -//0652 by 月詠み - -・グランドクロスを仮実装 - (db/) - skill_db.txt - cast_db.txt - (map/) - battle.c - Damage battle_calc_misc_attack - Damage battle_calc_magic_attack - skill.c - skill_additional_effect - skill_castend_damage_id - skill_castend_pos2 - skill_unit_group *skill_unitsetting - skill_unit_onplace - skill_check_condition - --------------- -//0651 by 波浪 - -・item_db.txtを修正 - (db/) - item_db.txt - 装備品のアイテム効果を修正 - --------------- -//0650 by 死神 - -・三段掌の発動条件を弓と二刀流以外に変更。 -・表示をせずに内部で処理だけするNPCのCLASSを111から32767に変更。 -・細かい修正。 - (map/) - clif.c - clif_getareachar_npc()、clif_spawnnpc()、clif_pcoutsight() 修正。 - npc.h 修正。 - battle.c - battle_calc_pc_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - --------------- -//0649 by 波浪 - -・DBとDOC修正 - (db/) - item_db.txt - グングニールはLV4武器なので、韓国のデータにあわせて風属性ではなくします。 - mob_db.txt - size_fix.txt - 楽器は大型に対して75%だそうです。 - (doc/) - item_bonus.txt - --------------- -//0648 by 死神 - -・ショップの値段に-を入れると鯖が落ちる問題修正。(itemdbの初期化をnpcより -先にするように変更。) それだけです。 - (map/) - map.c - do_init() - --------------- -//0647 by nini - -・item_db修正 -・スナッチャー仕様変更。弓以外のすべての武器で出るようになってます。 - (/map/) - battle.c - 三段掌の発動条件追加 - skill.c - スナッチャーの発動条件追加 - (/db/) - item_db.txt - シルクハットにSP上昇追加 - --------------- -//0646 by last - -・item_db.txtの修正(属性関連) - (/db/) - item_db.txt - --------------- -//0645 by るるる(&ree_ron) - -・item_value_db.txtにディスカウント&オーバーチャージ等のスキルによる価格変動を受けるかどうかのフラグメントを追加。 - 実際の形式はサンプルとして用意したitem_value_db.sample.txtを見てください。(設定価格は完全に独断と偏見です) - 同様のサンプルとしてNPC設置スクリプトも添付しておきます。 -・item_value_db.txtのアイテム価格設定で、売値と買値の設定を独立。(item_db.txtは従来どおり買値は売値の半額として自動処理) -・NPCショップにて、1NPCで扱えるアイテム数を最大64から最大100に変更。(クラ自体は120ぐらいまで可能ですが) - (/db) - item_value_db.txt - カラム数を整理しただけです。内容はまったく変更していません。 - (/map/) - clif.c - clif_buylist() clif_selllist() 変更 - itemdb.h - item_data 構造体変更 - itemdb_value_buy() itemdb_value_sell() itemdb_value_notdc() itemdb_value_notoc() マクロ追加 - itemdb.c - itemdb_search() itemdb_readdb() itemdb_read_itemvaluedb() 変更 - itemdb_sellvalue() 削除 - npc.c - npc_buylist() npc_selllist() npc_parse_shop() 変更 - (/sample/) - オマケです。次回SnapShotには含まないで宜しいです。 - -コメント -原型は私の友人ree_ronが行い、私が更に細かいミスを直しただけですが、テストはしましたので大丈夫でしょう。 -元々この処理を導入する理由として、特定アイテムの売値が1z固定にできないものか、という点だったからです。 -そしてやっていくうちに、NPCショップを利用したレアアイテムの販売とかで本鯖露店に近いことが出来るのではないか、 -ということが判ってきたわけです。 -それで一応はデータを用意しましたが、あくまでもサンプルとして利用してください。もし可能ならば、 -さらに修正を加えてアテナ独自として本採用としたデータをパッチアップしてくれればとも思いますがw - - --------------- -//0644 by nini - -・DBの間違い、643で追加されたスクリプト追加。 - (/db/) - item_db.txt - cast_db.txt - チャージアローのキャスト追加。 - exp_guild.txt - 46-50までのexp抜けに追加。 - size_fix.txt - 楽器、鞭、ナックルのサイズ補正修正。 - --------------- -//0643 by 死神 - -・色々と修正。 -・bMVPaddAtkRate削除。bAddRaceで処理するように変更。 -・bIgnoreDefEleとbIgnoreDefRace追加。 -bonus bIgnoreDefEle,n; n属性の敵の防御無視 -bonus bIgnoreDefRace,n; n種族の敵の防御無視 -・bMatkRate追加。魔法攻撃力を+n%上げます。よってbattle.cで計算していたロッドによる魔法攻撃力増幅の計算はなくしました。ステータス画面に上がった数値は表示されません。ダメージ計算の時に適用しています。 -・bCriticalDefに-を入れるとクリティカルを喰らう確率が上がるように変更。 -・NPC番号111は透明NPCですが落とし穴等のことを考えて表示を一切せずに -内部で処理だけするように変更。(flagを使うと何とかなりそうですがその -処理が全然わからなかったので透明NPCにクリックや名前の表示もできないように変更しました。) -・ショップの値段に-を入れるとitem_db.txtもしくはitem_value_db.txtの物を使うように変更。 -・スキルルアフのエフェクトがサイトと同じだったので修正。ついでにルアフの -ダメージも修正。 -・みすとれ巣によるとモンスター情報で表示される防御と魔法防御は乗算ではなく減算みたいなので修正。 -・他力本願ですがitem_db.txtの修正をお願いします。(全てのロッドにbonus bMatkRate,15; を入れる必要があります。その他の修正も必要です。) -・テストしていない物もかなりありますので問題があったら報告してください。 - (map/) - map.h 修正。 - map.c - map_quit() 修正。 - pc.h 修正。 - pc.c - pc_walk()、pc_stop_walking()、pc_setpos()、pc_authok() 修正。 - pc_calcstatus()、pc_bonus()、pc_natural_heal_sub() 修正。 - npc.h 修正。 - npc.c - npc_touch_areanpc()、npc_parse_shop() 修正。 - clif.c - clif_quitsave()、clif_getareachar_npc()、clif_spawnnpc() 修正。 - clif_skill_estimation() 修正。 - battle.c - battle_calc_magic_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_calc_mob_weapon_attack() 修正。 - mob.c - mobskill_use() 修正。 - skill.c - skill_status_change_end()、skill_status_change_timer() 修正。 - skill_status_change_start() 修正。 - (db/) - const.txt 修正。 - (doc/) - item_bonus.txt 修正。 - --------------- -//0642 by 死神 - -・装備バグ修正。(それだけ) - (map/) - pc.c - pc_authok()、pc_checkitem() 修正。 - --------------- -//0641 by 死神 - -・bAspdRateとbSpeedRateのバグ修正。(それだけ)0640で計算をちょっと変えて見ましたがそれがまずかったみたいです。今度も計算式を変えましたがもう大丈夫だと思います。(多分) - (map/) - pc.c - pc_calcstatus()、pc_bonus()、pc_delitem() - --------------- -//0640 by 死神 - -・バグ修正と少し修正。 -・みすとれ巣を参考してダメージ計算を少し修正。 -・battle_athena.confに項目追加。(詳しいことはconf_ref.txtで) -・キャラのHPとSPを2byteから4byteに変更。(テストはしていますがバグが出る -可能性もかなりあります。ただキャラセレクト画面でHPやSPが32768を越える時 -表示は32768になるけど内部の処理は正常に動きますのでそれはバグではありません。 -パケットの長さのせいでそれ以外手段がなかったので...) -・bCriticalDef(クリティカルを喰らわない確率+n%)の処理変更。100にすれば -クリティカルを喰らわないようになります。) -・bInnerAtkをbBaseAtkに変更。みすとれ巣でカードの攻撃は基本攻撃力の方に足されるとありましたので変更しました。今度は上がった攻撃力が表示されます。 -・bDoubleRateの処理変更。確率を足さずに一番高い物だけ適用します。それと左手 -装備の場合無視するように変更しまた。(左手はダブルが適用されませんので) -・bDoubleAddRate追加。機能はダブルアタック確率+n%(武器無視)です。 -左手装備は無視されます。 -・0635で攻撃力表示を本鯖にあわせました。そして今度は弓だけではなく -楽器とムチもdexによって攻撃力が上がるように変更しました。 -・装備した武器が消えるバグ修正の為に少し修正はしましたが本当に -大丈夫なのかは不明です。報告をお願いします。 - (conf/) - battle_athena.conf 修正。 - (db/) - const.txt 修正。 - item_db.txt 修正。 - (doc/) - item_bonus.txt 修正。 - conf_ref.txt 修正。 - (map/) - map.h 修正。 - pc.c - pc_calcstatus()、pc_bonus()、pc_equipitem() 修正。 - battle.h 修正。 - battle.c - battle_calc_mob_weapon_attack()、battle_calc_pc_weapon_attack() 修正。 - battle_config_read() 修正。 - clif.c - clif_updatestatus()、clif_parse_LoadEndAck()、clif_party_hp() 修正。 - (common/) - mmo.h 修正。 - (char/) - char.c - mmo_char_send006b()、parse_char() 修正。 - --------------- -//0639 by 胡蝶蘭 - -・ladminの修正など - ・プロンプトの入力にTerm::ReadLineを使うようにした - (入力履歴やコマンドラインの編集が可能に) - ・POSIX関係の処理の例外エラーをトラップするようにしました - (POSIXが全く使えない環境でも最低限、動くようになったかもしれない) - ・細部修正 - - (tool/) - ladmin - Ver.1.04に。 - -・MODバージョンがおかしい問題を修正 - (common/) - version.h - ATHENA_MOD_VERSIONが8進数で記述されている問題を修正 - 数字の頭に0をつけると8進数になるので注意してください - --------------- -//0638 by 波浪 - -・0635・0637で新しくアイテム効果が実装されたので、それに伴ってitem_db.txtを修正 -・item_bonus.txtを修正 - (db/) - item_db.txt 修正 - (doc/) - item_bonus.txt 修正 - --------------- -//0637 by 死神 - -・0635のバグ修正。 -・battle_athena.confに項目追加。(詳しいことはconf_ref.txtを見てください。) -・時間が遅すぎて0635で説明してなかったです。(寝不足だったので...) -まず仕様が変わったのは二刀流のダメージを武器別に完全に分けて行うように -変更とアサシンじゃなくても左手修練を覚えていれば二刀流を使えるように -変更しました。それとダメージの計算をちょっと修正。 -そしてbonusに追加されたのは -bonus bInnerAtk,n; 内部攻撃力+n -カードの引き上げダメージ用です。表示はされないけどダメージに計算されます。 -bonus bSpeed,n; 移動速度+n -移動速度をn上げます。 -bonus bAspd,n; 攻撃速度+n -攻撃速度をn上げます。 -bonus bSpeedRate,n; 移動速度+n% -移動速度をn%上げます。 -bonus bAspdRate,n; 攻撃速度+n% -攻撃速度をn%上げます。 -bonus bHPrecovRate,n; HP自動回復率+n% -自動回復するHPの量をn%上げます。スキルによる回復には影響がありません。本鯖の仕様とあっているかは不明です。 -bonus bSPrecovRate,n; SP自動回復率+n% -自動回復するSPの量をn%上げます。スキルによる回復には影響がありません。本鯖の仕様とあっているかは不明です。 -bonus bCriticalDef,n; クリティカルを喰らわない確率+n% -クリティカルの耐性をn上げます。10000以上にするとクリティカルを喰らいません。 -bonus bMVPaddAtkRate,n; MVPモンスターにn%の追加ダメージ -ボスモンスターにn%の追加ダメージを与えます。深淵の騎士カード用。 -bonus bNearAtkDef,n; 近距離攻撃のダメージをn%の減らす -全て近距離攻撃のダメージをn%の減らします。(魔法とトラップ、鷹を除く) -bonus bLongAtkDef,n; 遠距離攻撃のダメージをn%の減らす -全て遠距離攻撃のダメージをn%の減らします。(魔法とトラップ、鷹を除く) -bonus bDoubleRate,n; ダブルアタック確率+n%(武器無視) -武器に関係なく発動するダブルアタック確率をn%上げます。 -ダブルアタックスキルと別の判定を行う為ダブルアタックスキルが -あってもスキルによるダブルアタック確率が上がるわけではありません。 -サイドワインダーカード用。 - (map/) - pc.c - pc_bonus()、pc_calcstatus() 修正。 - pc_natural_heal_sub() 修正。 - battle.h - struct Battle_Config {} 修正。 - battle.c - battle_calc_pc_weapon_attack()、battle_calc_mob_weapon_attack() 修正。 - battle_config_read() 修正。 - (db/) - skill_db.txt - スティールのSPを10に修正。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - --------------- -//0636 by Sin - -・デバッグ用ポタ子さんスクリプト(npc_pota.txt)のアマツ・コンロンへの対応。 - すでに自力実装されていらっしゃる方々も多いかと思いますが…。 - コンロンダンジョンの名前がわからないため「崑崙D1」などとさせていただいています。 - (conf/) npc_pota.txt - --------------- -//0635 by 死神 - -・battle_athena.confに項目追加。(詳しいことはconf_ref.txtを見てください。) -・bonusにbInnerAtk(カード等で表示はされないけど実際には攻撃力に反映される物用です。)等を追加。他のはitem_bonus.txtを見てください。(追加はしたけどitem_db.txtは殆んど修正してません。) -・その他バグ修正や仕様変更もやりましたが一々書く時間がないので... - (map/) - makeile 修正。 - pc.c 修正。 - map.h 修正。 - clif.c 修正。 - battle.h 修正。 - battle.c 修正。 - itemdb.c 修正。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - item_bonus.txt 修正。 - (db/) - const.txt 修正。 - item_db.txt 修正。 - --------------- -//0634 by 死神 - -・weddingクラスには転職できないように修正。 -・スーパーノービスの為にexpテーブルをbase 4つjob 4つに拡張。 -exp.txtが変わりスーパーノービスだけの経験値を設定できます。(exp.txtの -4つ目がスーパーノービスのbase expで8つ目がjob expです。今は2次職業の物を -コピーした物に過ぎませんが。) exp.txtの設定方法も知らない方はいないと -思いますので説明は省略します。 -・スーパーノービスは転生のテストの為に韓国サクライだけ実装している物と -思われますが(転生が実装されればなくなると予測しています。)それを -実装していいのかと思ったりもしますが... -・結婚衣裳は既に0629で実装しているのにまたパッチとして -アップされるのもちょっと変(?)ですね。そういえば説明してなかったんですね。 -・装備専用スクリプトであるchangebaseの追加によってタキシードと -ウェディングドレスが実装しています。これは職業を変更せずに見た目だけ -変える物です。weddingクラス以外の適用も可能で変装セットとかも作れる -わけですが内部処理は変更せずに見た目だけ変えているので0631で説明したように -装備できない物を装備している場合鞍落ちが起こる可能性がありますので -他の職業で使うのはお勧めしません。仮実装なのは今の仕様はタキシードと -ウェディングドレスを装備するだけで見た目が変わるからです。韓国サクライの -方では何かの条件が必要だと思っているのでその条件がまだ実装されいないから -仮実装です。それにweddingクラスを職業にしてしまうと結婚するとスキル等が -リセットされるか変になるかのどちらなので変だと思ってなかったのでしょうか? - help.txt 修正。 - (db/) - job_db1.txt 修正。 - exp.txt 修正。 - (map/) - pc.c - pc_jobchange()、pc_readdb() 修正。 - pc_nextbaseexp()、pc_nextjobexp() 修正。 - --------------- -//0633 by 波浪 - -・装備の設定修正。結婚衣裳の職は、実際に転職するのではなくペコナイト(13)、ペコクルセ(21)のように画像を使うだけだと思うので - 何も装備できない設定にしました。スパノビはノビが装備できるものだけ設定しました。 -・古木の枝の出現モンスターを追加 -・アマツのモンスの沸き具合を本鯖に近くなるように修正(まだまだ違いますが・・・) - (conf/) - npc_monster.txt モンス名修正 - npc_monster_amatsu.txt 修正 - (db/) - item_avail.txt 鞍落ちアイテム追加 - item_db.txt 装備設定を修正、他多数 - mob_branch.txt 修正 - mob_db.txt モンス名修正 - skill_tree.txt 修正 - --------------- -//0632 by nini - -・@jobchangeで結婚衣裳とスーパーノービスになれるように。(注意:韓国桜井クライアントのみ) -・Sノビのステ、スキルなども暫定追加。(ノービスのコピーですが) - とりあえず見た目だけということで、結婚衣裳でも攻撃できますが(ただしノーモーション)、本来はできません。 -・上にあわせてitem_db編集。 - 結婚衣裳で武器もつとact、sprエラー出すので、結婚衣裳では武器を持てないようにした(はず)。 - (db/) - job_db1.txt - job_db2.txt - item_db.txt - 結婚衣裳、Sノビのデータ - skill_tree.txt - Sノビのスキル - (map/) - map.h - MAX_PC_CLASSに追加 - --------------- -//0631 by 死神 - -・細かい修正。 -・タキシードとウェディングドレスの表示をbattle_athena.confで設定できる -ように変更。 -・武器グラパッチについてですがパッチ前は使えない職業が装備をしても表示は -されないだけで鞍落ちまでは起こらなかったけど武器グラパッチの後はその武器を -装備することができない職業(本鯖で)が装備してしまった場合鞍落ちが起こる -ことがありますので注意してください。 - (db/) - item_db.txt - 1161、2338、7170 修正。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (map/) - battle.h - struct Battle_Configにwedding_modifydisplay 追加。 - battle.c - battle_config_read() 修正。 - pc.h - pc_cart_delitem() 修正。 - pc.c - pc_jobchange()、pc_additem()、pc_delitem()、pc_cart_delitem() 修正。 - pc_checkitem()、pc_getitemfromcart() 修正。 - clif.c - clif_changelook()、clif_send()、clif_parse_GlobalMessage() 修正。 - script.c - buildin_changebase() 修正。 - storage.c - storage_storageaddfromcart() 修正。 - vending.c - vending_purchasereq() 修正。 - --------------- -//0630 by 引退人 - -・ギルド脱退時にcharサーバが落ちることがあるのを修正 -・water_height.txtを更新 -・0627に関連してmodifydisplay関連を削除 - (char/) - int_guild.c - mapif_guild_leaved()のバッファ容量が足りなかったので、 - unsigned char buf[64]; -> unsigned char buf[128]; - と修正。 - (conf/) - battle_athena.conf - equip_modifydisplayを削除 - water_height.txt - prt_fild04.gatとmoc_fild01.gatの分を追加 - (doc/) - conf_ref.txt - equip_modifydisplayの説明を削除 - (map/) - battle.h - struct Battle_Config からequip_modifydisplayを削除 - --------------- -//0629 by 死神 - -・0627のバグ一部修正と新しい移動パケットに対応。(自分の間違いでした。 -モンスターやNPCも新しい移動パケットを使うと思っていたのですが -新しい移動パケットはプレイヤーのみのようです。) -・タキシードとウェディングドレス仮実装。(韓国のサクライ鞍じゃないと -鞍落ちされます。使用する時はitem_db.txtのコマントアウトされている -2338と7170を解除して使ってください。) -・SP回復アイテムもintによって効果が増えるように変更。 -・0627で書き忘れですがカートのアイテム計算とitemdb_を呼ぶのを最小化する -処理を入ってるせいでpc_additem()、pc_delitem()、pc_cart_additem()、pc_cart_delitem()以外の方法でカートアイテムやアイテムに変動がある場合 -正常に動作する保証がないので修正のさいには注意してください。 - readme0754をreadme0574に修正。 - makefile 修正。 - (map/) - map.h 修正。 - clif.c 修正。 - pc.c 修正。 - battle.c 修正。 - mob.c 修正。 - script.c 修正。 - (db/) - item_db.txt 修正。 - class_equip_db.txt 修正。 - skill_db.txt 修正。(誤字を治しただけです。) - (conf/) - npc_event_doll.txt 修正。(流浪人さんありがとうございます。) - --------------- -//0628 by NOCTURNE - -・snapshot -・snapshotからsnapshotまでのReadme分割 -・要望が多かったのでsnap作成(プログラム的な変更点は無し - --------------- -//0627 by 死神 - -・コードの最適化と少し修正。(少しは軽くなると思います。) -・ @modifydisplayコマンド削除。 -・新しい移動パケットに対応だと思ったら0x1d8、0x1d9、0x1daパケットの一部が -0x78、0x79、0x7bと変わってるみたいです。つまり今のままでは対応できません。 -X,Yの座標の部分の書式が変わったのかと予測はしていますが... -情報を求みます。(makefileのDPACKETVERを4にすれば0x1d8、0x1d9、0x1daを -使いますが座標がずれたらしく何も標示されません。) -・100000からだったchar_idを150000からに変更。(ペットの卵の問題で武器の名前がちょっと変になったので修正しました。) -・ペットのコード少し修正。(pet_idをcard[2]とcard[3]からcard[1]とcard[2]に変更しました。よって前に作った卵は使えません。鞍でcard[3]の機能が変わったので -仕方なく修正しました。今度はconvertツールがありません。作る時間がなかったので...) -・最適化の為に修正した所が多いですが全て正常動作する保証はありません。 -鯖落ちバグが発生したら報告お願いします。(batte.cはまだ最適化してません。) -カートのアイテム計算やアイテムの重量の計算を最初にだけするようにしているので表示に少し問題があるかも... -・修正したファイルだけ書いておきます。 - makefile - help.txt - (common/) - mmo.h - (map/) - map.h - atcommnad.h - atcommnad.c - pc.h - pc.c - clif.c - script.c - trade.c - itemdb.h - itemdb.c - battle.h - battle.c - pet.c - map.c - mob.c - (char/) - char.c - (conf/) - battle_athena-conf - atcommand_athena.conf - --------------- -//0626 by 引退人 - -・パケット長テーブル(新移動パケットなど)修正 - (doc/) - client_packet.txt パケット解析スレ Mさんの情報を反映 - conf_ref.txt 0624に合わせて修正 - (map/) - clif.c - packet_len_table[] client_packet.txtに合わせて修正 - --------------- -//0625 by 引退人 - -・@hide透明化をBOSSなどに見破られないように修正 - (map/) - pc.h - #define pc_iscarton(sd) 修正 - #define pc_isinvisible(sd) 追加 - mob.c - mob_attack() - mob_target() - mob_ai_sub_hard_activesearch() - mob_ai_sub_hard_mastersearch() - mob_ai_sub_hard() - 透明(pc_isinvisible(sd)!=0)で死人と同様に判定されるように修正 - (conf/) - npc_cTower.txt 修正(thx to holyzardさん) - --------------- -//0624 by るるる - -・武器画像表示処理の一新(新移動パケット使用) -・上と関連して、@modifydisplayコマンドを設けた - 機能としては、現在のアサシン武器などのがおかしい場合に、または気に入らないとかで、 - キャラ毎に旧パケを使用するようにしている。 - - (map/) - atcommand.c - atcommand() @modifydisplayコマンドを追加 - atcommand.h - struct Atcommand_Config { -'7d 変更 - clif.c - clif_set0078_and01d8() , clif_set007b_and01da() 関数名&処理の変更 - clif_spawnpc() , clif_movechar() , clif_changelook() , clif_getareachar_pc() , - clif_fixpcpos() , clif_parse_LoadEndAck() 変更 - map.h - struct map_session_data ・b} 変更 - pc.c - pc_setnewpc() , pc_calcstatus() , pc_equiplookall() , pc_changelook() 変更 - - (conf/) - atcommand_athena.conf - equip_modifydisplay 追加 - - 変更箇所は全てキーワード「modifydisplay」でサーチすればほぼわかるかと。 - -コメント:もうこれで問題は無いはず。実は大いなる勘違いをしてた個所があったのは内緒(マテw - --------------- -//0623 by 引退人 - -・@hideで透明化(見られない&MOBにタゲられない)するように修正など - (map/) - atcommand.c - @hideのoption設定を0x04から0x40に変更 - mob.c - mob_attack() - mob_target() - mob_ai_sub_hard_activesearch() - mob_ai_sub_hard_mastersearch() - mob_ai_sub_hard() - option判定を0x06から0x46に修正 - (conf/) - npc_event_potion.txt MORISON_MEAT修正(thx to holyzardさん) - --------------- -//0622 by 引退人 - -・mobがスキル使用に失敗した場合、通常攻撃するように - (map/) - mob.c - mobskill_use_id() スキル使用失敗で0、成功で1を返すように修正 - mobskill_use_pos() スキル使用失敗で0、成功で1を返すように修正 - mobskill_use() 上記を反映して失敗時には0を返すように修正 - --------------- -//0621 by 胡蝶蘭 - -・アイテムチェックを行うかどうかconf/battle_athena.cnfに書けるように -・アイテムチェックで不正と判断するかどうかをdb/item_avail.txtに書けるように -・@itemcheckで明示的にアイテムチェックできるように - - デバグやテストなどで色々なアイテムIDを使用したい場合は - アイテムチェックを無効にして下さい。(item_check: off) - 無効にした場合でも@itemcheckコマンドでチェックすることが出来ます。 - cnfファイルは用意してないので必要なら各自適当に書き換えてください。 - - (db/) - item_avail.txt - 新規追加。不正アイテムの列挙に使用。未完成。他力本願。 - item_db.txtに定義されてるが実際には使用できないアイテムを書く。 - (doc/) - conf_ref.txt - battle_athena.cnfとatcommand_athena.cnfの説明修正 - (map/) - itemdb.c/itemdb.h - itemdb_availableマクロ追加 - itemdb_read_itemavail()追加 - itemdb_readdb()でavailable=1にするように - itemdb_search()で存在しないIDはavailable=0でデータを作るように - do_init_itemdb()でitemdb_read_itemavail()を呼ぶように - pc.c/pc.h - pc_checkitem()をエクスポート - pc_checkitem()でavailableとbattleconfigをチェックするように - atcommand.c/atcommand.h - @itemでbattleconfigをチェックするように - @itemcheckコマンド追加 - atcommandconfigにitemcheckメンバ追加 - battle.c/battle.h - battle_configにitem_checkメンバ追加 - -・ladminの修正など - アカウント追加、パスワード変更の際にパスワードを省略すると、 - パスワード用のエコーしない専用プロンプトで入力できます(&入力確認)。 - 追加の際にパスワードが表示されたら困る場合などに。 - パスワード入力中はCtrl+Cが効かないので注意してください。 - - パスワードの不正文字の表示が、何文字目かで表示するようになりました。 - その他微妙にチェック追加など。 - - Cygwinでしか動作確認していません。POSIXモジュールを使っているので、 - POSIXでない(&エミュレーションもできない)プラットフォームだと - 動かないかもしれません。 - UNIX系ではnkfなどで改行コードを変換しないとだめかも? - - (tool/) - ladmin - Ver.1.03に。 - -------------- -//0620 by 月詠み - -・ホーリークロス実装 - - (db) - skill_db.txt 修正 - (map) - skill.c - skill_additional_effect()修正(コメントのみ) - battle.c - Damage battle_calc_weapon_attack()修正 - -------------- -//0619 by るるる - -・パッチ0617のでやり忘れと微妙な修正 - - clif.c - clif_movechar(),clif_parse_LoadEndAck() 修正 - --------------- -//0618 by nini - -・リザレクションの詠唱、ディレイ追加。回復量修正。 -・消費SP修正 -・アローシャワーの範囲を5*5にして2セル吹き飛ばし。 -・チャージアローの使用武器条件無し。 -・スピアスタブの飛距離を6セルに。 - (/db) - cast_db.txt 修正 - skill_db.txt 修正 - (/map) - battle.c - battle_calc_weapon_attack() 修正 - skill.c - skill_castend_damage_id() 修正 - skill_check_condition() 修正 - skill_castend_nodamage_id() 修正 - --------------- -//0617 by るるる - -・武器画像表示で他キャラが表示されないのを「とりあえず」修正 -・靴表示のパケットを送信停止(現時点ではムダ。コメントしただけですが) - clif.c - clif_spawnpc(),clif_getareachar_pc(),clif_fixpcpos(),clif_changelook()修正 - pc.c - clif_changelook()がある部分を修正(武器ー>盾と順になるように処理の入れ替え) - -コメント。 -新マップ移動パケ(0x1d8〜0x1da)を色々とやったが、そのパケ1つで武器表示が新式のに対応してる -というわけではないっぽい。旧移動パケだと自分以外のキャラが移動すると旧式表示になってしなう。 -更に、新武器表示パケは武器と盾の同時処理が出来てない。おそらくクライアントの問題だと思う。 -とりあえず、キャラが動くたびに新武器パケ=>旧盾パケの2つの装備パケを送ることで解決させている。 -本鯖ではどうなのかの実際のところのデータが無いため、これ以上のことはムリ。 - --------------- -//0616 by 胡蝶蘭 - -・water_height.txtを読んでいないとサーバーが落ちるバグ修正 - map.c - map_waterheight()修正 - -・PCのマップ移動時のアイテムチェックでアイテムIDの存在をチェックするように修正 -・一部の@コマンドでアイテムIDの存在をチェックするように修正 - pc.c - pc_checkitem()修正 - pc_authok()修正 pc_checkitem()追加 - clif.c - clif_parse_LoadEndAck()修正 - itemdb.c - itemdb_exists()追加(itemdb_searchと同じだが、dbに存在しない - 場合は新しいデータを作らずにNULLを返す) - itemdb_read_classequipdb()修正 itemdb_search=>itemdb_exists - itemdb_read_itemnametable()修正 itemdb_search=>itemdb_exists - itemdb_read_itemvaluedb()修正 itemdb_search=>itemdb_exists - atcommand.c - @item修正 itemdb_search=>itemdb_exists - @produce修正 itemdb_existsでチェックするように - --------------- -//0615 by 波浪 - -・アイテムDATA大幅修正 - 主な修正箇所は、回復アイテムの回復量の修正、消費アイテムをclass_equip_db.txt無しでも使用できる様に修正、 - 装備品の装備可能職を全て修正、カード効果を修正、etc・・・です。 - --------------- -//0614 by Nikita - -・アイテムDATAの修正(主に回復量) -・スキル解毒の射程修正 -・0612の細かい修正 - (conf/) - npc_town_prontera.txt 修正 - (db/) - item_db.txt 修正 - skill_db.txt 修正 - --------------- -//0613 by 引退人 -・checkweight修正 - (conf/) - npc_event_making.txt checkweight部分を修正 - npc_event_potion.txt ポーション、ジュースNPCのcheckweight修正 - --------------- -//0612 by nini - -・アイテムDATA修正 - (db/) - item_db.txt 修正 - (conf/) - npc_town_***.txt 修正 - R.O.M776さんを参照しました。 - --------------- -//0611 by 死神 - -・アイテム使用条件があわない時0xa8パケットを送るように変更。(バグ報告スレッド 243のno nameさん情報提供ありがとうございます。) -・QMで集中力向上と速度上昇、アドレナリンラッシュ、ラウドボイス、スピアクイッケン、ツーハンドクイッケンを解除するように修正。 -・速度上昇と速度減少で逆のスキルが解除されるように修正。 -・0609で書き忘れ。モンスターがQMの範囲から抜けても効果が維持するように -変更とブレッシングで呪いと石化が解除されるように修正。 - clif.c - clif_useitemack() 修正。 - skill.c - skill_status_change_start() 修正。 - pc.c - pc_insert_card() 修正。(これはカードバグとは関係ない修正です。そのバグの修正は自分が05xx当たりで修正しましたので。) - --------------- -//0610 by 波浪 - -・アイテムDATA修正 - (db/) - item_db.txt 修正 - --------------- -//0609 by 死神 - -・色々と修正。 -・モンスターが止まるように動く問題修正。 -・指弾のディレイ修正。 -・矢作成のコード片付け。 -・敵がスキル範囲から逃げた場合スキルが失敗するように変更。 -・class_equip_db.txtの仕様変更。 - 性別と装備レベルも設定可能に変更と使用アイテムの使用職業、性別と使用 - レベルの設定ができるように変更。(ただデータが多いせいで修正した - class_equip_db.txtはサンプル程度の物です。埋めてください。他力本願ですが...) - それとアイテム使用条件があわないとアイテムが使わないようにしては - いますが01c8パケットの<type>を0にしてもアイテムを使用した時と同じ - エフェクトが出ます。本鯖のアイテム使用パケットが分からないままじゃ - こうするしかなかったのですが... -・battle_athena.confに項目追加。 -・その他スキル少し修正と細かい修正。 -・修正した所を全て覚えてませんのでファイルだけ。 - (map/) - clif.c 修正。 - mob.c 修正。 - mob.h 修正。 - pc.c 修正。 - map.h 修正。 - skill.c 修正。 - skill.h 修正。 - itemdb.c 修正。 - battle.c 修正。 - battle.h 修正。 - (conf/) - battle_athena.conf 修正。 - (db/) - cast_db.txt 修正。 - skill_db.txt 修正。 - create_arrow_db.txt 修正。 - class_equip_db.txt 修正。 - item_db.txt 修正。 - (doc/) - client_packet.txt 修正。 - conf_ref.txt 修正。 - --------------- -//0608 by sk -・アマツNPC追加 - (conf/) - npc_town_amatsu.txt 城内NPC追加 - npc_warp_amatsu.txt 城内ワープポイント追加 - --------------- -//0607 by J -・アサルトタートルの手下召喚のバグ修正(報告ありがとうございます るるるさん) - (db/) - mob_skill_db.txt アサルトの修正ついでにテレポを使うMOBのスキルディレイも修正 - --------------- -//0606 by 引退人 -・スキルレベル最大値以上にクリックした時点で他スキルが上げられなくなるバグを修正(Thanx to 227さん) - (map/) - clif.c - clif_skillup() - スキルレベルが最大値のとき、パケット末尾を0にするように修正 - --------------- -//0605 by るるる - -・武器属性付与スキルの不都合修正 - 武器を持ち替えたり外したりした場合も、属性付与を解除するようにしました。 - 但し、素手=>武器装備のみ状態維持します。 -・スピアクイッケンのステータスアイコンを正しく表示 -・2HQ、スピアクイッケン、アドレナリンラッシュで該当以外の武器持ち替えで状態消滅 - スピアクイッケンは未確認ですが、2HQは確実なので2HQと不公平な仕様とは - 考えにくいので同様なパターンとしました。本鯖と相違がある場合は報告願います。 -・敵のQMで集中力向上と速度上昇を解除 - QMで影響するスキルはこれ2つだけかな? 私の記憶と掲示板での報告とで - 判断したのですが、もし相違がありましたら報告願います。 - - (map/) - clif.c - clif_parse_UnequipItem() 修正 - pc.c - pc_checkallowskill() pc_equipitem() 修正 - skill.h - skill_encchant_eremental_end() 追加 - skill.c - skill_status_change_start() skill_status_change_end() - skill_status_change_clear() skill_encchant_eremental_end() 修正 - その他細かいところ少々 - --------------- -//0604 by J -・MOBスキル再修正 -・MOBDB修正 - (db/) - mob_skill_db.txt - アークエンジェリングとタートルジェネラルが1回に2種類までしか - MOBを出さなかったのを修正 - mob_db.txt - ロードオブデスのドロップでエラーが出るのを修正(未確認) - 怨霊武士のドロップとMVPを追加(未確認) --------------- -//0603 by 引退人 -・新規アイテム時にも所持可能個数チェックをするように修正 - (map/) - pc.c - pc_checkadditem() - 新規アイテム時にMAX_AMOUNTを超えていたら - ADDITEM_OVERAMOUNTを返すように修正 - --------------- -//0602 by 引退人 -・Geffen鍛冶屋で落ちる問題を修正 - (conf/) - npc_town_geffen.txt if (!checkweight(,)) から if (!(checkweight(,))) に修正 - --------------- -//0601 by J -・MOBスキルの危ない所をいくらか修正 -・覚醒と狂気の使える職を修正 -・ゲフェニアダンジョンの配置をカボチャイベントで入れたときの配置に修正 - ただしボスがDOP2体ではなくドラキュラにしています。 - (conf/) - npc_monster.txt モンスター配置微変更 - (db/) - mob_skill_db.txt 怪しい設定などの修正 - item_db.txt 増速POTの修正 - --------------- -//0600 by 引退人 -・プロンテラ精錬所の横のファンに話し掛けると固まる問題を修正 -・MOBスキル取り込み(Thanx to Jさん) - (conf/) - npc_event_skillget.txt ファンのLabelを修正 - npc_town_prontera.txt ファンが重複していたので削除 - (db/) - mob_skill_db.txt ジュノー以降のMOBスキル追加 - --------------- -//0599 by るるる - -・セージの武器属性付与スキルの不都合修正とステータスアイコン表示 - アスペルシオとエンチャントポイズンとで多重にかかってしまってたので、 - 最後に付与したもの1つになるようにしました。 - そのついでにステータスアイコンも表示するようにもしました。 - (未テストですが、アイコン出なかったスピアクイッケンもでるはずです。) -・アイテムDBにて、増速ポーションの使用制限を追加 - Jazzさん提供です。 - それと私の趣味でラグナロクTシャツをアレナニしましたがw 気に入らなければ - 消すなり元通りに修正するなりしてしちゃってくださいませ〜。 - - (conf/) - battle_athena.conf 598での入れ忘れ - (map/) - skill_encchant_eremental_end() 追加 - skill_status_change_end() skill_status_change_start() skill_status_change_clear() 修正 - (db/) - iten_db.txt 修正 - --------------- -//0598 by るるる - -・装備武器の画像変更に対応 - 一応ながらクルセイダーの両手槍とかプリーストの鈍器とかはテストしましたが、 - 全ての職をチェックはいません。またこの時点ではクライアント自体の表示データに - 問題の有るのが多いのも付け加えておきます。 - あと、靴も一応は対応しました。但しこれは現時点では本鯖すらも未対応なのですが。 - 表示が化けて嫌だという場合は従来のやり方も出来ます。 - - (conf/) - battle_athena.conf - オプション equip_modifydisplay を追加 - (map/) - battle.h - Battle_Config 修正 - battle.c - battle_config_read() 修正 - clif.c - packet_len_table[] clif_changelook() 修正 - map.h - enum {} 修正 - pc.c - pc_calcstatus() pc_equiplookall() pc_changelook() 修正 - (common/) - mmo.h - mmo_charstatus {} 修正 - --------------- -//0597 by 波浪 - -・アマツに関する修正&微修正 - (conf/) - npc_mob_job.txt - npc_monster.txt - npc_monster30.txt - モンス名修正 - npc_monster_amatsu.txt - 追加(モンス数がかなり手抜きです・・・ - npc_town_amatsu.txt - ショップNPCを統合(npc_shop3.txtを消してもOKです - (db/) - mob_db.txt - アマツのモンスデータを現在分かる範囲で修正&草ときのこのdef,mdefを修正 - --------------- -//0596 by 死神 - -・0595の修正と細かい修正。 -・フリーキャストでキャストしている間は攻撃可能ですがキャストした後の -ディレイタイムでは攻撃できないようになっています。本鯖の仕様がどうなのかは -わかりません。 -・動いているPCにモンスターが攻撃できない問題修正。(テストしてませんが -多分これで大丈夫かと。) - (map/) - skill.h - SC_FREECAST 削除。 - skill.c - skill_use_id()、skill_use_pos() 修正。 - skill_castend_id()、skill_castend_pos() 修正。 - その他少し修正。 - pc.c - calc_next_walk_step()、pc_attack_timer()、pc_calcstatus() 修正。 - clif.c - clif_parse_ActionRequest()、clif_parse() 修正。 - map.h - struct map_session_dataにprev_speed追加。 - mob.c - mob_ai_sub_hard()、mob_changestate()、mob_attack() 修正。 - --------------- -//0595 by PRevEv -・フリーキャスト修正、実装(キャスティング中攻撃もできます。) - (/map) - pc.c - pc_calcstatus() 修正。 - calc_next_walk_step() 修正。 - pc_attack_timer() 修正。 - skill.c - skill_castend_id()、skill_castend_pos()、skill_use_id()、skill_use_pos() 修正。 - --------------- -//0594 by 死神 - -・韓国鞍のパーティ問題修正と細かい修正。 -・@partyコマンド修正と@guildコマンド追加。 -・battle_athena.confにguild_emperium_check追加。 -・スキル使用が失敗してもディレイがかかる問題修正。 - help.txt 修正。 - (map/) - clif.c - clif_parse_CreateParty2() 追加。 - clif_parse_ItemIdentify() 修正。 - その他少し修正。 - atcommand.h、atcommand.c 修正。 - battle.h - struct Battle_Configにguild_emperium_check追加。 - battle.c - battle_config_read() 修正。 - guild.c - guild_create()、guild_created() 修正。 - skill.c - skill_castend_id()、skill_castend_pos() 修正。 - Makefile 修正。 - (doc/) - client_packet.txt - パケット0x01e8 追加。 - conf_ref.txt 修正。 - (conf/) - atcommand_athena.conf 修正。 - battle_athena.conf 修正。 - --------------- -//0593 by 死神 - -・メテオとバミリオンのダメージ修正と細かい修正。 -・メテオの隕石が落ちてくる範囲を7*7から5*5に変更。(これで中央は全ての隕石の -ダメージを受けることになります。) -・自動回復計算式変更。 - スキルレベル*5 + (max_hp/50)から - スキルレベル*5 + (max_hp*スキルレベル/500)に変更。(SPと息吹も同じように変更。) -・GM右クリック命令「使用者強制終了」でatcommand_athena.confのkickの -レベルをチェックするように変更。 - (db/) - skill_db.txt - スキル気功のspを10から8に修正。 - (map/) - map.c - NO_WATERを100から1000000に変更。 - battle.c - battle_calc_magic_attack() 修正。 - skill.c - skill_castend_pos2() 修正。 - pc.c - pc_natural_heal_hp()、pc_natural_heal_sp()、pc_spirit_heal() 修正。 - clif.c - clif_parse_GMKick() 修正。 - (doc/) - conf_ref.txt 修正。 - --------------- -//0592 by 引退人 - -・水場の有り無しをwater_height.txtだけで決めるように変更。npc_water.txtは不要に。 -・カードスキルではレベル上げできないようになったため不要になった処理を削除。 - (conf/) - map_athena.conf - npc: conf/npc_water.txt 消去 - water_height.txt - デフォルト高さ3のマップ分を追加&all_waterを高さ-100としてコメントで追加 - (map/) - map.c - waterlistはmap_readwater()内でメモリ確保 - gat設定後は不要なのでmap_readallmap()でメモリ開放しています - map.h - struct map_dataのflagからwater_flagを消去 - npc.c - npc_parse_mapflag() - マップフラグwaterとall_waterを消去 - pc.c - pc_skillup() - 裏でスキルLvUPできなくなったのでskill[id].flagの分は消去 - skill.c - skill_check_condition() - map_getcellで水場判定するように修正 - --------------- -//0591 by CHRIS - -・モンクが氣弾をもっているとき、氣弾*3の必中ダメージが入る様になりました。─ battle.c修正 -・モンクスキル「指弾」と「発勁」と「気孔」の詠唱時間が正しく修正されました。─ cast_db.txt修正 - --------------- -//0590 by 死神 - -・grf-files.txtやconfファイル、account.txtファイルの名前と位置を変えるように変更。 -・マップ移動による鯖落ちを防ぐ為に修正。(マップが二度ロードされて鯖落ちが -起こったとの報告を受けたので。) -・0586をちょっと修正。装備によるスキルの場合レベル上げができないように修正。 -ただ装備によるスキルをスキルポイントを使って上げる時は装備を外す必要が -あります。 -・@partyちょっと修正。(名前に空白があっても大丈夫なように。) -・水場の高さをwater_height.txtで読み込むように変更。 -・confファイルで設定する物をファイルのパスに空白があっても大丈夫な -ように変更。 -・GM右クリック命令「使用者強制終了」でモンスターを倒せるように変更。 -(原因は不明ですがこれでモンスターを殺すと鯖がめちゃくちゃに遅くなることが -あります。) -・その他少し修正。 -・テストは殆んどしてませんので注意してください。 - athena-start 修正。 - (map/) - pc.c - pc_skill()、pc_resetskill()、pc_setpos()、pc_read_gm_account() 修正。 - pc_set_gm_account_fname() 追加。 - pc.h - pc_set_gm_account_fname() 追加。 - clif.c - clif_skillinfoblock()、clif_parse_LoadEndAck()、clif_parse_GMKick() 修正。 - clif_changemap() 修正。 - atcommand.c - @partty 修正。 - skill.c - skill_castend_nodamage_id() 修正。 - map.c - map_config_read()、map_readwater() 修正。 - script.c - script_config_read()、do_init_script() 修正。 - script.h - script_config_read() 追加。 - (common/) - version.h 修正。 - grfio.h - grfio.c - grfio_init() 修正。 - mmo.h - GRF_PATH_FILENAME 追加。 - (conf/) - map_athena.conf 修正。 - npc_water.txt 修正。 - water_height.txt 追加。 - login_athena.conf 修正。 - (login/) - login.c - login_config_read()、read_gm_account() 修正。 - (char/) - char.c - do_init() 修正。 - char_config_read() 追加。 - inter.c - inter_config_read() 修正。 - (doc/) - conf_ref.txt 修正。 - --------------- -//0589 by 胡蝶蘭 - -・GMの右クリックで切断される問題を修正 - とりあえず01dfパケットを無視するようにしました。 - なんとなくこのパケットはチャット禁止回数とは関係無いような気も…… - - clif.c - clif_parse_GMReqNoChatCount()追加 - -・startをathena.shでなくathena-startを使うように変更 - start - athena.sh => athena-start startに置き換えしただけ - --------------- -//0588 by Kalen - -・AmatsuNPC追加 - --------------- -//0587 by 胡蝶蘭 - -・loginサーバーの管理パケットの仕様を変更(0579のログイン拒否情報に対応) - (login/) - login.c - アカウントバン状態変更パケット追加(7936,7937) - アカウントリスト所得パケット修正(7921) - (doc/) - admin_packet.txt - -・ladminの機能追加 - ・バン状態を変更するコマンド追加 - ・リスト表示と検索でバン状態も表示されるようになった - ・"?"でもヘルプが出るように修正 - ・シンボリックリンクにstateaccountが追加されました。 - 使う人はladminの--makesymlinkをもう一度実行してください - - (tool/) - ladmin - 機能追加 - --------------- -//0586 by 引退人 -・カードスキルを修正 - (/map) - pc.c - pc_calc_skilltree() - pc_skill() - 覚えられないスキルならskill[id].flag=1とする - またはskill[id].flagに本来のlvを+2して記憶 - pc_skillup() - skill[id].flagも増やす - clif.c - clif_skillinfoblock() - skill[id].flag==1なら覚えられないスキル - (/char) - char.c - mmo_char_tostr() - skill[id].flagから本来のlv値を保存する - --------------- -//0585 by kalen -・script修正 - npc_town_guid.txt 外見変更 - --------------- -//0584 by 引退人 -・カードスキルを修正 - (/map) - pc.c - pc_calc_skilltree() cardスキルを忘れさせる処理を追加 - pc_skill() 整理 - --------------- -//0583 by kalen -・script修正 - npc_event_doll.txt 抜けていた部分の会話追加 - npc_town_guid.txt 町の案内要員の画像を表示できるように修正 - 基本的に最新jROで問題なしです。 - --------------- -//0582 by PRevEv -・580のバグ修正。 - (/map) - skill.c - skill_use_pos() 修正。 --------------- -//0581 by 引退人 -・水場高さ設定関連を少し修正 - (/map) - map.c - map_waterheight() - map_readwater() - map_readmap() - waterlist[512] -> *waterlistにして、mallocでメモリ確保するように修正。 - map_readallmap() - free(waterlist);追加 - -・バグ報告スレッドの修正パッチを取り込み - (conf/) - npc_town_refine.txt セミコロン抜け修正 - (db/) - item_db.txt 1161,バルムン修正 - --------------- -//0580 by PRevEv -・フリーキャスト仮実装(キャスティング中攻撃は不可能) - (/map) - clif.c - clif_parse_WalkToXY() 修正。 - pc.c - pc_calcstatus() 修正。 - skill.c - skill_castend_id()、skill_castend_pos()、skill_use_id()、skill_use_pos() 修正。 --------------- -//0579 by Aの人 -・ログインを弾く処理を仮実装 - conf/login.c - auth_dat構造体にstateを追加 - mmo_auth関数修正 - mmo_auth_new関数修正 - mmo_auth_sync関数修正 - mmo_auth_init関数修正 - - この値を変更するツール、改善策。他力本願です(><; --------------- -//0578 by 引退人 -・バグ報告スレッドの修正パッチを取り込みなど(thanx to るるるさん,Athefansさん,sageさん,zupportさん) - help.txt @goの説明ちょっと修正 - (conf/) - npc_mob_job.txt 第4列目をTab区切りに修正 - npc_water.txt 水場高さ修正 - (db/) - item_db.txt 640,...,{ pet 1155; },{},,に修正 - mob_db.txt 1162,RAFFLESIA,ラフレシア...修正 - --------------- -//0577 by るるる -・@コマンドを追加&修正 - atcommand.c - atcommand() @itemresetコマンド追加 @goコマンド修正(アマツ・コンロンを追加) - atcommand_config_read() 上に合わせてitemreset使用レベル指定を追加 - - doc/conf_ref.txt - conf/atcommand_athena.conf itemreset使用レベル指定を追加 - help.txt @itemresetの説明追加と@goの説明修正 - -------------- -//0576 by V&S -・ゴーストリングカードとバースリーカードの効果が逆になっていたのを修正 - { bonus bDefEle,7; }→ゴーストリングカード(念) - { bonus bDefEle,8; }→バースリーカード(闇) - ↑だったのを↓に修正 - { bonus bDefEle,7; }→バースリーカード(闇) - { bonus bDefEle,8; }→ゴーストリングカード(念) - - 鋼鉄の重量を修正 - --------------- -//0575 by 引退人 -・水場ファイルが"conf/npc_water.txt"固定だったのを修正 -(conf/map_athena.confのnpc:に書かれているファイルをみて水場高さ設定するように) - map.c - struct waterlist[512]; 新規追加。マップファイル名と水場高さを記憶。 - map_waterheight() 新規追加。水場の高さを返す。 - map_readwater() 水場ファイルをみてwaterlistを設定するように修正。 - map_readmap() map_waterheight()を呼ぶように修正。 - map_config_read() "npc"でmap_readwater(w2);追加。 - --------------- -//0574 by いど - -・サーバーSnapshot -・conf/shop_*.txtの内容をconf/npc_town_*.txtに統合 - --------------- -//0573 by Jazz - -・mapの penalty, nomemo, noteleport, nobranchの optionを設定。 -・map サーバーが cpuを無限占有することを検査するための script 添付. cygwin環境で作成と実験をしました. - (/conf) - mapflag.txt 追加。 - (/tool) - mapcheck.sh 追加。 - --------------- -//0572 by 引退人 -・"conf/npc_water.txt"の第4列で水場高さ設定 - (ちゃんとした水場判定が実装されるまでのつなぎとして・・・) - (/conf) - npc_water.txt サンプル修正。 - ・第4列で水場の高さを設定します。 - ・高さを書かなかった場合のデフォルト値は3になります。 - (/map) - map.c - ・水場高さ設定関数 map_readwater() 追加。 - --------------- -//0571 by code -天津フィールドのMOBの配置とワープポイントの設定の修正 -天津パッチに崑崙が含まれているのを確認したので崑崙のワープとmobを配置 - -conf/npc_monster35.txt - mobの配置 - -conf/npc_warp_amatsu.txt - 天津warp pointの設置 - -conf/npc_warp_gonryun.txt - 崑崙warp pointの設置 - -conf/npc_town_amatsu.txt - 暫定的にプロンテラ噴水前←→天津港/プロンテラ噴水前←→崑崙の接続NPC - --------------- -//0570 by code -天津フィールドのMOBの配置とワープポイントの設定です。 -conf/npc_monster35.txt - mobの配置 - -conf/npc_warp_amatsu.txt - warp pointの設置 - -conf/npc_town_amatsu.txt - 暫定的にプロンテラ噴水前←→天津港の接続NPC - --------------- -//0569 by 死神 - -・0561の@jobcange での♀バード&♂ダンサーによる鞍落ち防止をpc_jobchange()でするように変更。 -・@コマンド@party追加。パーティを作る命令です。韓国鞍を使うとパーティを作る時止まるので臨時的にこれを使ってパーティを作ってください。 -・水の判断処理修正。 -・マップフラグにwaterとall_water追加。詳しくはnpc_water.txtを参考してください。 -iz_dun0xだけ入力していますので他のは埋めてください。マップフラグwaterかall_waterが入ってないとセルのtypeが3でも水として認識しません。そして水だらけのiz_dun02から04までは全て水として認識するようにall_waterを入れています。(これ以外は方法がなかったので...) -・battle_athena.confに項目追加。一部はWeissを参考して作った物です。 -・テストしてない物も少しあります。 - (/conf) - atcommand_athena.conf 修正。 - battle_athena.conf 修正。 - map_athena.conf 修正。 - npc_water.txt 追加。 - (/doc) - conf_ref.txt 修正。 - (/map) - atcommand.h、atcommand.c 修正。 - battle.h 修正。 - battle.c - battle_config_read() 修正。 - pc.c - pc_jobchange()、pc_stop_walking() 修正。 - npc.c - npc_parse_warp()、do_init_npc()、npc_parse_mapflag() 修正。 - mob.c - mob_ai_sub_hard() 修正。 - pet.c - pet_food() 修正。 - skill.c - skill_check_condition() 修正。 - map.h - struct map_data 修正。 - --------------- -//0568 by 引退人 - -・アクアベネディクタ水場判定など -・ウォーターボール水場判定(read_gat(m,x,y)==3で水場と判定) - skill.c - skill_castend_nodamage_id() - case AL_HOLYWATER: アクアベネディクタ(聖水取得) - skill_check_condition() - case AL_HOLYWATER: アクアベネディクタ(水場判定) - case WZ_WATERBALL: ウォーターボール(水場判定) - --------------- -//0567 by るるる - -・アコライトのアクアベネディクタを仮実装(水場限定使用のみ未実装) -・プリーストのアスペルシオ、セージのフレイムランチャーでスキル使用時にアイテム消費 -・ミストレスカード装備時にセージの属性原石&ハンターの罠が消費されないバグを修正 - - (/map) - skill.c - skill_check_condition() 修正 - --------------- -//0566 by パイン - -・0563のスキル解除条件が間違っていたので修正。武器をはずす&武器を変えた場合は - 無条件で解除するようにした。 - -# pc_checkallowskill について(前回説明書くのを忘れていたので…) - 一応今後の含みとしてreturnを返すようにしていますが、現在は(戻り先では)使っていません。 - 今現在は騎士・クルセイダーくらいしかスキル使用時の武器制限がありませんが、今後出てこない - とも限らないので、もし(2次上位か3次?)出てきたらここでチェックしてください。 - - (/map) - pc.c - pc_checkallowskill() 修正 - --------------- -//0565 by 引退人 - -・マップ移動時に矢装備が外れないように修正 -・ログイン時に矢装備が表示されるように修正 - (/common) - mmo.h - (矢装備は0x8000なので)shortだとintへのキャスト時などに - 負値となってしまうためunsigned shortに修正 - struct item - short equip; -> unsigned short equip; - (/map) - clif.c - clif_itemlist() アイテムリストの矢のついでに矢装備もチェック - clif_arrowequip() シンプル化 - pc.c - pc_equipitem() 修正 - --------------- -//0564 by 紅葉 - -・@modelの服染め不可能判定修正。 -・@modelで、選べるハズの髪形に変更出来なかった部分を修正。 - 上記変更点に合わせてhelp.txtの修正。 - --------------- -//0563 by パイン - -・MOBの暗闇スキルを食らった後に回復しないのを修正。…なんだけど、適正な値が分からないので - 毒や沈黙と同じ時間にしてあります - 今後、また手を加えるかもしれません。 -・2HQとスピアクイッケンを使用中に武器を変えた場合は解除するように変更。 - - (/map) - skill.c - skill_castend_damage_id() 修正。 - skill_status_change_timer() 修正。 - pc.c - pc_checkallowskill() 新設。 - pc_equipitem() 修正。 - pc.h - pc_checkallowskill() 新設。 - --------------- -//0562 by huge - -・矢を弓装備時以外でも装備できるように戻しました。 -・矢の属性を適用するのを弓装備時のみに修正。 - - pc.c - pc_equipitem() 修正。 - pc_calcstatus() 修正。 - --------------- -//0561 by 引退人 - -・Linuxでもコンパイルできるように - (/map) - skill.c - skill_castend_damage_id() 変数dx,dyの宣言位置変更 - Makefile - LIBS に -lm 追加 - -・@jobcange での♀バード&♂ダンサーによる鞍落ち防止。 by (no name)さん - atcommand.c - @jobchange,@charjobに性別チェック追加 - -// ナナスさん修正 -・clif.c内でatcommand.hを2度includeしていたので一つ削除。 -・パーティー会話、ギルド会話でも@コマンドをチェックするように修正。 - (/map) - clif.c - clif_parse_PartyMessage()、clif_parse_GuildMessage 修正。 - --------------- -//0560 by パイン - -・0559 の athena-start を Unix Like OS でも動くようにリファイン。 - --------------- -//0559 by rowla - -・athena.shを全面的に書き直し、athena-startに。athena-start startで開始、athena-start stopでサーバー停止。cygwinでテスト、*BSD|Linuxでは未テスト(環境がないため)。 - --------------- -//0558 by 死神 - -・ブリッツビートを自動だけ弓を装備していないと発動できないように変更。(手動は武器に関係なく使えます。) 未テスト。 -・トラップの重さ修正。(何故かは知らないけど100になっていたのを10に修正。因みに倉の表示は100が10で10が1です。) -・弓で使うスキルの場合矢が減らないのが仕様だったと覚えているので矢をチェックしないように修正。 -・モンクスキル三段掌の表示をパッシブに変更。 -・マップフラグをセットする時dummyがなくてもセットできるように修正。 -(mapflag nomomo dummyからmapflag nomemoでも大丈夫なように変更。) -未テスト。 - (/db) - item_db.txt 修正。 - skill_db.txt 修正。 - (/map) - skill.c - skill_check_condition()、skill_additional_effect() 修正。 - skill_status_change_start() 修正。 - npc.c - do_init_npc() 修正。 - --------------- -//0557 by huge - -・矢を、弓装備時のみ装備できるように修正。 -・弓を装備から外したら、矢も外れるように修正。 -・矢を消費するスキルをいくつか修正。 -・鷹を、弓を装備しているときのみ発動するように修正。(未テスト) - - pc.c - pc_equipitem() 修正。 - pc_unequipitem() 修正。 - skill.c - skill_additional_effect() 修正。 - skill_check_condition() 修正。 - --------------- -//0555 by 死神 - -・細かい修正とプレゼントボックス、古い巻物のバグ修正。 -・@コマンド@refine、@produce少し修正。 -・サーバーのIPにDNS名を使えるように変更。(今さらですがYareから -持ってきた物です。) -・スティール計算式変更とMVPアイテム処理変更。 -・店NPCを利用によるジョブ経験値獲得計算式変更。 - 獲得ジョブ経験値 = ln(金*スキルレベル) * shop_exp / 100 -・ほとんどテストしてないのでバグの可能性があります。 - help.txt 修正。 - (/conf) - atcommand_athena.conf 修正。 - battle_athena.conf 修正。 - (/db) - item_db.txt 修正。 - (/doc) - conf_ref.txt 修正。 - (/char) - char.c - do_init()、check_connect_login_server() 修正と少し修正。 - (/map) - mob.c - mob_damage() 修正。 - pc.c - pc_getitemfromcart()、pc_steal_item() 修正。 - pet.c - pet_return_egg()、pet_get_egg()、pet_unequipitem() 修正。 - script.c - buildin_getitem() 修正。 - skill.c - skill_produce_mix() 修正。 - storage.c - storage_storageget() 修正。 - atcommand.c 修正。 - map.c - map_config_read() 修正と少し修正。 - chrif.c - check_connect_char_server()、do_init_chrif()、chrif_setip() 修正と少し修正。 - npc.c - npc_buylist()、npc_selllist() 修正。 - --------------- -//0554 by NOCTURNE -・サーバーSnapShot -・too/addaccountの削除 -・help.txtの更新 - --------------- -//0553 by 胡蝶蘭 - -・ladminのバグ修正と機能追加 - ・キーワードによるアカウント検索機能追加 - ・シェルコマンドとして使用できるようにプロンプトを使わないモード追加 - ・追加機能についてはladminを見てください - ・ ladminの--makesymlinkにより、シンボリックリンクとしてaddaccountを - 作成するため、以前のaddaccountは削除する必要があります。 - これらのシンボリックリンク(Cygwinではショートカット)と、 - 古いaddaccountは鯖snapshotには含まないで下さい。 - - (tool/) - ladmin - 機能追加と修正 - -・女性アカウントしか作成できないバグ修正 -・ladmin、checkversion使用時loginサーバーが暴走するバグ修正 -・GMアカウント周辺のIDを避けるためにSTART_ACCOUNT_NUMを変更 - (既にGMアカウントは避ける仕様になっていますが、混乱防止のため) - - (login/) - login.h - START_ACCOUNT_NUMを500000から2000000に変更 - login.c - 7532(切断)パケットの処理修正 - mmo_auth_new()修正 - -・backupがバックアップするファイルにpet.txtを追加 - (tool/) - backup - ファイル追加修正 - --------------- -//0552 by 死神 - -・安定性を上げる為の修正ですが本当に安定性上がったか -どうかは不明です。 -・PVPによりクライアントが落ちる問題修正。 - atcommand.c - @pvpoff、@pvpon、@gvgon、@gvgoff 修正。 - script.c - buildin_pvpon()、buildin_pvpoff()、buildin_gvgon()、buildin_gvgoff() 修正。 - clif.c - clif_pvpset() 修正。 - skill.c - skill_attack()、skill_unit_onplace()、skill_unit_onout() 修正。 - skill_unit_ondelete() 修正。 - --------------- -//0551 by Kalen -・DB修正 - db/create_arrow_db.txt 完成 - SourceID順にソートしました。 - --------------- -//0550 by huge - -・矢作成スキル実装 - - clif.c - clif.h - clif_arrow_create_list() 追加 - clif_arrow_created() 追加 - clif_parse() 修正 - - pc.c - pc_search_inventory() 修正 - - skill.c - skill.h - skill_arrow_db() 追加 - skill_readdb() 修正 - skill_castend_damage_id() 修正 - - db/create_arrow_db.txt 追加 - db/skill_db.txt 修正 - - まだdbは未完成です。 - --------------- -//0549 by Kalen - -・map_athena.conf - オリジナルスクリプト、季節限定スクリプトを整頓 - shop3.txt追加 - -・各種NPC追加&修正 - npc_event_yuno.txt [追加]ジュノーイベント(青石5個GET) - npc_cTower.txt [追加]地上地下の鍵NPC - npc_town_yuno.txt [修正]台詞修正 - - npc_event_carnival.txt [追加]旧鯖カーニバルイベント時のNPC - --------------- -//0548 by huge - -・矢を装備した時の表示バグ問題を修正。 - clif.c - clif_arrowequip() 修正。 - pc.c - pc_equipitem() 修正。 - -あとは、マップを移動するたびに装備が外れちゃう点ですね・・・。 - --------------- -//0547 by 死神 - -・安定性を上げる為の修正と細かい修正。 -・スキルユニットの判定をしている間メモリーを解除できないように変更。 - map.c - map_foreachinarea()、map_foreachinmovearea() 修正。 - map_foreachobject() 修正。 - block_free_maxを32000から50000に変更。 - pc.c - pc_calcstatus() 修正。 - skill.c - do_init_skill()、skill_unit_timer()、skill_status_change_clear() 修正。 - skill.c、battle.c、battle.h - struct battle_configのsanctury_typeをsanctuary_typeに変更。 - (英語スペル間違いで修正。) - battle_athena.conf - sanctury_typeをsanctuary_typeに変更。 - conf_ref.txt - sanctury_typeをsanctuary_typeに変更。 - --------------- -//0546 by 獅子o^.^o - -conf/npc_shop2.txt -.バ一ド、ダンサ一用の武器。コモドの武器屋で販売している。 -.モンク用の武器。カピト一リナ修道院で販売している。 - --------------- -//0545 by 死神 - -・ブリッツのダメージを自動で分散、手動で普通になるように変更。 -・オートブリッツバグ修正。(これで大丈夫だといいけど...) - map.c - block_free_maxを16000から32000に修正。 - block_list_maxを4096から5120に修正。 - battle.c - battle_weapon_attack() 修正。 - skill.c - skill_attack()、skill_castend_damage_id() 修正。 - --------------- -//0544 by Diex -・猛龍拳から阿修羅覇凰拳へのコンボ実装。 -・阿修羅覇凰拳発動後、敵の背後に移動するよう、修正。 -・三段掌のダメージ修正。 - (/map) - skill.c - skill_castend_damage_id() 修正。 - skill_check_condition() 修正。 - skill_use_id() 修正。 - pc.c - pc_attack_timer() 修正。 - pc_authok() 修正。 - battle.c - battle_calc_weapon_attack() 修正。 - battle.h - struct Battle_Config 修正。 - map.h - struct map_session_data 修正。 - (/conf) - battle_athena.conf 修正。 - -はっきりいってコンボ繋げづらいです。そのため阿修羅へのコンボはかなり甘い判定に -してます(一時的にですが)。繋げづらければbattle_athena.confのほうでデュレイ時 -間を大きくしてみてください。 - 動画見てて気づいたのですが、阿修羅覇凰拳は猛龍拳が発動した後、即時発動のスキ -ルに変わってるようなのです。他力本願ですが、阿修羅までのコンボのパケを記録した -物をどなたかアップしてもらえないでしょうか?詳細がわかり次第、修正します。 - --------------- -//0543 by 死神 - -・ブリッツのダメージを分散されるように変更。 -・普通のアカウント作りではGMアカウントを作れないように変更。 -(前に自分が入れた物がなくなったので戻しただけですが...) -・取り巻きが主と一緒に死ぬように変更。(ただちょっと重くなる -可能性があります。) 未テスト。 -・MVP経験値が表示だけされて実際には入ってない問題修正。 - (/login) - login.c - mmo_auth_new() 修正。 - (/map) - skill.c - skill_castend_damage_id() 修正。 - battle.c - battle_calc_misc_attack() 修正。 - mob.c - mob_damage() 修正。 - mob_deleteslave()、mob_deleteslave_sub() 追加。 - --------------- -//0542 by 死神 - -・オートブリッツバグ修正。(今度こそ大丈夫のはず...) -・自分に使ったヒールでは経験が入らないように変更。 -・店NPCを利用によるジョブ経験値獲得計算式変更。 - 獲得ジョブ経験値 = ln(金) * shop_exp / 100 -になります。 -logを使うことで金が多くても入る経験値が多く入らないように変更しました。 - (/map) - battle.c - battle_damage() 修正。 - skill.c - skill_attack()、skill_castend_damage_id() 修正。 - skill_castend_nodamage_id 修正。 - npc.c - npc_buylist()、npc_selllist() 修正。 - map.c - map_foreachinarea()、map_foreachinmovearea()、map_foreachobject() - 修正。(大した修正ではないです。) - (/conf) - battle_athena.conf 修正。 - (/doc) - conf_ref.txt 修正。 - --------------- -//0541 by huge - -・矢をまとめて持てるように修正。 -・弓で攻撃したときに、装備している矢を消費するように修正。 - - itemdb.c - itemdb_search() 修正 - itemdb_isequip() 修正 - - battle.c - battle_weapon_attack() 修正 - battle_calc_weapon_attack() 修正 - - clif.c - clif.h - clif_arrow_fail() 追加 - clif_parse_EquipItem() 修正 - --------------- -//0540 by 死神 - -・バグ修正と問題ありそうな所修正。(これでWZ_FIREPILLARとブリッツに -よる鯖ダウンはなくなるはず...) - map.c - map_foreachinarea()、map_foreachinmovearea() 修正。 - skill.c - skill_unitsetting()、skill_delunitgroup() 修正。 - pc.c - pc_damage() 修正。 - battle.c - battle_damage() 修正。 - npc.c - npc_parse_mob() 修正。 - mob.c - mob_spawn_dataset() 修正。 - --------------- -//0539 by 死神 - -・clif_pvpset()をマップからAREAかマップかを設定できるように変更。(pvpの時の処理は0535以前の物に戻そました。自分だけに転送してもいいような気もしますが...) - clif.h、clif.c - clif_pvpset() 修正。 - clif_parse_LoadEndAck() 修正。 - script.c - buildin_pvpoff() 修正。 - buildin_pvpon() 修正。 - atcommand.c 修正。 -・攻撃途中でアイテムを拾うと攻撃が止まるように修正。 - pc.c - pc_takeitem() 修正。 -・0535説明が爆裂波動になっているがそれは金剛に間違いです。 -・0537で説明を忘れましたがモンスターのdefとmdefを10000以上に設定すれば全ての攻撃に1ダメージになるモンスターになります。そしてモンスター情報でdefと -mdefが10000以上の場合def 100、mdef 99に表示するように変更。本鯖仕様に -するにはmob_db.txtを修正してください。 - --------------- -//0538 by huge - -・グリムトゥースを範囲攻撃に修正 -・サプライズアタック実装 (有効範囲って、これであってるのかな?) -・バックスタブの仮実装 - 本鯖でやってる人から話を聞いて、場所指定じゃなくて - タゲ取っても良さそうだったので変更しました。(やりやすかったので (^^; - まだ、mobの後ろに居るかどうかの判定は入ってません。 - -・battle.c - battle_calc_weapon_attack() 修正 - -・skill.c - skill_additional_effect() 修正 - skill_castend_damage_id() 修正 - skill_check_condition() 修正 - skill_use_id() 修正 - skill_castend_nodamage_id() 修正 - -・skilldb.txt - バックスタブの種類を[場所]から[敵]へ変更 - --------------- -//0537 by 死神 - -・スティールバグ修正とbattle_athena.confの項目追加、仕様変更と細かい修正です。 -(スティールは計算式に問題があったので修正して確率を更に落としました。) - battle.h - finger_offencive_typeをfinger_offensive_typeに修正。(英語スペル間違いで修正しました。) - struct battle_configにrestart_hp_rate、restart_sp_rate 追加。 - battle.c - battle_calc_weapon_attack()、battle_calc_magic_attack() 修正。 - skill.c - skill_attack() 修正。 - clif_skill_nodamage()にスキルレベルを送るように変更。(Mさんの指摘により修正。) - clif.c - clif_skill_estimation() 修正。 - conf_ref.txt - finger_offencive_typeをfinger_offensive_typeに修正と少し追加。 - mob.c - mob_ai_sub_hard()、mob_target()、mob_damage() 修正。 - pc.c - pc_steal_item() 修正。 - atcommnad.c、atcommnd.h - @コマンド@gvgon , @gvgoff 追加。 - battle_athena.conf - finger_offencive_typeをfinger_offensive_typeに修正と少し追加。 - --------------- -//0536 by hogefuga3 (Athena staff) - -・新GRFファイルフォーマット対応 - - Athena staff 様の作成されたパッチを適用しました。 - 更新履歴の部分はパッチミスになったので手動で組み込み。 - -(変更) - common/ - grfio.c - --------------- -//0535 by 死神 - -・0533の問題がありそうな部分全て修正。修正した所を全部チェックしてなかったので修正したファイルだけ... -・スクリプトsetmapflagnosave 追加。 - setmapflagnosave マップ名、セーブするマップ名、座標(X、Y) - nosaveフラグをonにします。 -・battle_athena.confに追加と一部仕様変更。(詳しくはconf_ref.txtを参考してください。) -・モンスターのdefとmdefが10000以上の場合全ての攻撃(クリティカル含めて)が1ダメージになるように変更。(トラップやブリッツの場合両方が10000以上の場合のみ1になります。) 草とキノコに1ダメージ固定は削除しました。(元々本鯖でも1固定ではないです。精練等による引き上げダメージはそのまま出ますので... 固定したいのならdefとmdefを10000にしてください。実はこれはクリスタルに為に作ろうとした物ですが...) -・爆裂波動の時アイテムによるスキルは使用できるように修正。 -・その他少し修正。(修正の物の中にテストしてない物もあります。) - (/doc) - conf_ref.txt 修正。 - (/conf) - battle_athena.conf 修正。 - (/map) - battle.h 修正。 - battle.c 修正。 - mob.h 修正。 - mob.c 修正。 - skill.c 修正。 - npc.c 修正。 - pc.c 修正。 - script.c 修正。 - clif.c 修正。 - chrif.c 修正。 - --------------- -//0534 by Diex - -・コンボシステム仮実装 - map/ - battle.c - battle_weapon_attack() 修正。 - clif.c - clif.h - clif_combo_delay() 関数追加。 - map.h - map_session_data 変数追加。 - pc.c - pc_authok() 変数追加。 - pc_attack_timer() 修正。 - skill.c - skill_castend_damage_id() 修正。 - skill_check_condition 修正。 - skill_use_id 修正。 - db/ - skill_db.txt 修正。 - -注)猛龍拳から阿修羅覇鳳拳にはまだつなげません。 - 阿修羅覇鳳拳を放った後、PCはMOBの背後(?)に移動してるっぽいのですが、 - そこらへんの情報が足りません。情報提供お願いします。 - --------------- -//0533 by るるる - -・草とキノコに1ダメージ固定 -battle.c の battle_weapon_attack() と battle_calc_attack() を修正 -battle.c の battle_get_mobid() を追加 -mob.c の mob_makedummymobdb() と mob_readdb() を修正 - -・スキルログにモブの固有番号&PCのID番号を表示 -(battle.c の battle_get_mobid() を追加したのでそのついでに) -mob.c skill.c の変更箇所多数(汗 -("MOB %d" もしくは "PC %d" で検索すれば変更箇所がわかるかと) - -・ハンターの罠を使ったスキルで罠を消費するようにした -batttle.c の skill_check_condition() を修正 -(ジェム消費処理の流用っぽいことをやってるんだけど処理中身は理解してないw) - -・サンクチュアリ&マグヌスのダメージ判定を不死属性&悪魔種族に再度修正 -0532で再び元に戻ってしまったのをなおしました。 -ただし、回数&人数判定には手を加えていません(ってか自分にはまだムリ) - -以上。 -切った貼ったの見様見真似でやったので言語的に果たしてこれでよいのか。。。 -もし処理方法に問題有りだったら修正なりをしていただけると嬉しいです。 - --------------- -//0532 by 死神 - -・修正した所を全然チェックしてなかったので修正したファイルだけ...汗 -・mapflagにnopenalty追加。使用方法は - mapflag nopenalty dummy -です。機能はそのマップで死んだ時経験が減らないようにします。 -・mapflagにpvp_noparty、pvp_noguild、gvg、gvg_noparty追加。 -pvp_nopartyはPVPモードで同じパーティに攻撃が当たらない、pvp_noguildはPVPモードで同じギルドに攻撃が当たらない、gvgはシーズモードに、gvg_nopartyはシーズモードで同じパーティに攻撃が当たらない物です。 -・可動してないタイマーは全て-1になるように変更。 -・吹き飛ばし処理修正。 -・マップロード直後気功が見えない問題修正。 -・残影の処理修正。 -・マップをロードすると死んだふりが解除されるように変更。 -・PVPを少し変更。 -・古木の枝で出るモンスターを自分のレベルより高い物は出ないように変更。 -・加速ポーションのsc_start SC_SpeedPot0,1,0;をsc_start SC_SpeedPot0,1800,0;のように変更。SC_SpeedPot?の後の数値は持続時間です。(単位は秒) -・@コマンド@pvpを@pvponに変更と@pvponと@pvpoff、@gatの機能変更。 -・battle_athena.confのpvp削除。 -・battle_athena.confにdeath_penalty_type追加。 -・ペナルティの適用を死んだ時から死んだ後リスタートした時に変更。(リザで復活すると経験が減りません。本鯖の仕様がかなり気にいらなかったので変更しました。) -・スクリプトsetmapflag、removemapflag、pvpon、pvpoff、gvgon、gvgoff追加。 - setmapflag マップ名、マップフラグタイプ - 指定したマップフラグをonします。(ただpvp、gvgはpvpon、gvgonでできるので指定しても動作しません。あとnosaveの場合処理がちょっと複雑になるので対応してません。) - removemapflag マップ名、マップフラグタイプ - 指定したマップフラグをoffします。(ただpvp、gvgはpvpoff、gvgoffでできるので指定しても動作しません。こちらはnosaveも可能です。) - pvpon マップ名 - 指定したマップをPVPモードにします。 - pvpoff マップ名 - 指定したマップのPVPモードを解除します。 - gvgon マップ名 - 指定したマップをシーズモードにします。 - gvgoff マップ名 - 指定したマップのシーズモードを解除します。 -ただ全てのスクリプトの動作は確認してませんので注意してください。 -・サンクチュアリ、マグヌスエクソシズムの処理を0529に戻しました。 -自分の調査ではサンクチュアリは人数の制限があります。(レベル1で4名で -1レベルに一人ずつ増えます。) -・その後少し修正。(したはず...) - (db/) - const.txt 修正。 - item_db.txt 修正。 - (conf/) - battle_athena.conf 修正。 - (doc/) - conf_ref.txt 修正。 - (map/) - clif.h、clif.c 修正。 - mob.c 修正。 - pc.h、pc.c 修正。 - skill.c 修正。 - pet.c 修正。 - npc.c 修正。 - map.h、map.c 修正。 - battle.h、battle.c 修正。 - atcommand.h、atcommand.c 修正。 - script.c 修正。 - makefile 修正。 - --------------- -//0531 by 獅子o^.^o - -conf/npc_turtle.txt -.タートルアイランドに行く時、サ一バ一を落って問題修正 -.npc_turtle.txtの508行目 -set Zeny - 10000,0; --> set Zeny,Zeny-10000; 修正 - --------------- -//0530 by RR -・スキル「サンクチュアリ」で攻撃対象をアンデット/悪魔種族から不死属性/悪魔種族に変更 -・スキル「マグヌスエクソシズム」で攻撃対象をアンデット/悪魔種族から不死属性/悪魔種族に変更 -・スキル「サンクチュアリ」の回復回数を人数からカウントに変更 - skill.c - skill_unit_onplace()修正 - skill_unit_onout()修正 - -多分この仕様で合ってるはずです…。 - --------------- -//0529 by 胡蝶蘭 - -・MOBがスキル「ヒール」を使用するとサーバーが落ちる場合があった問題を修正 -・スキル「サンクチュアリ」で攻撃対象を不死属性からアンデット/悪魔種族に変更 - - skill.c - skill_unit_onplace()修正 - skill_castend_nodamage_id()修正 - -・ログインサーバーのアカウントデータベース保守ツールを添付 - Perl製なので実行にはPerlが必要です。 - 使用方法などはエディタで開いて見てください。 - 使い方が良くわからない人は手を出さないほうがいいです。 - - 特に理由が無い限りアカウント作成もこちらのツールを使ってください。 - addaccountはパケットの都合上パスワード文字数の制限がきついので。 - - アカウントを削除してもキャラクターデータ、倉庫データ、 - その他のアカウント以外のデータは消えません。相手がログイン中だった場合 - 強制切断はされませんが、次回からはログインできないはずです。 - (つまりは、単にlogin-server上のアカウントを消しているだけです) - - (login/) - login.c - parse_admin()追加、parse_login()修正 - (doc/) - admin_packet.txt - 新規追加。管理パケット情報 - (tool/) - ladmin - login-server administration toolのPerlスクリプト - - --------------- -//0528 by RR -・スキル「ヒール」を使用した際に回復量に比例した分だけジョブ経験値が獲得できるように変更 -・商人系職業が店NPCを利用した際にジョブ経験値が獲得できるように変更 -・両方ともbattle_athena.confで調整可能にしました。初期設定は0倍(非適用) -・map_athena.confにてかぼちゃクエストのものが入ってなかったのでコメントアウトしながら追加。 - - map_athena.conf - - battle.c battle_config_read() - battle.h Battle_Config - battle_athena.conf - 以上、battle_athena.conf利用ために変更 - - pc.c pc_heal() - 戻り値をhp+spに。戻り値を利用してる部分がなさそうだったので使わせて貰いました。バグが起きたらすみません。 - - skill.c skill_casted_nodamage_id()のヒール部にてジョブ経験値獲得するよう変更 - - npc.c npc_buylist() - npc_selllist() 変更 - これらとの兼ね合いでskill.hをinclude。 - - -商人の店利用ジョブ経験値獲得ですが、計算式はまだ考え中なので仮で。 -計算式はアイテム購入が 代金 * スキルレベル(ディスカウント)/ ((1+300/アイテム個数) * 4000) -アイテム売却が 代金 * スキルレベル(オーバーチャージ) / ((1+500/アイテム個数) * 4000)です。 -常に矢をたくさん一緒に購入することで経験値を多量に稼ぐことが可能ですね…。 -どなたかいい式を思いついたら変更お願いします。 - -ところで転職NPCが一部かぶってるんですが修正しないでいいんでしょうか? - --------------- -//0527 by 死神 - -・0526のバグ修正。(テストの為に変えていた物を入れたままアップしてしまったのが原因でした。) - skill.c 修正。 - pc.c 修正。 - mob.c 修正。 - clif.c 修正。 - --------------- -//0526 by 死神 - -・0525のリザレクションを死んだキャラに使えないバグ修正。(テストはしてませんが治ったはずです。多分...) - skill.c 修正。 - clif.c 修正。 - --------------- -//0525 by 死神 - -・dmotionの間はキャラが動かないように変更。(テストしてません。) -・メテオのダメージ表示タイミング修正。(少し遅い気もしますが...) -・バックスライディングの時にモーションが出るように変更。(スキル使用後 -0.2秒後にスキル使用パケットを送るように変更しました。ラグ等によって変な動作をする可能性もあります。) -・0524の修正。 -・ハイディングしている時自然回復しないように変更。 -・0519で間違ったconfの修正と細かい所修正。 - map.h - struct map_session_dataのcanmove_tickをcanact_tickに変更。 - skillcanmove_tickをcanmove_tickに変更。 - skill.c 修正。 - pc.c 修正。 - pc.h 修正。 - clif.c 修正。 - battle.c 修正。 - battle.h 修正。 - mob.c 修正。 - mob.h 修正。 - char_athena.conf 修正。 - map_athena.conf 修正。 - --------------- -//0524 by huge - -・ローグ トンネルドライブ実装 - clif.c - clif_parse_WalkToXY() - pc.c - pc_calcstatus() - - どのくらい速度減少するのか分からなかったので、暫定的に - speed += speed * (20-スキルレベル)/40 - と、しました。本鯖仕様が分かる方居ましたら修正お願いします。 - --------------- -//0523 by NOCTURNE - -・npc_event_rental.txtにクルセイダー用のペコペコ管理兵を追加 --------------- -//0522 by 波浪 - -・mob_db.txtをジュノー後のデータに修正 - --------------- -//0521 by 胡蝶蘭 - -・mapサーバーに繋がらない問題を修正 - clif.c - clif_parse()の修正 - --------------- -//0520 by 胡蝶蘭 - -・charサーバーログの「set map X.Y HOGE.gat」が表示されなくなりました - 変わりに、「set map M from XX.YY.ZZ.WW:PP (CC maps)」 - というふうに何個のマップをセットしたかだけを表示するようになります。 - - char/char.c - parse_frommap修正 - -・複数mapサーバーに仮対応 - ・NPCのマップサーバー変数は鯖間では共有されません。共有すべき変数を - 持つNPCがいるマップ同士は同じmapサーバーで動かすべきです。 - おそらくPCのグローバル変数は共有できると思います(未テスト) - ・暫定的に動くようにしただけなので、不都合があるかもしれません。 - 特に、パーティ/ギルド/倉庫/ペット/Wisなどのinterサーバーを使う機能が - 正しく作動するか全くチェックしていません。 - ・「recv map on XX.YY.ZZ.WW:PP (CC maps)」というログが表示されます。 - これは他のmapサーバーが担当するマップのリストが、このmapサーバーに - 正常に受信されたという意味です。 - - (char/) - char.c/char.h - parse_frommap()修正 - mapif_sendallwos()追加 - (map/) - map.c/map.h - map_setipport()を修正 - struct map_session_dataのstateメンバにwaitingdisconnect追加 - chrif.c/chrif.h - 色々追加 - clif.c - waitingdisconnectが1ならパケットを無視するようにした - pc.c - pc_setpos()修正(マップサーバー変更処理など) - pc_setnewpc()修正 - --------------- -//0519 by 死神 - -・サーバーsnapshotと色々修正。 -・死んだキャラに攻撃が当たるバグ修正。(テストしてません。本当に治ったかどうか報告お願いします。) -・0517のアイスウォールの処理を少し変更。 -・メテオをモンスターも使えるように変更。(テストしてません。報告お願いします。) でもちょっとメモリーの使用量が増えました。(約10M程上がるようです。) -・ボスの取り巻きがボスと一緒に行動するように変更。(テストしてませんのでどんな動きをするかは確認してません。攻撃も受けてないのにボスの隣から勝手に離れるかどうかの確認をお願いします。) -・その他細かい物修正。 - client-packet.txt 修正。 - map.h - AREA_SIZEを15から20に変更。 - struct map_session_data、struct mob_data、struct skill_timerskill 修正。 - map.c - map_quit() 修正。 - clif.h - clif_changemapcell() 修正。 - clif.c - clif_getareachar_skillunit()、clif_clearchar_skillunit()、clif_changemapcell() 修正。 - skill.c - skill_unitsetting()、skill_unit_onlimit()、skill_castend_pos2() 修正。 - skill_castend_nodamage_id()、skill_check_condition()、skill_attack() 修正。 - skill_timerskill()、skill_addtimerskill()、skill_cleartimerskill() 修正。 - その他少し修正。 - skill.h - skill_addtimerskill()、skill_cleartimerskill() 修正。 - pc.c - pc_movepos()、pc_walk()、pc_authok() 修正。 - mob.c - mob_spawn_dataset()、mob_spawn() 修正。 - mob_changestate()、mob_damage() 修正。 - mob_ai_sub_hard_mastersearch()、mob_ai_sub_hard() 修正。 - その他少し修正。 - battle.c - battle_calc_weapon_attack()、battle_weapon_attack() 修正。 - その他少し修正。 - --------------- -//0518 by Kalen -・Event_pumpkin関連のフラグ不具合修正 - --------------- -//0517 by 死神 - -・アイスウォールで摺り抜る問題修正と少し修正。(Mさんパケットの提供ありがとうございます。) - clif.h - clif_changemapcell() 追加。 - clif.c - clif_changemapcell() 追加。 - skill.h - SC_STEELBODYを84から87に変更。 - skill.c - skill_unitsetting()、skill_unit_onlimit() 修正。 - skill_status_change_end()、skill_status_change_start() 修正。 - client_packet.txt 修正。 - --------------- -//0516 by 死神 - -・モンスターのメテオによる鯖ダウンを臨時に防いで置きました。(テストはしてません。) モンスターのスキルについてちょっと分析不足ですので分析した後に修正して置きます。 -・スキル指弾の仕様をbattle_athena.confで決めるように変更。(0515の物がちょっともったいなかったので...) - skill.c - skill_castend_pos2() 修正。 - battlc.h、battle.c - battle_configにfinger_offencive_type 追加。 - battle_calc_weapon_attack() 修正。 - battle_athena.conf 修正。 - conf_ref.txt 修正。 - --------------- -//0515 by 死神 - -・スキルメテオと指弾修正とパケット修正、0512の落とし物修正と少しだけの仕様変更です。 -・指弾の場合説明を見てこんな感じかなと思って作った物です。以前の物が本鯖にあっているなら元に戻します。 -・メテオの1発の範囲は5*5セル(range = 2)です。 -・アイテム使用パケットを新しい物に変更したがエフェクトが出ない物は出ないようです。(色々エフェクトが入っているみたいだから後は使って確認ですけどね。) -・0512でhitrateが10000以上で必中ではなく100000以上で必中ですのでコードの修正のさいには気をっつけてください。 -・battle_athenaに設定されている武器の製造率とペットの捕獲確率の計算方法を少し変えました。(気にする必要もない物ですけどね。) - skill.h - skill_addtimerskill()、skill_cleartimerskill 追加。 - skill.c - skill_attack() fix、skill_use_id()、skill_use_pos() 修正。 - skill_castend_damage_id()、skill_castend_nodamage_id() 修正。 - skill_timerskill()、skill_addtimerskill()、skill_cleartimerskill 追加。 - skill_castcancel()、skill_castend_pos2()、skill_unitsetting() 修正。 - skill_produce_mix()、do_init_skill() 修正。 - mob.c - mob_damage() 修正。 - battle.c - battle_calc_weapon_attack() 修正。 - map.h - struct skill_timerskill 追加。 - struct map_session_data 修正。 - map.c - map_quit() 修正。 - pc.c - pc_authok() 修正。 - pc_damage() 修正。 - clif.c - clif_parse_WalkToXY() 修正。 - clif_useitemack() 修正。(資料提供: Kalenさん) - pet.c - pet_catch_process2() 修正。 - skill_db.txt - 気功のSPを10に変更。(ネットの検索では10だったので変更しました。韓国蔵では15と表示されますが...) - client_packet.txt - 01c8の変更です。Kalenさん情報提供ありがとうございます。 - --------------- -//0514 by Kalen - -・script修正+追加 - - conf/npc_event_pumpkin.txt (新規)カボチャイベント - conf/npc_town_guide.txt (修正)Junoの「+」アイコンカラー修正 - conf/npc_town_lutie.txt (一部追加)カボチャイベントに影響するNPCの会話追加 - --------------- -//0513 by RR - -・転職時に装備が全て外れるようにしました。関数位置の変更してないので、ひょっとしたらおかしくなってるかもしれません。うちの環境(win2k cygwin)では平気でしたのでそのままにしてあります。。 -・ノービス時の死亡では、最大HPの2分の1で復活できるよう修正。(スキルによる復活は未確認) -・デスペナルティによる経験値減少を追加。battle_athena.confにて、減少率を変更できるように設定。減る経験値は小数点以下切り捨てなので、必要経験値が低いうちにはちょうどその%分引かれるという風にはなりません。 - battle.h - Battle_Configにdeath_penalty_baseとdeath_penalty_jobを追加。 - battle.c - battle_config_readでdeath_penalty_baseとdeath_penalty_jobを読むように修正。 - pc.c - pc_makesavestatus() 修正。 - pc_damege() 修正。 - pc_jobchange() 修正。 - battle_athena.conf - death_penalty_base,death_penalty_job追加。 - --------------- -//0512 by 死神 - -・問題になりそうな部分の修正と新しいパケットの対応がメインです。後バグも少し治しました。(動けない状態異常になっても動く問題の修正等です。) - athena.sh 修正。(いつも鯖を個別に実行していたので気がつきませんでした。) - makefile - DPACKETVERを2から3 に修正。ジューノ以後の蔵を使うのなら3にして使ってください。(その以前なら2か1) - clif.c - DPACKETVER=3に対応(今の所0x114を0x1deに変換と0x11fを01c9に変換するのみ対応) - clif_skill_damage3() 削除。 - clif_skillcastcancel() 追加。 - clif_skill_damage()、clif_getareachar_skillunit()、clif_skill_setunit() 修正。 - clif_fixmobpos()、clif_fixpetpos()、clif_fixpcpos() 修正。 - 他に少し修正。 - clif.h - clif_skill_damage3() 削除。 - clif_skillcastcancel() 追加。 - battle.c - battle_calc_weapon_attack() 修正。 - hitrateを10000以上にすれば必中になるように変更。(今の仕様ではモンスターの必中攻撃以外は必中になりません。) - 他に少し修正。 - client_packet.txt - 新しいパケット情報追加。 - pc.c - pc_spiritball_timer()、pc_delspiritball() 修正。 - pc_damage()、pc_skill() 修正。 - skill.h - SC_EXPLOSIONSPIRITSを89から86に変更。(86 = 0x56) - SC_DELUGEを86から89に変更。 - skill.c - skill_castcancel()、skill_use_id()、skill_use_pos() 修正。 - skill_check_condition() 修正。 - skill_castend_damage_id()、skill_castend_nodamage_id 修正。 - skill_status_change_end()、skill_status_change_start() 修正。 - skill_db.txt - 気功の消費SPを修正。(前の15が本鯖にあっているみたいですので...) - mob.c - mobskill_use_id()、mobskill_use_pos() 修正。 - map.c - map_quit() 修正。 - atcommand.h - atcommand.c - @コマンド@spiritball追加。(機能は使えばわかります。ただ1000以上は入れない方がいいです。蔵がパンクしますので...) - atcommand_athena.conf - 修正。 - conf_ref.txt - 修正。 -・0x196パケットに新しい物が追加されているので状態変化に直接に関係ないSC_xxxxの番号を調整する必要があります。(今はSC_EXPLOSIONSPIRITSにだけ対応しました。) それとskill_status_change_end()、skill_status_change_start()でclif_status_change()を呼ぶtypeの範囲が64(0x40)未満になっているがそれも追加されている物に合わせて修正する必要がありますが追加されている物が全てわかったわけでもないのでSC_EXPLOSIONSPIRITSにだけ対応しました。今度からは爆裂波動の解除が正確に見えます。金剛はデータを見つけられませんでした。 -※新しいパケットに対応する作業をしていますが情報が不足です。 -イグドラシルの実やイグドラシルの種のエフェクトが出るようにする為に01c8を使ってみましたが駄目でした。client_packet.txtのデータでは何も起こらないので何方が本鯖でイグドラシルの実やイグドラシルの種を使った時のパケットを提供してくれませんか?S 00a7の後00a8が来るのかそれとも01c8が来るのかの確認と00a8の後に01c8が来るのかの確認ができれば何とかなると思いますが... -それと01c9の後に来る?.81bがわかればアイスウォールを摺り抜る問題も解決できると思いますが... -情報提供をお願いします。 - --------------- -//0511 by Diex - -・指弾の攻撃回数修正。 -・阿修羅覇鳳拳、発勁が修練を無視し、無属性になるように修正。 -・金剛使用時、MDEFが正しく表示されてなかったバグを修正。 -・気功の消費SPを修正。 - pc.c - pc_calcstatus() 修正。 - battle.c - battle_calc_weapon_attack() 修正。 - skill.c - skill_check_condition() 修正。 - - skill_db.txt 修正。 - --------------- -//0510 by Diex - -・三段掌の表示バグ修正 -・指弾が気弾が無くても撃てるバグを修正 - map.h - struct map_session_dataにspiritball_old変数追加。 - skill.c - skill_check_condition() 修正。 - clif.c - clif_skill_damage3() 修正。 - battle.c - battle_weapon_attack()、battle_calc_weapon_attack 修正。 - --------------- -//0509 by - -・npc_warp.txt - プロ城→プロフィールドになっていたのを、 - プロ城→ヴァルキリーレルムに修正。 - プロフィールド→プロ城になっていたのをプロフィールド→ヴァルキリーレルムに修正 - --------------- -//0508 by 死神 - -・バグ修正と息吹、気功、気奪の修正がメインです。(今度からは他の人にも気がちゃんと見えます。) -・死んだキャラに経験値が入る問題修正。(テストはしてません。どうなのか報告をお願いします。) - pc.h - pc_addspiritball()、pc_delspiritball() 追加。 - pc_is50overweight() 修正。 - pc.c - pc_gainexp() 修正。 - pc_insert_card()、pc_item_identify() 修正。(大した修正じゃありませんが...) - pc_authok() 修正。 - pc_addspiritball()、pc_delspiritball() 追加。 - pc_spiritball_timer() 追加。 - do_init_pc()、pc_calcstatus()修正。 - pc_spirit_heal() 追加。 - pc_natural_heal()に関わる物の修正。 - map.h - struct map_session_data 修正。 - map.c - map_quit() 修正。 - map_addflooritem() 修正。 - clif.h - clif_spiritball_int()をclif_spiritball()に変更。 - clif_spiritball_ext() 削除。 - clif.c - clif_spiritball_int() をclif_spiritball()に変えて修正。 - clif_spiritball_ext() 削除。 - clif_set01e1() 追加。 - clif_getareachar_pc() 修正。 - skill.h - SC_CALLSPIRITS 削除。 - skill.c - SC_CALLSPIRITS 削除。 - skill_castend_nodamage_id()、skill_check_condition() 修正。 - skill_status_change_start() 修正。 -・床に落ちたアイテムが消えるまでの時間を設定できるように変更。 - battle.h、battle.c - battle_config_read() 修正。 - conf_ref.txt 修正。 - battle_athena.conf 修正。 - --------------- -//0507 by Diex -0505の修正 -・三段掌のエフェクト実装 - --------------- -//0506 by hoenny -全体的に少し式修正 -セイジのスキルがアイテムを消耗するように修正 -(スキルのDBに zeny, spiritball, item, equipを入れたいが時間がなくて臨時的に ...) - --------------- -//0505 by Diex - -・阿修羅覇鳳拳のダメージ修正 -・猛龍拳のダメージ修正 -・指弾実装 -・発勁実装 -・金剛が減算DEFと減算MDEFが90に固定されていたのを乗算DEFと乗算MDEFが90になるように修正 -・三段掌実装(ただしコンボは未実装) - map/clif.c - map/clif.h - clif_skill_damage3()追加 - map/pc.c - map/skill.c - map/battle.c - 修正・及び追加 -(計算式は+ Acolyte Maniax +を参考にしました。) - --------------- -//0504 by 死神 - -・atcommand.c 修正。(たった2文字を追加しただけです。) -atcommnad_gm_onlyがnoじゃなくても使用レベル設定を0にしたコマンドはGMじゃないキャラでも使えます。テストはしてません。 - --------------- -//0503 by nabe - -・精錬修正とLinux用にちょっと変更など - conf/map_athena.conf - npc_event_doll.txt, - npc_turtle.txt, - //npc_pota.txt項目追加 - conf/npc_pota.txt追加(socieさん作のダンジョンポタ子さん) - conf/npc_shop.txt - イズルード武器商人の価格修正 - conf/script_athena.conf - 0499での文字化け?修正 - login/login.c - #include <time.h>追加 - map/script.c - buildin_getequipname() - 精錬メニューのmallocを修正 - buildin_getequipisenableref() - 精錬可能条件修正(Athefansさんの条件文にしてみました) - map/skill.c - skill_check_condition()変数宣言位置の変更のみ - --------------- -//0502 by 死神 - -・カプラの倉庫もbattle_athena.confのbasic_skill_checkによって基本スキルが足りなくても使用することができるように修正しました。(プロンテラ中央のカプラのみ確認。) -・クェストスキルの取得は0492のせいです。0481にskillの最後が,2じゃなく,0だと書いたのですが何故か0492で,2になっていたので,0に修正しました。 -・スクリプトgetbaseskillcheckをbaseskillcheckに変更と自分で修正しましたが命令の後になんの数値も入らない場合はスクリプトが正しく作動しなかったので使用する場合はbaseskillcheck(0)にして使わないと正しい結果を得ることができません。 -(詳しくはnpc_town_kafra.txt参照。) - npc_event_skillget.txt 修正。 - npc_town_kafra.txt 修正。 - script.c 修正。 -・GM_account.txtに自分がテストの為に使っていた500000が入っていたので削除しました。(GM_account.txt作った理由は自分勝手にアカウントをGMにすることができるようにする為です。つまりGMとして表示されなくてもGMとして色んな権限を使うことができます。さすがにGM専用の右クリックコマンドは使えませんが... でもこれを活用している方はいないみたいなんですね...) - --------------- -//0501 by hoenny - -・500の問題点修正 --HP回復力向上,SP回復力向上 - map/pc.c - pc_natural_heal_hp()修正 - pc_natural_heal_sp()修正 - -500SP回復力向上 --------------- -//0500 by hoenny - -・修道僧の息吹実装 --基本的に座った時 10秒ごとに回復します. --所持量が 50%をオーバーした場合 20秒ごとに回復します. -・修道僧の気奪実装 --他の修道僧の氣球も吸収が可能です. -・修道僧の金剛実装 --金剛状態ではすべてのアクティブスキルを使うことができないです. - db/skill_db.txt - 気奪修正 - 金剛修正 - map/pc.h - pc_is50overweight()追加 - pc_is90overweight()追加 - map/pc.c - pc_calcstatus()修正 - pc_spheal()修正 - pc_hpheal()修正 - pc_natural_heal_hp()修正 - pc_natural_heal_sp()修正 - pc_natural_heal_sub()修正 - map/skill.c - skill_check_condition()修正 - skill_castend_nodamage_id()修正 - skill_status_change_start()修正 - --------------- -//0499 by 死神 - -・サーバーsnapshotとバグ修正。 -・スティールコインのゼニ量をモンスターレベル*10 + rand(100)に変更。 -・キャスティングタイムがないスキルはタイマーを使わないように変更。 -・カードの使用によるマップ鯖ダウンを防ぐ為に修正。(今度こそ治ったはず...) そして拡大鏡も同じようなことができるので修正。(これは鯖ダウンまでは起こさないようですが...) -・キャラにマップのロードが終わるまでペットのデータが来ないとマップ鯖が落ちる問題修正。(滅多なことがない限り起こらないですけどね。) -・オートバーサーク、重さのアイコンとチェックが正しく適用されるように修正。 -・増速ポーションの適用順番変更。今まではスピードアップポーションが最優先で次がハイスピードポーション、最後がバーサークポーションだったのですが順番を逆に変更しました。 -・アイテムで使うスキルはキャスティングタイムとディレイが0になるように変更。 -・アイテムで使うスキルのレベルがitem_dbに設定しているレベルより高くなるバグ修正。 - pc.h - pc_move()をpc_movepos()に変更。 - pc.c - pc_steal_coin()、pc_insert_card()、pc_item_identify()、pc_authok()、 - pc_calcstatus()、pc_checkweighticon()、pc_damage() 修正。 - skill.c - skill_castend_pos2()、skill_check_condition()、skill_use_id()、 - skill_use_pos() 修正。 - pet.c - pet_recv_petdata()、pet_change_name() 修正。 - map.h - struct map_session_dataにskillitemlv 追加。 - script.c - buildin_itemskill() 修正。 - clif.c - clif_parse_UseSkillToId()、clif_parse_UseSkillToPos()、 - clif_parse_LoadEndAck() 修正。 - mob.c - mobskill_use_id()、mobskill_use_pos() 修正。 - --------------- -//0498 by hoenny - -.氣球がすっかり見えるように修正(消耗スキル使用の時消耗するように修正) -.スキル残影を使用の時氣球を消耗するように修正 - doc/client_packet.txt - 0x1d0追加 - map/map.h - sdのstructureに spiritball追加 - map/clif.h - clif_spiritball_del() -> clif_spiritball_int()修正 - clif_spiritball_cre() -> clif_spiritball_ext()修正 - map/clif.c - packet_len_table[]修正 - clif_spiritball_del() -> clif_spiritball_int()修正 - clif_spiritball_cre() -> clif_spiritball_ext()修正 - map/pc.h - pc_item_steal() -> pc_steal_item()修正 - pc_coin_steal() -> pc_steal_coin()修正 - map/pc.c - pc_item_steal() -> pc_steal_item()修正 - pc_coin_steal() -> pc_steal_coin()修正 - pc_calcstatus()修正 - map/skill.c - skill_check_conditon()修正 - --------------- -//0497 by 死神 - -・0491のスキル残影のバグ修正とスティールとスティールコイン、スナッチャーの修正、mob_targetのバグ修正。 -・交換、座り、パーティ結成等の時に基本スキルをチェックするように修正。(battle_athena.confでチェックするかどうかを決めることができます。) -ただカプラの倉庫はスクリプトで制限をかけるしかありません。 -・スクリプトgetbasicskillcheck追加。 - 使用方法> getbasicskillcheck - 戻り値はbattle_athena.confのbasic_skill_checkです。0の場合は基本スキルのチェックなしで1の場合は基本スキルをチェックするのを意味します。 - skill.c - skill_castend_pos2() 修正。 - skill_additional_effect() 修正。 - pc.c - pc_move() 追加。 - pc_item_steal()、pc_coin_steal() 修正。 - pc.h - pc_move() 追加。 - map.h - struct mob_data 修正。 - mob.c - mob_spawn() 修正。 - mob_target() 修正。 - clif.c - clif_pcinsight()、clif_pcoutsight() 修正。 - clif_parse_ActionRequest()、clif_parse_Emotion()、 - clif_parse_TradeRequest()、clif_parse_CreateParty()、 - clif_parse_ReplyPartyInvite() 修正。 - battle_athena.conf 修正。 - conf_ref.txt 修正。 - skill_db.txt - スティールの射程を3から1に修正。 - battle.h、battle.c - battle_configにbasic_skill_check 追加。 - battle_config_read() 修正。 - trade.c - trade_traderequest() 修正。 - script.c - buildin_getbasicskillcheck() 追加。 - map/makefile 修正。 -※スティールとスティールコインの計算式は適当に作った物です。本鯖の方がどうなのか全然わからないので... - - スティール率 = (モンスターのアイテムdrop率 * (キャラレベル*0.5 + dex*0.4 +スキルレベル*5))% - スティールコイン率 = (スキルレベル + (キャラレベル - モンスターのレベル)*0.3 + dex*0.2 + luk*0.2)% - スナッチャー発動率 = (5.5 + スキルレベル*1.5 +スティールのスキルレベル)% - -本鯖の計算式がわかる方は情報提供をお願いします。 -スティールコインのゼニの量はモンスターのレベル*100になっています。これについても情報提供をお願いします。 -※残影の場合使った後普通に歩く前にはペットの装備が見えないバグがありますが原因がわからないので放置することにしました。 -※基本スキルが足りない時出るメッセージは殆ど合わせていますがパーティに入る時に基本レベルが足りない時に合う物がなかったのでパーティを作れない(基本スキルレベル7の物)と表示して勧誘した方には拒絶されたと表示されます。 - --------------- -//0496 by hoenny - -.WZのメテオストーム実装 -.スティールコイン修正 - db/skill_db.txt - メテオストーム修正 - map/pc.c - pc_coin_steal()修正 - map/skill.c - skill_castend_pos2()修正 - --------------- -//495 by nini - -・ARが片手斧、両手斧でしか発動しなかったところ修正→片手斧、両手斧、鈍器 - map/skill.c - skill_check_condition() 修正 - -前回修正のとき鈍器入れ忘れてたようです。 - --------------- -//0494 by 獅子o^.^o - -conf/mpc_warp.txt -.ハンタ一転職地出ていない修正 - --------------- -//0493 by 波浪 - -・script修正 - npc_town_comodo.txt コモド案内要員部分を削除(npc_town_guide.txtと重複していたので) - npc_town_guide.txt ジュノー案内要員を追加(viewpointの色が…) - npc_town_kafra.txt ジュノーカプラ部分をnpc_town_yuno.txtから移動 - npc_town_refine.txt ジュノー精錬所部分をnpc_town_yuno.txtから移動 - npc_town_yuno.txt 案内要員とカプラと精錬所部分を削除 - npc_turtle.txt 会話を微修正 - --------------- -//0492 by Kalen - -・script修正+追加 - - conf/npc_event_doll.txt (新規) - conf/npc_turtle.txt (新規)亀島関連NPC+亀島クエスト(航海日誌)追加 - - conf/npc_event_skillget.txt (修正)応急処置の不具合+へんなtab削除etc.. - conf/npc_town_alberta.txt (修正)Turtle分離、ちびっ子削除(Event_dollへ移動) - conf/npc_town_guide.txt (修正)台詞がかなり変更されていたので、修正 - - --------------- -//0491 by 死神 - -・スキル残影(韓国クライアントでは弓身彈影)実装。(ただ気弾のチェックはしてません。) - pc.h - pc.c - pc_can_reach() 追加。 - skill.c - skill_check_condition()、skill_castend_pos2() 修正。 - skill_db.txt - 残影修正。 -・script.c - set_posword() 修正。 -※一人でテストは済んでいますが他の人に正しく見えるかどうかは未確認です。 -変なのかどうか報告をお願いします。 - --------------- -//0490 by nabe - -・場所スキルエフェクトでマップ鯖が落ちることがあったのを修正。 - clif.c - clif_skill_poseffect()の - unsigned char buf[16];を、unsigned char buf[32];に修正。 - --------------- -//0489 by 死神 - -・0483のバグ修正。battle_athena.confのquest_skill_learnが正しく適用されるように変更と問題があった部分の修正。(テスト済み) - pc.c - pc_calc_skilltree()、pc_skill() 修正。 - atcommand.c - @lostskill 少し修正。 -・カードの使用によるマップ鯖ダウンを防ぐために少し修正。(ただカードの使用によるマップ鯖ダウンを再現できなかったので本当に治ったかどうかは不明...汗) - pc.c - pc_insert_card() 修正。 -・pc.h - pc_ishiding() 修正。 - --------------- -//0488 by hoenny - -・RGのスティールコイン実装 -・スティール修正 -(二スキル皆一度スチールした場合またスチールすることができない.そしてスキル成功の時モンスターは攻撃するように修正した.エフェクトは成功の時だけ出るように修正した.) - db/skill_db.txt - スティールコイン修正 - map/pc.h - pc_coin_steal()追加 - map/pc.c - pc_coin_steal()追加 - pc_item_steal()修正 - map/skill.c - skill_castend_nodamage_id()修正 - --------------- -//0487 by hoenny - -・485の問題点ちょっと修正 - map/pc.c - pc_item_steal()修正 - map/skill.c - skill_castend_nodamage_id()修正 - --------------- -//0486 by 獅子o^.^o - -db/class_equip_db.txt修正 -裂けた大地の書、燃える太陽の書、乾いてる風の書、默示録、プリーストは装備することができない問題修正 - --------------- -//0485 by hoenny - -・ RGのスナッチャー実装 -・ スティール修正 -・ 露店開設の時 skill_check_conditionで状態をチェクするように修正 - map/pc.h - pc_ishiding()追加 - pc_item_steal()追加 - map/pc.c - pc_item_steal()追加 - map/skill.c - skill_castend_nodamage_id()修正 - skill_additional_effect()修正 - skill_check_condition()修正 - --------------- -//0484 by 胡蝶蘭 - -・覚えてないクエストスキルにスキルポイントを振れる問題修正 - pc.c - pc_calc_skilltree()でクエストスキルのチェック追加 - skill.c - skill_readdb()でinf2を読むように修正 - -・ペコペコ騎乗、ファルコンのアイコンがログイン直後には表示されない問題修正 - clif.c - clif_parse_LoadEndAck()修正 - --------------- -//0483 by 死神 - -・0482の適用。 - npc_event_skillget.txt 修正。 - script.c 修正。 - skill.c 修正。 - pc.c 修正。 - --------------- -//0482 by 胡蝶蘭 - -・クエストスキルのスクリプト少し修正 -・スクリプトgetskilllvを呼ぶとマップサーバーが落ちるバグ修正 - (conf/) - npc_event_skillget.txt - 出来るだけ変数を使わないように修正(未テスト) - (map/) - script.c - buildin_getskilllv()修正 - -・スティールで失敗時のエフェクト変更 -・同じMOBには1回しかスティールできないように修正 - (map/) - skill.c - skill_castend_nodamage_id()修正 - map.h - struct mob_dataにsteal_countメンバ追加 - mob.c - mob_spawn()修正、steal_countを0に初期化するように - -・イドゥンの林檎でHPが32767を超えるとサーバーが落ちるバグ修正(未テスト) - (map/) - pc.c - pc_calcstatus()修正 - --------------- -//0481 by 死神 - -・これの適用には気をつけてください。0478の胡蝶蘭さんの物を Athena.txtのデータ形式変更せずにクェストスキルを覚えるように作った物です。自分が作ってる最中に胡蝶蘭さんが同じ物をアップしてくれたのですがデータは変えない方がいいと思って自分の物もアップしました。注意することは0478のathena.txtは使えないと言うことです。0478前の物を使ってください。 -・skill_db.txtにinf2を追加してこれを使ってクェストスキルかどうかを判断する仕組みです。 - skill.h 修正。 - skill.c - skill_readdb()修正と少し修正。 - skill_get_inf2() 追加。 - skill_db.txt 修正。 - skill_tree.txt 修正。(0478前の物) - clif.c - clif_skillinfoblock() 修正。 - char.c 修正。(0478前の物) -・battle_athena.confにquest_skill_learn追加。 - battle.h 修正。 - battle.c - battle_config_read() 修正。 - battle_athena.conf 修正。 -・/resetskillをbattle_athena.confにquest_skill_learnの設定に合わせてquest_skill_learnがyesの場合はスキルポイントに加算してquest_skill_learnがnoならリセットはされるがスキルポイントに加算されません。 - pc.c - pc_skill()、pc_resetskill() 修正と少し修正。 - pc.h 修正。 - atcommand.c 修正。 - atcommnad_athena.conf 修正。 -・スクリプトのskillコマンドでクエストスキルを覚えられるのは同じですが最後のフラグが2から0に変わってますので注意してください。 - npc_test_skill.txt 修正。 - npc_event_skillget.txt 修正。 - conf_ref.txt 修正。 - client_packet.txt 修正。 - --------------- -//0480 by Kalen - -・Eventskill追加 - conf/npc_event_skillget.txt - -・map_athena.conf変更 - warp.txtの読み込み優先度を変更 - prt_castle等、旧EPのワープと異なる場所に変更された場合 - 先に読み込んだ方が優先されるので、EPの高い順のがよろしいかと - conf/map_athena.conf - --------------- -//0478 by 胡蝶蘭 - -*** - Athena.txtのデータ形式変更!! (自動的に変換されます) - バックアップを忘れずに! - Data format of athena.txt is changed!! (convert automatically) - DONT FORGET BACKUP!! -*** - -・クエストスキル実装 -・スクリプトでスキルレベルをチェックできるように - ・スクリプトのskillコマンドでクエストスキルを覚えられます。 - 使用方法> skill スキルID,スキルLV[,フラグ] - フラグは省略可能で、省略すると1を指定したことになります。 - 1で装備品による一時的な習得、2でクエストによる恒久的な習得です。 - 恒久的な習得の場合、skill_tree.txtに依存します - ・getskilllvコマンド追加 - 使用方法> getskilllv(スキルID) 戻り値はレベルです。0で未習得。 - - (conf/) - npc_test_skill.txt - サンプル - (db/) - skill_tree.txt - クエストスキルとして必要スキルIDに-1を設定。 - (char/) - char.c - フラグもathena.txtに保存するように。 - 以前の形式のデータも読み込めます。 - (map/) - pc.c/pc.h - pc_skill(),pc_calc_skilltree()など修正 - script.c - buildin_skill(),buildin_getskillid()など修正 - -・@questskill,@lostskill追加 - ・@questskill スキルID でクエストスキルを覚えます。(クエストスキルのみ) - ・@lostskill スキルID でスキルを忘れます。(クエストスキル以外もOK) - - atcommand.c/atcommand.h - struct Atcommand_Configにlostskill,questskillメンバ追加 - @questskill,@lostskill処理追加 - --------------- -//0477 by nabe - -・一部変数の宣言位置の変更のみ(Linux等でコンパイルしやすいように)。 - atcommand.c,battle.c,clif.c,mob.c,npc.c,skill.c - --------------- -//0476 by nabe - -・conf/ ちょっと整理 - conf/map_athena.conf修正。 - tortoise.txtをnpc_town_alberta.txt中に移動。 - npc_script2.txtのコモドガイドをnpc_town_comodo.txt中に移動。 - -・npcがキャラ名を喋るときのバグ修正 - map/script.c - buildin_strcharinfo()でキャラ名用のメモリを - staticに確保してしまっていたのを、mallocに修正。 - --------------- -//0475 by hoenny - -泥棒のスティール実装。 -ギルド生成の時エンペリウム消耗するように修正。 - map/guild.c - guild_create()修正。 - guild_created()修正。 - map/skill.c - skill_castend_nodamage_id()修正。 - --------------- -//0474 by 死神 - -・0471の精練の時表示される文字の設定をmap_athena.confからscript_athena.confに変更。 - script.c - do_init_script() 修正と少し修正。 - script.h 修正。 - script_athena.conf 追加。 - map_athena.conf 修正。 - map.c - map_config_read() 修正。 -・古い巻物、プレゼントボックス実装と少し仕様変更。 -ランダムでアイテムを得る物にデフォルトで出るアイテムを設定できるように変更。今の仕様では1000回までアイテムが選択されなかったらデフォルトアイテムが出るようになっています。デフォルトアイテムが0の場合はアイテムを得られません。 -設定する確率を*1000から*10000に変更。ただitem_~.txtの修正はやっていません。誰かやってください。(他力本願) - itemdb.c - temdb_read_randomitem() 修正。 - itemdb_searchrandomid() 修正。 - item_purplebox.txt から item_violetbox.txt に修正。 - item_giftbox.txt、item_scroll.txt 追加。(moveさんありがとう。) - item_db.txt - 古い巻物、プレゼントボックス 修正。 -・trade.c - trade_tradecommit() 修正。pc_delitem()を使うように変更。 -※テストはやっていませんので問題があったら報告してください。 - --------------- -//0473 by Kuro - -・class_equip_dbを一部修正 - db/class_equip_db.txt - --------------- -//0471 by hoenny - -製錬の時出る文を変えることができるようにしました.(map_athena.confで調節可能) -気功の数字が市廛の時実際水路表示図緑修正 - conf/map_athena.conf - refine_posword:追加。 - map/map.c - map_config_read()修正。 - map/script.h - do_set_posword()追加。 - map/script.c - do_set_posword()追加。 - buildin_getequipname()修正。 - map/skill.c - skill_status_change_start()修正。 - --------------- -//0470 by 死神 - -・製造の時属性石が二度減る問題修正。(実は二度減るように見えるだけでマップを移動すると正しく表示されますが...) - pc.h、pc.c - pc_delitem() 修正。 - npc.c、script.c、storage.c、pet.c - pc_delitem()を全て修正。 - skill.c - skill_produce_mix() 修正。 - --------------- -//469 by 波浪 - -・npc_mob_job.txt、npc_monster.txt、npc_monster30.txt、mob_db.txtのモンス名を修正 -・item_db.txtの回復アイテムの回復量をジュノー後のものに修正 - --------------- -//468 by Kuro - -・魔剣製作クエスト追加 - conf/npc_event_ma_sword.txt - --------------- -//467 by nini - -・BBが両手剣でしか発動しなかったところ修正→すべての武器で -・ARが両手斧でしか発動しなかったところ修正→片手斧、両手斧、鈍器 -・スピアクイッケン発動を槍だけに -・キャストキャンセルされないものにグランドクロス、ローグのストリップシリーズ追加 -・ブリッツビートがキャストキャンセルされなくなってた点修正 - map/skill.c - skill_use_id() 修正 - skill_check_condition() 修正 -・2-2職スキルのキャスト・ディレイ追加 - db/cast_db.txt - - --------------- -//466 by hoenny - -・阿修羅覇鳳拳修正(公式修正及び sp消耗がすぐ見えるように) -・蓄気の時気弾が見えるように修正(Mr.NO NAME様のパケ情報ありがとうございます.気弾が消えるパケ情報が不足です.) -・パリの羽やテレポート1を連続使用の時,鯖オーバーが発生しないように仮初めで修正 - doc/client_packet.txt - 0x1e1パケ情報追加 - map/battle.c - battle_calc_weapon_attack()修正 - map/clif.h - clif_spiritball_cre()追加 - clif_spiritball_del()追加 - map/clif.c - packet_len_table[]修正 - clif_spiritball_cre()追加 - clif_spiritball_del()追加 - clif_changemap()修正 - map/skill.c - skill_castend_nodamage_id()修正 - skill_check_condition()修正 - --------------- -//0465 by 死神 - -・リザレクションとハイディング、ブリッツビートのバグ修正。(ブリッツビートは報告はなかったのですが分析したら問題があったので修正。) - skill.c - skill_use_id() 修正。 - skill_castend_nodamage_id() 修正。 -・0455のNPCを元に戻しました。 - npc_event_ice.txt 修正。 - npc_event_potion.txt 修正。 - npc_town_geffen.txt 修正。(454の物に戻しました。) -・0451のαマップをコマントアウトしました。必要な方はコマントアウトをなくして使ってください。 - map_athena.conf 修正。 -・リザレクションは0442の問題でハイディング、ブリッツビートは0445の問題でした。それと0445の修正でスキル番号をenumで宣言した文字に変えていますがそれに落としがあるようです。(ハイディング、ブリッツビートはそのせいでした。)前の番号ソースと比べて問題がある部分は修正する必要があります。ちょっと面倒ですが... - --------------- -//464 by 波浪 - -・モンクスキルの部分について修正(未実装スレに書かれていたものを追加しただけです。 - skill.c - skill_use_id()修正 - cast_db.txt - モンクスキル追加 - --------------- -//463 by 胡蝶蘭 - -・462のバグ修正 - ・NPCのSHOPの不都合修正 - ・READMEの間違い修正(warpwaitingpcがwarpwaitingroomになっていた) - - map.h - struct npc_dataのchat_idの位置を修正 - --------------- -//462 by 胡蝶蘭 - -・NPCチャット作成 - ・waitingroom命令でNPCチャットを作成します。 - 引数は waitingroom "チャット名",制限人数,イベント名 です。 - イベント名は人数が最大になったときに起こすイベント名で、省略可能。 - ・warpwaitingpc命令で、チャット内にいるPC全員をワープできます。 - 引数はwarpと同じで、warpwaitingpc "マップ名",x,y です。 - - map.h - struct npc_dataとchat_dataを修正 - script.c - buildin_waitingroom(),buildin_warpwaitingpc()追加 - chat.c/chat.h - 色々修正 - clif.c - clif_getareachar_npc()、clif_joinchatok()など修正 - -・NPCのOnInitイベントをサーバー起動時に呼ぶように。 -・エクスポートするときのNPC名と表示上のNPC名を別々に設定可能に。 - ・同じNPC名のイベントは重複できないため、エクスポート用NPC名を使い、 - 同じNPC名でも別のNPCとして識別できるようにしなければなりません。 - (もちろん、イベント処理を行わない場合はその必要はありません。) - ・npc_*.txtのscript命令でNPCの名前を設定するとき、 - 「表示名::エクスポート名」とすると、表示する名前と、イベント用に - エクスポートする名前を別々に指定できます。 - 表示名が全く同じ別々のNPCでイベントを動作させるときに使用します。 - ・ややこしいのでPVPのnpcスクリプトを見てイメージを掴んでください。 - - npc.c/npc.h - npc_parse_*()の修正 - npc_event_do_oninit(),npc_event_do_oninit_sub()など追加 - map.c/map.h - do_init()でnpc_event_do_oninit()を呼ぶように - struct npc_data修正 - -・スクリプトgetmapusers、getareausersの致命的なバグ修正 - ・該当マップが存在しない場合、マップサーバーが落ちるのを修正。 - ・マップが存在しないと、-1を返すようにした。 - - script.c - buildin_getmapusers(),buildin_getareausers()修正 - -・pvpのスクリプト修正 - ・チャットルームを作るようにした - - (conf/) - npc_pvproom.txt - 全てのNPCのエクスポート名(pvp??r)設定 - OnInit:でwaitingroomを実行するように - --------------- -//461 by Kuro -・アコライト転職クエスト一部修正 - conf/npc_job_aco.txt - --------------- -//460 by sagitarius -・item_dbの間違い修正 - 4032,Ambernite_Card,アンバーナイトカード,6,20,,10,,2,,,,,32,,,,{},{},,修正 - --------------- -//459 by hoenny -・アドレナリンラッシュ使用の時斧チェック(自分だけ) -・Old_Blue_Boxの確率が高いという報告によって修正 -・Script.cは0455以前ことで引換(NPCをここに合わせて修正してください) -・阿修羅覇鳳拳修正(公式を修正したんですが, 正確かはよく分からないですね.) -・修道僧の蓄気,爆期の仮実装.(阿修羅覇鳳拳使用の時蓄気,爆期状態をチェックします. ) -・ペコペコに乗った後に、ADPDが間違ったこと修正(バグを直してあげたが, 直す前ことに変わるせいでまた修正) -その外にも修正をしたようなのに覚えないですね.そして誤った部分があれば指摘してください. - conf/npc_event_ice.txt - checkweight修正 - conf/npc_town_geffen.txt - checkweight修正 - db/item_purplebox.txt - Old_Blue_Box修正 - map/battle.c - battle_calc_weapon_attack()修正 - map/pc.c - pc_spheal()修正 - pc_calcstatus()修正 - map/script.c - buildin_checkweight()修正 - map/skill.h - SC_ EXPLOSIONSPIRITS追加 - map/skill.c - SkillStatusChangeTable[]修正 - skill_castend_nodamage_id()修正 - skill_check_condition()修正 - --------------- -//458 by Kuro -・アコライト転職クエスト追加 - conf/npc_job_aco.txt - 会話文が分からなかったので適当にしてあります。また、NPCの外見の変え方が分からなかったので適当にしてあります。 - 分かる方は修正しておいて下さい。 - --------------- -//0457 by Kalen - -・PVP関連のNPC追加 - conf/npc_pvp.txt - conf/npc_pvproom.txt - --------------- -//0456 by 死神 - -・モンスターの最初攻撃時間が長すぎる問題修正。 -モンスターの最初攻撃時間を今まではmob_dbのaDelayを使っていましたがこれをaMotionに変更しました。今まではmob_dbのaMotionはゴミでしたが今度からはゴミではありません。aMotionさえ正しければモンスターの攻撃のモーションの前にダメージが出てくる問題もなくなるはずです。 - mob.c - mob_changestate() 修正。 -・アイテムを入手できない時その理由に当たるメッセージが出るように変更。 - pc.c - pc_additem() 修正。 -・job_db1.txtので問題になった.を,に修正。 - --------------- -//455 by Mr.NO NAME -・NPCとのアイテム交換や買い物関係のScriptが出来上がった当初の - NPCデータ(npc_event_making.txt、npc_town_geffen.txt等)に乗っ取り、以下を修正。 - conf/npc_event_ice.txt - npc_event_potion.txt - npc_town_geffen.txt(454以前の物に戻しました。) - map/script.c - buildin_checkweight()を修正。 - --------------- -//454 by Kuro -・ゲッフェン鍛冶屋で買い物が出来るように修正 - conf/npc_town_geffen.txt - --------------- -//0451 by code -・ 今更ですがαクライアントに対応(αクライアントのdata.grfをadata.grfとしてgrf-files.txtのadataのところに書いてください) - common/grfio.c - grfio_setadatafile()追加 - /grfio.h - grfio_setadatafile()追加 - conf/map_athena.conf - αクライアントのマップを読み込むように変更 - /npc_warp_a.txt - αマップのワープポイントの設定(ちょっとずれてるかも) - /grf-files.txt - αクライアントのdata.grfをadata.grfとして読み込むように設定 - adata: に記述 -※αクライアントは - ttp://www.castledragmire.com/ragnarok/ - あたりから入手してください。 - --------------- -//0450 by hoenny -・ 騎兵修練実装 -・ コムパルションディスカウント実装 -・ ディスカウント・オーバーチャージ修正(数が高い場合計算法が間違ったことを直しました.) -・ 鉄拳修正(素手な時も適用されるように) -・ 斧修練修正(片手斧な時も適用されるように) -・ ボンゴンが攻撃するように修正 - map/pc.c - pc_calcstatus()修正 - pc_modifybuyvalue()修正 - pc_modifysellvalue()修正 - map/battle.c - battle_addmastery()修正 - db/mob_db.txt - ボンゴン修正 - --------------- -//0449 by 死神 - -・変になった所修正。 - const.txt - bAtkとbDef 追加。 - battle.c - battle_calc_weapon_attack()を元に戻しました。(0445の物) - map.h - map_session_dataを元に戻しました。(0445の物) - pc.c - pc_calcstatus() 修正。 - pc_bonus() 修正。 - item_db.txtを元に戻しました。(0446の物) - --------------- -//0448 by hoenny -・増速修正(pc_walk()から pc_calcstatus()に移動) -・最大所持量修正 - map/pc.c - pc_calcstatus()修正。 - --------------- -//0447 by ゆう -・二刀流・矢の属性を正しく適応 -・ATKの上がるカードの効果を武器サイズ修正なしの底上げに変更 -・ATK・DEFの上がるカードの効果の適応の仕方を変更 - -map.h - map_session_dataにcatk(カードATK)を追加 - -pc.c - pc_calcstatus() - アサシンの二刀流の攻撃速度を修正した - スクリプトによる属性を左右正しく適応するようにした - 矢の属性を正しく適応するようにした(弓の属性優先) - ただし、矢がすべての攻撃に適応されます - カードATKの処理を追加した - -battle.c - battle_calc_weapon_attack() - カートATKを底上げダメージとして計算するようにした - -item_db.txt - カードの bonus bAtk、bDef を削除 - かわりに、装備と同様にATKとDEFを設定 - (変更前をitem_db2.txtとしているので、不具合があれば戻してください) - - --------------- -//0446 by hoenny -・ミストレスカード実装。 -・スキル使用の時ジェムストーン消費。 -・スキル使用の時装備チェック。(ハンマーフォールだけ修正しようとしたが...) -・ハンマーフォールの範囲を 半径5セル(全25セル)ロ修正 - map/skill.c - skill_check_condition()修正。 - skill_castend_pos2()修正。 - -・ミストレスカード修正。 - db/item_db.txt - --------------- -//0445 by Aya - -・基本ASPDと計算処理を修正。 - db/job_db1.txt - map/pc.c -・SP係数と計算処理を修正。 - db/job_db1.txt - map/pc.c -・スキル名をenumで宣言し、それを使うように変更。 - map/skill.h - map/battle.c - map/pc.c - map/skill.c -・リカバリーのスキルIDがスローポイズンになっていたのを修正。 - map/skill.c -・集中力向上にカード効果が適用されていた問題の修正。 - map/pc.c -・リムーブトラップ、スプリングトラップ、ポイズンリアクトのターゲットを修正。 - db/skill_db.txt -・GMアカウントをjROのclientinfo.xmlから追加。 - conf/GM_account.txt -・warning修正。 - map/party.c -・キャラセレ認証時にlogin_id2はチェックしないように変更。 - login/login.c -・object_def.bat以外全ファイルの改行コードをLFに変更。 -・*.cnfファイルを*.confファイルに名前変更。 - --------------- -//0444 by 死神 - -・GMコマンドや@コマンドにコマンド別に使用レベルを設定できるように変更と@コマンド少し修正。(@whereと@day、@nightの修正と他のキャラに使うコマンドの場合GMレベルが自分以上の場合使えないように修正。) - atcommand.h 修正。 - atcommand.c 修正。 - clif.c 修正。 - map/makefile 修正。 - map.c - do_init() 修正。 - conf/atcommand_athena.cnf 追加。 -・細かい修正。 - pc.c - pc_setghosttimer()、pc_skill() 修正。 - script.c - buildin_skill() 修正。 -・conf_ref.txt 修正。 -・item_db.txt - 彼女の想い修正。 - --------------- -//0442 by 胡蝶蘭 - -・増速ポーション実装 - ・Lvや職業判定は行いません - - (db/) - const.txt - SC_SpeedPot0,SC_SpeedPot1,SC_SpeedPot2追加 - item_db.txt - 増速ポーションのスクリプト追加 - (map/) - skill.c - skill_status_change_start()修正 - pc.c - pc_calcstatus()修正 - -・PvPシステムの仮実装 - ・pvpマップでは自動的に、PCのpvpフラグon、順位通知などを行います。 - ・マップにpvpフラグをつけるサンプルをnpc_pvp.txtとして添付しています。 - ・pvpの詳しいルールがよくわからなかったので、次のようにしています。 - ・最初の持ち点は5点、倒すと1点、倒されると-5点。 - ・0点以下のPCはリザレクションが掛からない - ・GMはpvpマップにいても足元にサークルが出現しないようです。 - (クライアントの仕様?) - ・pvpマップで@pvpoff/@pvpすると休憩したり、休憩をやめたりできますが、 - 使用するべきではありません。 - - (conf/) - npc_pvp.txt - pvpフラグを入れるサンプル。 - nosaveフラグや受け付けnpcなどを追加するとよいと思われる。 - (map/) - clif.c - clif_parse_LoadEndAck()修正 - npc.c - npc_parse_mapflag()修正 - skill.c - skill_castend_nodamage_id()修正 - pc.c - pc_damage()引数修正 - atcommand.c - pc_damage()引数修正に伴う修正 - battle.c - -・その他修正 - ・@pvpoff/@pvpで順位やサークルの表示をやめた - ・@jumptoでスペースの入ったキャラクターも指定できるように - ・@kamibコマンド復活(青文字天の声) - ・非PVPのときに、対象が敵のスキル使用時、敵味方判定を行うように - - skill.c - skill_castend_id()で敵味方判定 - atcommand.c - 各コマンド修正 - --------------- -//0440 by 中の人 - -・本家を再現する方向なら意味はないかもしれませんが - pc.c「スクリプトによるスキル所得」を若干変更して - カードによるスキル一時習得の際でも1レベル以上を設定できるように致しました。 - - 単純に符号を変えてごまかしただけですので - 必要にあわせて修正をして下さい。 - --------------- -//0439 by hoenny -・阿修羅覇鳳拳の修正。 - db/skill_db.txt -・モンスター情報の修正。 - map/clif.c -・見切りの実装。 - map/pc.c - --------------- -//0438 by Aの人 -・古木の枝が使える場所をNPCスクリプトから制御可能 - mapflagにnobranchとすればそのマップは古木の枝使用不可になります。 - map.h - enumにMF_NOBRANCH 追加。 - npc.c - npc_parse_mapflag() 修正。 - pc.c - pc_useitem() 修正。 -ソース汚くしてしまったかも・・・. -勉強不足です - --------------- -//0437 by 波浪 -・item_db.txtの英名を大幅修正。(s付きとそうでない武器の英名がいつの間にやら - 同じになっていたのでそれを直すついでに他の部分も修正しました。 - まったく違う名前になってるものもありますが、こっちの方が正しいと思います。 -・item_purplebox.txtを本家仕様っぽく作成(大体こんな感じかと -・アルベルタとイズルードNPCを修正 - --------------- -//0436 by hoenny -・morocc 宝石商人の修正 - conf/npc_shop.txt -・ハンマーフォールの実装(Alchemist氏ソースを参照ありがとう!) - map/skill.c -以前に文字化けは低のせい! -次から気を付けます. - --------------- -//0434 by Avethes - -・タートルアイランドへ行くNPC修正 -・ユノーNPC修正 -(前回のバグはすみませんでした) - --------------- -//0433 by 死神 - -・製造バグ修正。 - 何故かはわからないがskill.cのskill_readdb()が変になっていたので修正。(自分がやった修正ではありませんが...) - skill.c - skill_readdb() 修正。 - --------------- -//0432 by 死神 - -・0429で一部のアイテムのスキルが出ない問題修正。 - clif.c - clif_parse_UseSkillToId()、clif_parse_UseSkillToPos() 修正。 -・skill.c - skill_use_id() 修正。(大した修正ではないです。) -・item_db.txtの文字化け修正。言語設定が日本語ではない場合保存する時には気をつけましょう。 -・攻撃されたモンスターの反撃が早すぎる問題修正。始めての攻撃がモンスターの攻撃ディレイに関係なく100ms後になっていたので攻撃ディレイに合わせるように変更。(ただ少し反撃が遅いと思われたりもしますが...) - mob.c - mob_changestate() 修正。 -・鯖に接続する最大人数を決めるように変更。 - char.c 修正。 - conf_ref.txt 修正。 - char_athena.cnf 修正。 - --------------- -//0430 by Avethes - -・NPC関係。ほとんどテスト。 -本家会話情報が揃えば修正。 - --------------- -//0429 by 死神 - -・ギルドのレベルアップをキャラのレベルアップのように変更。 - int_guild.c - guild_calcinfo() 修正。 - guild_next_exp() 追加。 - exp_guild.txt 修正。(レベルが上がらないようにしたいレベルのexpに0を入れればそれ以上にレベルが上がらなくなります。) -・スクリプトresetstatus、resetskill 追加。 - pc.c - pc_resetskill() 修正。 - script.c - buildin_resetstatus()、buildin_resetskill() 追加。 -・0425の続きで少し修正。 - clif.c - clif_parse_ を少し修正。 -・ショートカットに覚えているスキルレベル以上のスキルが登録されていても覚えているスキルレベルまでのスキルを使うように変更。 - clif.c - clif_parse_UseSkillToId()、clif_parse_UseSkillToPos() 修正。 -・メモの最大数を10個に変更。(あくまでも拡張の為の物です。まだ機能はしません。) - mmo.h - struct mmo_charstatusのmemo_pointを3から10に変更。 - char.c - mmo_char_tostr() 修正。 -・mob,c - mob_once_spawn()、mob_summonslave() 修正。(別に意味がある修正じゃありませんが...) -・@monster コマンドで座標を指定しない時モンスターが一か所に集中して出るのをキャラの10*10マス以内にランダムで現れるように変更。 - atcomand.c 修正。 - --------------- -//0428 by Avethes - -・conf/npc_smilegirl.txt - スマイルマスクガールスクリプト。 - 0427のおかしい部分とか修正。 - 提供された各都市の座標に配置。(NONAMEさん提供ありがとう!) - --------------- -//0426 by 胡蝶蘭 - -・アイテムの名前をdata.grfから読み込むようにした - itemdb.cのITEMDB_OVERRIDE_NAMEを定義しなければ読み込みません。 - ITEMDB_OVERRIDE_NAME_VERBOSEはitemdb.txtのデバグ用にどうぞ。 - 普通は変える必要はないと思うのでbattle_configには入れていません。 - - itemdb.c - itemdb_read_itemnametable()追加 - do_init_itemdb()修正 - -・データベース読み込み部の不安定性の修正(結構致命的だったみたいです) - なくても問題ないDB(item_value_db.txtなど)のファイルがない場合に - 鯖が落ちたりする現象が発生していた場合はこれで直っているかもしれません. - - skill.c - skill_readdb()でNULLポインタチェックを追加 - itemdb.c - item_readdb()を複数に分けた。 - ランダムアイテムデータベースの読み込み部を1つに纏めた。 - do_init_itemdb()修正 - -・細かいバグ修正 - ・ワープポータルの開くまでの秒数調整 - - skill.c - skill_unitsetting()修正 - -・その他修正(by 某M氏) - db/job_db1.txt - ちょこっと修正 - db/job_db2.txt - 2-2次職の足りないJobボーナスを追加(参考:R.O.M 776) - conf/npc_town_kafra.txt - オークD前と炭鉱前にカプラ配置(動作未確認) - conf/npc_shop3.txt - ジューノ販売NPC(拾い物) - conf/npc_town_yuno.txt - ジューノNPC(拾い物を改良。動作未確認) - --------------- -//0425 by 死神 - -・0419で書き忘れた物ですがスキルラーニングポーションがSP回復アイテムにも効果があるように変更。 -・今度はバグ修正がメインです。鯖落ちがなりそうな所の修正とテレポートの時死んだまま移動できる問題と0419でアクティブモンスターの先攻問題修正、死んでいるのに他の人には死んだように見えない問題の修正です。少しテストはしましたが本当に治ったかどうかは不明です。報告をお願いします。 - pc.c - pc_attack_timer()、pc_damage()、pc_walk() 修正。 - map.c - map_quit() 修正。 - mob_db.txt - ビッグフットのmodeを修正(アクティブになっていた為) - clif.c - clif_parse_WalkToXY()、clif_pcoutsight()、clif_pcinsight()、 - clif_getareachar_pc()、clif_getareachar_mob()、clif_getareachar_pet() 修正。 - mob.c - mob_ai_sub_hard_activesearch()、mob_ai_sub_hard_mastersearch()、 - mob_walk() 修正。 - pet.c - pet_walk() 修正。 - --------------- -//0424 by hoenny - -・クリップボーナス SP 10追加 - db/item_db.txt -・warp_test_yuno.txtを npc_warp30.txtに含んで, ちょっと修正 - conf/npc_warp30.txt -・他のサーバーが落ちても復旧されるように修正 - /startクリップ - --------------- -//0420 by 紅葉 - -・EP 3.0でのカード効果変更に解る範囲で対応。 - ほぼ全ての変更点について、出来る限り修正してあります。 - ATK修正が正しく適用されているようなので追加してあります。(アンドレCなど) - --------------- -//0419 by 死神 - -・0414で書き忘れた物ですが MOBのmodeで0x20(32)を復活させました。ボスじゃなくてもmodeに0x20が入っている場合普通のMOBでも死んだふりを破れます。 -(今の所機能はそれだけです。本鯖はAI強化みたいですが...) ただゴーストはボスでも破ることはできません。 -それと取り巻きのAIで取り巻きがターゲットした時主がターゲットしてないと主が取り巻きのターゲットをターゲットする部分をコマントアウトしました。(これが本鯖にあっていると思いましたので...) -・古い青い箱、古い紫色の箱、古いカード帖で出るアイテムをファイルで設定できるように変更。 - script.c - buildin_getitem() 修正。 - item_db.txt - 古い青い箱、古い紫色の箱、古いカード帖修正。 - item_bluebox.txt、item_purplebox.txt、item_cardalbum.txt 追加。(使用例程度の物です。どのアイテムが出るようにするかは自分で設定して使ってください。ただクライアントを落とすアイテムは出ないように設定してください。) - itemdb.h - struct random_item_data 追加。 - itemdb.c - itemdb_searchrandomid()、itemdb_readdb() 修正。 -・mob.c - mob_target()、mob_ai_sub_hard() 修正。(問題がありそうな部分だけ修正。) -・pc.c - pc_itemheal()、pc_walktoxy_sub() 修正。 -・ペットの出現をMOBと同じように変更。 - clif.c - clif_spawnpet() 修正。 - pet.c - pet_change_name() 修正。 -・0418を少し修正。(if文の条件を少し修正しただけです。) - --------------- - -//0418 by hoenny -・ /mm(/mapmove) /nb /b /bb /resetskill /resetstate GM 命令語使用の制限 -clif_parse_MapMove ,clif_parse_ResetChar ,clif_parse_GMmessage 修正 - map/clif.c - --------------- -//0417 by れあ - -・0412でitem_db.txtがおかしくなっていたのを修正 - --------------- -//0416 by 紅葉 - -・ジュノー周辺のワープ定義と敵の配置。 - ワープ定義はnpc_warp30.txtとし、追加する形にしてあります。 - 敵の配置についてもnpc_monster.txtとは統合せず、npc_monster30.txtとしてあります。 - 問題が無いようであれば統合して下さい。 -・上記定義ファイル追加に従いmap_athena.cnfを変更。 -・@goコマンドへジュノー追加。 - 要望があったようなので追加しました。 - --------------- -//0415 by 中の人 - -・今は亡き旧ROエミュ鯖開発スレッド Lv02での死神氏の説明に従って - モンスター定義データを若干変更させて頂きました。 - ・過去のnpc_monster.txtから通常マップ上(ルティエ等除く)にいるサンタポリン、アンソニを抽出し - 新たに作った「npc_x-masmonster.txt」に移転 - ・上記の修正にあわせてmap_athena.cnfを修正。 - map_athenaにコメントアウト状態で「npc: conf/npc_x-masmonster.txt」を追加しました。 - 必要にあわせてコメントアウトをして下さい。 - --------------- -//0414 by 死神 - -・strcasecmpをstrcmpiに変更。 -・dbや設定ファイルを読む時// をコマントアウトとして認識するように修正。 -・ペットと離れすぎるとペットが早く動くように変更。(キャラの2倍の速度で動きます。) -・ルートモンスターがアイテムをターゲットした時攻撃を受けても攻撃してこない問題修正。 -・同族モンスターのAIを変更。今まではtraget_idを使うせいでモンスターが攻撃した相手を攻撃する仕組みだったが今度はattacked_idを使う為攻撃してきた相手を攻撃するように変更。 -ただ今の仕様だと同族モンスターを攻撃して逃げる場合攻撃を受けた時その場になかったモンスターはついて来なくなっています。本鯖の仕様にあってるかどうかは不明ですので情報提供をお願いします。(attacked_idはいつもリセットされる為です。対策がいないわけでもないですが本鯖の仕様を知らないので...) -・メモリーの使用量を減らす為struct mob_dataとstruct npc_dataを変更。(0412で -map-serverのメモリーの使用量が164???KBytesだったが0414では152???KBytesになりました。ほんの少し減っただけですが増えるよりはましだと思いますので...) -・ゴーストタイム実装。 - マップ移動やテレポート、復活した時に敵に狙われない時間を重力ではゴーストタイム呼んでいます。そのゴーストタイムの実装です。 -battle_athena.cnfで時間を設定できます。時間を0にするとゴーストタイムは作動しません。ただこのゴーストタイムは攻撃行動、スキル使用、アイテム使用をするとなくなります。 - char/int_guild.c - char/int_party.c - conf/battle_athena.cnf - db/mob_db.txt - doc/conf_ref.txt - login/login.c - map/atcommand.c - map/battle.c - map/battle.h - map/clif.c - map/itemdb.c - map/map.c - map/map.h - map/mob.c - map/npc.c - map/pc.c - map/pc.h - map/pet.c - map/skill.c を修正。(db/mob_db.txtは//を入れただけですが...) - 修正した所を全て覚えてませんのでファイルだけ知らせます。 - --------------- -//0412 by いど - -・モンスター定義データ(日本語)の再整理 - 旧掲示板で指摘のあった事項について大体の範囲で修正 - snapshot387のバージョンをベースに修正しました。 - conf/npc_monster.txt - -・アイテム名の定義を大幅修正 - (root) - item.list - (db/) - item_db.txt - item_value_db.txt - -・マップデータの定義でコメントアウトしていたジュノー関連マップのコメントアウトを解除 - conf/map_athena.cnf - --------------- -//0411 by 死神 - -・鯖snapshotです。それとlogin_port、char_port、map_portの設定がなくても -デフォルトで6900、6121、5121を使うように変更。 -・login.c、char.c、chrif.c、clif.c 少し修正。 -・conf_ref.txt 修正。 -・login_portを6900から他の物に変えた場合はclientinfo.xmlを変える必要があります。 - --------------- -//0410 by 死神 - -GM用右クリックメニュー「(name)使用者強制終了」実装。(テストはしてません。@コマンドはテスト済みですが...) -0407のEXPに関する修正に問題があるらしいので修正しました。今度はテスト済みです。 -GMのアカウントIDを設定できるように変更とGMをレベル別に分けるように変更。 -(GMのレベルによる@コマンド等に制限をかけるつもりですが今制限がかけている物は@kick、@kickallのみになっています。) -・pc.c - pc_readdb()、pc_gainexp()、pc_nextbaseexp()、pc_nextjobexp()、 - pc_checkbaselevelup()、pc_checkjoblevelup() 修正。 - pc_isGM()、pc_read_gm_account() 追加。 -・pc.h - pc_isGM() 修正。 - pc_read_gm_account() 追加。 -・exp.txt - レベルが上がらない数値を999999999から0以下に変更。 - レベルを上げる為に必要なEXPを999999999以上にすることも可能。 -・clif.c - clif_GM_kickack()、clif_GM_kick()、clif_parse_GMKick() 追加。 -・clif.h - clif_GM_kickack()、clif_GM_kick() 追加。 -・atcomand.c - strncmpiをstrcmpiに変更。 - @kick、@kickall コマンド追加。 - @kick <キャラ名> - 自分以外のキャラの接続を強制終了させる。(自分よりGMレベルが - 低いキャラにしか使えない。GMではないキャラのGMレベルは0) - @kickall - 鯖に接続している全てのキャラの接続を強制終了させる。(自分と - GMを含めて) 鯖ダウン用のコマンドです。GMレベルが99じゃないと - 使えない。 -・conf/GM_account.txt 追加。 - GMとして認識するアカウントIDを設定するファイルです。 -・mmo.h - DEFAULT_WALK_SPEEDを140から150に変更。(これが本鯖にあってる数値 - みたいですので...) - struct gm_account 追加。 -・client_packet.txt - パケット0x00cd 追加。 -・login_portをcnfで読むように変更。(ただ6900からポートを変えるとクライアントが認識できない模様なので無駄なことだったりもしますが...) - char.c、login.c、char_athena.cnf、login_athena.cnf 修正。 -・普通のアカウント作成ではGMになれないようにlogin.cを変更。 -・login/makefile、map/makefile 修正。 - --------------- -//0408 by 胡蝶蘭 - -・405の新しい@コマンドを以前のatcommand.cに取り込みました。 - ・@kamiを修正 - ・@kill,@recall,@charjob,@revive,@charstats,@charoption,@charsave, - @night,@day,@doom,@doommap,@raise,@raisemap,@charbaselvl,@charjlvl - を追加&メッセージを日本語に変更&少し修正 - - atcommand.c - 追加と修正 - -・一部のスキルの効果実装 - ・不死身のジークフリード、イドゥンの林檎、幸運のキス、 - フレイムランチャー、フロストウェポン、ライトニングローダー、 - サイズミックウェポン - - map.h - struct skill_unitにrangeを追加。 - skill.c - 色々修正 - skill.h - enumの修正など --------------- -//0407 by 死神 - -・ペットのバグ修正。(ただ自分で再現できなかったので問題になりそうな所だけ修正しました。) -・ペットの移動速度をpet_dbに追加。 - pet.h - struct pet_dbにspeed追加。 - pet.c - pet_catch_process2()、read_petdb() 修正。 - pet_db.txt - 移動速度追加。 - (コマントアウトしているのはジルタスとアリスです。捕獲用の - アイテムが存在することとパフォーマンスをすることから考えて - 追加される予定の物と考えられます。ただその捕獲用のアイテムが - あるとクライアントを落ちますので注意してください。追加しても - 台詞はポリンの物ですので... 捕獲用のアイテム以外は適当に入れた - 物です。) -・pc.c、clif.c - pc_equipitem() 修正。 - clif_parse_EquipItem() 修正。 - pc_equipitem()の未鑑定アイテムのチェックをclif_parse_EquipItem()に - 移動しました。(ペットの装備もありますので...) -・レベルを99以上にあげるように変更と職業別にベースレベルの限界レベルを設定できるように修正。 - map.h - MAX_LEVEL追加。 - pc.c - pc_nextbaseexp(), pc_nextjobexp() 修正。 - pc_readdb() 修正。 -・exp.txt 修正。職業レベルと同じようにベースレベルもEXPテーブルを3つ作りました。レベルアップを止めたいレベルのexpを999999999にすればそれ以上レベルが上がりません。つまりnovice、1次職業と2次職業のベースレベルの限界を違うように設定できます。そしてベースレベル99以上に上がるようにすることもできます。(exp.txtの修正が必要ですが本鯖と違うように設定したい場合に修正して使ってください。) -・属性による回復をbattle_athena.cnfで設定できるように変更。 - attr_fix.txt 修正。 - battle.h - struct Battle_Configにattr_recover 追加。 - battle.c - battle_config_read() 修正。 - battle_athena.cnf 修正。 -・conf_ref.txt 修正。 -・client_packet.txt 修正。ペットパケット追加と少し修正。 - --------------- -//0402 by 胡蝶蘭 - -・400のバグを一部修正 - ・掛かってないスキル効果によるステータス計算が行われてしまうバグ修正 - ・効果修正:あくまで効果の計算の修正で、使えないスキルは使えません。 - スピアクィッケン、プロヴィデンス、戦太鼓の響き、 - 夕陽のアサシンクロス、口笛、不死身のジークフリード、 - イドゥンの林檎、サービスフォーユー、幸運のキス - ・効果追加:あくまで効果の計算の追加で、使えないスキルは使えません。 - ハミング、私を忘れないで…、ニーベルングの指輪(武器レベル無視)、 - エターナルカオス、ドラゴノロジー - ・効果付加系はちょっとでも怪しいスキルは全て使用できないように修正 - ・攻撃系スキルはほとんど見てないのでたぶんバグ多いです。 - ・全て未テストです。怪しすぎる部分を修正しただけです。 - - map.h - MAX_STATUSCHANGEを128に修正 - pc.c - pc_calcstatus()修正 - skill.c/skill.h - enumを修正 - skill_status_change_start()修正 - battle.c - battle_calc_weapon_attack()など修正 - --------------- -//0400 by AppleGirl - -Can Someone Help Me. -2-2 Skills added. -All The Mastery Skills. -SpearQuicken,Providence -New Bard Skill Assassin Cross Of Sunset -Providence -Frost Joke -Apple of Idun -Service For You -Meteor Strike (Different Style) -Assassin Cross Of Sunset (not tested) -All Masteries Done -Providence -Musical Strike -Throw Arrow -Frost Weapon << (Problems with elements)? -Flame Launcher << (Problems with elements)? -Seismic Weapon << (Problems with elements)? -Lightning Loader << (Problems with elements)? -Spirit Recovery -Potion Pitcher (Tato) -Axe Mastery (Tato) -Spear Quicken -Not Totally Working: -Combo Finish -Quadruple strike -Triple Attack -(skills in skill.c) (need to be finished.) -CP_ARMOR -CP_HELM -CP_SHIELD -CP_WEAPON -STRIP_HELM -STRIP_WEAPON -STRIP_SHIELD -STRIP_ARMOR - -* 適当な和訳 * -2-2次職スキルを追加しました -全ての修練スキル、スピアクイッケン、プロヴィデンス、 -夕陽のアサシンクロス(未テスト)、寒いジョーク、イドゥンの林檎、 -サービスフォーユー、メテオストライク(少し違う)、 -ミュージカルストライク、矢撃ち、フロストウェポン(属性が問題あり?) -フレームランチャー(〃)、サイズミックウェポン(〃)、ライトニングローダー(〃) -息吹、ポーションピッチャー -完全には働かないスキル: -猛龍拳、漣環全身掌、三段掌 -(skills in skill.c) (完了される必要がある) -ケミカルアーマーチャージ、ケミカルヘルムチャージ、 -ケミカルシールドチャージ、ケミカルウェポンチャージ、 -ストリップヘルム、ストリップウェポン -ストリップシールド、ストリップアーマー - -*注意 !! CAUTION !! by 胡蝶蘭* -この400にはバグが大量に含まれています。注意してください。 -there are many many BUGS in this update(400) !! Be careful !! - --------------- -//0399 by 胡蝶蘭 - -・MOBスキル使用条件や行動を修正 - ・無行動MOBが待機時のスキルを使用できない問題を修正 - ・条件スキル反応(skillused)がどのスキルにも反応していたバグ修正 - ・非移動MOBが追撃してくる問題を修正 - - mob.c - mob_ai_sub_hard()修正 - mobskill_event()修正 - mobskill_use()修正 - skill.c - skill_attack()修正 - -・MOBスキル一部実装 - ・自決(エフェクト無し?)、自爆、タバコを吸う、範囲攻撃 - HP吸収2つ(通常/魔法)(回復エフェクト無し?)実装 - - (db) - skill_db.txt - スモーキングなどを修正 - (map/) - skill.c - skill_castend_damage_id(),skill_castend_nodamage_id()修正 - battle.c - battle_calc_misc_damage()修正 - -・未鑑定アイテムが装備できなくなりました -・未鑑定アイテムにカードがさせなくなりました - - pc.c - pc_equipitem(),pc_insert_card()修正 - clif.c - clif_use_card()修正 - -・battle_athena.cnfにMOBの配置割合を定義できるようになりました - ・配置数が1のMOBについては適用されません - ・計算後の配置数が1未満の場合1に修正されます。 - - (conf/) - battle_athena.cnf - mob_count_rate追加 - (doc/) - conf_ref.txt - 修正 - (map/) - battle.c/battle.h - struct BattleConfig に mob_count_rate メンバ追加 - npc.c - npc_parse_mob()の修正 - -・ボーリングバッシュが相手が1匹でもとりあえず当たるようになった。 - - skill.c - skill_castend_damage_id()修正 - -・学生帽作成イベントの修正 - - (conf/) - npc_event_making.txt - アロエベラ(606)をアロエ(704)に。 - -・パケット情報修正 - - (doc/) - client_packet.txt - 0199パケット修正 - --------------- -//0397 by いど - -・モンスター定義データ(日本語)の整理 - ・npc_monster25.txtをnpc_monster.txtにリネームし、内容を整理(現在mob数:13450) - ・その軽量版としてnpc_monster_lite.txtを作成(現在mob数:11959) - ・上記の修正にあわせてmap_athena.cnfを修正 - --------------- -//0395 by 胡蝶蘭 - -・取り巻きMOBの行動修正 - ・アンクルなどで移動できない場合主に近づかないように修正 - ・ロックしていると主に近寄る処理をしないように修正 - ・主がテレポートすると追いかけるように修正(付近10x10マス程度) - ・主のそばにいるときはランダム歩行をしないように修正 - - mob.c - mob_ai_sub_hard_mastersearch()修正 - mob_can_move()追加 - mob_ai_sub_hard()修正 - -・MOBの行動修正 - ・スキル使用ディレイ処理がおかしかったのを修正 - ・詠唱のないスキルはtimerを使わないように修正(死亡時処理対策) - - mob.c - mobskill_use(),mobskill_use_id()修正 - -・MOBエモーションの実装 - ・エモーションの種類がわからないものは全て「!」になります。 - 抜けているデータを埋めてくれるとうれしいです。 - - (db/) - mob_skill_db.txt - いくつかのMOBのエモーションの項目の値1に種類を入れた。 - - (map/) - skill.c - skill_castend_nodamage_id()修正 - clif.c/clif.h - clif_emotion()追加 - -・パケット解析.txtをclient_packet.txtに改名&修正 - - (doc/) - client_packet.txt - エモーションの説明追加 - -・どうやら取り巻きMOBの種類は古いデータだったっぽいです。 - しかもMOB召喚では手下召喚と違うMOBを召喚するみたいですね。 - 詳しい人はmob_skill_db.txtを直してくれると。 - --------------- -//0393 by いど - -・char鯖でのlogin鯖のポート設定を6900に固定し、変更できないようにした - (login側でポート6900固定になっていたのでchar側もそれに合わせました。) - char/char.c - conf/char_athena.cnf - doc/conf_ref.txt - --------------- -//0392 by 胡蝶蘭 - -・MOBの行動修正 - ・何故かlast_thinktickが初期化されていない問題修正 - ・上に関連してPCが近くにいても手抜き処理が行われる問題修正 - (どうやら初期からのバグだった模様? このバグと、 - 新しい手抜き処理の仕様がタッグを組んで残像を作っていた模様) - ・取り巻きMOB用のAI処理追加(まだ怪しいです) - ・MOBのスキルディレイをスキル項目ごとに持つように変更 - ・スキルディレイが大きな項目ではオーバーフローしていた問題を修正 - - map.h - struct mob_dataの skilldelayを配列にしてunsigned intに変更 - mob.h - struct mob_skillのcasttime,delayをintに変更 - mob.c - mob_ai_sub_hard_mastersearch()追加 - mob_changestate(),mob_delete(),mob_catch_delete(),mob_damage(), - mobskill_use(),mobskill_use_id(),mobskill_use_pos(), - mobskill_castend_id(),mobskill_castend_pos(), - mob_ai_sub_hard(),mob_ai_sub_lazy()など修正 - -・MOBスキルの手下召喚とモンスター召喚実装 - ・mob_skill_db.txtの書式変更(最後に値を1つ追加、取り巻きMOBのID) - ・取り巻きMOBがわからなかったものはコメント化しています - わかる人は入力よろしくお願いします。 - ・現在は取り巻きは一度倒したら沸きなおしません。 - ・ボスがテレポートしても取り巻きは追いかけません。 - ・本鯖でどうなってるのか知らないので、間違ってる場合は教えてください。 - - (db/) - mob_skill_db.txt - 手下召喚などのデータ修正 - - (map/) - skill.c - skill_castend_nodamage_id()修正 - --------------- -//0391 by 死神 - -・ペットの移動中にパフォーマンスをするとペットが停止するように変更。 - (ペットの位置がずれるため修正しました。) - pet.c - pet_performance() 修正。 -・死んだモンスターはどんな行動もとれないように変更。(これで無敵 - モンスターがいなくなるといいですが...) - mob.c - mob_changestate(),mob_delete(),mob_catch_delete(),mob_damage(), - mob_ai_sub_hard(),mob_ai_sub_lazy() 修正。 -・PC、NPC、床アイテムが使うIDの範囲を調整。 - 床アイテムは0から500000まででPCは500000から100000000、NPC - (モンスターを含めて)は110000000から約21億までになります。 - (-を含めるともっと範囲が広くなりますがさすがにそこまでは必要ないと - 思いますので...) - map.h - MAX_FLOORITEM 追加(これを変えると床アイテムの最大数を変える - ことができます。今は100000になっています。ただこれは必ず - 500000以下にしてください。そうしないと正しく動くかどうか - 保証できません。) - map.c - map.hに合わせて少し修正。 - npc.h - START_NPC_NUM 追加。 - npc.c - npc.hに合わせて少し修正。 - login.h - START_ACCOUNT_NUMとEND_ACCOUNT_NUM 追加。 - login.c - login.hに合わせて修正。END_ACCOUNT_NUM以上にaccountを - 作れないように変更。 -・カートレボリューションに武器研究を2回適用するように変更。 - (結局は元に戻すことになりました...^^;) - battle.c - Damage battle_calc_weapon_attack() 修正。 -・mobのスキル使用をbattle_athena.cnfで決めるように変更。 - mob.c - mobskill_use() 修正。 - battle.h - battle.c - struct Battle_Configにmob_skill_use追加。 - battle_athena.cnf - mob_skill_use追加。(設定しないとnoです。) -・battle_athena.cnf - mobを二重で読めないようにnpc: conf/npc_monster.txtを削除。 - (最新はnpc_monster25.txtなので...) - --------------- -//390 by 胡蝶蘭 - -・バージョン情報所得部分を少し変更 - ・MODバージョンを定義できるようになりました。詳細はversion.hを。 - 気が向いたときか、大きな更新があるときなどに変更してください。 - ・バージョンcheck時のset eofログが出ないようにパケット7532追加。 - - (common/) - version.h - MODバージョンを定義できるように。 - (tool/) - checkversion - MODバージョンを表示するように。 - (login/char/map) - login.c/char.c/clif.c - MODバージョンの処理追加、 - パケット7532(切断)処理追加。 - -・その他色々修正 - ・こまごました修正ばかりですが、あまり覚えていません。 - ・MOBスキル条件でslavelt,attackpcgt処理実装(未テスト)。 - ・MOBの手下召喚のための機構追加(まだ召喚できません)。 - ・範囲スキル効果範囲に死亡PCがいると鯖が落ちるバグ修正。 - ・MOB残像が出なく…なってたらいいな。 - - (map/) - mob.c/mob.h/map.h/battle.c - 色々追加 - - (db/) - mob_skill_db.txt - ルート時処理と、属性変更スキルのコメントを外した。 - (属性変更は本鯖で動いてないらしいものもコメントを外してます。 - 問題がある場合は再びコメント化してください) - --------------- -//389 by いど - -・388の変更 - バージョン情報をcommon/version.h内の定数を使用するように変更 - --------------- -//388 by 胡蝶蘭 - -・バージョン情報所得ツール添付 - Perl製なので実行にはPerlが必要です。 - 使用方法などはエディタで開いて見てください。 - 使い方が良くわからない人は手を出さないほうがいいです。 - - バージョンを確認する用途よりは、サーバーの生存確認用といったかんじです - パケット7530/7531の詳細はソースを見てください。 - - (tool/) - checkversion - バージョン確認ツールPerlスクリプト - - (login/) - login.c - パケット7530/7531の処理追加 - (char/) - char.c - パケット7530/7531の処理追加 - (map/) - clif.c - パケット7530/7531の処理追加 - -・384以前のathena.txtも読み込めるようにしました - ・convertが面倒な人向け。 - ・正しく読み込める保証無し。バックアップを忘れずに。 - - (char/) - char.c - 384の方式で読み込めないデータは384以前の方式も試すように。 - -・conf_ref.txt/help.txt/getaccount修正 - help.txt - petコマンドの説明追加 - (doc/) - conf_ref.txt - pet関連の設定の説明追加 - (tool/) - getlogincount - 表示の修正 - --------------- -//387 by いど -・confフォルダ内のNPC定義データの整理 - 以下のファイルを削除しました - npc_kafraJ.txt - npc_mind_prtmons.txt - npc_script2J.txt(npc_event_mobtim.txtに同じものがあったため) - npc_testJ.txt(ほぼ同じことが@コマンドで出来るため) - npc_warp25.txt(npc_warp.txtに統合) - - 以下のファイルの名前を変更しました - npc_monster3.txt -> nop_monster2E.txt - npc_monster3J.txt -> npc_monster25.txt - npc_monster.txt -> npc_monsterE.txt - npc_monsterJ.txt -> npc_monster.txt - npc_sampleJ.txt -> npc_sample.txt - npc_script3j.txt -> npc_script2.txt - npc_script25J.txt -> npc_town_lutie.txt - npc_shop1J.txt -> npc_shop_test.txt - npc_shop2J.txt -> npc_shop_mobtim.txt - npc_shop3J.txt -> npc_shop2.txt - npc_shop.txt -> npc_shopE.txt - npc_shopJ.txt -> npc_shop.txt - npc_testJ.txt -> npc_test.txt - npc_warp3.txt -> npc_warp2.txt - npc_warp4.txt -> npc_warp25.txt - -・マップ定義の追加 - ジュノーアップデートで追加されるマップと、韓鯖独自(?)のクイズゾーン - (コモドアップデート)と天津アップデートのマップ定義を追加 - 現在、日鞍に無いものに関してはコメントアウトしていま。 - conf/map_athena.cnf - --------------- -//385 by 胡蝶蘭 - -・MOBの行動修正 - ・手抜き処理で移動しないモードのMOBも歩く問題修正 - ・MOBを倒したとき、再spawn時刻がおかしな値になる場合がある問題修正 - (MOBが沸かなくなる問題が修正されたはず) - ・MOBのワープで場所検索に1000回失敗したら元の場所に出るように修正 - ・MOBを詠唱中に倒すと、タイマーを削除するように修正 - - mob.c - mob_delete(),mob_catch(),mob_damage(), - mob_ai_sub_lazy(),mob_ai_sub_hard()など修正 - mobskill_deltimer()追加 - --------------- -//0384 by 死神 - -・ペット実装。 -思ったより長くかかりました。一周もかかったせいで何処を修正したか -覚えてない問題がありますが... それで念の為にmapとcharのファイルは全て -含めてアップします。 -それとmakefileとathena.shは自分が使ている物です。 -Yare-launcherは使てませんがいつも鯖の実行ファイルで実行していますので... - char/char.c、char/char.h、char/inter.c、char/makefile 修正。 - char/int_pet.c、char/int_pet.h 追加。 - map/makefile 修正。 - map/intif.c、map/intif.h、map/map.c、map/map.h、map/mob.c、map/mob.h、 - map/npc.c、map/npc.h、map/battle.c、map/battle.h、atcomand.c、map/pc.c、 - map/clif.c、map/clif.h、map/script.c 色々修正。 - map/pet.c、map/pet.h は殆どを自分の物に書き換えました。 - common/mmo.h 修正。 - db/pet_db.txt 修正。 - db/item_db.txt 修正。(携帯卵孵化機のbpet スクリプトが抜けていたので - 入れただけですが...) - doc/INTER鯖パケット.txtの名前をinter_server_packet.txtに変更とペットの - 保存等に使うパケットを追加。 -* 今度のペット実装によりキャラファイルの構造が変わり以前の物と互換できない - ので tool/convert.c を追加しました。 - 単独でコンパイルできますのでコンパイルしたあと実行してキャラ - ファイルを変換してください。そうしないとキャラが全部飛びますので... -* ペットの親密度が0になるとペットはその場で動けなくなりその状態で他の - マップに移動するか終了するとペットは消滅します。一応ペットの逃走を - 実装するつもりで作ったのですが本鯖にあってるかどうかはわかりません。 -* 移動速度が遅いペットの場合離れ過ぎるとついて来れなくなります。でも - この場合マップを移動してもちゃんとついて来ます。 - 消滅したりはしません。 -* 移動速度が速いペットはキャラより先に移動します。本鯖の方がどうなのか - わからないのでペットの移動はモンスターの移動速度で移動する - ようにしました。 -・battle_athena.cnf -pet_catch_rate 追加。 - ペットの捕獲倍率を設定します。(設定しないと100) - 基本的にペットの捕獲に使ってる公式は - (pet_db.txtの捕獲率 + (キャラレベル - モンスターレベル)*0.3 + luk *0.2) - * (2 - モンスターの現在HP/モンスターの最大HP) - になります。自分なりに作った物ですので本鯖とはかなりの - 違いがあるかも知れません。(モンスターのHPを減らせば減らす程捕獲率が - 上がる仕組みですが...) -pet_rename 追加。 - ペットの名前を変更するかどうかを決めます。(設定しないとno) - yesは何度でも名前の変更が可能。 - noは一度変更するともう変更不可能になる -pet_hungry_delay_rate 追加。 - ペットの腹が減る時間の倍率です。(設定しないと100) - 倍率が高いと腹が減り難くなります -mvp_exp_rate 変更。 - すでにstruct mob_dbのmexpperはゴミになっているので(MVP EXPは - MVPアイテムが取れなかった場合入るので意味がありません。) - MVP EXPの量の倍率になるように変更。(mob.cを修正) -・char_athena.cnf -autosave_time 追加。 - 自動保存する時間を決めます。(設定しないと300) - 單位は秒です。(ファイルに保存する時間の間隔です。) -・map_athena.cnf -autosave_time 追加。 - 自動保存する時間を決めます。(設定しないと60) - 單位は秒です。(キャラ鯖にデータを送る時間の間隔です。これは - ファイルに保存する時間の間隔じゃありません。) -・inter_athena.cnf -pet_txt 追加。 - ペットのデータを保存するファイルを決めます。(設定しないとpet.txt) -・@makepet コマンド追加。 - ペットの実装によって@itemで作った卵は使っても無駄になりますので - これを使って卵を作ってください。 - @makepet <モンスターのID or 卵のID> -・@petfriendly コマンド追加。 - @petfriendly <数字> - ペットを連れている時にペットの親密度を変更。(0~1000) -・@pethungry コマンド追加。 - @pethungry <数字> - ペットを連れている時にペットの満腹度を変更。(0~100) -・@petrename コマンド追加。 - @petrename - ペットを連れている時にペットの名前を変更できるように変更。 -・int_guild.c、int_party.c 読み込むファイルにエラーがあってもプログラムを - 終了せずに進むように変更。 -・pc_walk 123 != 1234 等のエラーが出ないように - if((i=calc_next_walk_step(sd))>0) { - sd->walktimer=add_timer(tick+i/2,pc_walk,id,sd->walkpath.path_pos); - を - if((i=calc_next_walk_step(sd))>0) { - i = i/2; - if(i <= 0) - i = 1; - sd->walktimer=add_timer(tick+i,pc_walk,id,sd->walkpath.path_pos); - のように変更しました。 - tickが同じ数値になるのを防いたのですがこれでどんな影響が出るかは - さっぱりわかりません。 - pc.c、mob.cを修正。 - でもこの修正をしても連続でクリックしたりするとキャラがしばらく - 止まるようです。(ペットのせいと思いましたがペットがなくても - 同じだったので他の原因かと...) -* doc/code_ref.txtとhelp.txtは面倒くさいので修正してません。 -・gm_all_skill: yesで2-2のスキルも表示されるように変更。(試いせはいませんが...) - pc.c - pc_calc_skilltre() 修正。 -・カートレボリューションのダメージ計算を修正。 - 武器研究を二重計算していたので修正。 - battle.c - Damage battle_calc_weapon_attack() 修正。 - --------------- -//381 by 胡蝶蘭 - -・MOBの行動修正 - ・PCのいないマップのMOBは時々ワープするようになりました - ・PCのいるマップのMOBは歩く以外に、時々沸き直すようになりました - (これまたパフォーマンスに影響があるかもしれません:少し重くなるかも) - ・手抜き処理でブロックの有効判定を行うようにしました - (HP無限MOB問題修正?) - ・ルート時スキル使用機構実装 - - mob.c/mob.h - mob_ai_sub_lazy(),mob_ai_sub_hard()修正 - MSS_LOOT追加,mob_readskilldb()修正 - -・MOBスキルの属性変更を実装しました。 - - map.h - struct mob_dataに def_eleメンバ追加 - mob.c - mob_spawn()でdef_eleをセットするように変更 - battle.c - battle_get_element()でdef_eleを読むように変更 - skill.c - skill_castend_nodamage_id()修正 - -・クァグマイアの効果範囲から出ると効果が切れるようになりました - - skill.c - ユニット系処理修正 - --------------- -//380 by Aの人 - -・カートレヴォリューションのダメージ計算実装 - battle.cを変更。 - -CHRISさん、ありがとう御座います。 -ノックバック実装できなくて、困ってました(><; - --------------- -//379 by CHRIS - -・カートレヴォリューションの実装 - skill.cとbattle.cを変更。 - -・マグナムブレイクにノックバックを追加。 - battle.cを変更。 - -(ソースを弄ったのは初めてなので、有ってるかどうか分かりませんが、自分では出来ました。) -(プログラム関係の書籍を買って勉強して初めて弄ったのです・・・。ガンバリマス!。) - --------------- -//377 by 胡蝶蘭 - -・MOBの行動修正 - ・近くにPCのいないMOBが時々ワープする仕様を止めました。 - ・PCのいないマップのMOBは全く動かなくなりました。 - ・PCのいるマップで、近くにPCのいないMOBは時々歩くようになりました。 - ・その他細かいところ修正 - (パフォーマンスに影響があるかもしれません:少し重くなるかも) - - mob.c - mob_randomwalk()追加 - mob_ai_sub_lazy(),mob_ai_sub_hard()修正など - -・スキル修正 - ・MOBがテレポートできるようになりました - - mob.c - mob_warp()追加 - skill.c - skill_castend_nodamage_id()修正 - -・ステータス異常の一部を実装/修正 - ・PC/MOBともに速度減少の効果が現れるように(AGIの表示は変わらず) - ・PCのエンジェラス、インポシティオマヌス、速度上昇の効果を修正 - ・MOBの2HQ、アドレナリンラッシュ、エンジェラス、インポシティオマヌス、 - 速度上昇/減少、グロリア、ブレッシングなどの効果実装 - ・睡眠、凍結、スタンの必中効果実装 - ・睡眠のクリティカル倍効果実装 - ・暗黒の命中率、回避率減少効果実装 - ・呪いのATK減少効果、LUK減少効果実装 - - battle.c - battle_get_*()修正 - battle_calc_weapon_damage()修正 - mob.c - mob_get_speed(),mob_get_adelay()追加 - pc.c - pc_calcstatus()修正 - -・item_value_db.txtでアイテムの価格を設定できるようになりました - ・価格データをオーバーライドできるようにしました。 - ・これでitem_db2.txtを用意する必要がありません。 - - (db/) - item_value_db2.txt - item_db2.txtの価格データ。 - item_value_db.txtにリネームすると読み込みます。 - (map/) - itemdb.c - itemdb_readdb()修正 - -・古木の枝を使うとMOBの名前が 0 になる問題の修正 - - (db/) - item_db.txt - 古木の枝のデータ修正 - --------------- -//375 by 胡蝶蘭 - -・MOB専用スキルの効果をいくつか実装 - 多段攻撃、毒などの追加効果付与攻撃、属性付き攻撃、魔法打撃攻撃 - 必中攻撃、防御無視攻撃、ランダムATK攻撃など。 - ただし、**全くテストしてません**。 - - (db/) - skill_db.txt - MOB用スキルのデータを修正 - mob_skill_db.txt - 少し追加 - (map/) - skill.c - skill_castend_damage_id()修正 - skill_status_change_start()修正 - skill_additional_effect()修正 - battle.c - battle_calc_weapon_attack()修正 - -・スキルを少し修正 - ・ウォーターボールで敵が死んでいても撃つモーションをする問題修正 - - skill.c - skill_status_change_timer()修正 - -・MOBデータが変なので某Wのデータベースを流用してみる - ・データの並び順とか全く同じなんですね - - (db/) - mob_db.txt - 某Wのmob_db.txt - -・各種confのリファレンスを添付 - あくまでリファレンスなので、HowToなんかは書いてません。 - - (doc/) - conf_ref.txt - confのリファレンス+α - - --------------- -//373 by 胡蝶蘭 - -・MOBスキル使用機構仮実装 - ・スキル使用時の処理はプレイヤーと共用(skill.c)です。 - ・不都合が多いと思うので報告お願いします。 - ・mob_skill_db.txtを埋めてくれる人も募集。 - このデータは「ラグナロクのたまご」を参考にしています。 - - (db/) - mob_skill_db.txt - MOBスキルデータベース(未完成) - テスト用のデータしか入ってません。 - (map/) - mob.c/mob.h - mobskill_*追加、その他多数修正 - map.h - struct mob_data に skill* 追加 - skill.c/skill.h - skill_castcancel()やスキルユニット処理をMOBに対応させた - battle.c - battle_calc_damage()など修正 - -・ギルドのスキルが触れない問題修正 - ・いつのまにかpc_skillupが古いものに変わっていたので修正 - - pc.c - pc_skillup(),pc_checkskill()修正 - --------------- -//368 by 胡蝶蘭 - -・MOB系の修正など - ・MOBが策敵範囲内のPC/アイテムを等確率でロックするようになりました - (アクティブ、ルート:いままでは該当ブロックのリンクリストの順などに - 依存していた) - ・射程範囲内かつ、到達不可能地帯のPCをMOBがロックすると、 - MOBが停止したり、その場で暴れだしたりする問題の修正 - ・MOBロック中にIWなどで到達不可能になった場合、ロックを解除するように。 - ・AEGIS方式で敵の移動を計算して移動不可能なら、Athena式で計算するように - ・ロックが解除されるときに数秒その場で停止するようにした - ・歩行が遅いMOBがとまらない/次の歩行開始が早すぎる問題を修正しました - ・ルート関連処理を少し修正 - - mob.c - mob_ai_sub_hard*()修正 - mob_can_reach()追加 - -・スキル使用時にターゲットブロックの有効性判定を行うように修正 -・ルアフのダメージが武器計算になっているのバグを魔法計算に修正 - - skill.c - skill_castend_id()修正 - skill_status_change_timer_sub()修正 - - ----------- -//364 by いど -・以下のパケットの説明を変更 - doc/パケット解析.txt - R 006a <error No>.B - R 0081 <type>.B - -・363でビルド時にwarningが出る不具合を修正 - map/guild.h - --------------- -//363 by 胡蝶蘭 - -・ギルドの修正 - ・ログインしていないPCを追放するとマップ鯖が落ちるバグ修正 - ・メンバー追加直後に追加されたPCがギルド表示に追加されない問題修正 - ・同じギルドに同垢別キャラが要るPCが脱退する/追放されると別キャラが - 脱退してしまう場合があるバグ修正 - ・メンバーがいるのに解散しようとするとマップ鯖が落ちるバグ修正 - - (char/) - int_guild.c - guild_calcinfo(),mapif_parse_GuildAddMember()修正 - (map/) - guild.c - guild_member_leaved(),guild_member_added() - guild_recv_info(),guild_break()修正 - --------------- -//362 by 胡蝶蘭 - -・ギルド解散実装 - - (char/) - int_guild.c - 解散処理を追加 - (map/) - guild.c/guild.h - guild_break(),guild_broken(),guild_broken_sub()など追加 - clif.c/clif.h - clif_guild_broken(),clif_parse_GuildBreak()追加 - intif.c/intif.h - intif_parse_GuildBroken()追加 - --------------- -//361 by いど - -・360での@healの変更間違いを訂正 - map/atcommand.c - --------------- -//360 by いど - -・353の修正を削除 -・@healで変更後の値がマイナスにならないように修正 - --------------- -//359 by いど - -・class_equip_db.txtの文字化け修正 - --------------- -//358 by 胡蝶蘭 - -・ログイン時のdelete_timerのエラーを出ないようにした - pc.c - pc_authok()の修正 - -・ギルド関係の修正 - ・メンバ勧誘時に最大人数の確認を行うように - ・データ通知処理をいくつか修正 - - (char/) - int_guild.c - 色々修正 - (map/) - clif.c/clif.h - clif_guild_inviting_refused()をclif_guild_inviteack()に改名 - guild.c/intif.c - 色々修正 - -・@guildlvupコマンド作成。ギルドレベルが調整できます。 - - (char/) - int_guild.c - 色々修正 - (map/) - atcommand.c - @guildlvup処理追加 - -・Makefikeのclean部分を修正 - - (char/ map/ login/) - Makefile - ・削除する実行ファイルのパスを ../athena/ から ../ に修正 - --------------- -//357 by 胡蝶蘭 - -・pc.cの文字化け修正 - 文字化けしたファイルをアップするのも、それを改造するのも禁止しませんか? - 直すの面倒くさすぎます。 - - pc.c - 文字化けの修正 - -・パーティやギルドに勧誘された状態でマップ移動やログアウトすると、 - 勧誘を拒否するように修正 - - pc.c - pc_setpos()修正 - map.c - map_quit()修正 - -・I-Athena自動復旧システム(B-NSJ氏作)をAthena用に改造して添付しました - プログラムの性質上./toolフォルダではなく./にあります。 - athena.shの変わりにstartで起動するとmap鯖が落ちても10秒程度で復旧します - プロセスは「map」で調べてますが他のプロセスに反応するときは - 「map-server」などに変えてみてください。 - - start - map鯖自動復旧システムのシェルスクリプト - - --------------- -//0356 by 死神 - -・athena.shを使わなくてもYare-launcherを使えるように変更。(自分試してましたが -一応動きました。でも窓の場合login-server.exeがlogin-server.exに登録されてしまい -Yare-launcherがlogin-server.exe続けて実行する問題があります。これはathenaの -問題ではありませんが...) - comm/makefile以外のmakefile全てを修正。 - athena.sh修正。 - 実行ファイルは.,/athena フォルダーじゃなく./ フォルダーに作られます。 -・ 新規accountの許容するかどうかをlogin_athena.cnfで決めるように変更。(これは - YareCVSを参考した物です。) - login.c - int mmo_auth() 修正。 - login_athena.cnf - new_account 追加。 -・char.c、login.c、inter.c、map.c、battle.cで一部のstrcmpをstrcmpiに変更。 - --------------- -//355 by ゆう - -・左手装備も考慮した二刀流に修正 - (ダメージ計算のみで見た目等は変更なし) - -map.h - map_session_dataに左手用の変数を追加 - -battle.h - battle_get_attack_element2()追加 - -battle.c - battle_get_attack_element2()追加 - battle_calc_weapon_attack()に - 二刀流の処理を追加修正 - クリティカルよりダブルアタックを先に判定するように修正 - 過剰精錬の追加ダメージを精錬ダメージの次に処理するように修正 - (これらは独自に調べたもので間違っている可能性あり) - -pc.c - pc_calcstatus()に左手用の変数に値を入れる処理を追加 - pc_equipitem()の二刀流装備の場所がおかしかったのを修正 - --------------- -//353 by いど - -・Yare-launcherを使うことが出来るようにMakefileとathena.shを変更 - --------------- -//352 by 胡蝶蘭 - -・詠唱中にクライアントを終了するとmap鯖が落ちる問題の修正 - skill.c - skill_castend_id(),skill_castend_pos(),skill_castend_map()修正 - map.c - map_quit()修正 - - -・データバックアップ用のツール添付 - Perl製なので実行にはPerlが必要です。 - 使用方法などはエディタで開いて見てください。 - 使い方が良くわからない人は手を出さないほうがいいです。 - データが消えても責任は持ちません - - (tool/) - backup - データバックアップ用Perlスクリプト - --------------- -//0351 by 死神 -skill.c - skill_use_id()に詠唱反応モンスターの処理を変更。(攻撃状態以外の場合 - 詠唱反応を最優先にします。) -mob.c - mob_ai_sub_hard_castsearch() 詠唱反応モンスターを二重処理して - いたので削除。 - mob_ai_sub_hard() 詠唱反応モンスターを二重処理しないように変更。 -pet.c - 0344に戻しました。(修正は少し分析をしてからにします。) -pet.h - 0344に戻しました。 -char.h - CHAR_CONF_NAME 追加。 -char.c - do_init() 実行する時ファイル名が入力されていないとCHAR_CONF_NAMEを - 使うように変更。 -map.h - MAP_CONF_NAME 追加。 -map.c - do_init() 実行する時ファイル名が入力されていないとMAP_CONF_NAMEを - 使うように変更。 -これでlogin.exe、char.exe、map.exeをathenaフォルダーにコピーした後名前を -login-server.exe、char-server.exe、map-server.exeに変更するとYare-launcherを使う -ことができます。これを使うと鯖が落ちる度に自動的に再実行してくれます。 - --------------- -//0345 by 死神 -・キャスティング探知実装。 - mob.c - mob_ai_sub_hard_lootsearch() 修正。 - mob_ai_sub_hard() 修正。 - mob_ai_sub_hard_castsearch() 追加。 - mob_target(), mob_ai_sub_hard_activesearch() ボスモンスターを - mvp経験値によって認識するように変更。 - mob_ai_sub_hard_linksearch() 修正。 - mob_attack() 死んだふり、ハイディングをチェックするように変更。 - mob_readdb() 修正。 -・pet.h - MAX_PET_DBを100に変更。 -・pet.c - read_petdb() 修正。 - --------------- -//0344 by 過去の人i1 -・ ペット腹減り実装およびそのほか色々修正 -・ ペット餌やり実装 - - pet.c - pet_calcrate(struct map_session_data *sd); - ペットの獲得確率計算 - pet_food(struct map_session_data *sd); - ペット餌やりシステム - pet_hungry_change( int tid, unsigned int tick, int id,int data ); - ペットが腹を減るロジック - pet_status_int(struct map_session_data *sd); - 親密度計算 - pet_status_hungry(struct map_session_data *sd); - 満腹度計算 - pet_status_1a3(struct map_session_data *sd); - パケット1a3設定関数 - pet_initstate(struct map_session_data *sd); - ペットが初めて生まれたときの初期ステータス設定 - pet.h - int pet_calcrate(struct map_session_data *sd); - int pet_food(struct map_session_data *sd); - int pet_hungry_change( int tid, unsigned int tick, int id,int data ); - int pet_status_int(struct map_session_data *sd); - int pet_status_hungry(struct map_session_data *sd); - int pet_status_1a3(struct map_session_data *sd); - int pet_initstate(struct map_session_data *sd); - を追加 - clif.c - clif_pet_emotion(int fd,struct map_session_data *sd) - 餌をあげたときにエモーションを行う - clif.h - clif_pet_emotion(int fd,struct map_session_data *sd); - --------------- -//0341 by 死神 -・ルートモンスター実装。 - map.h - LOOTITEM_SIZEを20に修正。 - struct mob_dataにint lootitem_count 追加。 - mob.c - mob_spawn() 少し修正。 - mob_ai_sub_hard_lootsearch() 追加。 - mob_ai_sub_hard() 修正。 - struct delay_item_drop2 追加。 - mob_delay_item_drop2() 追加。 - mob_damage() 修正。 - battle.h - struct Battle_Configにint monster_loot_type 追加。 - battle.c - battle_config_read() 修正。 - battle_athena.cnf - monster_loot_type: 0 追加。(基本的に0になっています。 - 0の場合はLOOTITEM_SIZEまでアイテムを食べても - またアイテムを食べて前のアイテムが消える仕様です。 - 1の場合はLOOTITEM_SIZEまでアイテムを食べると - もうアイテムを食べなくなります。 - --------------- -//0340 by 死神 -・mvpバグ修正。 - mob.c - mob_damage()でjに変えたはずの物に見落としありましたので - 修正しました。これでmvpアイテムで変な物が出なくなるはずです。 -・class_equip_db.txt - EUC-JISをS-JISに変更。(意味はありませんが他のファイルは - 全部S-JISだったので...単なるミスですが...) - ----------- -//339 by いど - -・338を適用した状態でビルドエラーが発生する不具合を修正 - ----------- -//338 by 過去の人i1 - -・ pet_db.txtに対応しました。 -・ pet_dbをつかったプログラムの書き方に修正しました。 -・ ペットの名前を変更する事が出来ます -・ ペットにアクセサリーをつける事が出来ます。 -・ 現在ペット餌やり進行中 - - (map/) - clif.c/clif.h - ・ pet関連の関数をほぼ修正及び追加いたしました。 - ・ clif_parse_EquipItem()内部でペット用装備であるかどうかの判定を行ってます - ・ clif_parse()を修正しました。 - - battle.h/battle.c - ・ battle_config.pet_rate変数を増やしました。mobに対する卵の獲得率 - を設定する事が可能となります - - pet.c/pet.h - ・ pet_initstate(struct map_session_data *sd); - 初期のペットステータスを設定する関数です - ・ pet_npcid(struct map_session_data *sd,int egg_name_id); - ペットに割り当てられたnpc_idを返します - ・ pet_itemid(struct map_session_data *sd,int mob_id); - モンスターIDから卵のIDを割り出します - ・ pet_equip(struct map_session_data *sd,int equip_id); - ペットのアクセサリー装備です - ・ pet_unequip(struct map_session_data *sd); - ペットのアクセサリー解除です - ・ pet_calcrate(struct map_session_data *sd); - 卵獲得確率計算を行い1or0を返します。 - ・ pet_food(struct map_session_data *sd); - ペット餌やり考案です。まだ正常に動作しません。 - ・ read_petdb() - pet_db.txtを読み込みpet_db[]に値を入れる関数です - - ・ do_init_pet() - map鯖初期化でよびだしpet_db[]を使えるようにする為の - ペット情報初期化関数です。 - - map.c/map.h - ・ BL_PET変数を加えました - ・ map鯖初期化の時にdo_init_pet()を呼び出します。 - - mmo.h - ・ s_pet構造体に変数追加。キャラクターがペットのデータを保持する為のシステム - の為今後も変数はそのつど増加する予定 - - npc.c - 改善しました。 - - (conf/) - battle_athena.cnfに卵の獲得確率pet_rateを加えました。 - ----------- -//337 by 胡蝶蘭 - -・ギルドの追加と修正 - ・ギルドに経験値を上納すると、上納されるEXPが異常な値になるバグ修正 - ・ギルドの敵対関係の追加 - - guild.c/guild.h - guild_payexp()の修正(上納EXP処理) - guild_opposition()追加 - guild_allianceack(),guild_reqalliance(), - guild_reply_reqalliance()の修正 - clif.c/clif.h - clif_guild_oppositionack(),clif_parse_GuildOpposition追加 - -・ディレイ時間がdexの影響を受けるかどうかをbattle_athena.cnfに書けるように - - (conf/) - battle_athena.conf - delay_dependon_dex を追加 - (map/) - skill.c - skill_delay_fix()の修正 - battle.c/battle.h - struct Battle_Configにdelay_dependon_dex追加 - battle_config_read()の修正(読み込み処理も変えてます) - --------------- -//0336 by 死神 -・スキルインデュアを少し修正。 -・clif.c - clif_skill_damage()、clif_skill_damage2() インデュア合わせて修正。 - (ただスキルや魔法になるとモーションが出ないパケットを - 見つけなかったので完全じゃありません。) - clif_parse_ActionRequest()、clif_parse_UseSkillToId()、clif_parse_UseSkillToPos() - スキルディレイの時にメッセージが出るように修正。 -・バックステップ実装、オリデオコン研究実装。 -・skill.c - skill_castend_damage_id()にあったスキルバックステップの処理を - skill_castend_nodamage_id()に移動しました。 - スキルバックステップの処理でclif_skill_damage2()を呼ぶのをclif_fixpos()を - 呼ぶように変更。(これでダメージのモーションが出ずに - 移動できます。) - バックステップと叫ぶように変更。 - skill_produce_mix() オリデオコン研究適用。武器レベルが3以上の時に - スキルレベル*1%がボーナスとして製造確率に付きます。 - エルニウムの確率判定追加。 -・skill_db.txt - バックステップのnkを0から1に変更。(スキル番号150の物です。) -・produce_db.txt オリデオコン,エルニウムを追加。(これは本鯖にはない物です。 - よってクライアントには必要なアイテムが表示されません。) - オリデオコン研究を少し使える物にするために追加しました。 - オリデオコンの場合はオリデオコン原石3つと石炭1つが必要で - エルニウムはエルニウム原石3つと石炭1つが必要です。 -・pc.c 少し修正。 - pc_heal()pc_percentheal() 少しだけ修正。 - pc_gainexp() ギルドにexpを上納する時にexpがマイナスにならないように - 修正。同時に2つ以上のレベルが上がるように変更。 - 最大レベル以上にレベルが上がらないように修正。 - pc_checkbaselevelup()、pc_checkjoblevelup() 追加。レベルアップを - チェックします。 - pc_itemheal() 追加。アイテムを使う時にVITとスキルによってボーナスが - 付く物です。スキルラーニングポーション実装。 -・pc.h - pc_checkbaselevelup(),pc_checkjoblevelup() 追加。 - pc_itemheal() 追加。 -・script.c - スクリプトfixhealを除去。itemhealを追加。healがfixhealの機能をする - ように変更。 - buildin_fixheal() を消しbuildin_heal()を元の物に戻しました。(つまり - buildin_heal()がbuildin_fixheal()になりました。) - buildin_itemheal() 追加。アイテムによる回復はこれを呼ぶようにして - ください。 - buildin_heal()からボーナスの計算を除去。 -・item_db.txt、 item_db2.txt - healをitemhealに変更。 -・mob.c - mob_damage() 0335でmvpに少し間違いがありましたので修正しました。 -・skill.h - MAX_SKILL_PRODUCE_DBを64から100に変更。 - - -//0335 by 死神 -・char/char2.cの一部にRETCODEが適用されてなかったのでそれを修正。 -・char/char2.cのparse_char()でキャラを消す時に問題がありそうな所を修正。 -・char/cha2.c,login/ login2.cをchar/cha.c, login/login.cに変更。 -・char/makefile,login/makefileを変更。 -・makefileとcommon/mmo.hを変更してOSを自動認識してRETCODEを自動に - 適用するように変更。 -・common/grfio.cのgrfio_init()を修正。(コードをちょっときれい(?)に - しただけですが,,,) -・インデュア実装。よってアンティペインメントも実装。 -・map/clif.c - clif_parse_LoadEndAck() 韓国クライアントのパッチに合わせて少し変更。 - (マップが変わる度に武器とシールドが見えなくなるためです。まだ - 日本クラとは関係ありませんが...) - clif_skillinfoblock() upはいらないと思うので消しました。スキルポイントが - 256、512等の時スキルツリーが正しく表示されないことは - もうありません。 - clif_guild_skillinfo() 同じようにupを消しました。 - clif_birthpet() pc_delitem() 呼ぶように変更。 - clif_damage() インデュアに対応するように変更。 -・map/pc.c - pc_percentheal() マイナスを入れても動くように変更。少し修正。 - pc_heal() 少し修正。 - natual_heal() 少し修正。 - do_init_pc() natual_healの修正に合わせて変更。 - pc_calcstatus() 弓を装備してないとワシの目が適用されないように変更。 - トラスト実装。 - pc_damage() インデュアに対応するように変更。 -・map/pc.h - pc_checkoverhp(), pc_checkoversp()を追加。 -・map/map.h - MAX_PC_CLASSを+1に。 -・map/atcomand.c - comandをcommandに変更。 - strncmpをstrcmpiに変更。よってコマンドが大文字、小文字を区別する - 必要がなくなりました。 -・map/npc.h - npc_parse_mob()を追加。(意味はありませんが...) -・map/temdb.c - itemdb_readdb()でclass_equip_db.txtを読むように変更。 -・db/class_equip_db.txt を追加。ここで装備するクラスを指定します。ない場合は - item_db.txtにあるjobを使います。含まれてる物は完全な物ではなく - 使用例程の物です。 -・map/skill.c - skill_status_change_start() インデュアの時間を正しく変更。 -・map/battle.h - battle_configのexp_rateをbase_exp_rateに変更。,job_exp_rateを追加。 - battle_get_mexp()を追加。 -・map/battle.c - battle_configのexp_rateをbase_exp_rateに変更。,job_exp_rateを追加。 - battle_get_mexp()を追加。 - battle_calc_magic_attack()を変更。ダーンアンデッドでボスの認識をmvp - expでするように変更。 -・map/mob.c - mob_readdb() base_exp_rate,job_exp_rateに対応。 - mob_readdb() ボスの認識をmvp経験値でするように変更。 - mob_damage() mvpを取る時の処理を変更。重さが50%を越えると床に - 落ちるように変更と色々。 -・conf/battle_athena.cnf - base_exp_rate、,job_exp_rateを追加。 -・0308で忘れた物 - 古く青い箱、古いカード帖、古い紫色の箱の使用で得られたアイテムを - 持ってなくなったらアイテムを床に落とすように変更。 - 製造はすでに0302で適用。 - ----------- -//334 by C}{RIS - -・あぷろだの332.txtをpet_db.txtとして同梱。 - -・各種テキストファイルのミスを修正 - ・attr_fix.txt 属性修正がマイナスに働いて敵が回復する問題を修正。 - >元の回復仕様に戻したい場合attr_fix.txtをリネームし、attr_fix_old.txtをattr_fix.txtにリネームして下さい。 - ・mob_db.txt モンスターの日本語名を本鯖と統一。 - ・cast_db.txt 詠唱時間、ディレイを本鯖と統一。 - ----------- -//333 by 胡蝶蘭 - -・ギルド機能追加 - ・ギルドの同盟と同盟解消 - - (char/) - inter.c/int_guild.c - パケット長/ギルド処理追加 - (map/) - clif.c/clif.h - clif_guild_reqalliance,clif_guild_allianceack, - clif_guild_delalliance,clif_parse_GuildRequestAlliance, - lif_parse_GuildReplyAlliance,clif_parse_GuildDelAlliance追加 - (ギルド同盟関係のパケット処理) - intif.c/intif.h - ギルド同盟関係のパケット処理追加 - guild.c/guild.h - ギルド同盟関係の処理追加 - map.h - struct map_session_dataにguild_alliance,guild_alliance_account追加 - -・ギルドエンブレムの変更がマップ鯖を再起動しないと有効にならないバグ修正 - - guild.c/guild.h - guild_emblem_changedの修正 - ----------- -//331 by 過去の人i1 - -・ペットシステム修正(完成度25%) - - ・各種捕獲用アイテムをそれぞれ対応する敵に対して使用することで - 正しく卵が手に入るようになりました。 - ・各種捕獲用アイテムを対応しない敵に使用した場合はルーレットが必ず失敗します。 - ・ペットが瞬時に表示されるようになりました。 - ・ペットを右クリックするとメニューが出るようになりました - ・他色々危険な要素を修正しました。(アイテムの数の減少等のバグを直しました) - - (db/) - item_db.txt - 各種捕獲用アイテムに対応するようpetコマンドを正しく書きました。 - - (common/) - mmo.h - s_pet ペット構造体にpet_item_idを追加 - - (map/) - clif.c - clif_birthpet()を修正。正しく卵が減る、正しい卵のIDを取得するよう修正 - これによって、正しくnpc_pet関数が動きます。 - - clif_spawnnpc()を修正(WBUFPOS(buf,36,nd->bl.x,nd->bl.y)と、数値を26から36へ変更しました) - これによってペットが瞬時に表示されるようになりました。 - - npc.c - npc_pet()を修正。 - - pet.c/pet.h - ペット関連の細かな関数をこちらにまとめる為、追加しました。 - 現在はペットの判定関係をまとめてあります。 - - script.c - 特に大きな修正はありません。 ----------- -//330 by 過去の人i1 - -・ペットシステム導入(完成度20%) - ・敵に対して捕獲用アイテムを使用する事が可能となりました。 - (まだ熟していないリンゴのみ使用可能、敵につかってもポリンの卵が手に入ります。) - ・各種卵に対してペットを表示する事ができます、ただしなぜか一度画面外に - でないとペットが表示されません。 - (恐らくペット表示の際に行っているNPCステータスが正しく入っていない) - ・表示されたペットがパフォーマンスを行います。 - - (db/) - item_db.txt - 携帯卵孵化機を使用可能に bpetコマンド(携帯卵孵化機使用) - 「まだ熟してないリンゴ」を使用可能に petコマンド(あるmobに対して使用可能にする) - (common/) - mmo.h - s_pet ペット構造体追加 - mmo_charstatus ペット構造体宣言変数追加(pet) - (map/) - clif.c/clif.h - - int clif_catchpet(struct map_session_data *sd,int pet_id); - void clif_ruletpet(int fd,struct map_session_data *sd); - int clif_judgepet(struct map_session_data *sd,int target_id); - int clif_sendegg(struct map_session_data *sd); - void clif_listpet(int fd,struct map_session_data *sd); - int clif_birthpet(struct map_session_data *sd,int pet_id); - void clif_menupet(int fd,struct map_session_data *sd); - - 以上の関数を追加しペットに関する処理を行っております。 - (ルーレット、卵選択窓、パフォーマンス、そのほか色々) - - npc.c/npc.h - int npc_pet(struct map_session_data *sd,int name_id); - ペット表示の為の関数を追加 - (この関数内部でペットの表示処理を行っています。適切に修正してください) - - script.c - int buildin_catchpet(struct script_state *st); - int buildin_birthpet(struct script_state *st); - を追加しました。スクリプトにpet,bpetを追加しました。 ----------- -//329 by 胡蝶蘭 - -・ギルド機能追加 - ・ギルドへのEXPの上納 - ・ギルドレベルアップ - ・ギルドスキルの割り振り - - (db/) - exp_guild.txt - ギルドレベルの経験値データベース - (common/) - mmo.h - GBI_*,GMI_*の定義の追加など - (char/) - int_guild.c - EXPやレベルアップ、スキルアップ処理追加など - inter.c - パケット長追加 - (map/) - guild.c/guild.h - ギルド処理追加 - intif.c/intif.h - ギルドパケット処理追加 - clif.c - clif_guild_skillinfo()修正 - clif_guild_skillup()追加 - pc.c - pc_skillup()でギルドスキルの場合はguild_skillup()を呼ぶように - pc_gainexp()で上納EXPのためにguild_payexp()を呼ぶように - -・ギルド機能修正 - ・ギルドメンバーがログインやログアウトすると、 - ログイン中のギルドメンバーにギルド系パケットが送られなくなる問題修正 - - guild.c - guild_recv_memberinfoshort()の修正 - ----------- -//328 by 胡蝶蘭 - -・ギルド機能の追加など - ・追放機能仮実装(追放したキャラも再加入可能&一部情報がダミー) - ・スキルの表示(表示だけです。上げたりは出来ません) - - (common/) - mmo.h - struct guild_explusionの変更 - (char/) - int_guild.c - 追放処理追加 - 空ギルドチェックなど追加 - (map/) - guild.c/guild.h - ギルドスキル関係のアクセサなど追加 - clif.c - clif_guild_skillinfo()の修正 - clif_guild_explusionlist()追加 - -・ターンアンデッドがボス系アンデッドでMISSになるバグ修正 - ・ターンアンデッド失敗時のダメージが使われます - - battle.c - battle_calc_magic_damage()の修正 - ----------- -//327 by いど -・経験値テーブルに1箇所間違いがあったので修正 - db/exp.txt - ----------- -//326 by いど -・char鯖の新鯖,メンテナンス中のフラグ情報を設定できるようにした -・char鯖の鯖名の長さが16バイトになっていた部分を20バイトに修正 - - (login/) - login2.c - parse_login()の修正 - login.h - struct mmo_char_serverの修正 - (char/) - char2.c - check_connect_login_server(),do_init()の修正 - (conf/) - char_athena.cnf - ・char_maintenanceを1にするとログイン人数の後ろに(点検中)がつく - ・char_newを1にすると鯖名の前に[新]がつく - (doc/) - パケット解析.txt - ・今回の変更に伴う一部修正 - ----------- -//325 by Mind Twist(224&0293) -・敵(NPC)スキルの追加(ツリーに追加のみ) - db/skill_db.txt - ・ギルドスキル相変わらず不明…この形式じゃないのかな? - ----------- -//324 by non - -・mobのターゲット後移動を修正 -・mobの移動速度をDBから反映させるように - - (map/) - mob.c - mob_ai_sub_hard()の修正 - -・斜め判定を修正 - ・FW等での斜め範囲を本鯖仕様に - - (map/) - map.c - map_calc_dir()の修正 - ----------- -//322 by 胡蝶蘭 - -・ログイン時に必ずパーティーから除名されるバグ修正 - ・0318の「パーティを除名されたのに〜」での修正ミス - - (char/) - int_party.c - パーティー競合時のメッセージに改行追加 - (map/) - party.c - party_check_member()の修正 - -・ギルド会話実装&修正など - (char/) - int_guild.c - ギルド競合時のメッセージに改行追加 - (map/) - guild.c/guild.c - guild_send_message(),guild_recv_message()など追加 - intif.c/intif.h - intif_parse_GuildMessage()など追加 - clif.c/clif.h - clif_guild_message(),clif_parse_GuildMessage()など追加 - clif_guild_basicinfo()のパケットを0150から01b6に変更 - -・バックステップがものすごく怪しいけど仮実装 - ・使うとダメージを1喰らったように見えます。(実際はダメージ0です) - - skill.c - skill_castend_damage_id()修正 - ------------------- -//321 by 過去の人i -・弓矢装備効果のみ実装(多々おかしい点は存在するが装備が出来、矢の効果が出る) - map/clif.c map/clif.h - clif_itemlist()追加 - 持ち物の中で弓矢に割り当てるパケット番号を0x8000とする処理追加 - - clif_arrowequip(struct map_session_data *sd,int val); //self - を追加。この中で弓矢装備パケット処理を行ってます - map/pc.c - pc_equipitem() 弓矢装備追加 - - 残された問題点: - ・ 矢が減らない - ・ リログすると矢が1になる - ・ 装備している矢が表示されない(←多分装備posの設定をしていない為かと) - ・ 矢を装備解除できない(他の矢を装備しなおせば装備した矢の効果になります - ----------- -//320 by いど -・以下のパケットのエラーコードの説明を追加 - doc/パケット解析.txt - R 006a <error No>.B - R 0070 <error No>.B - R 0081 <type>.B - ----------- -//319 by mk -・NPCとの会話中に装備変更、アイテム、スキルを使用できないようにしました - map/clif.c - 各所でsd->npc_idをチェックしてます - -・一部の被り物でも精錬後に装備箇所がおかしくなるバグを修正 - map/script.c - buildin_successrefitem のコードを修正 - -・カードによる追加効果および異常耐性発動処理の修正 - map/skill.c - インデックス初期値が間違っていると思われるので修正(SC_POISON -> SC_STONE) - -・ボウリングバッシュの仮実装、グリムトゥースの使用条件追加 - ・ボウリングバッシュを仮実装。吹き飛ばし処理やってるので - battle.c のblewcountをコメントアウトしました - ・グリムトゥースの使用条件(ハイディング&カタール装備)チェック追加 - こんな感じで他のスキル使用条件も追加してもよいのかな? - ・skill_blown の吹き飛ばし方向をターゲットとの位置が重なっているときは - ランダムではなくキャラクターを後ろへ吹き飛ばすように変更しました - map/skill.c - skill_castend_damage_id()変更 - skill_check_condition()変更 - skill_blown()変更 - -・アサシン二刀流処理に関する修正? - ・装備一覧へdrag&drop時に両手が赤くマーキングされるように修正 - アサシンでは武器装備箇所が両手になるようitem_equippointを変更 - それに伴いpc.cのpc_equipitemを修正 - ・逆手ダメージを表示してみました - まともにダメージ計算やってないので攻撃回数の確認だけです - ・カタール追撃と左手攻撃のMISSを無理やり表示 - (map/) - itemdb.c (itemdb.h、clif.c、pc.c) - itemdb_equippoint() を変更 (二刀流を考慮) - 引数を(int nameid) -> (struct map_session_data *sd,int nameid)に - 引数変更に伴い宣言(itemdb.h)と呼び出し側(clif.c ,pc.c)も変更 - pc.c - pc_equipitem(), pc_checkitem()装備チェックを修正 - battle.c - battle_calc_weapon_attack(),battle_weapon_attack() - 上にも書きましたが左手のダメージ計算は行ってません - (カード、属性等も未適用)右手と同じダメージ入れて左右修練適用してます - カタール追撃と左手ダメージをミスさせる方法(パケット?)がわからないので - 計算後のダメージが-1の場合、damage=0を送るようにしています - もっとよい方法があるのでしたら修正お願いします - -・完全回避の計算をLukではなくFlee2で判断するように修正 - map/battle.c - battle_calc_weapon_attack() - - (db) - item_db.txt、item_db2.txt - 装備品の一部ボーナス効果を追加 - mob_db.txt - 某所でうpされていたものを少し修正 - まだModeやDropに問題点があるかもしれません - ----------- -//0318 by 胡蝶蘭 - -・ある公平分配PTとそのPTに属さないPCが共闘すると鯖が暴走するバグ修正 - - mob.c - mob_damage()のEXP分配処理修正 - -・パーティを除名されたのに所属しているように見えるバグ修正 - ・該当キャラがログアウト状態の時に除名され、その後、同垢別キャラが - 同パーティに所属しなおし、さらに元のキャラでログインすると、 - 除名判定に失敗してパーティに所属したままであるとされてしまう問題修正 - - party.c - party_check_member()の修正 - - ----------- -//0317 by nabe - -・「〜さんから取引を要請されました。」が自分の名前になっていたのを修正 - trade.c/clif.c/clif.h - clif_traderequest()で取引相手のキャラ名を渡すように変更 - ----------- -//0316 by nabe - -・両手武器を精錬すると片手装備になるバグを修正 - script.c - buildin_successrefitem()で、両手武器の場合等に装備箇所チェック - ----------- -//0315 by 胡蝶蘭 - -・PCのSPAWNタイミングを変更 - ・マップ移動(ログイン)時、ローディング終了後にSPAWNするように。 - ・ロード中に攻撃されたりしなくなります。 - ・ギルド/パーティ情報読み込み前に名前解決パケットが来る問題も - 修正されるはずです。 - - pc.c - pc_setpos()でmap_addblock,clif_spawnpcの呼び出しを止めた。 - clif.c - clif_parse_LoadEndAckでmap_addblock,clif_spawnpcを呼ぶように。 - -・inter鯖パケット処理の重大な問題を修正 - ・一度にパケットを送信できなかった場合、無限ループに陥る問題修正 - - (char/) - char2.c - parse_frommap()修正 - inter.c - inter_parse_frommap()修正 - (map/) - chrif.c - chrif_parse()修正 - intif.c - intif_parse()修正 - -・ギルドの機能追加 - ・他人のエンブレムが見えるように。 - ・ログイン直後の自分のエンブレムが見えるように。 - ・脱退できるように。(追放はまだです) - - <パケット情報引き続き模集> - ・016c,016d,0163,015cなどの詳細な情報 - ・ギルドスキルのIDがわかる人、教えてほしいです。 - 158,205,331あたり調べましたがダメな模様。 - - (common/) - mmo.h - MAX_GUILDを36に。 - (char/) - int_guild.c - 脱退のパケット変更 - inter.c - パケット長修正 - (map/) - clif.c/clif.h - clif_set0078,clif_set007bの修正 - clif_guild_belonginfoの修正 - clif_guild_skillinfo追加 - guild.c/guild.h - 脱退などの処理追加 - intif.c/intif.h - 脱退などの処理追加など - - ----------- -//0314 by いど - -・char鯖とmap鯖の鯖数上限を30に引き上げ - login/login.h - char/char.h - -・map_athena1.cnfをmap_athena.cnfにリネーム - それに伴い、athena.shを変更 - -・パケット解析資料をdoc/に移動 - - ----------- -//0313 by 胡蝶蘭 - -・ギルドの機能追加 - ・ギルド勧誘/役職内容変更/メンバーの役職変更など - ・guild.txtの書式がまた変わりましたが、前のデータも読み込めるはずです。 - - <パケット情報引き続き模集> - ・016c,016d,0163,015cなどの詳細な情報 - ・自分以外のPCの所属ギルドIDを通知するパケット - - (common/) - mmo.h - struct guild を変更 - (char/) - int_guild.c/inter.c - 処理追加/パケット長追加 - (map/) - guild.c/guild.h/intif.c/intif.h - 処理追加 - clif.c/clif.h - ギルド関係のパケット処理追加 - -・help.txtを修正 - help.txt - -・0311による文字化けを修正 - README - map/pc.c - ----------- -//0312 by いど - -・@hコマンドを@helpに変更 -・読み込むマップデータの定義部分を変更 - ----------- -//0311 by tk44 -・Assassin 二刀流装備、ASPD問題修正 - - map\pc.c - pc_equipitem(), pc_calcstatus(), pc_checkitem() - -・二刀流傷害計算修正まだ処理中 - ----------- -//0310 by 胡蝶蘭 - -・ログやデータに使う改行コードをmmo.hで設定可能に - (common/) - mmo.h - RETCODEで改行コードを文字列で定義します。 - Windows系だとCR/LFなので"\r\n",UNIX系だと"\n"です。 - 別に正しく指定しなくてもAthena自体は問題なく動作するはずです。 - (login/) - login2.c - (char/) - char2.c/int_storage.c/int_party.c/int_guild.c - 保存する改行コードをRETCODE依存に変更。 - 改行コードに依存せずに読めるように修正。 - -・クライアントから不明なパケットが来たらダンプするように - ・#define DUMP_UNKNOWN_PACKET 1 をコメント化すればダンプしません。 - - clif.c - 不明パケットの処理でダンプ処理を追加。 - -・ギルド機能の追加 - ・エンブレム変更/告知変更実装 - ・guild.txtの書式が変わりましたが、前のデータも読み込めるはずです - - (char/) - int_guild.c/inter.c - ギルドパケット処理、パケット長 - (map/) - guild.c/guild.h - 機能追加 - intif.c/intif.h - ギルド関係パケット追加 - clif.c/clif.h - ギルド関係パケット追加 - ----------- -//0309 by C}{RIS - -・ボウリングバッシュを範囲攻撃化しました。 -・プロンテラに装備品販売NPCを追加しました。 - map_athena1.cnfの - npc_shop1J.txtをコメントアウトすれば無効に出来ます。 -・アイテムの名前とIDを書いたテキストファイルを添付。(item.list) - ----------- -//0308 by 死神 -・自然回復のプログラムを修正しました。 - これで大丈夫だといいですが... - pc.c - pc_natural_heal()等を修正。 - pc_percentheal()を少し修正。 - pc_checkskill()を少し修正。スキルがない場合0を返すように - 変更しました。他の.cファイルも修正する必要がありましたので - 修正しました。 -・4人目と5人目のキャラを消せない問題を修正。 -・始めからナイフとコットンシャツを持つように変更。 -・LOOK_SHEILDをLOOK_SHIELDに修正。 -・mmo_charstatusのsheildをshieldに修正。 -・.logファイルやaccount.txtファイルをnotepadで開くと列が全部繋いでいる - 問題を修正。 -・乱数を時間によって初期化するように変更。 - map.c - do_init()を少し修正。 - -他に変更したファイルもありますが全部覚えてませんので... - ----------- -//0307 by 胡蝶蘭 - -・新規PCの初期位置をchar_athena.cnfに書けるようにした - start_point: マップ名,x,y のように指定します。 - <例> start_point: new_1-1.gat,53,111 - - (char/) - char2.c - -・ギルドの一部機能 - ・ギルド作成くらいしか動きません - ・勧誘/脱退/解散/情報の変更/エンブレム/告知などはすべて未実装です - - <切実な要望> - ギルド関係のパケット情報が全然足りません。わかる人は教えてください。 - 現在のままではエンブレムと告知くらいしか実装できない可能性が…。 - - (common/) - mmo.h - ギルド関係の構造体と定数追加 - (char/) - inter.c - パケット長情報追加 - int_guild.c/int_guild.h - 実際の処理追加 - (map/) - map.h - struct map_session_dataにギルド関係のメンバ追加 - guild.c/guild.h - 新規追加。ギルド機能用 - pc.c - pc_authok()でギルド所属時、guild_request_info()を呼ぶように。 - clif.c/clif.h - ギルドパケット追加 - intif.c/intif.h - ギルドパケット追加 - -・0303での修正「MAXHPなどがサーバーとクライアントで〜」を元に戻した - ・新PCを作るときに正しくHPなどを計算してくれるようになったので - 戻しても平気だろうと予測。 - ・ログイン直後に重量警告が出てしまうため。 - - pc.c - pc_authok()の修正 - -・範囲指定沸きの処理修正 - ・できるだけ指定した数と同じだけ沸くように - (障害物などによる沸き妨害の回避失敗時、前の回避結果を使う) - - mob.c - mob_once_spawn_area()の修正 - ----------- -//0305 by いど -・新規PCの位置を初心者修練場に変更。 -・map鯖がchar鯖に接続できない不具合の修正。 - ----------- -//0304 by 死神 -・自然回復の量と時間を変更。韓国鯖に適用されてる物ですが日本にも - 適用されてるはずです。(多分... やってませんのでわかりません。汗) - HPは毎4秒に 1 + vit/6 + max_hp/200 を回復、 - SPは毎8秒に 1 + int/6 + max_sp/100 を回復します。 -・スキルHP回復力向上による回復を - スキルレベル*5 + max_hp/50に変更。 -・スキルSP回復力向上による回復を - スキルレベル*3 + max_sp/50に変更。 -・スキル移動時HP回復実装。 - 今の所止まってるのと比べて1/4の量を回復します。(時間は同じです。) -・vitとintによって回復時間が短くなるのではなく回復量が増えます。 -・最大HPと最大SPの計算公式を変更。 - map.h - int inchealtickの変わりにint inchealhptick;と int inchealsptick;を追加。 - int parame[6] を追加。最大SPの計算の為の物で装備によって上がった - パラメータを持っつ。 - pc.c - pc_hpheal(),pc_spheal(),pc_natural_heal_sub(),pc_natural_heal()を - 自分のコードに書き換えましたが一応正常に動きますが - 他のコードに影響がないかどうかはわかりません。 - pc_additem()を少しだけ修正。 - hp_coefficientをintからdoubleに変更。 - pc_calcstatus()とpc_readdb()を修正。 - job_db1.txt - 職業の計数を変更しました。(クルセイダー等のデータは - 完全な物じゃありません。) - -・char2.cを少しだけ変更。 - char2.c - make_new_char()を少しだけ変更。(作った直後にHPとSPが完全に - 回復してるように変えました。) - parse_char()を少しだけ修正。韓国のクライアントで繋いても - 異常がないようにしました。(0x187パケットの処理を入れただけ - ですが... これはYareから持ってきた物です。) -・strcmpi等のdefineをatcomand.hからmmo.hに移動しました。 - atcomand.h, mmo.h 修正。 -・回復アイテムを使用する時vitとスキルHP回復力向上によるボーナスが付く - ように変更。ボーナスは - 回復量 *(1 + HP回復力向上スキルレベル*0.1 + vit/100) - になります。 -・イグドラシルの実とイグドラシルの種を仮実装。(回復はしますがエフェクトが - 出ません。item_dbでタイプを変えても駄目でした。) - script.c - buildin_fixheal()とbuildin_percentheal()を追加。 - buildin_fixheal()はbuildin_heal()がスキルとvitによって回復量が変わる - 仕様になったので元のbuildin_heal()の名前だけを変えた物です。 - buildin_percentheal()は入力された数字を%としてHPとSPを最大HPと - 最大SPを %比率に回復します。 - スクリプトfixheal 、 percentheal 追加。使用方法はhealと同じです。 - fixhealはvitとスキルHP回復力向上によるボーナスがない物で - percentheal は後の数字を %に認識します。 - pc.h - pc.c - pc_percentheal()を追加。 - item_db.txt、item_db2.txt - イグドラシルの実とイグドラシルの種を変更。 - ----------- -//0303 by 胡蝶蘭 - -・*.grfのパスをmap_athena.cnfにも書けるようにした。 - ・map_athena.cnfに「data_grf: ../data/data.grf」や - 「sdata_grf: ../sakurai/sdata.grf」のようにパス指定できます。 - ・grf-files.txtがある場合そちらの設定が優先されます - - (common/) - grfio.c/grfio.h - grfio_setdatafile(),grfio_setsdatafile()追加。 - data_file,sdata_fileをファイルローカルなグローバル変数に変更。 - -・@stpoint,@skpointに負値指定の範囲チェックを追加 -・@zenyコマンド追加(ゼニーの調整) -・@str,@agi,@vit,@int,@dex,@lukコマンド追加(基本パラメータ調整) - - atcommand.c - @stpoint,@skpoint修正 - @zeny,@str,@agi,@vit,@int,@dex,@luk追加 - -・メマーナイトを使うとぼったくられていた問題を修正 -・武器製造部分のコードを多少変更 - ・材料消費処理をアイテムが複数インデックスに分かれている場合に対応させた - (3万個限界を超えると別インデックスを使う仕様だった気がするので) - ・失敗時にも周りに通知するようにした - - skill.c - skill_check_condition()の修正 - skill_produce_mix()の修正 - -・武器製造確率をconfファイルで倍率指定できるように修正 - - (conf/) - battle_athena.cnf - weapon_produce_rate追加 - (map/) - skill.c - skill_produce_mix()の修正 - -・武器ATKサイズ補正テーブルを外部から読み込むようにした -・精錬成功確率/精錬ボーナスなどを外部から読み込むようにした -・過剰精錬ボーナスによる追加ダメージ実装 - - (db/) - size_fix.txt - サイズ補正テーブル - refine_db.txt - 精錬関係データ - (map/) - pc.c - pc_readdb()で読み込み - battle.c - battle_calc_weapon_attack()に過剰精錬ボーナス処理追加 - -・MAXHPなどがサーバーとクライアントで違う値に見えるバグ修正 - ログイン直後のステータス計算の結果を直ちに送信するようにした - - (map/) - pc.c - pc_authok()でのpc_calcstatus()のフラグを0にした - これでpc_calcstatus()のフラグパラメータは未使用? - -・item_dbの「忍者ス−ツ」を「忍者スーツ」に修正 - (db/) - item_db.txt/item_db2.txt - 忍者スーツの名称変更 - -・ログイン人数を調べるツールを添付 - Perl製なので実行にはPerlが必要です。 - 使用方法などはエディタで開いて見てください。 - 使い方が良くわからない人は手を出さないほうがいいです。 - - (tool/) - getlogincount - ログイン人数所得Perlスクリプト - ----------- -//0302 by 死神 -・アイテム製造 確率判定実装。 - 鉄の場合成功率は - (20 + base_level*0.3 + DEX*0.2 + LUK*0.1 + 要求スキルレベル*6)% - 鋼鉄と属性石、星のかけらの場合 - (10 + base_level*0.3 + DEX*0.2 + LUK*0.1 + 要求スキルレベル*5)% - 武器は - ((2.5 + base_level*0.15 + DEX*0.1 + LUK*0.05 + 要求スキルレベル*5 + - 金敷 - 属性石と星のかけら) * (1 - (武器レベル - 1)*0.2) + - スキル武器研究レベル*1)% - 金敷: ない場合 -5%で金敷は 0%、オリデオコンの金敷は - 2.5%、黄金の金敷は 5%、エンペリウムの金敷は 7.5% - 属性石と星のかけら: 属性石がある場合 5%で更に - 星のかけらの数 * 5%を足します。 - になりますがちょっと確率が低すぎる気もしますので - base_level*0.3 + DEX*0.2 + LUK*0.1をbase_level*0.5 + DEX*0.4 + LUK*0.3に - base_level*0.15 + DEX*0.1 + LUK*0.05をbase_level*0.4 + DEX*0.3 + LUK*0.2 - 程度に変えた方がいいかも知りません。 - skill.c - skill_can_produce_mix() と skill_produce_mix() を修正。 - produce_db.txt - 星のかけらをスキル属性石製造が必要に変更。 -・*.grf等を設置せずディレクトリからの読み込むように修正。(これはYareから - 持ち込んだ物ですが...) - grfio.c - grfio_init()を修正。 - grf-file.txt - 新規追加。grfファイルがあるディレクトリ設定用。 -・読み込むマップの最大数を512に修正。 - mmo.h - MAX_MAP_PER_SERVERを384から512に修正。 -・pc.cにpc_search_inventory()を追加。 - 機能はitem_idのアイテムを持ってるかどうかを確認して - 持ってる場合そのindexを返す。 - item_idが0の場合は空けてる所のindexを返す。 - pc_additem()とpc_takeitem()だけを少し修正。 -・GMコマンドに@stpointと@skpointを追加。 - @stpoint 数字 - ステータスポイントを上げる。 - @skpoint 数字 - スキルポイントを上げる。 - atcomand.c - 修正。 - atcomand.h - strcmpi等をLinuxでも使えるように修正。 - ----------- -//0301 by 胡蝶蘭 - -・最大HPが32767を超えると異常な値になる問題の修正 -・Lvが99を超えるときもエフェクトを出すようにした(自分には見えない模様) -・配置MOBによるイベントでイベント名が4バイト以上という制限をつけた -・teleport時に取引中断、チャット退室、倉庫保存処理をするようにした - - pc.c - pc_calcstatus()の修正(HP計算) - pc_setpos()の修正(取引中断など) - clif.c - clif_set0078(),clif_set007b(),clif_spawnpc()の修正(Lv99エフェクト) - npc.c - npc_parse_mob()の修正 - -・@hでhelp.txtが読めないときに落ちるバグ修正 -・@lvup/@joblvupで負値を入れるとLvダウンが可能になった - - atcommand.c - @h,@lvup,@joblvup処理の修正 - -・テレポートなどの消滅エフェクトの修正 - - skill.c - テレポの消滅エフェクトを変更 - -・状態異常に関するスクリプト実装 [sc_start]と[sc_end]。 -・緑POT、緑ハーブなど実装 -・装備ボーナスデータ追加 - - (db/) - item_db.txt/item_db2.txt - 装備ボーナスデータを追加 - 緑POT、緑ハーブなどのスクリプト追加 - (map/) - script.c - buildin_warp()で消滅エフェクトを変更 - buildin_sc_start(),buildin_sc_end()追加 - ----------- -//0299 by 胡蝶蘭 - -・NPCイベントでエクスポートされたラベルを指定できるようにした - NPCスクリプトでOn〜で始まるラベルを定義すると、エクスポートします。 - NPCイベントで"NPC名(orイベント名)::ラベル名"とすると、 - 指定したラベルから実行できます。 - ラベル名は24バイト以内にして下さい。 - あとプログラム的にメモリ効率悪いです。後日修正予定 - <例> - NPC「test」のスクリプト内で OnEvent: とラベル定義した場合、 - NPCイベント「test::OnEvent」で指定位置から実行できます。 - - (conf/) - npc_test_ev.txt - ラベル指定のサンプルもちょこっと追加 - (map/) - script.c/script.h - script_get_label_db()などの追加。 - parse_scriptでscriptlabel_dbにラベルデータを追加する - npc.c/npc.h - npc_event_export()など追加 - npc_parse_scriptでラベルデータをエクスポートする - map.h - struct map_session_data のeventqueueのイベント名のサイズを - 50バイトにした。 - -・AGIとDEXによるASPD計算の最大値を180から190に変更 - pc.c - pc_calcstatus()のASPD計算修正 - -・skill_db.txt/cast_db.txtの読み込みをskill.cに変更 - - pc.c - pc_readdb()の修正 - skill.c - skill_readdb()の追加 - -・アイテム製造仮実装 - 確率判定が未実装です。必ず成功します。 - - (db/) - item_db.txt/item_db2.txt - アイテム製造に対応(携帯用溶鉱炉、金槌など) - produce_db.txt - 新規追加。製造リスト。 - (map/) - skill.c/skill.h - struct skill_produce_db追加 - skill_readdb()でproduce_db.txtを読むように - clif.c/clif.h - clif_skill_produce_mix_list(),clif_parse_ProduceMix()追加 - script.c/script.h - 製造用コマンド[produce]作成。 - 引数は製造用数値で、1-4が武器製造(Lv)、16が鉱石 - - ----------- -//0298 by 胡蝶蘭 - -・Login鯖のパスワード暗号化タイプを自動認識できるように変更 - login.hのPASSWORDENCを3にすると自動認識します。 - 最初にpasswordencryptでチェックし、失敗すれば - passwordencrypt2でチェックします。 - - (login/) - login2.c/login.h - 暗号化パスワードの照合部分を修正 - -・アカウント作成ツールを添付 - Perl製なので実行にはPerlが必要です。 - 使用方法などはエディタで開いて見てください。 - 使い方が良くわからない人は手を出さないほうがいいです。 - - (tool/) - addaccount - アカウント作成ツールPerlスクリプト - -・スキルの追加修正 - ・ファイヤーウォールの回数制限をグループ毎からユニット毎に修正 - ・クァグマイア仮実装 (敵の移動速度、キャラの表示数値は変化せず) - ・ウォーターボール仮実装(動作が正しいのか不明) - ・フロストノヴァ仮実装(エフェクトが良くわからないので適当) - ・ベノムダスト仮実装(範囲とかが正しいかどうか不安) - ・プロボック、オートバーサーク、聖体降福、砂まき、石投げの実装 - ・エンチャントポイズンの毒付与実装 - - *注意* 毒状態は見た目だけで効果は未実装 - - (db/) - skill_db.txt - 砂まき/石投げ/ウォーターボールなど修正 - (map/) - skill.c/skill.h - 色々修正 - mob.c/mob.h - mob_target()追加。MOBのタゲ用 - battle.c - battle_get_*()系修正など - pc.c - pc_calcstatus()修正 - ----------- -//0297 by 胡蝶蘭 - -・Login鯖がパスワード暗号化に対応 - 暗号化keyは鯖起動時に一度だけ作成します。 - - **注意** - 暗号化パスワードを使っている場合は、アカウントを作成できません。 - アカウントを作る場合はclientinfo.xmlを編集するなどして、 - パスワードを暗号化しないクライアントを使う必要があります。 - - (login/) - login2.c/login.h - 暗号化パスワードのパケット処理追加 - 暗号化keyの生成処理追加 - md5calc.c/md5calc.h - 新規追加。md5計算用 - - -・スキル使用ディレイにDEXが反映されないように修正 - skill.c - skill_delay_fix()の修正 - -・死亡後も一部の状態異常の効果が持続する問題を修正 - pc.c - pc_damage()で死亡時にpc_calcstatus()を呼ぶように修正 - atcommand.c - 死亡時処理を一本化するため@dieではpc_damageを呼ぶように修正 - - ----------- -//0295 by 胡蝶蘭 - -・クレイモアートラップなどにスキルを使うとマップ鯖が落ちる問題の修正 - - battle.c - battle_get_*()などでBL_PC,BL_MOBじゃないときの処理を追加 - skill.c/skill.h - skill_unit_ondamage()追加 - -・約21Mzを超えるアイテムをNPCで扱うときOC,DC計算で値段がおかしくなるバグ修正 - DCでは20Mz、OCでは70Mzを超えるアイテムはdouble型にして計算します - - pc.c - pc_modifysellvalue(),pc_modifysellvalue()の修正 - ----------- -//0294 by 胡蝶蘭 - -・スクリプトコマンドでエリア指定のMOB沸き命令を作成 - areamonster "マップ名",x0,y0,x1,y1,"MOB表示名",MOBのclass,数,"イベント名" - 座標指定が(x0,y0)-(x1,y1)の任意ポイントになるだけで他はmonster命令と同じです - - script.c - buildin_areamonster()追加 - mob.c/mob.h - mob_once_spawn_area()追加 - -・アイスウォールの鯖側処理仮実装 - 攻撃できないなどの問題はあるものの、鯖側ではとりあえず動きます。 - ただ、クライアントに進入不可能エリアを教えるパケットがわからないので、 - 鯖側ではIWの回り込みを行う場合でも、クライアント側ではすり抜けている - ように見えます。 - - skill.c - 該当処理追加など - ----------- -//0293 -・2-2次職のスキルコメントの修正(一部追加) - (db/) - skill_db.txt - skill_tree.txt - - ----------- -//0292 by 胡蝶蘭 - -・SHOP NPCに話し掛けるとNPCが反応しなくなる問題のまともな?修正Part2 - ・売買できなかった問題修正 - - map.h - struct map_session_data にnpc_shopidメンバ追加 - npc.c - npc_click()など修正 - -・スクリプト命令追加 - ・指定エリアのユーザー数の所得 - getareausers("マップ名",x0,y0,x1,y1) - 指定マップの(x0,y0)-(x1,y1)にいるPCの数を計算 - ・指定エリアのユーザーのワープ - areawarp "転送元マップ名",x0,y0,x1,y1,"転送先マップ名",x,y; - 指定マップの(x0,y0)-(x1,y1)にいる全PCを指定マップの(x,y)に転送。 - - script.c - buildin_areawarp(),buildin_getareausers()追加 - -・スキル修正 - ・テレポート使用時に「テレポート!!」と叫ぶように。 - ・ストーンカースの成功率が低いのを修正 - - skill.c - skill_castend_nodamage_id()修正 - ----------- -//0291 by 胡蝶蘭 - -・スクリプト命令追加 - ・NPCの有効無効が切り替えられるようになりました - disablenpc "NPC名"で無効化、enablenpc "NPC名"で有効化。 - NPC名が重複しているときの動作は不定です。 - 主にワープポイントを無効化するときに使います。 - - ・タイマーのカウントを変更するスクリプト命令追加 - addtimercount "イベント名",ミリ秒 - で、タイマの期限を延ばせます(負値を指定して減らすことも出来ます) - - ・アナウンスの拡張 - mapannounce "マップ名","アナウンス文字列",フラグ - で指定マップにアナウンスを流します。フラグは0で黄色、16で青です。 - areaannounce "マップ",x0,y0,x1,y1,"文字列",フラグ - で指定マップの(x0,y0)-(x1,y1)のエリアにアナウンスを流します。 - フラグはmapannounceと同じで、0で黄色、0x10で青です。 - - (conf/) - npc_test_arena.txt - サンプルの修正 - (map/) - script.c - buildin_disablenpc(),buildin_enablenpc(), - buildin_mapannounce(),buildin_areaannounce(), - buildin_addtimercount()の追加 - npc.c/npc.h - NPCの有効無効処理追加 - map.h - struct npc_dataにflagメンバ追加(1ビット目が無効フラグ) - clif.c - clif_getareachar_npc()の修正 - pc.c/pc.h - pc_addeventtimercount()追加 - -・SHOP NPCに話し掛けるとNPCが反応しなくなる問題のまともな?修正 - SHOP NPCと取引中でもイベントが起こるようになります。 - これはROの仕様上避けるのが難しいためこのような結果で落ち着きました。 - - npc.c - npc_click()等の修正 - -・スキッドトラップで残像が残る問題修正 - skill.c - skill_blown()でclif_walkok()などを呼ぶように。 - skill_unit_onplace()のclif_fix*pos()を削除。 - ----------- -//0290 by 胡蝶蘭 - -・スクリプトでMAP鯖内共有変数が使えるようになりました。 - 変数名を$で開始すると、MAP鯖内の全員で共有する変数になります。 - - 言葉の問題ですが、PCのglobalregは「大域的」というより「永続性のある」 - 変数であって、MAP鯖内共有変数のほうが大域的ってイメージが強いんですが… - - script.c - mapval_db定義 - buildin_set(),buildin_input()の修正 - do_init_script()追加 - map.c - do_init()でdo_init_script()を呼ぶように。 - -・イベントキューが実装されました - ・キューサイズは2です。必要なら増やしますが。 - - サンプルの[ev_doテスト]がちゃんと動くようになったと思います。 - - map.h - struct map_session_dataにeventqueueメンバ追加 - npc.c - npc_event_timer()追加 - script.c - run_script()でEND処理でキューの処理追加 - -・スクリプトでタイマーが使用できるようになりました - 使用方法は、addtimer ミリ秒,"イベント名" でタイマー追加、 - deltimer "イベント名" でタイマー削除。 - - (common/) - timer.c/timer.h - get_timer(),addtick_timer()追加 - (map/) - map.c/map.h - struct map_session_dataにeventtimerメンバ追加 - map_quit()でpc_cleareventtimer()を呼ぶように。 - pc.c - pc_addeventtimer(),pc_deleventtimer(),pc_eventtimer(), - pc_cleaereventtimer()追加 - pc_authok()でeventimerの初期化 - script.c - buildin_addtimer(),buildin_deltimer()追加 - -・スクリプトの追加 - ・getusers,getmapusers,killmonsterの追加 - getusers(x)はユーザー数所得、x=0でPCのMAP,1=全MAP,8=NPCのMAP。 - getmapusers("マップ名")は指定マップのユーザー数を所得する。 - killmonster "マップ名","イベント名"で該当のマップにいる、 - 該当のイベント駆動指定モンスターを全て削除。 - ・announceコマンド拡張 - フラグの0x08ビットが1ならマップやエリア計算にPCでなくNPCを使う - - mob.c/mob.h - mob_delete()追加 - script.c - buildin_getusers(),buildin_getmapusers(), - buildin_killmonster()追加 - clif.c/clif.h - clif_GMmessage()の引数変更 - -・イベントサンプル追加 - 簡単なアリーナのサンプルを追加。 - - (conf/) - npc_test_ev.txt - 従来のサンプルの修正 - npc_test_arena.txt - 簡単なアリーナのサンプル - ワープポイントの無効化コマンドなどが必要と思われる。 - -・SHOP NPCに話し掛けるとNPCが反応しなくなる問題修正 - - npc.c - npc_buylist(),npc_selllist()修正 - ----------- -//0289 by 胡蝶蘭 - -・イベント駆動型スクリプトの修正など - ・他のNPCに話し掛けているときはイベントが無視されるようになりました - =>キューに入れるなどの処理がいると思われる。 - - この関係で、サンプルの[ev_doテスト]NPCをクリックしても - IDエラーが出て何も起きません。イベントキューを作れば直るはず。 - - npc.c - npc_event(),npc_click()にnpc_idチェックを追加 - script.c - 終了時にnpc_idをクリアするように - -・スクリプトコマンド[announce]の追加 - ・GMメッセージによるannounce。 - 第1引数は文字列、第2引数はフラグで、 - フラグの下位4ビットが0=全て、1=同じマップ、 - 2=画面内、3=自分のみ、4=同じマップ鯖に送信。 - フラグの4ビット目は色フラグで、0x10=青、0x00=黄色 - - script.c - buildin_announce()の追加 - clif.c - clif_send()でSELFの処理追加 - clif_GMmessage()の引数変更 - intif.c - intif_GMmessage()の引数変更 - -・メモ禁止、テレポ禁止、セーブ禁止マップが指定できるようになりました。 - ・NPCで、mapflagというタイプで、名前を nomemo 、 noteleportで - メモとテレポ禁止。nosave で、引数にセーブするマップ名と座標を指定。 - - 詳しくは同梱のconf/npc_test_ev.txtを参照。 - - (conf/) - npc_test_ev.txt - 修正 - (map/) - map.h - struct map_data にflag,savemap,savex,saveyメンバ追加 - npc.c - npc_parse_mapflag()追加 - do_init_npc()の修正 - pc.c - pc_memo()でメモ禁止かどうかを確認 - pc_makesavestatus()でセーブ禁止ならマップを変更 - pc_randomwarp()でテレポ禁止かどうか確認 - skill.c - テレポとポタでテレポ禁止か確認 - - -・ファイヤーウォールで落ちる問題修正…だといいな - - skill.c - さらにチェックを追加 - skill_blown()に落ちる原因っぽいもの発見したので修正 - ----------- -//0288 by 胡蝶蘭 - -・自動鷹発動時に「ブリッツビート!!」と叫ばなくなりました - skill.c - skill_attack(),skill_additional_effect(), - skill_castend_damage_id()の修正 - -・イベント駆動型スクリプトが記述できるようになりました -・モンスターを倒したときにイベントスクリプトを動かせるようになりました - - NPC定義のscriptで表示クラスを-1にするとイベント扱いになります。 - NPC定義のmonsterにイベント名を設定できます。 - スクリプトのmonsterコマンドにイベントを起こす引数追加。 - 詳しくはサンプルを見てください。 - 今後タイマーでイベントを起こせるようにしようと思っています。 - - 現状では、NPCウィンドウ操作中にイベントがおきて、 - そのイベントのスクリプトでNPCウィンドウを出すと問題が起きます。 - この辺は今後の課題ということで。 - - (db/) - item_db.txt/item_db2.txt - monsterコマンドの変更による修正(古木の枝)。 - (conf/) - npc_test_ev.txt - サンプル - (map/) - npc.c - npc_event()追加 - npc_parse_script()修正 - npc_checknear()修正 - clif.c - clif_getareachar_npc()修正 - map.h - struct mob_dataにnpc_eventメンバ追加 - mob.c/mob.h - mob_once_spawn()の引数変更 - mob_damage()で死亡時にイベントを起こすように - atcommand.h - mob_once_spawn()の引数変更 - script.c - buildin_monster()の修正 - ----------- -//0287 by 胡蝶蘭 - -・モンスター情報スキルでHPが65535を越えていると正常な値が見れないバグ修正 - - clif.c - clif_skill_estimation()の修正 - -・古木の枝アイテムでクライアントがリソースエラーを出す問題が修正されました -・古木の枝アイテムで召喚できる敵が指定できるようになりました - - (db/) - mob_branch.txt - 召喚可能な敵のリスト - (map/) - mob.c/mob.h - struct mob_dataにsummonflagメンバ追加。召喚可能性。 - mob_once_spawn()の修正 - mob_readbranch()の追加 - do_init_mob()でmob_readbranch()を呼ぶように。 - -・古く青い箱、古い紫色の箱が実装されました。 - 一部の未実装アイテムも出ます。item_db.txtにあるデータを検索しています。 - スクリプトgetitemで負の値を指定すると、その絶対値をフラグとして - ランダムにアイテムを選択します。 - - (db/) - item_db.txt/item_db2.txt - 該当部分のスクリプト修正 - (map/) - script.c - buildin_getitem()の修正 - itemdb.c/itemdb.h - itemdb_searchrandomid(),itemdb_searchrandomid_sub()追加 - -・詠唱データの一部修正 - (db/) - cast_db.txt - 速度上昇などの修正 - -・NPCの向き修正など - (conf/) - npc_*.txt - ----------- -//0286 by 胡蝶蘭 - -・モンスター情報スキルでクライアントが落ちるバグ修正 - clif.c - clif_skill_estimation()の修正 - -・詠唱反応モンスターが反応しないことがある問題を修正 - skill.c - skill_use_id(),詠唱反応時、最低追跡距離を13に設定するように。 - -・スクリプトコマンド[warp]でセーブポイント移動やランダム移動が可能になりました -・ハエの羽、蝶の羽アイテムが実装されました - スクリプトwarpでマップ名に"SavePoint"や"Random"が指定できます。 - - (db/) - item_db.txt/item_db2.txt - ハエの羽、蝶の羽のスクリプト修正 - script.c - buildin_warp()の修正 - -・@monsterコマンドによるMOBが復活しないようになりました -・スクリプトコマンド[monster]でMOBを発生させることができるようになりました -・古木の枝アイテムが実装されました - - スクリプト引数は monster マップ名,x,y,MOB名,MOBのID,数 です。 - マップ名が"this"の場合、スクリプトを実行したプレイヤーのいるマップ、 - x,yが-1ならプレイヤーの座標(どちらか一方のみそろえることも可能)、 - MOB名が"--en--"の場合、本来の英語名になり、"--ja--"の場合、 - 本来の日本語名になります。MOBのIDが-1の場合、適当なIDになります。 - - (db/) - item_db.txt/item_db2.txt - 古木の枝のスクリプト修正 - (map/) - mob.c/mob.h - mob_once_spawn()追加 - mob_setdelayspwan()で復活禁止処理追加。 - npc.c/npc.h - npc_get_new_npc_id()追加 - script.c - buildin_monster()追加 - atcommand.c - @monsterの修正 - -・@itemコマンドの修正(装備品などの問題) - - atcommand.c - @itemの修正 - ----------- -//0284 by 胡蝶蘭 - -・障害物があると遠距離攻撃ができなくなりました -・対地スキルが障害物上に使用できなくなりました - - path.c - path_search(),can_move()の修正、can_place()の追加 - battle.c/battle.h - battle_check_range()追加、射程と障害物判定。 - battle_weapon_attack()でbattle_check_range()を呼ぶ。 - skill.c - skill_use_id()、skill_use_pos()でbattle_check_range()を呼ぶ。 - mob.c - mob_ai_sub_hard()の処理を修正 - -・詠唱反応/リンクモンスターが実装されました - skill.c - skill_use_id()に詠唱反応モンスの処理追加 - mob.c - mob_ai_sub_hard_linksearch()の追加 - mob_ai_sub_hard()にリンク処理を修正 - ----------- -//0283 by れあ -・リザレクションの修正 - 0282で生きてるPCにリザがかけれるのに、 - 死んでるPCにはリザがかからなくなって - いたのを修正しました。 - ----------- -//0282 by 胡蝶蘭 - -・スキルの修正と追加実装 - ・キリエエレイソンのエフェクトの問題修正。 - ・リザレクションが生きているPCには掛けられないようになりました - ・ターンアンデッド/攻撃リザレクションがBOSSには効かないようになりました - ・ファイヤーウォールのヒット数制限を実装 - ・ストームガストの実装 - ただし、本鯖と違い凍結は確率のみで、最大ヒット数などが変です。 - - skill.c - skill_castend_nodamage_id()の修正 - ストームガストの処理追加 - -・スキルユニット処理に意地になって安全性チェックを追加。 - (落ちなくなる日は遠い??) - - map.h - MAX_SKILLUNITGROUPを32に増やした - skill.c - skill_status_change_*()にNULLチェック追加 - battle.c - battle_calc_damage()に生存チェック追加 - map.c - map_freeblock_unlock()にロック数チェックを追加 - -・その他修正 - ・PCの最大HPが30000に制限されました。 - ・PCの回復処理が修正されました - ・吹き飛ばし処理の修正 - ・0281のitem_db.txtの変更をitem_db2.txtにも適用 - - (map/) - pc.c - pc_heal(),pc_calcstatus()の修正 - path.c - path_blownpos()の修正 - (db/) - item_db2.txt - 0281の名前修正などを適用 - ----------- -//0280 by 胡蝶蘭 - -・管理者のシステムを作成 - "conf/login_athena.cnf"の作成、管理者パス、GMパスの設定。 - アカウントを作るとき、 - <例> ID: hoge_M Pass: foobar@admin - のように、パスワードの後ろに「@管理者パス」が必要に。 - login_athena.cnfのadmin_passの欄を消せば、今までのようにもつかえます。 - (その場合、admin_passの後ろだけでなく、行ごと消してください) - - (login/) - login.h - 設定ファイルのデフォルト名追加 - login2.c - アカウント作成のところを修正 - 設定ファイルの読み込み追加 - -・@GMコマンド復活 - ただし、「@gm GMパス」として使います。 - GMパスはlogin_athena.cnfのものです。 - 鯖の再起動の必要はありませんが、 - クライアントはリログする必要があります。 - - <注意> - 同じアカウントの全てのキャラはPTから抜けて置いてください。 - また、倉庫のアイテムは全部引き出して置いてください。 - そうしないとゴミデータが残ります。 - - (login/) - login2.c - アカウントID変更処理追加 - (char/) - char2.c - アカウントID変更処理追加 - (map/) - chrif.c/chrif.h - chrif_changegm(),chrif_changedgm()追加 - -・@pvpoffコマンド復活 - clif.c/clif.h - clif_pvpoff()追加 - atcommand.c - @pvpoffの処理追加 - -・空の倉庫データは保存されないように変更 - (char/) - int_storage.c - inter_storage_save()、storage_tostr()を修正 - -・@memoコマンド追加。 - 任意の記憶域にメモを取れるようになりました。 - - atcommand.c - @memoの処理追加 - - ----------- -//0279 by 胡蝶蘭 - -・スキルユニット処理の問題対策 - とりあえずひたすらチェックを入れました。 - - skill.c - skill_unit_timer_sub(),skill_unit_move_sub(), - skill_delunit()にユニットの生存判定を追加。 - skill_unitgrouptickset_search(),skill_unitgrouptickset_delete() - skill_delunitgroup()にNULLポインタチェックを追加。 - -・スキルの追加実装と修正 - テレポート、ワープポータルの実装 - キリエエレイソンをMOBに掛けると落ちるバグ修正 - - (db/) - cast_db.txt - ワープポータルの詠唱時間設定 - (map/) - map.h - struct skill_unit_groupのvalstrをポインタに変更 - clif.c/clif.h - clif_parse_UseSkillMap(),clif_skill_warppoint()、 - clif_parse_Memo(),clif_skill_memo()追加 - skill.c/skill.h - skill_castend_map(),skill_unit_onlimit()の追加 - skill_unit_*系の処理いろいろ追加。 - skill_status_change_start()のキリエの処理修正 - pc.c/pc.h - pc_randomwarp(),pc_memo()追加 - ----------- -//0278 by nabe - -・スキルポイントを振ったときにステータスを更新 - pc.c - pc_skillup()でpc_calc_skilltree()の代わりにpc_calcstatus() -・所持量増加を修正 - pc.c - pc_calcstatus()の所持量増加によるmax_weight増分をskill*1000に - ----------- -//0277 by nabe - -・付属品(カート、鷹、ペコ)の付け外しを改良 - (conf/) - npc_event_rental.txt - 鷹、ペコを付けるスクリプトコマンドを変更 - (map/) - battle.c - battle_addmastery(),battle_calc_weapon_attack()で - ペコペコ騎乗時の槍攻撃力補正を実装 - clif.c - clif_parse_CartOffをclif_parse_RemoveOptionに変更 - pc.c/pc.h - pc_calcstatus()でカート、ペコペコ乗りによる速度変化を計算 - pc_setoption(),pc_setcart()改良 - pc_setfalcon(),pc_setriding()追加 - pc.hにpc_isfalcon(),pc_isriding()マクロ追加 - script.c - buildin_setfalcon() 鷹付加 - buildin_setriding() ペコペコ乗り - ----------- -//0276 by nabe - -・精錬NPC実装 - (conf/) - npc_town_refine.txt - 精錬NPCスクリプトファイル新規追加 - (map/) - pc.c/pc.h - 精錬成功率の表percentrefinery[5][10]を追加 - script.cから呼ばれる関数 - pc_percentrefinery() 精錬成功率 - pc_equipitemindex() 装備品インデックス - を追加 - script.c - buildin_getequipname() 装備名文字列(精錬メニュー用) - buildin_getequipisequiped() 装備チェック - buildin_getequipisenableref() 装備品精錬可能チェック - buildin_getequipisidentify() 装備品鑑定チェック - buildin_getequiprefinerycnt() 装備品精錬度 - buildin_getequipweaponlv() 装備品武器LV - buildin_getequippercentrefinery() 装備品精錬成功率 - buildin_successrefitem() 精錬成功 - buildin_failedrefitem() 精錬失敗 - を追加 - -・スクリプトにWeight,MaxWeightパラメータを追加 - const.txt - Weight,MaxWeightを追加 - -・スクリプトでのキャラ名表示方式を変更 - (conf/) - npc_job_merchant.txt/npc_job_thief.txt/npc_town_kafra.txt - mes "$charaname"; を mes strcharinfo(0); に変更 - (map/) - script.c - buildin_strcharinfo()を追加 - ----------- -//0275 by 胡蝶蘭 - -・MVPの実装 - MVPの判定にはdmglogを使ってます。すなわち与ダメだけが計算対象です。 - 被ダメは考慮されてません。 - 経験値は無条件で入り、確率でさらにアイテムが入ります。 - アイテムは複数手に入ることもあります。 - - clif.c/clif.h - clif_mvp_effect(),clif_mvp_item(),clif_mvp_exp()追加 - mob.c - mob_damage()にMVP処理追加 - -・スキルの追加実装と修正 - ・マグナムブレイク、アローシャワー実装 - ・吹き飛ばし系スキルが一部使用されないバグ修正 - ・ダブルストレイフィングのダメージ計算式修正 - ・武器攻撃系属性付きスキルで属性が反映されない問題修正 - ・場所指定スキルが攻撃しながら詠唱できた問題を修正 - - battle.c - battle_calc_weapon_attack()の該当個所修正&追加 - skill.c - skill_castend_damage_id()に処理追加 - skill_use_pos()に攻撃停止処理追加 - -・カードスキルがカードを外しても使用可能な問題を修正 - pc.c - pc_calc_skilltree()を修正 - -・アイテムドロップ率、exp所得倍率などの調整機能追加 - battle_athena.cnfで調整できる項目が増えました。 - 詳しくはそちらを参照してください。 - - (conf/) - battle_athena.cnf - mvp_hp_rate,item_rate,exp_rate,mvp_item_rate,mvp_exp_rate追加 - (map/) - battle.c/battle.h - 増えた項目を読み込むように処理追加 - mob.c - mob_db.txt読み込み時、データを調整する処理追加 - ----------- -//0274 by 胡蝶蘭 - -・スキルの追加実装 - スキッドトラップ、ランドマイン、ブラストマイン、クレイモアートラップ、 - フリージングトラップ、サンドマン、アンクルスネア - - 睡眠や凍結などの確率は適当です。 - 罠発動時のエフェクトが出ません。ていうか出し方がわかりません。 - わかる人は教えてください。もしくは本鯖で罠発動時の複合化済みの - 生パケットデータでもいいので教えてください。 - - (db/) - skill_db.txt - 属性の修正 - (map/) - skill.c - 該当個所 - battle.c/battle.h - battle_calc_misc_damage()の該当個所 - battle_stopwalking()追加 - clif.c/clif.h - clif_fixpcpos()追加 - clif_parse_WalkToXY()にアンクルで動けなくする処理追加 - mob.c - mob_ai_sub_hard()にアンクルで動けなくする処理追加 - -・装備などのクリティカルボーナスが1/10になっているバグが修正されました - battle.c - battle_calc_weapon_attack()に追加分を計算する処理修正 - -・ブリッツビートの計算式が全然違うバグが修正されました - battle.c - battle_calc_attack()のBF_MISCの処置が間違っていたのを修正 - -・SWとニューマが武器攻撃ならどんなレンジの攻撃でも防いでいた問題を修正 - battle.c - battle_calc_damage()のレンジ判定を修正 - -・オーバートラストとウェポンパーフェクションがPTメンバにもかかるように修正。 - 効果は使用者とPTメンバで違いはありません。 - - skill.c - skill_castend_nodamage_id()の修正。 - ----------- -//0273 by 胡蝶蘭 - -・キャラクターが消失したり幻影が出る問題が修正されました - ・吹き飛ばしスキルを受けると発生していた - ・斜め以外の歩行で発生していた - - map.c - map_foreachinmovearea()の修正。 - skill.c - skill_blown()に表示範囲更新処理を追加。 - mob.c - mob_walk()で歩き終わったときに位置を再送信するように修正 - pc.c - pc_walk()で歩き終わったときに位置を再送信するように修正 - -・スキルの追加実装と修正 - ファイヤーウォール、ファイヤーピラーの実装 - サンクチュアリでのノックバック方向を修正 - - (db/) - skill_db.txt - ファイヤーピラー、ブリッツビートのヒット数修正 - (map/) - skill.c - skill_blown()に対象の向きによるノックバック処理追加 - その他必要な場所修正 - mob.c - mob_walk(),mob_attack()で向きを保存 - pc.c - pc_walk(),pc_attck()で向きを保存 - map.c - map_calc_dir()追加。相対的な方向を求める - - -・クリティカル増加装備が戦闘時に計算されてないバグが修正されました - battle.c - battle_calc_weapon_attack()に追加分を計算する処理追加 - - -・防御ユニット(SW/ニューマ)が敵に影響を及ぼすかどうかを - battle_athena.cnfで制御できるようになりました - デフォルトは「及ぼさない」です。 - - (conf/) - battle_athena.cnf - 項目defunit_not_enemyを追加 - (map/) - battle.c/battle.h - struct Battle_Config に defnotenemyメンバ追加。 - battle_read_config()の処理を修正。 - skill.c - skill_unitsetting()でSW/ニューマの処理を修正 - -・フェンカード装備時、死んでも詠唱が続くバグを修正 - (詠唱終了前に復活すれば魔法が発動する問題も修正になります) - - pc.c - pc_damage()で死亡時skill_castcancel()を呼ぶように修正 - -・敵味方判定処理にバグがあったのを修正 - battle.c - battle_check_target()の修正 - ----------- -//0272 by 胡蝶蘭 - -・スキルの追加実装と修正 - ・セイフティウォール、ニューマが実装されました。 - ・ロードオブバーミリオン発動中に効果範囲外から範囲内に入ってきたとき、 - 敵味方の区別無く攻撃が当たる問題が修正されました。 - ・サンクチュアリの射程が修正されました。 - ・範囲魔法で倒した敵がHP0で残る場合がある問題が修正されました。 - - (db/) - skill_db.txt - セイフティウォールとサンクチュアリの射程を8に変更 - (map/) - skill.c - skill_unit_onplace(),~ondelete(),~onout()などに、 - セイフティウォールとニューマの処理追加。 - skill_unit_move()にターゲットの敵味方判定を追加。 - skill_unit_timer_onplace(),~ondelete()にユニット生存判定を追加. - skill_clear_unitgroup()追加。ユニットグループの全削除をする。 - battle.c - battle_calc_damage()にセイフティウォールとニューマの処理追加。 - map_foreachinarea()など修正 - map.c - map_quit()でskill_clear_unitgroup()を呼ぶように。 - -・スキルの吹き飛ばし処理を実装 - ユピテルサンダー、サンクチュアリ、スピアスタブ、 - ボーリングバッシュ、チャージアローの吹き飛ばし処理実装 - - path.c/map.h - path_blownpos()追加 - battle.c/battle.h - struct Damageにblewcountメンバ追加 - battle_calc_*_damage()でblewcountをセットするように。 - skill.c/skill.h - skill_blown()追加。吹き飛ばし処理。 - skill_attack()でskill_blown()を呼ぶように。 - skill_attack()のflagの吹き飛ばしビットは未使用に。 - -・歩行中のモンスターに攻撃したとき、モンスターにディレイが入るようになりました - (攻撃のモーションの遅延を考えてないのであんまり意味がないかも?) - - (map/) - mob.c/mob.h - stateにMS_DELAYを追加。 - mob_damage(),mob_timer()などの修正 - -・歩行中のモンスターに攻撃したとき、位置がずれる問題の応急処置 - (まだ位置はずれるようです) - - clif.c/clif.h - clif_fixmobpos()を追加 - mob.c - mob_attack()でclif_fixmobpos()を呼ぶように。 - -・その他修正 - pc.c - pc_stop_walking()でpath_lenを初期化するように。 - ----------- -//0271 by れあ - -・PTに関して少しだけ修正 - 公平にしてからキャラを加入させると公平が解除されないバグを修正 - ----------- -//0270 by 胡蝶蘭 - -・スキルの追加実装と修正 - ロードオブバーミリオン、サンクチュアリ、マグヌスエクソシズム - - (db/) - skill_db.txt - マグヌスのヒット数、属性調整 - サンクチュアリの属性調整 - (map/) - map.h - struct map_session_dataの修正 - clif.c/clif.h - clif_skill_setunit(),clif_skill_delunit()、 - clif_getareachar_skillunit(),clif_clearchar_skillunit()追加 - clif_pcoutsight(),clif_pcinsight(),clif_getareachar()修正 - skill.c/skill.h - 忘れるほど多数変更。主にスキルユニット関連部分。 - pc.c - pc_authok()でskillunit,skillunittickを初期化するように。 - pc_walk()でskill_unit_move()を呼ぶように。 - mob.c - mob_spwan()でskillunittickを初期化するように。 - mob_walk()でskill_unit_move()を呼ぶように。 - battle.c/battle.h - battle_calc_magic_attack()修正 - battle_check_target()修正 - map.c - map_foreachobject()など修正 - -・こまかいバグ修正など - ・mobが回復しない問題修正 - - battle.c - battle_damage()修正 - ----------- -//0266 by 胡蝶蘭 - -・魔法計算式の修正 - 魔法倍率をダメージに掛けていたのをMATKにかけるようにしました。 - …こっちが正しいとしていいのかな?違うなら教えてください。 - - battle.c - battle_calc_magic_attack()の修正 - -・スキルの追加実装 - サイト、ルアフ、ロードオブヴァーミリオン - - ロードオブバーミリオンは3回の判定時に詠唱音が鳴ります…。 - clif_skill_damage()のtypeを色々変えてみましたがどうもうまくいきません。 - 直せる人は直してくれるとうれしいです。 - (うーん、ひょっとしたら本来はグラフィックのないスキルユニットを - 設置して、そのユニットのIDでダメージを与えるのかも??) - - (db/) - skill_db.txt - ロードオブバーミリオンのヒット数を3から10に変更。 - (map/) - skill.c - skill_status_change_timer_sub()追加。 - skill_status_change_*()に処理追加。 - -・blockのメモリ解放の安全性の向上 - map_foreachinarea,party_foreachsamemapで回っているときに - blockをチェインから削除すると、うまく回らない可能性がある問題修正。 - さらに、blockをメモリから解放すると危険な問題も修正。 - - ・foreach内で関数を呼ぶ前にblockがチェインから外れてないかチェック。 - ・foreachに入ったときにロックしてメモリから解放されないようにする。 - これはユーザーがfreeじゃなくmap_freeblockによって解放するように - プログラムする必要がある。(ループから呼ばれる可能性のある関数を作る - 場合のことで、普通はfreeでもいちおう動く。) - ・map_foreachinmoveareaについては改良していないが、 - このループでblockを削除することはありえない気がするのでいいとする。 - - これは今後を見越した改良であって、現在の不安定さを直すものではない。 - (現在はforeach内でメモリを解放していない…はずなので。 - ただ、スキルユニットなど一時オブジェクトを多用し始めると効果がある) - - map.c - map_freeblock(),map_freeblock_lock(),~_unlock()追加。 - map_delobject()のfree()をmap_freeblock()に置換。 - map_foreachinareaでロックと安全性チェック。 - party.c - party_foreachsamemap()でロックと安全性チェック - - -・スキルユニット機構実装 - 設置系のスキルのための機構実装。実際のスキルの実装はまだです。 - - skill.c - なんかもう色々追加しました。 - map.c - do_init()でdo_skill_init()を呼ぶように。 - map.h - struct skill_unit,skill_unit_groupなど追加。 - map_session_dataの書き換えなど。 - -・その他細かいところを修正したと思うけど忘れました。 - ----------- -//0264 by nabe - -・$charanameを喋るNPCと話した時、map鯖が落ちることがあるバグを修正しました。 - script.c - replacestr()がおかしかったのを手直ししました。 - ----------- -//0263 by nabe - -・露店開設中にカートアイテムを出し入れできないよう修正 - pc.c - pc_putitemtocart(),pc_getitemfromcart()に、露店判定を追加 - -・露店アイテム購入のチェックを追加 - vending.c - vending_purchasereq()で諸々の条件判定を追加 - ----------- -//0261 by 胡蝶蘭 - -・拡大鏡、イグドラシルの葉が実装されました - スクリプトにitemskillコマンド作成。一時的にスキルが使用できます。 - - (map/) - script.c - buildin_itemskill()の追加など。 - skill.c - アイテムスキルならSPなどを検査&消費しないように修正 - clif.c/clif.h - clif_item_skill()の追加。 - (db/) - item_db.txt/item_db2.txt - スキル使用アイテムのスクリプト修正 - -・パーティスキルの実装 - アンゼルス、マグニフィカート、グロリア、アドレナリンラッシュが - 画面内のパーティ全員に効果を及ぼすようになりました。 - - skill.c - skill_castend_nodamage_id()の該当個所の修正 - party.c - party_foreachsamemap()の修正 - -・スキル関係の修正 - キリエエレイソンが即時発動になっているのを修正。 - ストーンカースでエフェクトが存在しないバグ修正。 - - (db/) - skill_db.txt - キリエエレイソイン修正 - (map/) - skill.c/skill.h - skill_check_condition()追加。スキル使用条件検査の一本化。 - skill_castend_nodamage_id()でストーンカース修正 - -・スクリプトのコードを整理 - get_val()でconst.txtの定数を所得できるように修正。 - - (map/) - script.c - get_val()の修正(const.txtのtype==0の値が所得可能に) - bonus(),bonus2()などの修正。 - (db/) - const.txt - type=1である必要が無いものを0に。 - item_db.txt/item_db.txt - const.txtの変更に伴う修正。 - ----------- -//0260 by 胡蝶蘭 - -・戦闘関係の設定がファイルに書けるになりました - map鯖の第2引数にファイル名が設定されていると、それを使い、 - 設定されてない場合は "conf/battle_athena.cnf"を使います。 - - あと、一応範囲攻撃スキルについて説明。 - 鯖が常にPVPに設定されている場合、パーティメンバじゃないPCにも範囲攻撃が - あたります。嫌な場合はパーティを組むか、常にPVPをoffにして下さい。 - 常にPVPがoffでも、@pvpでpvpフラグを入れた人の間では攻撃が当たります。 - ただし、一度pvpをonにすると、リログするまでonのままなので注意。 - - (conf/) - battle_athena.cnf - 中に説明書いてるので各自好きなように書き換えてください。 - - (map/) - battle.c/battle.h - struct Battle_Configの定義。 - battle_config_read()など追加。 - skill.c - CASTFIX,DELAYFIXの廃止とBattle_Configによる修正の追加。 - atcommand.c - @pvpコマンドでpvpフラグをセットするように。 - (鯖設定の常にPVPがoffの時、両人がpvpをonにしてたら戦闘可能) - map.c/map.h - struct map_session_dataにpvp_flagを追加 - do_init()でbattle_config_read()を読むように。 - -・戦闘関係のコードが少し整理されました - battle.c/battle.h - battle_weapon_attack()追加。 - battle_calc_weapon_attack()の引数変更 - battle_calc_attack()を追加してbattle_calc_*_attack()を一本化。 - skill.c/skill.h - skill_weapon_attack(),~_magic_~(),~_misc_~()の廃止、 - skill_attack()に一本化。 - pc.c/mob.c - 攻撃処理をbattle_weapon_attack()に一本化。 - -・アイテム鑑定スキルを実装 - 商人のスキルの方です。虫眼鏡はまだです。 - - skill.c - スキル処理追加 - pc.c/pc.h - pc_item_identify()追加 - clif.c/clif.h - clif_item_identify_list(),clif_item_identified()追加 - clif_parse_ItemIdentify()追加 - -・スキルデータベースのコメント修正 - (db/) - skill_db.txt - 商人のスキルのコメントがずれていたのを修正 - ----------- -//0259 by れあ -・mob_db.txtの修正 - 亀島モンスターやBOSSのステータス調整 - 亀島モンスに適当にドロップを付けました。 - 本鯖と異なる物を落とす場合もあります。 - ----------- -//0258 by 胡蝶蘭 - -・パーティで一度公平にしたら各自所得に戻せないバグ修正 - (char/) - int_party.c - mapif_parse_PartyChangeOption()の判定修正 - -・スキルの追加実装(主に範囲攻撃系) - ナパームビート(分散対応)、ファイヤーボール、 - サンダーストーム、ヘブンズドライブ、 - ブリッツビート(自動鷹込み)、スチールクロウ - スキンテンパリング - - (db/) - skill_db.txt/skill_tree.txt - 一部修正 - (map/) - battle.c/battle.h - battle_check_target()を追加。対象になるかを検討する。 - battle_calc_magic_damage()の引数変更。ダメージ分散処理追加。 - battle_calc_misc_damage()追加。 - battle_calc_weapon_damage()修正。 - clif.c/clif.h - clif_skill_damage(),clif_skill_damage2()の引数変更。 - clif_skill_poseffect()追加。 - skill.c/skill.h - skill_weapon_attack(),skill_magic_attack()に微妙に処理を纏めた. - skill_area_sub()追加。範囲スキル用。 - skill_area_sub_count()追加。skill_area_sub()用、敵カウント。 - skill_castend_damage_id()修正。引数と処理を追加。 - skill_castend_nodamage_id()修正。引数と処理を追加。 - skill_misc_attack()追加。 - skill_additional_effect()修正(自動鷹) - skill_castend_pos()修正。 - skill_castend_pos2()追加。 - -・弓で攻撃したとき計算にDEXでなくSTRが使われる問題を修正。 - battle.c - battle_calc_weapon_damage()修正。 - ----------- -//0257 by 胡蝶蘭 - -・item_db.txtの職業フラグと、カードの装備個所フラグを修正 - 装備品はI-Athenaのデータを参考にして機械的にコンバートさせました。 - I-Athena側にない装備品は、あきらかに変なのは修正しましたが、 - 知らないものが多すぎて、ほとんど放置です。 - カードは、武器用カードの装備個所が0になってるのを2(左手)に修正。 - 両手武器の場合は別に判定してるので両手武器も問題ないはず。 - - (db/) - item_db.txt/item_db2.txt - 該当個所修正 - -・カード追加実装 - スタンなどの追加効果、それらへの耐性系統、オークヒーローカード実装 - - (db/) - item_db.txt/item_db2.txt - スクリプトの修正 - (map/) - map.h - struct map_session_dataにaddeffなどのメンバを追加 - pc.c - pc_calcstatus()、pc_bonus2()の修正 - pc_attack()でskill_additional_effct()を呼ぶように。 - skill.c/skill.h - skill_additional_effect()でカードによる判定追加 - skill_status_change_start()で耐性を付けた。 - battle.c - battle_calc_weapon_attack()でオークヒーローカード - (クリティカル耐性)の処理を追加 - -・回避判定の修正 - 攻撃者がPCの場合、最大命中率95%制限をなしにしました。 - battle.c - battle_calc_weapon_attack()を修正 - - -・完全回避を実装 - へんてこな処理してます&計算式適当です。 - - battle.c - battle_calc_weapon_attack()に処理追加。 - -・倉庫を開いたままログアウトしたときmap鯖内では開きっぱなしになってる問題を修正 - storage.c - storage_storage_quitsave()を修正 - -・@item,@monster,@produceで名前指定できるように変更 - 英語名、日本語名どちらでもOK。英語の場合は大文字小文字区別しません。 - - atcommand.c - 該当個所修正 - itemdb.c/itemdb.h - itemdb_searchname(),itemdb_searchname_sub()追加 - mob.c/mob.h - mobdb_searchname()追加 - -・@refineで上げる数値を指定できるように変更 - atcommand.c - 該当個所修正 - -・@produceによる製造時のエフェクトを正しいものに修正 - clif.c/clif.h - clif_produceeffect()追加 - atcommand.c - 該当個所修正 - -・露店スキル使用時の処理を少し修正 - skill.c - skill_castend_id()でなく、skill_castend_nodamage_id()で - 露店開設を呼ぶようにした。 - -・stricmpの変わりにstrcasecmpを使うようにした - (_WIN32か__EMX__が定義されているとstricmpを使います) - - (char/) - int_party.c - (map/) - itemdb.c/mob.c - マクロ定義の修正など - -・スキルを少し修正 - グリムトゥースがハイディングで使えない問題修正 - 武器研究の命中修正を実装 - - skill.c - skill_use_id()の修正 - pc.c - pc_calcstatus()で武器研究に従って命中修正 - ----------- -//0256 by nabe - -・露店アイテム購入のバグ修正 - clif.c - clif_vendinglist()で売り切れたアイテムは表示しないように - ----------- -//0255 by nabe - -・露店アイテム購入のバグ修正 - vending.c - vending_purchasereq()でzeny,weight部分修正 - ----------- -//0254 by nabe - -・露店を実装 - vending.c/vending.h - 新規追加。露店メイン処理 - skill.c - skill_castend_id()に露店開設スキル処理を追加 - clif.h/clif.h - 露店関連パケット処理を追加 - map.h - struct map_session_dataに、 - int vender_id; - int vend_num; - char message[80]; - struct vending vending[12]; - を追加 - ----------- -//0253 by 胡蝶蘭 - -・stricmp未定義エラーがでる環境用の修正 - エラーが出た場合、int_party.cの最初のマクロ定義のコメント化のうち、 - どちらかを外してやり直してみると、うまくいくかも。 - 最悪、下を有効にしたらうまくいくはず。(大文字小文字を区別するようになります) - - (char/) - int_party.c - コメント化済みのマクロ定義追加 - ----------- -//0252 by 胡蝶蘭 - -・カードの一部実装 - (ステータス変化全般、武器属性、スキルはすでに実装済み) - 防具属性、詠唱時間変化、属性攻撃耐性、種族耐性、種族追加ダメージ、 - 属性追加ダメージ、サイズ追加ダメージ、MAXHP、MAXSP増減、使用SP変化系、 - フェン、ドレイク、ホルン、深淵の騎士、黄金蟲、オシリスカードを実装 - - (db/) - const.txt - bonus用の定数追加、bonus2の定数も追加 - item_db.txt/item_db2.txt - カードのスクリプト追加 - (map/) - map.h - struct map_session_dataにhprateなど多数メンバ追加 - script.c - bonus2コマンド追加 - buildin_bonus2()追加 - pc.c/pc.h - pc_bonus2()追加 - pc_bonus()の処理追加 - pc_calcstatus()で各種追加メンバの初期化を行うようにし、 - hprateやsprateに従いmax_hp,max_spの調整もするように変更。 - pc_makesavestatus()でオシリスカード修正 - skill.c - skill_castfix()でcastrateに従い、詠唱時間を調整。 - skill_castend_id()でdsprateに従い、使用SPを調整。 - skill_castend_nodamage_id()でカード修正を追加 - battle.c - battle_calc_weapon_attack()でカード修正を追加 - battle_calc_magic_attack()でカード修正を追加 - battle_damage()でフェンカード修正を追加 - -・ステータス割り振りの表示上の問題修正 - STRを上げてもATKが変わらない問題、INTを上げてもMATKが変わらない問題修正 - - map.h - struct map_session_dataにmatk1,matk2メンバ追加 - pc.c - pc_calcstatus()の修正 - clif.c - clif_initialstatus()の修正 - battle.c - battle_calc_magic_attack()の修正 - - ----------- -//0251 by nabe - -・0250のバグ修正など - カートを付けずにログインまたはマップ移動した後にカートを付けると、 - カートの中身が2倍の量に表示されてしまっていたのを修正。 - カートのアイテム数を更新するように修正。 - pc.h/pc.c - pc_iscarton()マクロを追加 - pc_cart_additem(),pc_cart_delitem()にそれぞれ - sd->cart_num++;とsd->cart_num--;処理を追加 - clif.c - clif_parse_LoadEndAck()で、 - カートを付けているときのみカート情報を送信するようにした - ----------- -//0250 by nabe - -・カートOFF、チェンジカート実装。 - (map/) - pc.c/pc.h - pc_setcart()を追加 - script.c - buildin_setcart()を追加 - スクリプトコマンド「setcart;」でカートがつく - clif.c/clif.h - clif_parse_CartOff()追加。(カートをはずす) - clif_parse_ChangeCart()追加。(チェンジカートのカート選択) - (conf/) - npc_town_kafra.txt - カートサービスを「setcart;」に置換 - - ----------- -//0249 by 胡蝶蘭 - -・パーティのデータベースの矛盾を出来るだけ抑えるように。 - 複数パーティに所属してるデータの検査、追加に失敗したときに脱退など。 - - (char/) - int_party.c - party_check_conflict(),party_check_conflict_sub(), - mapif_parse_PartyCheck()追加 - inter.c - パケット長リストに0x3028追加 - INTER鯖パケット.txt - パケット0x3028追加 - (map/) - party.c/party.h - party_check_conflict()追加。 - party_invite()で同アカウント所属チェックを行うように。 - party_member_added(),party_send_movemap()で - party_check_conflict()を呼ぶように。 - intif.c/intif.h - intif_party_checkconflict()追加 - -・パーティの座標、HP通知を実装 - 変化があれば1秒に一回送信。 - - map.h - struct map_session_dataにparty_x,~_y,~_hpの3メンバ追加 - party.c/party.h - party_send_xyhp_timer_sub(),party_send_xyhp_timer(), - party_send_xy_clear(),party_send_hp_check()追加。 - party_recv_movemap()でsd->party_*を初期化するように。 - clif.c/clif.h - clif_sendのPARTY*フラグを有効に。 - (PARTY,PARTY_SAMEMAP,PARTY_AREA,PARTY*_WOSの6種) - clif_party_xy(),clif_party_hp()追加。 - pc.c/pc.h - pc_authok()でsd->party_*を初期化するように。 - pc_walk()でパーティメンバが視界内に入ってきたときに - party_hpを初期化するように。 - -・パーティのexp公平分配を実装 - party.c/party.h - party_share_exp()追加 - mob.c/mob.h - mob_damage()で公平分配処理追加 - -・スキルの修正と追加実装 - バッシュ、ピアースの命中率修正実装 - ピアースのサイズによる回数変動実装(プレイヤーは中型と仮定) - バッシュ、ソニックブロウのスタン効果実装 - ストーンカース、フロストダイバ、インベナム、 - アスペルシオ、エンチャントポイズン、レックスデビーナ実装 - - skill.c - skill_additional_effect()追加 - skill_castend_damage_id()該当個所修正 - skill_castend_nodamage_id()該当個所修正 - skill_use_id(),skill_use_pos()でスキルが使用できないときは - 何もしないように修正。 - battle.c - battle_calc_weapon_attack()の該当個所修正 - battle_get_dmotion(),battle_get_attack_element()修正 - clif.c - clif_mob007b(),clif_mob0078でoptionなどを送るように修正 - pc.c - pc_attack(),pc_walktoxy()で行動不可能なときは何もしないように。 - mob.c - mob_stopattack()修正 - mob_ai_sub_hard()で行動不能なときは何もしないように。 - -・攻撃射程の判定追加 - 相手が移動して届かないときは、移動パケットを送信 - - clif.c/clif.h - clif_movetoattack()追加 - pc.c - pc_attack()で射程判定、届かないならclif_movetoattack()を呼ぶ。 - ----------- -//0248 by nabe - -・パーティ作成時に既にパーティに所属していた場合の処理を追加 - party.c - party_create()に、既にパーティに所属していた場合 - clif_party_created(sd,2)を追加 - -・ディスカウント、オーバーチャージを計算 - pc.c - pc_modifybuyvalue()、pc_modifysellvalue()で値段を計算 - - ----------- -//0247 by 胡蝶蘭 - -・パーティ実装 - 公平分配は設定しても実際には公平分配されてない。 - パーティスキルはまだ自分にしかかからない - - (char/) - int_party.c/int_party.h - まともに実装 - inter.c - パケット長リスト追加 - INTER鯖パケット.txt - パーティのパケット追加 - (map/) - party.c/party.h - 新規追加 - map.c/map.h - struct map_session_dataにparty_sendedメンバ追加 - do_init()でdo_party_init()を呼ぶ - map_quit()でparty_send_logout()を呼ぶ - intif.c/intif.h - パーティ関連の部分追加 - clif.c/clif.h - パーティ関連の部分追加 - clif_parse_LoadEndAck()でparty_send_movemap()を呼び出す - pc.c - pc_authok()でparty_request_info()を呼ぶようにし、 - party_sendedを初期化するように。 - -・詠唱妨害されたとき画面上で詠唱をやめるように修正 - (map/) - skill.c - skill_castcancel()で詠唱中止パケ(合ってるのかな?)を送信 - -・超遠距離攻撃だと敵が反撃してこない問題を修正 - (map/) - map.h - struct mob_dataにmin_chaseメンバ追加(最低追跡距離) - mob.c - mob_attack()でmin_chaseを13に初期化する - mob_walk()でmin_chaseが13より大きいなら少しずつ引いていく - mob_ai_sub_hard()でmin_chaseにより追跡を判断、 - 攻撃を受けた時にmin_chaseを彼我距離+13に設定 - ----------- -//0246 by 胡蝶蘭 - -・カート実装 - map.h - struct map_session_dataにcart_weightなど4つメンバ追加 - pc.c/pc.h - pc_cart_additem(),pc_cart_delitem(), - pc_cart_putitemtocart(),pc_cart_getitemfromcart()追加 - pc_calcstatus()でカート重量や個数などの情報を計算 - clif.c/clif.h - clif_cart_itemlist(),clif_cart_equiplist(), - clif_cart_additem(),clif_cart_delitem(), - clif_parse_PutItemToCart(),clif_parse_GetItemFromCart()追加 - clif_parse_LoadEndAck()でカート情報、内容送信 - clif_updatestatus()でSP_CARTINFOでカート情報を送れるように - clif_parse_MoveFromKafraToCart(),~ToKafraFromCart()追加 - storage.c/storage.h - storage_additem(),storage_delitem()追加 - storage_storageadditemfromcart,~getitemtocart()追加 - storage_storageadd(),storage_storageget()で、 - storage_additem(),storage_delitem()を呼ぶように変更 - -・スキル詠唱ディレイなど実装 - clif.c - clif_parse_WalkToXY()にskilltimerによる移動可否を追加 - clif_parse_UseSkillToId(),clif_parse_UseSkillToPos()に - canmove_tickによる攻撃可否追加 - skill.c/skill.h - skill_castcancel()を追加 - skill_use_id(),skill_use_pos()でディレイ時間計算および、 - canmove_tickの設定 - battle.c - battle_damage()でskill_castcancel()の呼び出し追加 - -・0245のアイテムデータベース修正の通常価格版用意 - (db/) - item_db.txt - item_db2.txtに前のitem_db.txtの価格情報をマージしただけです。 - ----------- -//0245 by れあ - また例によって、相場修正版のみです。 -・item_db2.txtの修正 - 亀島新装備の効果を実装しました。 - ウィザードが杖を装備できないのを修正 - ウィザードがマジシャンハット、とんがり帽を - 装備できないのを修正 ----------- -//0244 by れあ -・mob_db.txtの修正 - 亀島モンスターのデータをいれました。 - ただ、間違ってる部分がかなりあります。 - Speed,Delayは適当です。 - また、わからないのは韓国版のデータなので - Mdefとか異常に高い気も。 ----------- -//0242 by 胡蝶蘭 - -・取引関連の変更と修正 - 取引に使う変数をmmo_charstatusからmap_session_dataに移動しました - - (common/) - mmo.h - struct mmo_charstatusから取引関係のメンバ削除 - (map/) - map.h - struct map_session_dataに取引関係のメンバ追加 - trade.c - 構造体の変更にあわせて修正 - map.c - map_quit()で取引中ならキャンセルするようにした - -・カードの組み合わせ実装 - pc.c/pc.h - pc_insert_card()でカードを実際に挿入する - clif.c/clif.h - clif_parse_UseCard(),clif_parse_InsertCard()追加 - clif_use_card(),clif_insert_card()追加 - -・一部のカード効果実装 - スキル習得カード、ステータスボーナスカードなど。 - - (map/) - map.h - struct map_session_dataに装備カード検索用の変数追加 - pc.c/pc.h - pc_calcstatus()でカードの処理追加 - あるIDのカードが装備済みか検索するための関数、 - pc_equip_card(),pc_equip_wcard(),pc_equip_dcard()を用意 - -・重量オーバー/鷹/騎乗アイコンの表示 - (map/) - pc.c/pc.h - pc_checkweighticon()追加、重量のアイコン処理 - clif.c - clif_updatestatus()で重量送信時にpc_checkweighticon()の実行 - clif_changeoption()で鷹と騎乗のアイコン処理 - -・0241のアイテムデータベース修正の通常価格版用意 - (db/) - item_db.txt - item_db2.txtに前のitem_db.txtの価格情報をマージしただけです。 - - ----------- -//0241 by れあ -・アイテムデータベースの修正 - 新頭装備のグラフィックが異なるのを修正 - 装備の効果の実装 - 上段・中段が間違ってたのを少し修正 - 速報版ってことで間違え多いかも。 - テストもあまりしてません。 - あと、相場調整版しか用意してません。 - - item_db2.txt - 亀島にあわせて調整 - ----------- -//0240 by nabe - -・取引を実装しました。 - (common/) - mmo.h - struct mmo_charstatus に - int trade_partner; - int deal_item_index[10]; - int deal_item_amount[10]; - int deal_zeny; - short deal_locked; - を追加 - (map/) - clif.c,clif.h - clif_traderequest() : 0xe5(取り引き要請受け) - clif_tradestart() : 0xe7(取り引き要求応答) - clif_tradeadditem() : 0xe9(相手方からのアイテム追加) - clif_tradeitemok() : 0xea(アイテム追加成功) - clif_tradedeal_lock() : 0xec(ok押し) - clif_tradecancelled() : 0xee(取り引きキャンセル) - clif_tradecompleted() : 0xf0(取り引き完了) - を追加。 - trade.c,trade.h - trade_traderequest() : 取引要請を相手に送る - trade_tradeack() : 取引要請 - trade_tradeadditem() : アイテム追加 - trade_tradeok() : アイテム追加完了(ok押し) - trade_tradecancel() : 取引キャンセル - trade_tradecommit() : 取引許諾(trade押し) - を実装。それぞれclif.c::clif_parse_Trade*から呼ばれる。 - - ----------- -//0238 by れあ - -・速度変更に関して少し修正 - atcommand.c - 速度変更の部分を少し修正 - これで一応動くみたい? - pc.c - ついでにですが - 速度上昇で歩行速度が上がるようにした。 - 一応動くみたいですが適当なので - おかしなところがあればお願いします。 - ----------- -//0236 by nabe - -・スクリプトでmenuで飛んだ先で直ぐmenuを書くと誤動作するバグを修正しました。 - script.c - goto動作の後のRERUNLINEに対処するため、 - goto,menuで飛んだ後には、st.state==GOTOでrerun_posを更新。 - - ----------- -//0233 by nabe - -・アイテムを装備する際の装備判定を追加しました。 - pc.c - pc_equipitem()に装備判定(性別判定、装備LV判定、職業判定)追加 - -・重量判定スクリプトコマンドを追加しました。 - if (checkweight(アイテムID,アイテム数量)) - でそのアイテム×数量を取得できるかどうか判定できます。 - script.c - buildin_checkweight()を追加 - -・スクリプト詰め合わせをathena dev-2.1.1用に移植しました。 - map_athena1.cnf - npc_event_*.txt イベントNPC - npc_job_*.txt 転職NPC - npc_mob_job.txt 転職用モンスター - npc_town_*.txt 町NPC - - ----------- -//0232 by 胡蝶蘭 - -・装備ボーナスが実装されました - ボーナスに使うスクリプト(bonus,skill)を実装 - スクリプトはI-Athenaのデータを使ってコンバートしました。 - (まだカードには対応していません) - - (common/) - mmo.h - struct skillにflagメンバ追加(カードスキルかどうか) - (map/) - map.h - struct map_session_dataにatk_eleなどのメンバ追加 - enumでSP_ATKELEMENTなど追加 - pc.c - pc_bonus()の実装、pc_skill()追加 - script.c - buildin_skill()の追加 - buildin_bonus()の修正(const.txtの定数が使えるように) - clif.c - clif_skillinfoblock()の修正(カードスキルは上げられない) - (db/) - const.txt - bonusに使うための定数追加 - item_db.txt - 標準のデータに装備スクリプトを追加したもの - item_db2.txt - 0213で相場調整されたデータに装備スクリプトを追加したもの - -・詠唱関係のバグが修正されました - (map/) - skill.c - skill_use_id(),skill_use_pos()を修正 - (db/) - cast_db.txt - 少し追加(ブリッツビートなど) - -・攻撃属性が適用されるようになりました -・星のかけらの修正が適用されるようになりました - map.h - struct map_session_dataにstarメンバ追加 - pc.c - pc_calcstatus()で属性初期化 - battle.c - battle_get_element(),battle_get_attack_element()修正 - battle_calc_weapon_damage()の該当個所修正 - -・杖装備時にMATK+15%が適用されるようになりました - battle.c - battle_calc_magic_damage()の該当個所修正 - -・製造武器のキャラクター名が正しく表示されるようになりました - - 原理としては、map鯖内のキャラクタ名データベースを検索して、 - 存在すれば即返信、存在しなければchar鯖に解決要求を出す。 - このとき、名前を要求してきたクライアントのIDをデータベースに登録する。 - char鯖から名前データがくると、対応するデータベースに名前をセットし、 - 要求してきたクライアントに名前を返信する。 - 未解決の同じキャラID解決を複数のクライアントが要求してきた場合、 - 最後に要求してきたクライアントにしか返信しないが、 - 返信されなかったクライアントは数秒後に再び解決要求を送ってくる - (そしてそのときはmap鯖から即返信される)ので大きな問題はない。 - - パケット0x2b08,0x2b09でmap鯖とchar鯖が通信してます。 - - (char/) - char.h - UNKNOWN_CHAR_NAME定義(キャラデータが無いときに返される名前) - char2.c - parse_frommap()にパケット0x2b08の処理を追加 - - (map/) - chrif.c/chif.h - chrif_searchcharid()追加 - chrif_parse()で0x2b09の処理追加 - map.c - データベース charid_db 宣言 - struct charid2nick宣言。nickは名前、 - req_idは0で名前解決済み、0以外で未解決で解決待ちのブロックID - map_addchariddb()追加。データベースへ名前登録、要求に返信。 - map_reqchariddb()追加。要求があったことをデータベースへ追加。 - map_charid2nick()でデータベースの検索 - do_init()で charid_db の初期化を追加 - clif.c/clif.h - clif_parse_SolveCharName(),clif_solved_charname()追加 - - ----------- -//0231 by nabe - -・スクリプトで mes "$charaname"; 等と書くとキャラの名前をしゃべる機能を追加。 - script.c - buildin_mes()内で - mes内部の$charanameをキャラの名前に置換する処理を追加。 - #同様にして変数の値などをmes内部で表示するようにすることも - #できますが、これについては未実装です・・・。 - #とりあえず - # mes Global_Val; - #のように直接書くことで対処してください。 - -・敵に攻撃されたときにmap鯖が落ちることがあるのを修正。 - battle.c - battle_calc_weapon_attack()の - ディバインプロテクションのスキルチェック部分、 - pc_checkskill(sd,22)を、 - pc_checkskill(tsd,22)に。 - ----------- -//0230 by nabe - -・回避率増加スキルをステータスに反映。 - pc.c - 0228でのpc_calcstatus()の回避率増加分を元に戻しfleeを増加。 - battle.c - battle_calc_weapon_attack()のhitrate計算で回避率保証を計算。 -・グローバル変数を実装。 - '@'もしくは'l'で始まらない変数名は、全てグローバル変数とみなされます。 - mmo.h - struct mmo_charstatus に - int global_reg_num; - struct global_reg global_reg[GLOBAL_REG_NUM]; - を追加。 - pc.c - pc_readglobalreg(),pc_setglobalreg()を追加。 - script.c - get_val(),buildin_input(),buildin_set()に - グローバル変数のための処理を追加。 - char2.c - mmo_char_tostr(),mmo_char_fromstr()に - グローバル変数のための処理を追加。 - ----------- -//0229 by 胡蝶蘭 - -・一部スキルの実装/修正 - ディバインプロテクション、デーモンベイン、ビーストベイン実装 - エナジーコート修正(魔法による攻撃にはスキルが働かないように修正) - 武器攻撃系スキル修正(エフェクトを通常攻撃からスキルに変更) - - battle.c - battle_addmastery()でベイン系追加 - battle_calc_damage()でエナジーコート修正 - skill.c - skill_castend_damage_id()の武器攻撃系スキルの部分を修正 - -・敵攻撃計算をPCのものと一本化 - これでPCvsPC、PCvsMOB、MOBvsPC、MOBvsMOB(!?)を1つの関数で計算できます - - battle.c/battle.h - battle_calc_weapon_attack()を修正 - battle_calc_weapon_attack_pc(),~mob()を削除 - mob.c - mob_attack()で計算にbattle_calc_weapon_attack()を使うように修正 - -・詠唱時間データがない場合のデフォルトの詠唱時間を0に変更 - 今までは1秒にしてましたが、バッシュとかがおかしくなるので。 - (バッシュとかのデータを用意すればこうしなくても直るんですが) - - pc.c - pc_readdb()で1000msをセットするのを止めた - -・遠距離攻撃してこないバグ、その他を修正 - mob.c - mob_attack()の射程を修正し忘れていた - mob_ai_sub_hard()で射程距離外の時、無移動の敵は - ターゲットを外すようにした - - ----------- -//0228 by nabe - -・ダブルアタックのSkillIDを修正。 - battle.c - battle_calc_weapon_attack_pc()で - pc_checkskill(sd,49) -> pc_checkskill(sd,48)に。 -・回避率向上を陽に表さない - pc.c - pc_calcstatus()でのfleeの回避率向上分を削除し、 - mob.c - mob_attack()のhitrate計算で回避率向上を計算。 -・盗蟲、盗蟲雌、盗蟲雄を正常化。 - npc_monster3J.txt - mob_db.txtに合わせて、たぶん正しいと思われるIDに修正。 - 盗蟲 1006 -> 1051 - 盗蟲雌 1017 -> 1053 - 盗蟲雄 1021 -> 1054 -・デバッグメッセージの消し忘れ(?)を削除。 - pc.c - printf("pc.c 63 clif_clearchar_area\n");をコメントアウト - ----------- -//0227 by 胡蝶蘭 - -・一部のスキル効果が実装されました - HP回復向上、SP回復向上、マグニフィカート、 - ハイディング、クローキング、死んだふり、応急手当 - - map.h - struct map_session_data に inchealtick メンバ追加 - pc.c - pc_spheal()でマグニフィカート処理追加 - pc_natual_heal_sub()で回復向上スキル処理追加 - pc_authok()でinchealtickを初期化するように変更 - pc_walk()でincheaktickを再設定するように変更 - pc_walk()でクローキングの終了条件を調査するように変更 - pc_walktoxy()で状態によって移動不可能にした - skill.c/skill.h - skill_status_change_start(),~timer(),~end()に処理追加 - skill_check_cloaking()追加、クローキングの終了条件を検査 - battle.c/battle.h - battle_stopattack()追加 - battle_calc_weapon_attack()で攻撃を止める処理追加 - mob.c - mob_ai_sub_hard()で攻撃を止める処理追加 - -・通常攻撃処理、対MOB、対PCを共用に。 - pc.c - pc_attack_mob(),pc_attack_pc()削除 - pc_attack()に攻撃処理追加 - -・モンスターの行動の一部実装 - アクティヴ、無反応、移動しない、遠距離攻撃一部 - - mob.c - mob_ai_sub_hard()に行動追加 - mob_ai_sub_hard_activesearch()追加、近くのPCへの策敵 - -・オーバートラストの増加倍率が100倍になっているバグが修正されました - battle.c - battle_calc_weapon_attack()で、該当個所を修正 - - ----------- -//0226 by 胡蝶蘭 - -やっぱりテストはあんまりしていません - -・一部のスキル効果が実装されました - 速度増加、エンジェラス、キュアー - インポシティオマヌス、サフラギウム、リカバリー、グロリア - ふくろうの目、ワシの目、集中力向上、回避率向上、解毒 - 所持量増加、ラウドボイス、アドレナリンラッシュ、オーバートラスト - ウェポンパーフェクション、マキシマイズパワー、2HQ - - (map/) - map.h - struct map_session_dataにwatk2,def2など追加 - pc.c - pc_calcstatus()にスキル修正追加 - atk2なども送信するように変更 - battle.c/battle.h - battle_get_def2()など多数追加 - battle_calc_weapon_damage()で敵減算防御の所得を - battle_get_def2()に変更 - battle_calc_magic_damage()で敵減算魔法防御の所得を - battle_get_mdef2()に変更 - battle_calc_weapon_damage()でスキル修正を追加 - skill.c/skill.h - skill_use_nodamage_id()の該当個所追加 - skill_status_change_start()の該当個所追加 - clif.c - clif_updatestatus()のatk2などの処理追加 - clif_initialstatus()でatk2などの扱い変更、aspdなど送信追加 - -・精錬ダメージ修正/精錬防御修正が適用されました - (map/) - pc.c - pc_calcstatus()でwatk2とdefの追加計算追加 - battle.c - battle_calc_weapon_damage()でwatk2をダメージに追加 - -・inter鯖のパケット解析部の致命的な問題が修正されました - TCP/IPプログラムでやってはいけないことをそのままやってました(汗 - inter鯖のパケット長データをinter.cに持つように修正されました。 - - (char/) - inter.c/inter.h - パケット長データ inter_*_packet_length[] を追加 - パケット長チェック inter_check_length() を追加 - mapif_parse_*()でRFIFOSKIPをなしに変更 - int_storage.c/int_storage.h - mapif_parse_*()でRFIFOSKIPをなしに変更 - int_party.c/int_guild.c - 仕様変更に対応させた変更 - INTER鯖パケット.txt - パケット長リスト追加 - -・ちょっとした修正 - (char/) - inter.h - inter_cfgNameを"conf/inter_athena.cnf"に修正 - char2.c - char.exe第2引数省略時、inter_cfgNameを使うように修正 - (db/) - cast_db.txt - ホーリーライトの詠唱時間追加(ディレイは適当) - 詳しい人追加求む - ----------- -//0225 by 胡蝶蘭 - -なんかかなり弄りましたが相変わらずテストはあんまりしてません。 - -・スキル使用時の変数を変更 - よく見たら最初から用意されてましたね。 - - map.h - struct map_session_dataのcast_*を削除 - skill.c - cast_*の変数をskill*に変更。 - -・ステータス異常スキルの処理を追加(効果は未実装) - 見かけ上、ステータス異常に掛かったりとかだけ。 - 効果はまだなし。 - - skill.c/skill.h - skill_status_change_start(),~end(),~timer(),~clear()追加。 - それぞれステータス異常の開始、終了、タイマ処理、全消去。 - map.c/map.h - map_quit()でskill_status_change_clear()を呼ぶようにした。 - struct map_session_dataにsc_data,sc_count追加。 - struct mob_dataにsc_data,sc_count,option,opt1,opt2追加。 - pc.c - pc_authok()でsc_data,sc_countを初期化するようにした。 - pc_setoptionでclif_changeoption()の引数変更。 - pc_damage()で死亡時にskill_status_change_clear()を呼ぶように。 - mob.c - mob_spawn()でsc_data,sc_countを初期化するようにした。 - mob_attack()でbattle_calc_damage()を呼ぶようにした。 - mob_damage()で死亡時にskill_status_change_clear()を呼ぶように。 - battle.c/battle.h - battle_get_*()たくさん追加。 - battle_calc_damage()追加。最終的なダメージ計算用。 - battle_calc_magic_attack(),battle_calc_weapon_attack()で - battle_calc_damage()を呼ぶようにした。 - clif.h/clif.c - clif_status_change()追加。ステータス異常アイコン表示用。 - clif_changeoption()の引数変更。 - atcommand.c - clif_changeoption()を呼んでいる2ヶ所で引数変更。 - @dieでskill_status_change_clear()を呼ぶように。 - -・マグヌスエクソシズムの習得条件が間違っているのを修正。 - db/skill_tree.txt - 該当個所修正。(レックスエーテルナの必要Lvを1に) - -・アクティブな敵は攻撃するとき時々ターゲットが変わるようになりました - mob.c - mob_ai_sub_hard()の攻撃されたか確認する部分に - アクティブなら25%の確率でターゲットが変わるように変更。 - -・一部のスキル効果が実装されました - キリエエレイソン、エナジーコート、レックスエーテルナ、 - ホーリーライト、リザレクション、ターンアンデッド、モンスター情報 - - skill.c/skill.h - skill_castend_nodamage_id()にスキルの処理を追加。 - skill_castend_*_id()の引数を変更 - battle.c - battle_calc_damage()にスキルの処理を追加。 - battle_damage(),battle_heal()の引数変更 - battle_calc_weapon_damage(),battle_calc_magic_damage()引数変更 - clif.c/clif.h - clif_skill_estimation()追加。モンスター情報送信用 - pc.c - battle_calc_weapon_damage()呼び出しの引数変更 - -・storage.txtが無い場合inter鯖が強制終了する仕様を変更しました - (char/) - int_storage.c - inter_storage_init()でファイルが読めないとexitしてたのを修正 - - ----------- -//0224 -・2-2次職のスキルをツリーに追加しました(実装はまだです) - (db/) - skill_db.txt - skill_tree.txt - - ----------- -//0223 by 胡蝶蘭 -・カプラ倉庫をinter鯖に対応させました - いままでのstorage.txtはそのまま使えます。 - inter鯖用の設定ファイルとしてconf/inter_athena.cnfを使います。 - (設定ファイルはchar.exeの第2引数で他のファイルを指定できます) - - カプラ倉庫のinter鯖実装の概要 - - inter鯖はstorage.txtの全データを持つ。map鯖はアカウントが要求するまで - そのアカウントの倉庫データを持たない。クライアントから倉庫を開く要求が - あったとき、map鯖は対応するアカウントの倉庫データをinter鯖に要求する。 - inter鯖からデータが届くとクライアントに倉庫データを送る。 - 倉庫の出し入れはクライアントとmap鯖間の通信だけで行われる。 - クライアントが倉庫を閉じるか終了すると、map鯖は該当アカウントの - 倉庫データをinter鯖に送る。このときinter鯖の応答を待たずにクライアントに - 倉庫クローズを送る。inter鯖は倉庫データを受け取ると、 - 全員分のデータをファイルに保存して、map鯖に成功ステータスを返す。 - map鯖は成功ステータスを無視する。(デバッグ用に画面に出力するだけ) - inter鯖終了時にも倉庫データをファイルに保存する。 - - map鯖でaccount2storageで新しい倉庫データを作るとき、 - すでに閉じられている倉庫データのメモリを使いまわしたほうがメモリが - 節約できるかも?(これは実装していません) - - (common/) - mmo.h - struct storage を map/storage.h から移動。 - inter鯖とmap鯖両方で使用するため。 - (char/) - char2.c - do_final()を作成、終了時にmmo_char_sync()以外にinter_save()を - 呼ぶようにした(これでinter_*_save()は全部呼ばれます) - inter_init()をchar.exeの第2引数もしくは"conf/inter.cnf"で - 呼ぶようにした(athena.shにinter鯖コンフィグファイルを指定できます) - inter.c/inter.h - inter_storage_init(),inter_storage_save(), - inter_storage_parse_frommap()を呼ぶように。 - inter_init()にコンフィグファイル名の引数を付けた。 - inter_config_read()追加、コンフィグファイルから - 倉庫とパーティー、ギルドのファイル名を読み込みます。 - int_storage.c/int_storage.h - 新規追加。倉庫部分のinter鯖機能。 - int_party.h/int_party.c/int_guild.h/int_guild.c/ - ファイル名変数の宣言追加 - INTER鯖パケット.txt - 倉庫パケットの解説追加 - - (map/) - storage.h/storage.c - storage_fromstr(),storage_tostr()をchar/int_storage.cに移動。 - 同じくdo_init,do_finalでのファイル処理も移動。 - do_final()は処理なし、do_init()は変数初期化のみに変更。 - storage_storageopen()では単にintif_request_storage()を呼ぶだけに。 - storage_storageclose()にintif_send_storage()を追加 - storage_storage_quitsave()追加。クライアント終了時に - カプラ倉庫が開いていればintif_send_storage()を呼ぶ関数。 - intif.h/intif.c - intif_parse_LoadStorage(),intif_parse_SaveStorage(), - intif_send_storage(),intif_request_storage()追加 - map.c - map_quit()でstorage_storage_quitsave()を呼ぶように。 - - (conf/) - inter_athena.cnf - 新規追加。inter鯖用のコンフィグレーションファイル - - ----------- -//0221 by 胡蝶蘭 - -・スキルターゲットのIDが正しく所得できない問題修正 - clif.c - clif_parse_UseSkillToId()でIDをWORDとして扱ってたのをLONGに修正 - -・スキル詠唱時間と属性表、および魔法系スキルの属性修正実装 - 属性ダメージ修正は battle_attr_fix() で計算します。 - atk_elemは属性そのまま、def_elemは(属性lv*20+属性)です。 - 詠唱時間はskill.cのCASTFIXの値を変えることで倍率を調整できます - - pc.c - pc_readdb()でcast_db.txtとattr_fix.txtの読み込み追加 - skill.c/skill.h - struct skill_db にcast,delay追加、それらのアクセサも追加 - スキル詠唱時間を skill_get_cast() で所得するようにした - battle.c/battle.h - attr_fix_table定義 - battle_attr_fix()追加、属性修正を計算する - 属性系アクセサ(battle_get_element()など)を追加 - battle_calc_magic_damage()に属性修正を追加 - cast_db.txt - 新規追加。詠唱時間とディレイのデータベース - 全然足りないので、誰か追加希望。 - attr_fix.txt - 新規追加。属性修正テーブル - -・ヒールの実装 - clif.c/clif.h - clif_skill_nodamage()追加、支援系や回復のエフェクト - skill.c/skill.h - skill_castend_damage_id()、skill_castend_nodamage_id()追加、 - 攻撃系と支援/回復系で関数を分けた - ヒール計算マクロ skill_calc_heal() 追加 - battle.c - battle_calc_magic_damage()でヒールのダメージ計算追加 - - ----------- -//0220 by れあ - -0216の修正 -HITの計算がおかしかったので修正してみました。 -間違ってたらごめんなさい。 - -・battle.c - 256行目の - hitrate=battle_get_hit(&sd->bl) - battle_get_flee(&sd->bl) + 80; - がたぶん、自分のHITと自分のFLEEで計算してる気がするので - hitrate=battle_get_hit(&sd->bl) - battle_get_flee(target) + 80; - に修正しました。 - - ----------- -//0218 by 胡蝶蘭 - -実際に分散させてテストしていなかったり。 - -・map鯖分散処理用にinter鯖機能をつけてみる(今後のための拡張) - char鯖にinter鯖を寄生させました。複数のmap鯖間の通信に利用します。 - map鯖を分散して処理できるようにするための機能です。 - 今後partyやguild実装時にきっと役にたってくれるかと。 - - 倉庫の実装もinter鯖に移動すべきかもしれません。 - どのキャラクターがどのmap鯖にいるか検索する機能もいるかも。 - - 使うパケットのIDは以下のようになります - map鯖=>inter鯖はパケット0x3000〜 - inter鯖=>map鯖はパケット0x3800〜 - パケットを作った場合は、INTER鯖パケット.txtに書いてください - - この機能によるメリット - map鯖分散にも対応できる - この機能によるデメリット - inter鯖経由の全ての命令の動作速度が落ちる - (一回inter鯖まで渡すため) - 鯖とクライアントを同じPCで使っているとつらいかも - - (char/) - char2.c/char.h - mapif_sendall()追加(全MAP鯖にパケットを送る) - mapif_send()追加(特定MAP鯖に送る:生存判定付き) - parse_frommap()でinter_parse_frommap()を呼ぶようにした - (inter鯖のmap鯖解析部をchar鯖に寄生させたことになる) - inter.h/inter.c - 新規追加。inter鯖の中核。 - inter_parse_frommapでMAP鯖からのパケットを解析します。 - int_party.h/int_party.c/int_guild.h/int_guild.c - 新規追加。今後のための予約。パーティやギルド機能用 - initでデータを読んで、saveで保存すべき? - saveはまだ呼ばれない。parseでパケット解析。 - common/mmo.hあたりでパーティーやギルドの構造体を - 定義する必要があると思われる。 - INTER鯖パケット.txt - パケットのリスト - - (map/) - intif.h/intif.c - inter鯖と通信する部分。 - inter_parse()でinter鯖からのパケットを解析します。 - inter鯖へデータを送るときはinter_fdを使います。 - chrif.h/chrif.c - chrif_parse()でinter_parse()を呼ぶようにした - (intif.cのinter鯖解析部をchar鯖解析部に寄生させたことになる) - -・@kamiコマンドをinter鯖経由に変更 - 原理としては次のような感じです - クライアント=>map鯖=>inter鯖=>全map鯖=>全クライアント - - (char/) - inter.c - mapif_GMmessage()追加 - (map/) - intif.h/intif.c - intif_GMmessage()追加 - intif_parseでGMメッセージの処理を追加 - clif.c/clif.h - clif_GMmessage()の引数を変更 - atcommand.c - @kami部分でintif_GMmessage()を呼ぶようにした - -・Wisをinter鯖経由に変更 - 原理としては次のような感じです - - 送り主クライアント=>送り主map鯖=>inter鯖=>全マップ鯖=>(分岐A) - [分岐A] - 1.相手の人いるmap鯖=>相手のクライアント - 〃 =>inter鯖=>送り主map鯖=>送り主クライアント - 2.相手のいないmap鯖=>inter鯖(分岐B) - [分岐B] - 1.全map鯖が応答したinter鯖 =>送り主map鯖=>送り主クライアント - 2.(全部は応答してないときは、全map鯖の応答を待つ) - - ものすごい複雑になってますね。 - - (char/) - inter.c - struct WisList 定義(Wisデータのリンクリスト) - add_wislist(),del_wislist(),search_wislist(), - check_ttl_wislist()追加,リンクリストを扱う関数群 - mapif_wis_message(),mapif_wis_end()追加 - (map/) - intif.h/intif.c - intif_wis_message(),intif_wis_end()追加 - intif_parse_WisMessage()追加,intif_parse()から呼ばれるように - clif.c/clif.h - clif_wis_message(),clif_wis_end()追加 - clif_parse_Wis()を変更,intif_wis_message()を呼ぶようにした - -・スキル使用時のヒット数/消費SP所得のバグ修正 - skill.c - skill_get_sp(),skill_get_num()で参照する配列インデックスをlv-1にした - - ----------- -//0216 by 胡蝶蘭 - -いつもどおりテストほとんどしてないので、バグ大量かも。 - -・0213の修正?のよくわからないところ修正 - itemdb.c - コンパイルが通らないのでitemdb_equipointの引数リスト変更 - -・Athena dev 2.1.1の適用 - dev-2.1.1で適用された修正を適用しました - - timer.c - 2.1.1のものと差し替え - script.c - C_NE: の修正の適用 - README - 最後の文章を2.1.1のものに差し替え - -・スキルデータベースの修正 - 一部の消費SPやヒット数などを修正。 - - skill_db.txt - 該当個所の修正 - -・スキル攻撃の実装変更&追加実装 - バッシュ、メマーナイト、ダブルストレイフィング、ピアース - スピアブーメラン、スピアスタブ、ボーリングバッシュ - ソニックブロー、グリムトゥース などの実装変更 - - ナパームビート、ソウルストライク、 - ファイヤーボルト、コールドボルト、ライトニングボルト、アーススパイク、 - ユピテルサンダー などを追加実装 - (全て、範囲攻撃やステータス異常などは未実装) - - pc.c/pc.h - 0213の変更をなかったことにした - pc_attack_mob()の修正、計算はbattle_calc_weapon_attack()に任せ、 - その計算結果を適用するだけに変更 - clif.c/clif.h - clif_skill_fail(),clif_skill_damage(),clif_skill_damage2()追加 - それぞれ使用失敗、使用エフェクト、吹き飛ばし付き使用エフェクト - skill.c/skill.h - 0213の変更をなかったことにした(ダメージ倍率計算がおかしい) - skill_castend_id()にSP/Zeny確認と消費部分を追加、 - 種類別に処理を追加。 - battle.c/battle.h - 新規追加 - 武器攻撃計算用にbattle_calc_weapon_attack(), - 魔法攻撃計算用にbattle_calc_magic_attack()を用意 - (双方とも、MOBとPC両方計算可能なはず) - ファイル増やしすぎという意見も…(汗) - - ----------- -//0214 by れあ -・ダブルアタックがおかしかったところを修正。 -・スキルの一部実装 - バッシュ・メマーナイト・ダブルストレイフィング・ピアース - スピアブーメラン・スピアスタブ・ボーリングバッシュ - ソニックブロー・グリムトゥースなどです。 - - 適当なのでどこか、不具合があるかもしれません。 - あと、テストもあまりしてませんのでおかしいところがあったら修正をお願いします。 - 他にも問題があったら手直しをお願いします。 - 変更内容は以下の通りです。 - - clif.c,clif.h - clif_skill_damage()を追加しました。 - - pc.c,pc.h - pc_attack_mob()の引数を一つ追加。 - ダブルアタックがおかしかったので正常に動作するように修正。 - - skill.c - 一部スキルの実装をしてみました。 - - ----------- -//0213 by れあ -・0208の@コマンドで少し修正 - atcommand.c - @itemで個数指定が無い場合、入手個数を1個にするようにした。 - @itemでIDの指定が無い場合、アイテムを入手してたことになって - いたのを修正 - itemdb.c - item_db.txtでSellの項目を店売りの値段としてみた。 - item_db2.txt - 試しにカードやレアアイテムの店売り価格を値段を本鯖の相場にし - てみたもの。使用する場合はitem_db.txtと差し替えてください。 - - ----------- -//0208 by nabe - -・@コマンド実装。 - atcommand.h,atcommand.c - ほぼI-Athenaの@コマンド相当ですが、@GMとPVPは未実装です。 - help.txtも同梱しています。 - GM(アカウントID=704554〜704583)専用にするには、 - atcommand.cの該当部分のコメントアウトを解除して下さい。 - clif.h,clif.c - clif_displaymessage() - clif_GMmessage() - clif_heal() - clif_resurrection() - clif_pvpon() - clif_pvpset() - clif_refine() - を追加しました。 - clif_parse_GlobalMessage()内でatcommand()を呼んでいます。 - -・ちょっとだけ修正。 - script.c - {buildin_openstorage,"openstorage","s"}, - から - {buildin_openstorage,"openstorage",""}, - に修正しました。 - - ----------- -//0206 by 胡蝶蘭 -・スキルツリー/スキル使用機構の実装 - mmo.h - MAX_SKILLを増やした - char2.c - mmo_char_fromstr() - mmo_charstatusのskillのインデックスにスキル番号を使うようにした - =>スキルの検索高速化のため(かわりにメモリ使用量が増える) - pc.h/pc.c - pc_skillup(),pc_calc_skilltree()追加 - pc_checkskill()変更(インデックスをスキル番号に) - pc_readdb()でskill_db.txtも読むようにした - pc_authok()でcast_timerを初期化するようにした - pc_calcstatus()でpc_calc_skilltree()とclif_skillinfoblock()を - 呼ぶようにした - clif.c/clif.h - clif_skillinfoblock(),clif_skillcasting(), - clif_skillup()を追加 - clif_parse_SkillUp(),clif_parse_UseSkillToId(), - clif_parse_UseSkillToPos()を実装 - skill.h/skill.c - ファイル追加(map/) - map.h - struct map_session_dataにcast_*を追加 - skill_db.txt - ファイル追加(db/) - (I-Athena0200のskill_info2.txtをコンバートしたもの) - (スキル使用部分開発者向け情報) - スキルの効果を実装する場所はskill.cの - skill_castend_id(),skill_castend_pos()です。 - ターゲットや使用スキルは sd->cast_* から得ます - スキルデータベースへは skill_get_* でアクセスしてください - 今後、キャスティングタイムもデータベースに入れる予定 - ----------- -//0205 by nabe - -・storage.cのバグフィクス。 -・倉庫データを、マップ鯖起動時に読み、マップ鯖終了時に書くように変更。 - storage.h,storage.c - storage_init()をdo_init_storage()に改名。 - storage_save()をdo_final_storage()に改名。 - fcloseを忘れていたのを追加。 - map.c - #include "storage.h"を追加。 - do_final()にdo_final_storage()を追加。 - do_init()にdo_init_storage()を追加。 - ----------- - -//0203(unofficial) by なみ - -item_db.txtの書き換えのみです。 - -・アイテムの回復量を追加/変更 - 赤ポーション HP 30- 44 - 紅ポーション HP 70- 89 - 黄色いポーション HP 175-234 - 白いポーション HP 350-429 - 青いポーション SP 40- 99 - 赤いハーブ HP 12- 19 - 黄色いハーブ HP 21- 29 - 白いハーブ HP 80-111 - 青いハーブ SP 15- 44 - リンゴ HP 12- 15 - バナナ HP 11- 16 - ブドウ SP 10- 24 - いも HP 11- 15 - にく HP 70- 99 - ハチの蜜 HP 72- 97 / SP 20- 59 - ミルク HP 25- 34 - キャンディ HP 31- 74 - スティックキャンディ HP 46-109 - リンゴジュース ※ HP 28- 32 - バナナジュース HP 27- 33 - ブドウジュース SP 15- 39 - ニンジンジュース ※ HP 29- 32 - カボチャ HP 14 - ペットフード HP 53- 83 - よく焼いたクッキー HP 80-177 - ひとくちケーキー HP 251-359 - ひなあられ HP 175-234 - 菱餅 HP 350-429 - レッドスリムポーション ※ HP 30- 44 - イエロスリムポーション ※ HP 175-234 - ホワイトスリムポーション ※ HP 350-429 - 現在のAthenaではVITやスキルによるボーナスは加味されません。 - (適用する場合はscript.c内のbuildin_heal関数あたりにに手を加える必要あり) - なお、※付のアイテムのデータは適当です。 -・古いカード帖を実装(UseScript) -・その他修正 - ひなあられ 重量なし→重量0.1に修正 - 菱餅 重量なし→重量0.1に修正 - バルムン 重量0.1S4片手剣→重量100S0両手剣に修正 - なお、Sellの項目はあるだけ無駄っぽいので全部消しました。 - ----------- - -//0202 by nabe - -・カプラ倉庫の「同一アカウントなのに共有できないバグ」を改良しました。 - 各キャラに倉庫データを持たせるのは無駄が多い気がするので、 - アカウントIDで管理するように仕様を変更しました。 - ついでに、倉庫データは全てstorage.cでまかない、 - char鯖は関与しないようにしました。 - これに伴い、char_athena.cnf,mmo.h,char2.cは元に戻しました。 - また、倉庫ファイル名は“storage.txt”に固定しています。 - - 改変、追加したのは次のファイルです。 - map/storage.h, - map/storage.c, - map/clif.h,//引数変更だけ - map/clif.c,//引数変更だけ - conf/char_athena.cnf,//元に戻しただけ - common/mmo.h,//元に戻しただけ - char/char2.c,//元に戻しただけ - map/itemdb.h,//itemdb_equippoint()引数宣言変更だけ - map/itemdb.c,//itemdb_equippoint()引数宣言変更だけ - map/pc.c,//itemdb_equippoint()引数宣言変更だけ - ----------- - -//0201 by nabe - -・カプラ倉庫を実装しました。 - - スクリプトから呼び出すには、スクリプト内で - openstorage; - としてください。 - サンプルとしてnpc_kafraJ.txtを付けてあります。 - 併せてnpc_script3J.txtの該当部分も改変しました。 - - char_athena.cnfの - stor_txt: - で倉庫ファイル名を指定しています。 - - 改変、追加したのは次のファイルです。 - map/Makefile, - map/storage.c, - map/storage.h, - map/clif.c, - map/clif.h, - map/script.c, - char/char2.c, - common/mmo,h - 詳しくは、上記ファイルのコメントなどを参考にしてください。 - -・カプラ倉庫実装に伴い、map_athena1.cnfを少し書き換えました。 - -・全てのコメント文をEUCからSJISに変換しました。 - ----------- - - Athena Dev. v2.1.1 Released: Middle July, 2003 - (c) 2003 Athena Project. - http://project-yare.de/ - -1. Athena(アテナ)について -2. このリリースについて -3. 必要な物 -4. 使い方 -5. 現在の仕様 -6. 祝辞 -7. 免責事項 -8. 募集 -9. English - - -1. アテナについて - アテナとは2003年1月半ばにでた0052.lzhをベースとして作られているエミュレータの一つです。 - 基本的なライセンスはオリジナルがGPLの下に配布されている為、 - これに従いGPLの下配布を許可します。 - /* - 改良版を配布する場合は必ずこのREADMEを書き換えてください。 - 何処を改良したのか報告(athena@project-yare.deまで)して貰えると助かります。 - バイナリのみの配布はGPL違反ですので"必ず"ソースも添付してください。 - */ - 動作の確認は以下の通りのみ行っています。 - // ただし完璧に動く事を保証するものでありません - 対象CPU: Intel Pentium系 // PentiumII以上で確認. - FreeBSD 4.8R, 4.6.2R - Linux RedHat 7.3 - cygwin + gcc 3.2 20020927 (prerelease) - 開発元URL: http://project-yare.de/ - - -2. このリリースについて - 今回のリリースは前回(V2.1)同様開発版のリリースのみです。 - 2.1に比べ下記の点が修正されています。 - mapのデフォルト設定が韓国data.grfのみ正常に動作するようになっていた点 - common/timer.cやmap/script.cの幾つかのバグ - - 迅速にUpdateを強く推奨するものではありませんが各自の判断で行って下さい。 - - -3. 必要な物 - data.grf //sdata.grfは必要に応じて - account.txt //存在しない場合athena.shが自動生成します - conf/*.cnf //Map用とChar用の二種類あります - conf/npc*.txt //npc設定用ファイルです。複数のファイルに分けることが可能です。 - db/*.txt //アイテム、job情報など - - -4. 使い方 - > tar xvfz athena-d?.?.tar.gz - > cd athena-d?.?.tar.gz - > make - > vi conf/char_athena.cnf //IP(127.0.0.1)の部分を環境に合わせて変更してください - > vi conf/map_athena.cnf //同上、またmap設定などは、このファイルで行います。 - > ./athena.sh - 上記を行えば"たぶん"起動します。 - - 補足: - conf/npc_sampleJ.txtにはスクリプトの書き方について色々な説明が記載されています。 - もし、独自のMap設定を行ってみたい人や、スクリプトを弄りたい方は参考にしてください。 - ただし、開発中のためスクリプトの仕様が変更される可能性が高いです。 - command.txtには実装済みの特殊コマンドについての説明を記載しています。 - - -5. 現在の仕様 - 本鯖と比べておかしい(例えばプバが歩く、ポリンがアイテムを拾わないなど)点は、 - 全て現在開発中に因るものです。 - 現状としてキャラクタ系及びモンスター系のバグ報告は無視される可能性が高いです。 - - バグ報告について必ず発生条件をお書き下さい。 - 下にある報告用テンプレートを使って報告して頂くと助かります。 - 報告先はエミュ板の開発スレにでも。 - ---- Athena v 2.0 (stable or develop) ---- - 【gcc ver】gcc -vを実行時に表示される内容 - 【動作システム】FreeBSD, Linux(ディストリビュージョンも), cygwinなど - 【発生内容】mapが落ちてしまった時の表示されていたデバッグ情報など具体的に書いてください。 - 【操作内容】具体的にどんな操作を行ったかを書いてください。 - ------------------ END ------------------- - 理想はテンプレに加えてmap.coreなどcoreファイルをUploaderにアップして頂くことですが - 問題のMapだけの状態にしcoreの吐く容量に注意してください。 - /* - 確認した限りでは324個ほどmapデータを読み込ませると、 - 40MB近いcoreファイルを吐き出します @FreeBSD - cygwinの場合はstackdumpというファイルになるそうです。 - しかし、coreファイルなどをgzip圧縮などすれば大幅に小さくなります。 - 大凡30MBのcoreファイルが2.9MBほどになるようです。 - ですので、もしアップロードする場合はgzip圧縮など各自行ってください。 - */ - - 今回のリリースだけでなくHISTORYを作成すると大量に記述が必要な為省略しています。 - // 多い日だと本当に結構ありますので‥‥。 - - -6. 祝辞 - 今回このAthena開発版を出すに当たって感謝したい方々(順番不同) - Lemming氏 (Project YARE) - 0052氏 (Uploader) - 35氏 (エミュ開発スレ) - Johan Lindh氏(Author of memwatch) - YARE forumのNPC情報を作成した方々 - weiss研究会BBSの様々な情報ファイルを作成した方々 - 最後に、.coreファイル達 - - -7. 免責事項 - Athena Projectは一切Athenaの動作に関する保証等は行いません。 - つまり、Athenaは無保証です。 - athena@project-yare.deに動作・操作等に関する質問などを送られても一切お答えできません。 - 又Athenaを用いたことにより生じた被害・問題等の責任は一切Athena Projectは負いません。 - - -8. 募集 - athenaの開発に参加したい//興味があるという方ご連絡下さい。 - 我々は貴方の参加をお待ちしています。 - // 最新版が欲しいだけで何ら協力して頂けないという方はお断りです;-) - [募集要項: プログラマ(2-3人)] - 年齢: 不問 - 性別: 不問 - 言語: 日本語が理解可能 - 内容: C言語もしくはC++による開発。(特にネットワークやDBの経験が有る方大募集!) - [募集要項: 翻訳(?人)] - 年齢: 不問 - 性別: 不問 - 言語: 日本語、英語が理解可能 - 内容: 仏蘭西語、独逸語、西班牙語、伊太利亜語、泰(タイ)語、朝鮮語、中国語へ文献、サイトなどの翻訳 - 連絡先: athena@project-yare.de 雑務担当まで。 - - -9. English - This release is just fixed some bugs in timer.c, script.c and map_athena1.conf. - - -(c) 2003 Athena Project. diff --git a/doc/Readme2.txt b/doc/Readme2.txt deleted file mode 100644 index 0f938fa..0000000 --- a/doc/Readme2.txt +++ /dev/null @@ -1,368 +0,0 @@ - ______ __ __ - /\ _ \/\ \__/\ \ - __\ \ \L\ \ \ ,_\ \ \___ __ ___ __ - /'__`\ \ __ \ \ \/\ \ _ `\ /'__`\/' _ `\ /'__`\ -/\ __/\ \ \/\ \ \ \_\ \ \ \ \/\ __//\ \/\ \/\ \L\.\_ -\ \____\\ \_\ \_\ \__\\ \_\ \_\ \____\ \_\ \_\ \__/.\_\ - \/____/ \/_/\/_/\/__/ \/_/\/_/\/____/\/_/\/_/\/__/\/_/ - _ _ _ _ _ _ _ _ _ _ _ _ _ - / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ -( e | n | g | l | i | s | h ) ( A | t | h | e | n | a ) - \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ - - --------------------------------------------------------------- -eAthena VERSION --------------------------------------------------------------- -Version 1.0.0 Release Candidate 3 --------------------------------------------------------------- -This is a release candidate to iron out any bugs before -official release. --------------------------------------------------------------- -Caution : Make sure you are giving your users account id's -greater than 2000000, failure to do so can cause a number of -problems. --------------------------------------------------------------- -eATHENA README --------------------------------------------------------------- -Thank you for downloading eAthena. -We hope that you'll enjoy using this software. --------------------------------------------------------------- --------------------------------------------------------------- -eAthena Features --------------------------------------------------------------- -> eAthena Completed Features --------------------------------------------------------------- -- PvP (Player VS Player) -- GvG (Guild VS Guild) -- qPets (Cute Pets) -- Monster skills -- 2-2 Jobs (Alternate 2nd Jobs) -- SuperNovice (Alternate 1st Job) -- WoE (War of Emperium) -- Remote administration of accounts (ladmin softwares) -- Pet-Equipped Mobs -- Management of day/night --------------------------------------------------------------- -> eAthena Incompleted Features (List) --------------------------------------------------------------- -- Advanced Classes (Upper Jobs) -- Baby Classes (Baby Jobs) -- Pet Skills -- Equipment Breaking System -- PK Server Mode --------------------------------------------------------------- -> eAthena Features - Estimated completion rate (Detailed) --------------------------------------------------------------- -- Guild Wars (War of Emperium) - 100% Complete (4/4) -- Novice Skills - 100% Complete:(3/3) -- 1st Job Skills - 100% - * Swordsman - 100% Complete:(10/10) - * Acolyte - 100% Complete:(16/16) - * Archer - 100% Complete:(7/7) - * Magician - 100% Complete:(14/14) - * Merchant - 100% Complete:(10/10) - * Thief - 100% Complete:(10/10) -- 2-1 Skills (2nd Job Skills) - 100% - * Knight - 100% Complete:(10/10) - * Priest - 100% Complete:(18/18) - * BlackSmith - 100% Complete:(21/21) - * Wizard - 100% Complete:(13/13) - * Assassin - 100% Complete:(10/10) - * Hunter - 100% Complete:(17/17) -- 2-2 Skills (Alternate 2nd Job Skills) - 90.5% - * Crusader - 100% Complete:(18/18) - * Monk - 100% Complete:(15/15) - * Alchemist - 54% Complete:(12/22) Complete:(10/22) (Blame Gravity For The Missing Skills) - * Sage - 100% Complete:(20/20) - * Rogue - 80% Complete:(12/15) Incomplete:(3/15) - * Bard - 100% Complete:(16/16) - * Dancer - 100% Complete:(16/16) -- 2-1-1 Skills (Advanced 2-1 Job Skills) - 80.5% - * Lord Knight - 94% - Complete:(7/8) Incomplete:(1/8) - * High Priest - 66% - Complete:(1/3) Incomplete:(2/3) - * High Wizard - 100% Complete:(4/4) - * Whitesmith - 75% Complete:(3/4) Incomplete:(1/4) - * Sniper - 88% - Complete:(3/4) Incomplete:(1/4) - * Assassin Cross - 60% Complete:(3/5) Incomplete:(2/5) -- 2-2-1 Skills (Advanced 2-2 Job Skills) - 47% - * Paladin - 65% - * Champion - 100% - * Professor - 100% - * Stalker - 65% - * Creator - 0% - * Clown - 0% - * Gypsy - 0% -- Pet Skills - 95% - * Loot Skills - 100% - * Buff Skills - 100% - * Attack Skills - 90% - * Assist Skills - 100% -- Equipment Breaking System - 50% - * Weapon Breaking - 85% - * Armor Breaking - 80% - * Equipment Repair - 80% -- PK Server Mode - ??% - * Need more info on this mode to be called complete. --------------------------------------------------------------- -> eAthena - What we currently do not have --------------------------------------------------------------- -- Wedding System (In Progress!) --------------------------------------------------------------- --------------------------------------------------------------- - - --------------------------------------------------------------- --------------------------------------------------------------- -System Requirements --------------------------------------------------------------- -> Minimum System Requirements --------------------------------------------------------------- -800Mhz Processor -256MB RAM - -NOTE: For this setup, it's recommended to not load as many maps -and spawn as many monsters as it comes default with eAthena. -To do this, comment off unused maps and control monster spawn -rate using mob_count in battle_athena.conf. - --------------------------------------------------------------- -> Recommended System Requirements --------------------------------------------------------------- -1+Ghz Processor -512+MB RAM - -NOTE: For this setup, generally, running the eAthena default -should be fine. If you have alot of extra RAM, you might even -consider raising the mob_count in battle_athena.conf so that -there will be more than normal monsters in your server --------------------------------------------------------------- --------------------------------------------------------------- - - --------------------------------------------------------------- --------------------------------------------------------------- -Setting up eAthena --------------------------------------------------------------- -> Setting up a new eAthena --------------------------------------------------------------- -1. Run the setupwizard program. This will assist you in - configuring Athena for the first time. Just follow the - instructions in the program. -2. Edit motd.txt, grf-files.txt & .conf files as neccessary -3. If you want to add a user, go to tools and use the AddUser - tool -4. Run the login-server, char-server and map-server in the - main Athena directory -5. You're done! - --------------------------------------------------------------- -> Upgrading from older eAthena: --------------------------------------------------------------- -- From a release newer than 953 or 817: -1. Transfer your old /save/ folder contents (Athena.txt, - Account.txt, Storage.txt, etc.) to the new /safe/ folder -2. Transfer/Edit grf-files.txt, gm-account.txt and motd.txt as - neccessary -3. Transfer any extra custom NPCs to the /npc/ folder and - edit if neccessary -4. Edit .conf files to setup your server -5. You're done! - -NOTE: It is not recommended to transfer your DB files -as the DB files are constantly updated by the eAthena/jAthena -team. Just read your changes to the new DB files instead of -replacing the new DB file with your old one. --------------------------------------------------------------- -- From a release older than 670: -1. Transfer your old data files (Athena.txt, Account.txt, - Storage.txt, Pet.txt, etc) into the /save/ folder -2. Transfer/Edit grf-files.txt, gm-account.txt as neccessary -3. Transfer any extra custom NPCs/DBs to the new /npc/ folder - and edit if neccessary -4. Edit .conf files to setup your server -5. You're done! - -NOTE: It is not recommended to transfer your .conf files from -your old eAthena setup to this new one because there are always -changes and new additions to these .conf files all the time - -NOTE 2: It is also not recommended to transfer your DB files -as the DB files are constantly updated by the eAthena/jAthena -team. Just readd your changes to the new DB files instead of -replacing the new DB file with your old one. --------------------------------------------------------------- --------------------------------------------------------------- - - --------------------------------------------------------------- --------------------------------------------------------------- -Playing eAthena --------------------------------------------------------------- -1. Make sure all the files are setup properly (conf files) -2. Load eAthena - 2a. Run login-server - 2b. Run char-server - 2c. Run map-server -3. Wait for map-server to finish loading. -4. Play using a custom XML. --------------------------------------------------------------- --------------------------------------------------------------- - - --------------------------------------------------------------- --------------------------------------------------------------- -Frequently Asked Questions --------------------------------------------------------------- - -A: You're missing the cygwin dlls. Please get the latest dll at: - http://www.cygwin.com/snapshot. If you're unsure, asking - around in our IRC chatroom will get you around too, but - always remember - use common sense and search before asking. - -Q: My map-server won't load! It appears to be loading things - before it dissapeared suddenly! HELP! -A: Use command line to load map-server. It should tell you the - error. If you're missing a map, update your kRO Sakray or - uncomment the map from map_athena.conf. If you have an - errornous NPC, fix it or comment it off. Anything other than - that, feel free to ask around. - -Q: My map-server failed to load 'adata.grf'! Where do I find - this adata.grf? My map-server won't load without it! -A: The error that caused the map-server to not load is not the - adata.grf. You do NOT need to have adata.grf so that the map - server can load. The error is probably something else. - -Q: All 3 of the servers are loaded, but I am still having - problems accessing it! What do I do? -A: First, check the IPs in map_athena.conf and char_athena.conf. - If that's correct, check the ports to make sure they match. - If that's correct too, you probably cannot handle the server - load. Lower the monster spawning rate using mob_count in - battle_athena.conf and it should be fine. - -Q: You said eAthena has 2-2 skills. Well, I tried it and there - are no 2-2 skills when I use 2-2 characters! You lie! -A: No, I did not. You have an outdated Ragexe/Sakexe that does - not support 2-2 skills. Update it to a later one which does. - -Q: How do I start Guild Wars/War of Emperium??? HELP!!! -A: Read the help.txt for full list of commands that GMs can use. - @agitstart and @agitend is also listed there as commands to - start and end Guild Wars. - -Q: My Ragnarok Online crashed while playing with eAthena! What - do I do now? -A: Well, if your Ragnarok crashes, it's most probably not - anything to do with eAthena. Something is wrong with your - Ragnarok installation. Try reinstalling or updating. - -Q: Is eAthena compatible with mySQL? Can I use mySQL as the DB - instead of using text files? -A: Yes, eAthena is compatible with mySQL. A tutorial on how to - setup this is coming soon. - -Q: Is eAthena compatible with msSQL? Can I use msSQL as the DB - instead of using text files? -A: No, eAthena is not compatible with msSQL. You cannot use - msSQL with eAthena. - -Q: I found a bug! Where do I report it? -A: Drop the developers a line at the IRC chatroom. Or just post - it in the bug report forum. We check them out too. :) - -Q: I know alot of C and I'm able to help improve eAthena and - add new features. How can I join your development team? -A: Try talking to one of the current developers in the eAthena - channel. - -Q: What is this AthenaAdvanced/omniAthena that I keep hearing of? -A: Huh? What's that? - -Q: Why does eAthena crash, and how come you can't prevent this? -A: eAthena is a working in progress we never stated eAthena is - bug free, most likely no software is bugfree, if they state - this they are lying sons of beeps and you should sue them - for false advertisement. --------------------------------------------------------------- --------------------------------------------------------------- - - --------------------------------------------------------------- --------------------------------------------------------------- -Support --------------------------------------------------------------- -For support, first check the Frequent Asked Questions. -If the question doesn't exist, check the forums. Search before -posting to see if the question had been asked and answered. -If not, post and we'll try and help you. -Our forums is located at: http://eathena.deltaanime.net -You can also visit our IRC chatroom and ask your questions -there. -Our IRC chatroom is located at: irc.deltaanime.net #athena --------------------------------------------------------------- --------------------------------------------------------------- - - --------------------------------------------------------------- --------------------------------------------------------------- -Development --------------------------------------------------------------- -eAthena is based on the original Athena, by the Japanese -Development Team. A big thanks to them for working hard on -Athena. - -The eAthena Development Team: -AppleGirl -Akaru -Evera/Lorri -Wizputer -Valaris -Yor -Kalaspuff -Syrus22 -Darkchild -CLOWNISIUS -RichG -Kashy -Lupus - -NOTE: Sorry if I missed anyone while writing this. If you are -in the team but not included in this list, PM me. --------------------------------------------------------------- --------------------------------------------------------------- - - --------------------------------------------------------------- --------------------------------------------------------------- -Special Thanks and Shoutouts! --------------------------------------------------------------- -The eAthena development team would like to specially thank: -- the Japanese Development Team. A big thanks to them for - working hard on Athena which eAthena is based on. -- RoVeRT, our ex-developer. eAthena wouldn't have this many - features without him! -- sara-chan, who had also contributed alot to the development - of eAthena! Thanks! -- Gravity, for making Ragnarok Online. eAthena wouldn't even - exist if it wasn't for them! -- ASB for hosting our forum section :) -- Deltaanime for hosting our new official forums :) -- And others who gave continuously endless support to eAthena! -- fov and Kinko for their bugfixes. - -NOTE: Sorry if I missed anyone while writing this. If you are -in the team but not included in this list, PM me. --------------------------------------------------------------- --------------------------------------------------------------- - - --------------------------------------------------------------- --------------------------------------------------------------- -License: --------------------------------------------------------------- -eAthena is licensed under the GPL. Please refer to LICENSE in -your Athena folder for the full GPL License statement. --------------------------------------------------------------- --------------------------------------------------------------- diff --git a/doc/admin_packet.txt b/doc/admin_packet.txt deleted file mode 100644 index 670a038..0000000 --- a/doc/admin_packet.txt +++ /dev/null @@ -1,281 +0,0 @@ -=========================================================================== -=========================================================================== - DETAIL OF ADMINISTRATION PACKETS ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- - -=========================================================================== - COMMON PACKETS FOR ALL SERVERS ---------------------------------------------------------------------------- -S 7530 (void) - It's a request to obtain the version of the server. - Answer packet: 0x7531. - -R 7531 <major_version>.B <minor_version>.B <revision>.B <release_flag>.B <official_flag>.B <server_type>.B <mod_version>.w - It's the reply to a request about the server version (0x7530). - It gives the information about the version of the server. - release_flag : 0 = release, 1 = debug - official_flag: 0 = official, 1 = mod - server_type: 1 = login, 2 = char, 4 = inter, 8 = map (add all values if the server have more than 1 type) - -S 7532 (void) - End of connection (no reply is sended back) - -=========================================================================== - ADMINISTRATION PACKETS OF THE LOGIN-SERVER ---------------------------------------------------------------------------- - -NB: All information about an account can be obtain by an administration packet, except the password. - The login-server will never send back the password af an account. - If someone sniffs the password from the login-server, he can not obtain it. - But, it exists a packet to check the password. - It's to secure the password. - -CONNECTION SYSTEM IN ADMINSTRATION MODE - -S 7918 <encrypt_flag>.w <administration_password>.24(16)B - It's a request to obtain an (administration) connection on the login-server. - The packet size changes according to the encrypted password or not. - A non-encrypted password is sended with 24 bytes (plain text with NULL terminate), - and an encrypted password is sended with 16 bytes. - Answer packet: 0x7919. - encrypt_flag: 0 = plain text, 1 = md5 (key + password), 2 = md5 (password + key) - -R 7919 <flag>.B - It's the reply to a request for an (administration) connection (0x7918). - Flag: 0 = accepted, 1 = refused - -S 791a (void) - It's a request to obtain the encrypted key. This key is used to create the encrypted password. - This packet must be called before the packet 0x7918 if you want connect you with an encrypted password. - The reply is the packet 0x01dc, as like a player sends a connection request with the packet 0x01db. - -PACKETS OF ADMINISTRATION MODE - -R 791f (void) - Ready signal (no reply is sended back). NOT USED. - -S 7920 <start_id>.l <end_id>.l - It's a request to obtain an accounts list. - start_id: 0 for begining of the list, or presumed start id value of the first account. - end_id: 0 to go until the last id, or the upper id limit value that you want. - If 'end_id' is lower to 'start_id', you give no limit for the last id. - Answer packet: 0x7921. - -R 7921 <length>.w { <account_id>.l <GM_level>.B <account_name>.24B <sex>.B <count>.l <state>.l }.38B* - It's tje reply packet of the packet 0x7920. - It gives an accounts list. - If you receive at least an account, you must do an additional request (packet 0x7920 begining with the last received account id +1) - to be sure that you receive all asked accounts, because this packet is limited in size when it sends information. - if <state> is 7, there are 2 possibilities: banishement or state{Your are Prohibited to log in until %s}. - -S 7930 <account_name>.24B <password>.24B <sex>.B <E-mail>.40B - It's a request to create a new account. - If e-mail is not valid, the e-mail is replaced by the default e-mail (a@a.com). - The default e-mail is like no e-mail to protect your characters against a deletion. - Answer packet: 0x7931. - -R 7931 <account_id>.l <account_name>.24B - It's the reply to an account creation (0x7930). - If the account_id value is -1, the login-server fails to create the new account - (an account already exists with the same name, the request is invalid, etc.). - Otherwise, the account_id is the id of the new account. - -S 7932 <account_name>.24B - It's a request to delete an account. - Answer packet: 0x7933. - -R 7933 <account_id>.l <account_name>.24B - It's the reply to an account deletion (0x7932). - If the account_id value is -1, the login-server fails to delete the account (the account doesn't exist). - Otherwise, the account_id is the id of the deleted account. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - -S 7934 <account_name>.24B <password>.24B - It's a request to modify the password of an account. - Answer packet: 0x7935. - -R 7935 <account_id>.l <account_name>.24B - It's the reply to an password modification (0x7934). - If the account_id value is -1, the login-server fails to modify the password (the account doesn't exist). - Otherwise, the account_id is the id of the account that the login-server have modified the password. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - -S 7936 <account_name>.24B <state>.l <error_message>.20B - It's a request to modify the state of an account. - State: It's the state like the packet 0x006a +1. - Error_message: it's the message of the error code #6 = Your are Prohibited to login until <error_message> (packet 0x006a). - If state is 7 (6+1), the error_message is saved in the account. - For another state, the error_message is deleted (voided) in the account. - Answer packet: 0x7937. - -R 7937 <account_id>.l <account_name>.24B <state>.l - It's the reply to a state modification (0x7936). - If the account_id value is -1, the login-server fails to modify the state (the account doesn't exist). - Otherwise, the account_id is the id of the account that the login-server have modified the state. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - -S 7938 (void) - It's a request to obtain information about the servers connected to the login-server (servers list with details) - Answer packet: 0x7939. - -R 7939 <length>.w {<IP>.l <port>.w <server_name>.20B <#_of_users>.w <maintenance>.w <new>.w}.32B* - It's the reply to an request to obtain servers information (0x7938). - It returns all information about the servers connected on the login-server. - -S 793a <account_name>.24B <password>.24B - It's a request to test a password. REMEMBER: Never create a packet to send the password from the login-server. - Answer packet: 0x793b. - -S 793b <account_id>.l <account_name>.24B - It's the reply to a password check (0x793a). - If the account_id value is -1, the login-server doesn't valid the password (the account doesn't exist or the password is not the correct one). - Otherwise, the account_id is the id of the account that the login-server have checked the password. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - -S 793c <account_name>.24B <sex>.B - It's a request to modify the sex of an account. - Answer packet: 0x793d. - -R 793d <account_id>.l <account_name>.24B - It's the reply to a request to modify a sex (0x793c). - If the account_id value is -1, the login-server fails to modify the sex (the account doesn't exist or the sex is already the good sex). - Otherwise, the account_id is the id of the account that the login-server have modified the sex. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - -S 793e <account_name>.24B <GM_level>.B - It's a request to modify the GM level of an account. - Answer packet: 0x793f. - -R 793f <account_id>.l <account_name>.24B - It's the reply to a request to modify a GM level (0x793e). - If the account_id value is -1, the login-server fails to modify the GM level (the account doesn't exist, or GM_account file can not be modified or the GM level is already the good sex). - Otherwise, the account_id is the id of the account that the login-server have modified the GM level. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - -S 7940 <account_name>.24B <e-mail>.40B - It's a request to modify the email of an account. - Answer packet: 0x7941. - -R 7941 <account_id>.l <account_name>.24B - It's the reply to a request to modify an email (0x7940). - If the account_id value is -1, the login-server fails to modify the e-mail (the account doesn't exist). - Otherwise, the account_id is the id of the account that the login-server have modified the email. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - -S 7942 <account_name>.24B <length_of_memo>.w <memo>.(length_of_memo)B - It's a request to modify the memo of an account. - The length can be 0 to have a void memo. - Answer packet: 0x7943. - -R 7943 <account_id>.l <account_name>.24B - It's the reply to an request to modify a memo (0x7942). - If the account_id value is -1, the login-server fails to modify the memo (the account doesn't exist). - Otherwise, the account_id is the id of the account that the login-server have modified the memo. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - -S 7944 <account_name>.24B - It's a request to obtain (by the name) the id of an account. - Answer packet: 0x7945. - -R 7945 <account_id>.l <account_name>.24B - It's the reply to an request (by the name) to obtain an account id (0x7944). - If the account_id value is -1, the login-server fails to obtain the account id (the account doesn't exist). - Otherwise, the account_id is the id of the found account. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - -S 7946 <account_id>.l - It's a request to obtain (by the id) the name of an account. - Answer packet: 0x7947. - -R 7947 <account_id>.l <account_name>.24B - It's the reply to an request (by the id) to obtain an account name (0x7946). - If the account_name value is "" (void), the login-server fails to obtain the account name (the account id doesn't exist). - Otherwise, the account_name is the name of the found account. - -S 7948 <account_name>.24B <validity>.l - It's a request to set the validity date of an account. - This packet fixes an absolute validity time. - Answer packet: 0x7949. - -R 7949 <account_id>.l <account_name>.24B <validity>.l - It's the reply to an request to set the validity date of an account (0x7948). - If the account_id value is -1, the login-server fails to set the validity date (the account doesn't exist). - Otherwise, the account_id is the id of the account that the login-server have fixed the validity date. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - -S 794a <account_name>.24B <end_date_of_banishment>.l - It's a request to set the final date of a banishment of an account. - This packet fixes an absolute time for the end of the banishment. - Answer packet: 0x794b. - -R 794b <account_id>.l <account_name>.24B <end_date_of_banishment>.l - It's the reply to an request to set the final date of a banishment of an account (0x794a). - If the account_id value is -1, the login-server fails to set the final date of a banishment (the account doesn't exist). - Otherwise, the account_id is the id of the account that the login-server have fixed the final date of a banishment. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - -S 794c <account_name>.24B <+/-years_modification>.w <+/-months_modification>.w <+/-days_modification>.w <+/-hours_modification>.w <+/-minutes_modification>.w <+/-seconds_modification>.w - It's a request to adjust the final date of a banishment of an account. - This packet modifies the final date of a banishment by add/sustract of some parameters. - If you adjust a non-banished account, you fix a banishment with actual time + adjustments. - Answer packet: 0x794d. - -R 794d <account_id>.l <account_name>.24B <end_date_of_banishment>.l - It's the reply to an request to adjust the final date of a banishment of an account (0x794c). - If the account_id value is -1, the login-server fails to adjust the final date of a banishment (the account doesn't exist). - Otherwise, the account_id is the id of the account that the login-server have adjusted the final date of a banishment. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - Note: if value is impossible, the returned value is the (unchanged) value of the final date of the banishment. - -S 794e <broadcast_type>.W <length_of_message>.L <message>.(length_of_message)B - It's a request to send a broadcast to all map-servers. - The length can not be 0. - broadcast_type: - 0: normal (yellow) - 0x10: blue - Answer packet: 794f. - -R 794f <answaer>.W - It's the reply to an request to send a broadcast to all map-servers (794e). - If the answer value is -1, the login-server fails to send the message (no char-server are conected). - Otherwise, the answer is 0. - -S 7950 <account_name>.24B <+/-years_modification>.w <+/-months_modification>.w <+/-days_modification>.w <+/-hours_modification>.w <+/-minutes_modification>.w <+/-seconds_modification>.w - It's a request to adjust the validity date of an account. - This packet modifies the validity date by add/sustract of some parameters. - You can not adjust an unlimited validity date. - Answer packet: 0x7951. - -R 7951 <account_id>.l <account_name>.24B <validity>.l - It's the reply to an request to adjust the validity date of an account (0x7950). - If the account_id value is -1, the login-server fails to adjust the validity date (the account doesn't exist). - Otherwise, the account_id is the id of the account that the login-server have found to try the adjustement of the validity date. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - If the returned validity date is 0, the login-server haven't modify the validity date (the account have an unlimited validity, - the modification is impossible because the new date is too far in the future, etc...). - If the returned validity date is not 0, it's the new validity date of the account. - -S 7952 <account_name>.24B - It's a request (by name) to obtain complete information about an account. - Answer packet: 0x7953. - -R 7953 <account_id>.l <GM_level>.B <account_name>.24B <sex>.B <count>.l <state>.l <error_message>.20B <last_login_time>.24B <last_authorised_login_ip>.16B <email>.40B <validity_date>.l <until_ban_date>.l <length_of_memo>.w <memo>.(length_of_memo)B - It's the reply to an request to obtain complete information about an account (0x7952 and 0x7954). - It sends all informations about an account. - Reply of 0x7952: - If the account_id value is -1, the login-server fails to found the account (the account doesn't exist). - Otherwise, the account_id is the id of the found account. - The login-server returns the correct sensitive case account_name (use strcmpi to compare). - Reply of 0x7954: - If the account_name value is "" (void), the login-server fails to found the account (the account id doesn't exist). - Otherwise, the account_name is the name of the found account. - -S 7954 <account_id>.l - It's a request (by id) to obtain complete information about an account. - Answer packet: 0x7953. - -S 7955 - It's a request to re-load GM file definition. - Answer packet: NONE. - diff --git a/doc/agitdb_ref.txt b/doc/agitdb_ref.txt deleted file mode 100644 index aeb2d41..0000000 --- a/doc/agitdb_ref.txt +++ /dev/null @@ -1,48 +0,0 @@ -■Agit DBに設定する項目(本鯖のScriptから推測。参考にどうぞ)
-
-mapName 城のMAP
-agitName 城の名称(jROだとValkyrie Realms○とか)
-GDID ギルドのID
-economy 商業投資記録(0:投資量最大 1:投資不可能 2:投資可能)
-defense 防御投資記録(0:投資量最大 1:投資不可能 2:投資可能)
-triggerE 商業投資回数
-triggerD 防御投資回数
-nextTime ?次にカプラに支払う時間
-payTime カプラに支払った時間
-createTime ?カプラと契約した時間
-visibleC カプラがいるか?(0:いない1:いる)
-visibleC [不明]
-visibleG0 ガーディアン1がいるか?(0:いない1:いる)
-visibleG1 ガーディアン2がいるか?(0:いない1:いる)
-visibleG2 ガーディアン3がいるか?(0:いない1:いる)
-visibleG3 ガーディアン4がいるか?(0:いない1:いる)
-visibleG4 ガーディアン5がいるか?(0:いない1:いる)
-visibleG5 ガーディアン6がいるか?(0:いない1:いる)
-visibleG6 ガーディアン7がいるか?(0:いない1:いる)
-visibleG7 ガーディアン8がいるか?(0:いない1:いる)
-
-■バグっぽいの
-・killmonsterでMVPがあるMobを消すと鯖停止するかも
- (MVP処理するべき相手が居ないから?)
-
-■GvG実装する上であるといいもの
-・文字列を代入できる鯖フラグ(既に有ったらすいません)
-
-・ガーディアンのAI(本鯖ではputmob(Athenaでmonster)とputmob2とでコマンドを分けることにより実装)
- ガーディアンAIの特徴
- 攻城戦時間以外はうろつくのみ
- 攻城戦時間になると城主ギルド以外に攻撃(同盟ギルドについては調べてません)
-
-・鯖共有フラグの保存(上のDBみたいなの)
- オリジナルスクリプトを作るうえでも便利なので、
- AgitDBとは別にあっても良いと思われる。
-
-・ギルドのマスターだけに働くコマンド(執事実装で必要)
- 既存のgetcharid(2)を使ってこんな感じがいいかと
- if (getcharid(2)==getmaster(GUILDID))
- (GUILDIDの部分にAgitDBのGDIDを代入して使用する)
-
-・フラッグへのギルドアイコンの貼り付けコマンド
-
-・ScriptからAgitDB各要素の呼び出し。
- strcharinfo(1)のような感じだといいかと
diff --git a/doc/client_packet.txt b/doc/client_packet.txt deleted file mode 100644 index 5b3ba44..0000000 --- a/doc/client_packet.txt +++ /dev/null @@ -1,1072 +0,0 @@ - - 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -#0x0040 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,108, 3, 2, - 3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6, -#0x0080 - 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0, - 7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6, - 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6, - 8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3, -#0x00C0 - 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 6, 2, 27, - 3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1, - 30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2, - 3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10, -#0x0100 - 2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1, - 10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16, - 6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1, - 6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26, -#0x0140 - 22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6, - 110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42, - -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14,186,182, - 14, 30, 10, 3, -1, 6,106, -1, 4, 5, 4, -1, 6, 7, -1, -1, -#0x0180 - 6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6, - 90, 86, 24, 6, 30,102, 9, 4, 8, 4, 14, 10, 4, 6, 2, 6, - 3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4, - 11, 7, -1, 67, 12, 18,114, 6, 3, 6, 26, 26, 26, 26, 2, 3, -#0x01C0 - 2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 0, 9, 9, 29, 6, 28, - 8, 14, 10, 35, 6, 8, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6, - 30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1, - -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10, -#0x200 - 26, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 19, - -S クライアントから見て送信 -R クライアントから見て受信 - -B バイト -w ワード=2B -l ロングワード=4B -* 0個以上くりかえし - -S 0064 <version>.l <account name>.24B <password>.24B <version2>.B - アカウントID&パスワード送信 -S 0065 <account ID>.l <login ID1>.l <login ID2>.l ?.2B <sex>.B - キャラセレ鯖接続要求 -S 0066 <charactor number>.B - キャラクタ選択要求 -S 0067 <charactor name>.24B <param etc>.11B - キャラクタ作成要求 -S 0068 <charactor ID>.l <mail address>.40B - キャラクタ削除要求 -R 0069 <len>.w <login ID1>.l <account ID>.l <login ID2>.l ?.32B <sex>.B {<IP>.l <port>.w <server name>.20B <login users>.w <maintenance>.w <new>.w}.32B* - login成功&鯖情報 -R 006a <error No>.B - login失敗 その1 - err No=00 未登録のIDです - err No=01 パスワードが違います - err No=02 使用期間が終了しています - err No=03 サーバーから接続拒否されました - err No=04 解約されたID、またはアカウントブロックされているIDです - err No=05 最新のパッチではありません - err No=06 解約されたID、またはアカウントブロックされているIDです - err No=07 サーバーが混雑しています -R 006b <len>.w <charactor select data>.106B* - キャラセレ鯖接続成功&キャラクタデータ - <charactor select data> = <charactor ID>.l <base exp>.l <zeny>.l <job exp>.l <job level>.l ?.8B <option>.l <karma>.l <manner>.l ?.2B <HP>.w <MaxHP>.w <SP>.w <MaxSP>.w <speed>.w <class>.w <hair>.w <weapon>.2w <base level>.w <skill point>.w <head_bottom>.w <sheild>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <name>.24B <STR>.B <AGI>.B <VIT>.B <INT>.B <DEX>.B <LUK>.B <charactor number>.B ?.B -R 006c <error No>.B - キャラクタ選択失敗 -R 006d <charactor select data>.106B - キャラクタ作成成功 -R 006e <error No>.B - キャラクタ作成失敗 -R 006f - キャラクタ削除成功 -R 0070 <error No>.B - キャラクタ削除失敗 - err No=00 メールアドレスが違う - err No=01 削除が拒否された -R 0071 <charactor ID>.l <map name>.16B <ip>.l <port>.w - キャラクタ選択成功&マップ名&ゲーム鯖IP/port -S 0072 <account ID>.l <charactor ID>.l <login ID1>.l <login ID2>.l <sex>.b - ゲーム鯖接続要求 -R 0073 <server tick>.l <coordidate>.3B ?.2B - ゲーム鯖接続成功&サーバ側1ms時計&出現位置 -R 0078 <ID>.l <speed>.w <opt1>.w <opt2>.w <option>.w <class>.w <hair>.w <weapon>.w <head option bottom>.w <sheild>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.l <emblem>.l <manner>.w <karma>.B <sex>.B <X_Y_dir>.3B ?.B ?.B <sit>.B <Lv>.B - マップロード時&移動時用、向き付き用キャラ情報? -R 0079 <ID>.l <speed>.w <opt1>.w <opt2>.w <option>.w <class>.w <hair>.w <weapon>.w <head option bottom>.w <sheild>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.l <emblem>.l <manner>.w <karma>.B <sex>.B <X_Y_dir>.3B ?.B ?.B <Lv>.B - テレポ等の表示範囲内沸きキャラ用、向き付き無しキャラ情報? -R 007b <ID>.l <speed>.w <opt1>.w <opt2>.w <option>.w <class>.w <hair>.w <weapon>.w <head option bottom>.w <server tick>.l <sheild>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.l <emblem>.l <manner>.w <karma>.B <sex>.B <X_Y_X_Y>.5B ?.B ?.B ?.B <Lv>.B - 表示範囲内キャラ移動情報 -R 007c <ID>.l <speed>.w ?.6w <class>.w ?.7w <X_Y>.3B ?.2B - NPC用表示範囲内キャラ情報 -S 007d - mapロード終り -S 007e <client tick>.l - クライアント側1msタイマ送信 -R 007f <server tick>.l - サーバ側1msタイマ送信 -R 0080 <ID>.l <type>.B - type=00 キャラ消滅 (画面外移動。死体消滅等?) - type=01 キャラ死亡 - type=02 キャラ消滅 (logout等?) - type=03 テレポート (テレポ,蝿,蝶等?) -R 0081 <type>.B - login失敗 その2 - type=01 サーバー接続終了 - type=02 同じIDで他の使用者がログインしました - type=03 サーバーとの同期に失敗しました - type=04 地域の収容人員超過で接続できません - type=05 18歳以下は接続できません - type=06 決済されたアカウントではありません - type=07 サーバーが混雑しています - type=08 前の接続情報が残っています - type=0b アカウントが保留されました - type=0c 課金システム変更のため、一時終了します - type=0d IPが一致しないため、接続を終了します - type=10 有料サービスになりました - type=11 チケットが買われていないか、有効期限が切れています -S 0085 <X_Y>.3B - 移動要求 -R 0087 <server tick>.l <X_Y_X_Y>.5B ?.B - 移動応答 -R 0088 <ID>.l <X>.w <Y>.w - 移動途中停止 -S 0089 <target ID>.l <type>.B - type=00 targetを1回殴る - type=02 座る - type=03 立ち上る - type=07 targetを殴り続ける -R 008a <src ID>.l <dst ID>.l <server tick>.l <src speed>.l <dst speed>.l <param1>.w <param2>.w <type>.B <param3>.w - type=00 param1=0 miss - type=00 param1:ダメージ(の合計?) param2:分割数 param3:アサシン2刀流逆手ダメージ - NPCからの攻撃の場合、param2,param3はゴミデータ - speedはPCの場合内部ASPDと一致 - type=01 itemを拾う ID*2以外ゴミ - type=02 座る src ID以外ゴミ - type=03 立つ src ID以外ゴミ - type=08 複数攻撃 - type=09 ダメージモーションなしにダメージだけ表示される物(インデュア) - type=0a クリティカル - type=0b 完全回避 -S 008c <len>.w <str>.?B - 通常発言送信。チャット中はチャット内発言用になる - 先頭の"<nick> : "の部分はクライアント側で付ける事 -R 008d <len>.w <ID>.l <str>.?B - IDさんの発言受信。チャット中はチャット内発言用になる -R 008e <len>.w <str>.?B - 自分の発言受信。チャット中はチャット内発言用になる -S 0090 <ID>.l <type?>.B - NPCに話しかける。typeは01しか見た事無し -R 0091 <map name>.16B <X>.w <Y>.w - 鯖内マップ間移動、テレポ,蝿等用 -R 0092 <map name>.16B <X>.w <Y>.w <IP>.l <port>.w - 鯖間移動 -R 0093 - 8月中に1回だけ観測。謎 -S 0094 <ID>.l - IDのキャラ名等要求。0095か0195の返答があるはず -R 0095 <ID>.l <nick>.24B - NPC,ギルド未所属PCの0094への返答 - 0193 <charID>.l で問い合わせて - 0194 <charID>.l <name>.24B の応答で得てます。 - -S 0096 <len>.w <nick>.24B <message>.?B - wis送信 -R 0097 <len>.w <nick>.24B <message>.?B - wis受信 -R 0098 <type>.B - type=00 wis送信成功 - type=01 wis相手がloginしてない? - type=02 wis相手からignoreされてる? -S 0099 - 神の声送信 -R 009a <len>.w <message>.?B - GMからの天の声 -S 009b <head dir>.w <dir>.B - 体&頭の方向変更要求。クライアントへの応答は無い模様 - dirは00〜07で体の向き。00で北から反時計回りに45°単位で07まで - head dirは00,01,02で頭の向き。00で体と同じ、01が右、02が左 -R 009c <ID>.l <head dir>.w <dir>.B - IDの体&頭の方向変更 -R 009d <ID>.l <item ID>.w <identify flag>.B <X>.w <Y>.w <amount>.w <subX>.B <subY>.B - 移動等で床アイテムが画面内に入ってきた時 -R 009e <ID>.l <item ID>.w <identify flag>.B <X>.w <Y>.w <subX>.B <subY>.B <amount>.w - item drop。何故か009dとマス目内位置&個数が入れ変っている -S 009f <ID>.l - IDの床アイテムを拾う -R 00a0 <index>.w <amount>.w <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w <equip type>.w <type>.B <fail>.B - fail=02 取得失敗? - fail=06 ルート権無し。取得失敗 -R 00a1 <ID>.l - IDの床アイテム消去 -S 00a2 <index>.w <amount>.w - 所有アイテムを落す -R 00a3 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B}.10B* - 所有消耗品&収集品リスト -R 00a4 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <equip type>.w <equip point>.w <attribute?>.B <refine>.B <card>.4w}.20B* - 所有装備リスト -R 00a5 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B}.10B* - カプラさんに預けてある消耗品&収集品リスト -R 00a6 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <equip type>.w <equip point>.w <attribute?>.B <refine>.B <card>.4w}.20B* - カプラさんに預けてある装備リスト -S 00a7 <index>.w <ID>.l - 所持アイテムindexを使用する。IDは自分のみ? -R 00a8 <index>.w <amount>.w <type>.B - アイテム使用応答。type=00の場合使用失敗? amountもゴミの模様 - type=01の場合成功で、amountは使用後の残り個数 -S 00a9 <index>.w <equip type>.w - アイテム装備 -R 00aa <index>.w <equip point>.w <type>.B - アイテム装備応答。type=00の場合装備失敗? equip pointもゴミの模様 -S 00ab <index>.w - 装備解除 -R 00ac <index>.w <equip point>.w <type>.B - 装備解除応答。type=00の場合失敗? equip pointもゴミの模様 -R 00af <index>.w <amount>.w - アイテム数減少。amount個だけ減らす -R 00b0 <type>.w <val>.l - 色々な能力値の更新。以下type:対応する数値を列挙 - 0000:speed 0003:悪行値 0004:マナーポイント 0005:HP 0006:MaxHP - 0007:SP 0008:MaxSP 0009:ステータスポイント 000b:ベースレベル - 000c:スキルポイント 0018:重量(表示されてる数字の10倍) - 0019:最大重量(表示されてる数字の10倍) - 0029:ATK前 002a:ATK後 002b:MATK前 002c:MATK後 - 002d:DEF前 002e:DEF後 002f:MDEF前 0030:MDEF後 - 0031:HIT 0032:FLEE前 0033:FLEE後 0034:クリティカル - 0035:ASPD(2ms単位の時間?) 0037:ジョブレベル - 0082:謎 ATK後と同じ数字? -R 00b1 <type>.w <val>.l - 色々な能力値の更新。以下type:対応する数値を列挙 - 0001:ベース側経験値 0002:ジョブ側経験値 0014:zeny - 0016:ベース側必要経験値 0017:ジョブ側必要経験値 - β1では00b0はvalがshort、00b1はvalがlongという使い分けがあったんだけど - 今となっては差が無くなって、盲腸みたいなもの? -S 00b2 <type>.B - type=00 死亡時リスタート - type=01 キャラセレ要求 -R 00b3 <type>.B - type=01 キャラセレ応答 -R 00b4 <len>.w <ID>.l <str>.?B - IDのNPCからのメッセージ -R 00b5 <ID>.l - IDのNPCとのメッセージウィンドウに"NEXT"アイコンを出す -R 00b6 <ID>.l - IDのNPCとのメッセージウィンドウに"CLOSE"アイコンを出す -R 00b7 <len>.w <ID>.l <str>.?B - IDのNPCの会話で選択項目表示。各項目は':'で区切られる -S 00b8 <ID>.l <select>.B - IDのNPCの会話の選択。各項目に順に1〜が振られる。ffでキャンセル? -S 00b9 <ID>.l - IDのNPCとの会話。NEXTボタンを押した -S 00bb <type>.w <amount>.B - ステータスup要求。typeは000dから0012が順にSTR,AGI,VIT,INT,DEX,LUKに対応 -R 00bc <type>.w <fail>.B <val>.B - ステータスup応答。fail=01なら成功。typeは00bbと同じ。valは上った後の数字 - 失敗例は見た事無いので謎。ステータスポイントが足りない状態で - 00bbを発行できるクライアントが有れば、fail=00になるのではないかと予想 -R 00bd <status point>.w <STR>.B <STRupP>.B <AGI>.B <AGIupP>.B <VIT>.B <VITupP>.B <INT>.B <INTupP>.B <DEX>.B <DEXupP>.B <LUK>.B <LUKupP>.B <ATK>.w <ATKbonus>.w <MATKmax>.w <MATKmin>.w <DEF>.w <DEFbonus>.w <MDEF>.w <MDEFbonus>.w <HIT>.w <FLEE>.w <FLEEbonus>.w <critical>.w ?.w - まとめてステータス情報を送るパケット -R 00be <type>.w <val>.B - 必要ステータスポイント更新パケット。typeは0020〜0025が順にSTR〜LUKに対応 -S 00bf <type>.B - エモーションを出す。typeは00-0c(,0d)がALT+1〜ALT+9,ALT+0,チョキ,グー,パー(,韓国旗)に対応 - 00=! 01=? 02=うれしい(♪) 03=ハート 04=汗 05=あはは(電球) - 06=いやだな(#) 07=怒り(もやもや)08=お金($) 09=… 0a=チョキ - 0b=グー 0c=パー 0d=韓国旗 0e=大きいハート 0f=ありがとう(thanks) - 10=無念 11=ごめん(sorry) 12=笑い 13=汗かき 14=あの - 15=最高(GoodJob)16=キョロキョロ 17=ショック 18=まる 19=バツ - 1a=ヘルプ(help) 1b=go 1c=えーん 1d=くすくす 1e=ちゅ - 1f=ちゅちゅ 20=ふん 21=うんうん -R 00c0 <ID>.l <type>.B - IDの人がエモーションを出した。typeは00bfと同じ -S 00c1 - login人数問い合わせ -R 00c2 <val>.l - login人数応答 -R 00c3 <ID>.l <type>.B <val>.B - 見た目変更。typeは00で本体(転職時等)、02が武器、03が頭(下)、04が頭(上)、05が頭(中)、08が盾 -R 00c4 <ID>.l - 話かけたNPCが商人だったのでbuy/sell選択窓出 -R 00c5 <ID>.l <type>.B - buy/sell選択。type=00ならbuy。type=01ならsell -R 00c6 <len>.w {<value>.l <DCvalue>.l <type>.B <item ID>.w}.11B* - NPCのお店buy選択時。DCvalueは商人DC後の値段 -R 00c7 <len>.w {<index>.w <value>.l <OCvalue>.l}.10B* - NPCのお店sell選択時。OCvalueは商人OC後の値段 -S 00c8 <len>.w {<amount>.w <item ID>.w}.4B* - NPCのお店から買う -S 00c9 <len>.w {<index>.w <amount>.w}.4B* - NPCのお店に売る -R 00ca <type>.B - NPCから購入終了。type=00成功 -R 00cb <type>.B - NPCへ売却終了。type=00成功 -S 00cc <ID>.l - GM用右クリックメニュー「(name)使用者強制終了」使用 -R 00cd <ID?>.l - GM用右クリックメニュー「(name)使用者強制終了」の応答 - <ID>が0の場合は失敗と表示。(このパケットはただの応答です。接続終了の機能はありません。) -S 00cf <nick>.24B <type>.B - type=00 nickからの発言受け付け拒否 (/ex nick) - type=01 nickからの発言受け付け許可 (/in nick) -S 00d0 <type>len.B - type=00 全ての発言受け付け拒否 (/exall) - type=01 全ての発言受け付け許可 (/inall) -R 00d1 <type>.B <fail>.B - fail=00 発言受け付け拒否成功 - fail=01 発言受け付け拒否失敗 -R 00d2 <type>.B <fail>.B - fail=00 全発言受け付け拒否成功 - fail=01 全発言受け付け拒否失敗 -S 00d5 <len>.w <limit>.w <pub>.B <passwd>.8B <title>.?B - チャット立て。ここからチャット関係が続くけど調べが甘いので補完よろ -R 00d6 <fail>.B - チャット立て応答 -R 00d7 <len>.w <owner ID>.l <chat ID>.l <limit>.w <users>.w <pub>.B <title>.?B - 画面内チャット情報 -R 00d8 <chat ID>.l - チャット消去 -S 00d9 <chat ID>.l <passwd>.8B - チャット参加要請 -R 00da <fail>.B - チャット参加失敗 -R 00db <len>.w <chat ID>.l {<index>.l <nick>.24B}.28B* - チャット参加者リスト -R 00dc <users>.w <nick>.24B - チャットへの参加者追加(?) -R 00dd <index>.w <nick>.24B <fail>.B - チャットから参加者抜け -S 00de <len>.w <limit>.w <pub>.B <passwd>.8B <title>.?B - チャットステータス変更 -R 00df <len>.w <owner ID>.l <chat ID>.l <limit>.w <users>.w <pub>.B <title>.?B - チャットステータス変更成功 -S 00e0 ?.l <nick>.24B - チャットルーム所有者変更要求? -R 00e1 <index>.l <nick>.24B - チャット参加者番号付け直し? -S 00e2 <nick>.24B - チャットkick -S 00e3 - チャット抜け -S 00e4 <ID>.l - 取り引き要求 -R 00e5 <nick>.24B - 取り引き要請受け -S 00e6 <type>.B - type=03 取り引き要請ok - type=04 取り引き要請キャンセル -R 00e7 <fail>.B - 取り引き要求応答 - fail=00 距離が遠過ぎ - fail=03 要請受けてくれた - fail=04 キャンセルされた? -S 00e8 <index>.w <amount>.l - アイテム追加。index=0でzeny追加。正規クライアントではzenyは00ebの直前のみ -R 00e9 <amount>.l <type ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w - 相手方からのアイテム追加 -R 00ea <index>.w <fail>.B - fail=00 アイテム追加成功 - fail=01 追加失敗。相手側重量オーバ -S 00eb - アイテム追加完了(ok押し) -R 00ec <fail>.B - fail=00 自分からのok受領 - fail=01 相手からのok受領 -S 00ed - 取り引きキャンセル -R 00ee - 取り引きがキャンセルされました -S 00ef - 取り引き許諾(trade押し) -R 00f0 - 取り引き完了 -R 00f2 <num>.w <limit>.w - カプラさん許容アイテム個数&現状 -S 00f3 <index>.w <amount>.l - カプラさん倉庫にアイテム放り込み -R 00f4 <index>.w <amount>.l <type ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w - カプラさん倉庫のアイテム追加 -S 00f5 <index>.w <amount>.l - カプラさん倉庫からアイテム取り出し要求 -R 00f6 <index>.w <amount>.l - カプラさん倉庫からアイテム取り出し応答 -S 00f7 - カプラさん倉庫閉じ要求 -R 00f8 - カプラさん倉庫閉じ応答 -S 00f9 <party name>.24B - パーティ作成要求 -R 00fa <fail>.B - パーティ作成応答 - fail=00 「パーティーを結成しました。」 - fail=01 「同じ名前のパーティーがあります。」 - fail=02 「すでにパーティーに加入しています。」 -R 00fb <len>.w <party name>.24B {<ID>.l <nick>.24B <map name>.16B <leader>.B <offline>.B}.46B* - パーティ情報まとめて送り -S 00fc <ID>.l - パーティ勧誘する -R 00fd <nick>.24B <fail>.B - fail=00 相手は既にパーティに入っていた - fail=01 相手に拒否された - fail=02 勧誘成功 -R 00fe <ID>.l <party name>.24B - パーティに誘われた -S 00ff <ID>.l <fail>.l - パーティに誘われた時の返答。fail=1 ok返答? -S 0100 - パーティ脱退要求 -R 0101 <exp>.w <item?>.w - パーティ設定現状? exp=2の場合は公平配分設定失敗? -S 0102 <exp>.w <item?>.w - パーティ設定変更 -R 0104 <ID>.l ?.l <X>.w <Y>.w <offline>.B <party name>.24B <nick>.24B <map name>.16B - パーティ1人分情報更新 -R 0105 <ID>.l <nick>.24B <fail>.B - nickさんがパーティから離脱 -R 0106 <ID>,l <HP>.w <MaxHP>.w - パーティメンバHP更新 -R 0107 <ID>.l <X>.w <Y>.w - パーティメンバ位置更新 -S 0108 <len>.w <message>.?B - パーティ内発言 -R 0109 <len>.w <ID>.l <message>.?B - パーティ内発言受信 -R 010a <type ID>.w - MVPアイテム取得 -R 010b <exp>.l - MVP経験値取得 -R 010c <ID>.l - MVPキャラ表示 -R 010e <skill ID>.w <lv>.w <sp>.w <range>.w <up>.B - スキル情報更新。spは未使用? -R 010f <len>.w {<skill ID>.w <target type>.w ?.w <lv>.w <sp>.w <range>.w <skill name>.24B <up>.B}.37B* - スキル情報の塊。skill nameは一部流れて来ない物がある>AL_PNEUMA,PR_SLOWPOISON等 - target typeは0-パッシブ、1-敵、2-場所、4-即時発動、16-味方 - lv=0 up=0の場合はリストに出してない? -R 0110 <skill ID>.w <basic type>.w ?.w <fail>.B <type>.B - fail=00の時にスキル利用失敗? - type 00:basic typeの方 01:SP不足 02:HP不足 03:memo無し 04:delay中 - 05:お金無し(めまー) 06:武器がよろしくない 07:赤ジェム無し 08:青ジェム無し 09:謎 - basic type 00:取り引き 01:emotion 02:座り 03:チャット 04:パーティ - 05:shout? 06:PK 07:マナーポイント -R 0111 <skill ID>.w <target type>.w ?.w <lv>.w <sp>.w <range>.w <skill name>.24B <up>.B - 010fの1つ分。β2だと未使用? - 20040415転職時に観測 -S 0112 <skill ID>.w - スキルlvup要求 -S 0113 <level>.w <skill ID>.w <ID>.l - IDをターゲットにskillを使う -R 0114 <skill ID>.w <src ID>.l <dst ID>.l <server tick>.l <src speed>.l <dst speed>.l <param1>.w <param2>.w <param3>.w <type>.B - 攻撃系スキルエフェクト@ - type=04 火壁で観測 type=06とほぼ同じ? - type=05 NB/FBlの分散したダメージ用? - type=06 単発もの? param1はダメージ合計、param2はlevel、param3は1固定と予想 - type=07 ダメージ表示無し? - type=08 連打もの? param1はダメージ合計、param2はlevel、param3は分割数と予想 - type=09 ダメージモーションなしにダメージだけ表示される物(インデュア)と思ったのだがダメージモーションが出る物。(機能は謎) -R 0115 <skill ID>.w <src ID>.l <dst ID>.l <server tick>.l <src speed>.l <dst speed>.l <X>.w <Y>.w <param1>.w <param2>.w <param3>.w <type>.B - 弾き飛ばし有り攻撃系スキルエフェクト - type=05 ダメージ&弾き飛ばし。param1はダメージ合計、param2はlevel、param3は分割数と予想 - type=06 爆心地? 少なくともparam1はゴミの模様 - type=09 ダメージモーションなしにダメージだけ表示される物(インデュア)と思ったのだがダメージモーションが出る物。(機能は謎) -S 0116 <level>.w <skill ID>.w <X>.w <Y>.w - (X,Y)をターゲットにskillを使う -R 0117 <skill ID>.w <src ID>.l <val>.w <X>.w <Y>.w <server tick>.l - 場所相手のスキルエフェクト表示。valはレベルか、一部固さ?(氷壁) -S 0118 - 攻撃キャンセル -R 0119 <ID>.l <param1>.w <param2>.w <param3>.w ?.B - 見た目変更 - param1=02 フロストダイバで凍り漬け? - param2=01 毒? - param2=20 ANGELUS状態? - param3=01 サイトかルワッチ? - param3=0b ハイディング状態? - param3=0b クローキング状態? - param3=0d カート付き - param3=0e 鷹付き - param3=0f ペコペコ乗り - -R 011a <skill ID>.w <val>.w <dst ID>.l <src ID>.l <fail>.B - 非ダメージ系スキル表示。ヒールの場合valは回復量 - fail=00の場合失敗ぽいが、スチール以外では見た事無し -S 011b <skill ID>.w <map name>.16B - 011cへの応答。使わない場合"cancel"、マップ内ランダムの場合"Random"を送る -R 011c <skill ID>.w <map1>.16B <map2>.16B <map3>.16B <map4>.16B - テレポ/ポタの場所選択。 - テレポの場合、Random/セーブ場所、ポタの場合、セーブ場所/memo1/memo2/memo3となる - マップ名のみ送られる -S 011d - 現在居る所をメモ要求 -R 011e <fail>.B - fail=00 メモ成功 - fail=01 メモ失敗 -R 011f <dst ID>.l <src ID>.l <X>.w <Y>.w <type>.B <fail>.B - スキル効能地作成 - type 7e:SW 7f:火壁 80:ポタ発動中 81:ポタ発動前 83:サンク 85:フニューマ - 86:バーミリオン 8c:トーキーボックス発動時 8d:氷壁 8e:くあぐまいやー 91:あんくるすねあ - 93:らんどまいん 97:?? 99:トーキーボックス発動前 - 他情報求む -R 0120 <ID>.l - スキル効能地消去 -R 0121 <num>.w <num limit>.w <weight>.l <weight limit>l - カートの種類&重さの現在値&上限 -R 0122 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <equip type>.w <equip point>.w <attribute?>.B <refine>.B <card>.4w}.20B* - カート内アイテム。装備品 -R 0123 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B}.10B* - カート内アイテム。消耗品/収集品 -R 0124 <index>.w <amount>.l <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w - カートにアイテム追加 -R 0125 <index>.w <amount>.l - カートからアイテム削除 -S 0126 <index>.w <amount>.l - カートにアイテムを入れる -S 0127 <index>.w <amount>.l - カートからアイテムを取り出す -S 0128 <index>.w <amount>.l - カプラさんからカートへアイテムを移す -S 0129 <index>.w <amount>.l - カートからカプラさんへアイテムを移す -R 012c <fail>.B - fail=00 「重量オーバーです。」 - fail=01 「アイテム最大種類数を超過しました。」 -R 012d <num>.w - 露店開設。アイテムリスト要求。numは置ける最大数 -S 012e - 露店閉鎖 -S 012f <len>.w <message>.80B {<index>.w <amount>.w <value>.l}.8B* - 露店開設、露店名&アイテム,値段リスト -S 0130 <ID>.l - 露店アイテムリスト要求 -R 0131 <ID>.l <message>.80B - 露店看板表示 -R 0132 <ID>.l - 露店看板消去 -R 0133 <len>.w <ID>.l {<value>.l <amount>.w <index>.w <type>.B <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w}.22B - 露店アイテムリスト -S 0134 <len>.w <ID>.l {<amount>.w <index>.w}.4B* - 露店アイテム購入 -R 0135 <index>.w <amount>.w <fail>.B - 露店アイテム購入失敗。 - fail=1 「お金が足りません。」 - fail=2 「重量オーバーです。」 -R 0136 <len>.w <ID>.l {<value>.l <index>.w <amount>.w <type>.B <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w}.22B* - 露店開設成功 -R 0137 <index>.w <amount>.w - 露店アイテム販売報告 -R 0139 <ID>.l <X>.w <Y>.w <X2>.w <Y2>.w <range>.w - IDの敵は(X,Y)に居て自分は(X2,Y2)に居るので攻撃が届きませんでした - 攻撃可能距離はrangeなので、近寄って下さい? -R 013a <val>.w - 攻撃射程 -R 013b <type>.w - 各種メッセージ表示。3=矢が装備できました -R 013c <ID>.w - 装備された矢のItemID。0で、未装備状態。 -R 013d <type>.w <val>.w - HP回復スキル/SP回復スキルによる回復 - type=5ならHP type=7ならSP -R 013c <index>.w - 装備している矢 - -R 013e <src ID>.l <dst ID>.l <X>.w <Y>.w <lv?>.w ?.w <wait>.l - スキル詠唱中。PC/NPCが相手の場合は(X,Y)は0。場所がターゲットの場合はdst IDは0になる - - 0x013e の offset+16(dword) はスキル属性です(調査済)。 - 00:無 01:水 02:地 03:火 04:風 05:毒 06:聖 07:暗 08:念 09:死 - 将来的に、詠唱中のエフェクトが属性で変わるのかと。 - - waitはms単位かな? -R 0141 <type>.l <base>.l <bonus>.l - ステータス情報。typeは0dから12が順にSTR,AGI,VIT,INT,DEX,LUKに対応 - base+bonusと表示される -R 0142 <ID>.l - 数値入力用窓表示 -S 0143 <ID>.l <amount>.l - 0142の窓に入力した数値の送信 -R 0144 <ID>.l <type>.l <X>.l <Y>.l <point ID>.B <color>.3B ?.B - 案内員用、マップ上アイコン表示パケット - type=1 アイコンを表示 - type=2 アイコンを消去 -R 0145 <file name>.16B <type>.B - (今の所)カプラさんcutin表示 - type=02 表示 - type=ff 消去 -S 0146 <ID>.l - IDのNPCとの会話。CLOSEボタンを押した。ack無しにNPCメッセージウィンドを同時に閉じる -R 0147 <skill ID>.w <target type>.w ?.w <lv>.w <sp>.w <range>.w <skill name>.24B <up>.B - アイテム利用の結果一時的に得られたスキル情報 -R 0148 <ID>.l - リザレクションの相手決め? @ β1 -S 0149 <ID>.l <type>.B <time>.w - IDにチャット禁止時間を付加 type=0 マイナス type=1 プラス - tymeは分単位 -R 014a <fail>.l - マナーポイントを与えた結果。fail=0 成功 fail=1 失敗 -R 014b <type>.B <nick>.24B - マナーポイントを貰った。type=00 プラス type=01 マイナス -R 014C <len>.w (<type>.l <guildID>.l <guild name>.24B).* - 同盟・敵対ギルド表示 - type=0 同盟 - type=1 敵対 -S 014D - ギルド情報表示開始? -R 014E <type?>.l - type=0x57 一般ギルド団員 - type=0xD7 ギルドマスター -S 014F <page>.l - ギルド表示タブ送信 -R 0150 <guildID>.l <guildLv>.l <接続数>.l <定員>.l <Avl.lvl>.l <経験値>.l <next_exp>.l <上納ポイント>.l <性向左右VW>.l <性向上下RF>.l <人数?>.l <guild name>.24B <guild master>.24B <本拠地>.16B - ギルド情報 -S 0151 <guild ID>.l - エンブレム要求 -R 0152 <len>.w <guild ID>.l <emblem ID(変更回数?)>.l <emblem data>.?B - エンブレムイメージ送付 -S 0153 <len>.w <emblem data>.?B - エンブレムイメージ変更 -R 0154 <len>.w {<accID>.l <charactorID>.l <髪型>.w <髪の色>.w <性別?>.w <job>.w <lvl?>.w <上納経験値>.l <online>.l <Position>.l <メモ?>.50B <nick>.24B}* - ギルドメンバリスト -S 0155 <len>.w {<accID>.l <charaID>.l <index>.l}.12B* - 役職変更 -R 0156 <len>.w {<accID>.l <charaID>.l <index>.l}.12B* - 役職変更通知 -S 0159 <guildID>.l <accID>.l <charID>.l <mess>.40B - ギルド脱退送信 -R 015A <nic>.24B <mess>.40B - ギルド脱退(全員)受信 -S 015B <guildID>.l <accID>.l <charID>.l <mess>.40B - ギルド追放送信 -R 015C <nick>.24B <mess>.40B <アカウントID>.24B - ギルド追放(全員)受信 -S 015D <guild name>.24B <?>.16B - ギルド解散 -R 015E <fail>.l - ギルド解散正否通知 - 0x00:成功 - 0x01:住民登録番号不一致 -R 0160 <len>.w {<index>.l <mode>.l <index>.l <exp_mode>.l}.16B - 職位情報 -S 0161 <len>.w {<index>.l <mode>.l <index>.l <exp_mode>.l <nickname>.24B}.40B* - 職位変更 -R 0162 <len>.w <skill_point>.w {<skill ID>.w <target type>.w ?.w <lv>.w <sp>.w <range>.w <skill name>.24B <up>.B}.37B* - ギルドスキル -R 0163 <len>.w { <nick>.24B <アカウントID>.24B <追放理由>.40B }.88B* - ギルド追放リスト -S 0165 <myaccID>.l <guild name>.24B - ギルド作成 -R 0166 <len>.w {<index>.l <name>.24B }.28B* - 職位名リスト -R 0167 <type>.b - ギルド作成合否 - type = 0 ギルド作成成功 - type = 1 すでにギルドに所属している - type = 2 同名のギルドがある - type = 3 エンペリウム無し -S 0168 <TargetAccID>.l <sourceAccID>.l <myCharactorID>.l - ギルド勧誘 -R 0169 <type>.B - ギルド勧誘結果 - type = 0 他のギルドに加入している - type = 1 拒否された - type = 2 加入した - type = 3 定員を超過 -R 016A <guild ID>.l <guild name>.24B - ギルド勧誘された -S 016B <guild ID>.l <type>.l - ギルド勧誘返信 - type=0 拒否する - type=1 許諾する -R 016c <guild ID>.l <emblem ID>.l <mode>.l ?.5B <guild name>.24B - login時ギルド情報 - mode=自分の所属職位のmode -R 016d <ID>.l <charactor ID>.l <online>.l - ギルドメンバがloginした抜けた等 -S 016E <guildID>.l <mess1>.60B <mess2>.120B - ギルド告知設定 -R 016F <mess1>.60B <mess2>.120B - ギルド告知 -S 0170 <TargetAccID>.l <sourceAccID>.l <myCharactorID>.l - 同盟要請勧誘 -R 0171 <SorceAccID>.l <guild name>.24B - 同盟要請勧誘された -S 0172 <SorceAccID>.l <type>.l - 同盟要請返信 - type=0 拒否する - type=1 許諾する -R 0173 <type>.B - type = 0 すでに同盟関係 - type = 1 同盟拒否された - type = 2 同盟成功 - type = 3 相手ギルドの同盟ギルド数が超過 - type = 4 自分のギルドの同盟ギルド数が超過 -R 0174 <len>.w {<index>.l <mode>.l <index>.l <exp_mode>.l <nickname>.24B}.40B* - 職位変更通知 -R 0177 <len>.w <index>.w* - 鑑定可能アイテムリスト -S 0178 <index>.w - アイテム鑑定 -R 0179 <index>.w <fail>.B - アイテム鑑定結果。fail=00で成功。fail=01ってあるのか? -S 017A <index>.w - カードWクリック -R 017B <len>.w {<index>.w}* - カード挿入できるアイテムIndex番号 -S 017C <SrcIndex>.w <DescIndex>.w - Src をDescに突っ込む -R 017D <DescIndex>.w <SrcIndex>.w <fail>.b - Src をDescに突っ込み<fail> 0=成功 1=失敗? -S 017e <len>.w <message>.?B - ギルド内メッセージ発言 -R 017f <len>.w <message>.?B - ギルド内メッセージ受信 -S 0180 <charactorID>.l - ギルド敵対 -R 0181 <flag>.b - ギルド敵対可否 - flag=0 敵対成功 - flag=1 敵対ギルド数が多すぎる - flag=2 すでに敵対関係 -R 0182 <accID>.l <charactorID>.l <髪型>.w <髪の色>.w <性別?>.w <job>.w <lvl?>.w <上納経験値>.l <online>.l <Position>.l ?.50B <nick>.24B - -S 0183 <guild_id>.l <type>.l - ギルド関係解消 -R 0184 <guild_id>.l <type>.l - ギルド関係解消通知 -R 0185 <flag>.l <guild_id>.l <guild_name>.24B - ギルド関係追加 flag=0 同盟/ 1 敵対 -R 0187 <account ID>.l - alive信号? -R 0188 <fail?>.w <index>.w <val>.w - 武器精錬。結果+val武器に -R 0189 <fail?>.w - 謎。テレポ(ワープポータルmemo)失敗? - 1 memo禁止地域 -S 018a ?.w - ゲーム終了 -R 018b <fail>.w - ゲーム終了/キャラセレ応答。fail=0成功。fail=1失敗? -R 018C <MonsID>.w <等級>.w <大小>.w <生命値>.w <?>.w <防御力>.w <種族>.w <魔法防御力>.w <属性>.w <魔法相性属性>.9b - wizの敵のセンス結果 - 0 小型 - 1 中型 - 2 大型 -R 018d <length>.w { <ItemID>,w ?.w <CharID?>.l }.8B* - 製造可能アイテムリスト表示(?の部分は0012固定) -S 018e <MakeItemID>.w <slot1ItemID>.w <slot2ItemID>,w <slot3.ItemID>.w - 製造アイテムの選択 -R 018f <flag>.w [00] <MakeItemID>.w - 製造結果(flag = 00なら成功 01なら失敗) -S 0190 <skill lv>.w <skill code>.w <x & y>.l <message>.80b - メッセージ(トーキーボックス) -R 0191 <ID>.l <message>.80B - トーキーボックスのメッセージ -R 0192 <x & y>.l <type>.w <mapname>.16b - アイスウォール等による地形属性変化 -S 0193 <ID>.l - ギルドメンバ名前引き? -R 0194 <ID>.l <nick>.24B - ギルドメンバ名前引き応答? -R 0195 <ID>.l <nick>.24B <party name>.24B <guild name>.24B <class name>.24B - ギルド所属PCの場合の0094返答 -R 0196 <type>.w <ID>.l - 増強系スキル使用時のメッセージ色々。IDはtargetと思われるが自分相手のみしか来ない? - type=00 2HQ付与「攻撃速度が増加しました。」 - type=01 2HQ解除「攻撃速度が減少しました。」 - type=02 IMPOSITIO付与「武器の攻撃力が増加しました。」 - type=03 IMPOSITIO解除「武器の攻撃力が減少しました。」 - type=04 「スキル使用ディレイが減少しました。」 - type=05 「スキル使用ディレイが元に戻りました。」 - type=06 「武器に毒属性が付与されました。」 - type=07 ASPERSIO付与「武器に聖属性が付与されました。」 - type=08 ASPERSIO解除「武器の属性が元に戻りました。」 - type=09 「防具に聖属性が付与されました。」 - type=0a 「防具の属性が元に戻りました。」 - type=0b KYRIE付与「バリア状態になりました。」 - type=0c KYRIE解除「バリア状態が解除されました。」 - type=0d 「ウェポンパーフェクションモードになりました。」 - type=0e 「ウェポンパーフェクションモードが解除されました。」 - type=0f 「オーバートラストモードになりました。」 - type=10 「オーバートラストモードが解除されました。」 - type=11 「マキシマイズパワーモードになりました。」 - type=12 「マキシマイズパワーモードが解除されました。」 -R 0196 <type>.w <ID>.l <switch>.b (コモド以降) - switch=0で解除,1で付加 - type=00 プロボック - type=01 インデュア - type=02 「攻撃速度が増加しました。」(2HQ) - type=03 集中力向上 - type=04 ハイディング - type=05 クローキング - type=06 「武器に毒属性が付与されました。」(エンチャントポイズン) - type=07 「毒を反射できる状態になりました。」(ポイズンリアクト) - type=08 「クァグマイア状態になり、・・・」 - type=09 「エンジェラス状態になり、・・・」 - type=0a ブレッシング - type=0b シグナムクルシス - type=0c 「速さが増加しました」(速度増加) - type=0d 「速さが減少しました」(速度減少) - type=0e 「スローポイズン状態になりました」(スローポイズン) - type=0f 「武器の攻撃力が増加しました」(インポシティオマヌス) - type=10 「スキル使用ディレイが減少しました」(サフラギウム) - type=11 「武器に聖属性が付与されました」(アスペルシオ) - type=12 「防具に聖属性が付与されました」(聖体降臨) - type=13 「バリア状態になりました」(キリエエレイソン) - type=14 「マグニフィカート状態になりました」 - type=15 「グロリア状態になりました」 - type=16 「レックスエーテルナ状態になりました」 - type=17 「アドレナリンラッシュ状態になりました」 - type=18 「ウェポンパーフェクションモードになりました」 - type=19 「オーバートラストモードになりました」 - type=1a 「マキシマイズパワーモードになりました」 - type=1b ペコペコ騎乗 - type=1c 鷹 - type=1d 死んだふり - type=1e 「叫びました」(ラウドボイス) - type=1f 「エナジーコート状態になりました」 - type=20 「防具が壊れました」 - type=21 「武器が壊れました」 - type=22 謎(目のアップというアイコン:盲目??) - type=23 重量50%超え - type=24 重量90%超え - type=25 謎「攻撃速度が増加しました」(x2アイコン:速度系ポーション?) - type=26 謎「攻撃速度が増加しました」(x2アイコン:速度系ポーション?) - type=27 謎「攻撃速度が増加しました」(x2アイコン:速度系ポーション?) - type=28 (未使用っぽい?:不可と解除で効果が違う) - type=29 謎「速さが増加しました」(白いアイコン) - type=32 ストリップウエポン - type=33 ストリップシールド - type=34 ストリップアーマー - type=35 ストリップヘルム - type=36 ケミカルウェポンチャージ - type=37 ケミカルシールドチャージ - type=38 ケミカルアーマーチャージ - type=39 ケミカルヘルムチャージ - type=3a オートガード - type=3b リフレクトシールド - type=3d プロヴィデンス - type=3e ディフェンダー - type=41 オートスペル - type=44 スピアクィッケン - type=56 爆裂波動(アイコンは表示されません。) - type=57 金剛(表示はされないが金剛の解除はされるようです。) - type=59 コンボディレイ - type=5a フレイムランチャー - type=5b フロストウェポン - type=5c ライトニングローダー - type=5d サイズミックウェポン - -S 0197 <type>.w - type=0 /resetstate - type=1 /resetskill - 効能は無し? -R 0199 <type>.w - type=1 pvpモード開始? - type=3 gvgモード開始? -R 019a <ID>.l <rank>.l <num>.l - pvp順位 rank/num -R 019b <ID>.l <type>.l - 他人のlvupや武器精錬等の表示? - type=0 base lvup? - type=1 job lvup? - type=2 武器精錬失敗 - type=3 武器精錬成功 - -R 019d <?>.4B - GMコマンド/hide - -S 0149 <ID>.l <type>.B <time>.w - GM用右クリックメニュー「チャット禁止時間を下げる(解ける)」使用 → type=00 - GM用右クリックメニュー「チャット禁止時間を上げる(掛ける)」使用 → type=01 - timeは分単位です(確か - -R 019e - 捕獲モンスター決め -S 019f <ID>.l - 捕獲モンスター指定 -R 01a0 <fail>.B - 捕獲判定 - fail=01で成功、00で失敗 -S 01a1 <param>.1B - <param> - 0x00:ペット状態表示 - 0x01:餌を与える - 0x02:パフォーマンス - 0x03:卵に戻す - 0x04:アクセサリ解除 -R 01a2 <pet name>.24B <name flag>.B <lv>.w <hungry>.w <friendly>.w <accessory>.w - ペットの状態 - name flag:00=名前未設定 01=名前設定済み(変更不可) - lv=ペットのレベル、hungry=満腹度(0~100)、friendly=親密度(初期値250?)、accessory=アクセサリのItemID -R 01a3 <fail>.B <itemID>.w - <fail> - 0x00:餌やり失敗 - 0x01:餌やり成功 -R 01a4 <type>.B <ID>.l <val>.l - ペット関連通知 - type=00,val=00 ペット孵化時に送られてくる。ペット認識用? - type=01 親密度変化 - type=02 満腹度変化 - type=03 アクセサリ変化(0で未装備) - type=04 パフォーマンス 確認されたval=1~3 - (4はスペシャルパフォーマンス?) - type=05 ?確認されたval=0x14 -S 01a5 <pet name>.24B - ペットの名前決め -R 01a6 <len>.w <index>.w* - ペットの卵リスト -S 01a7 <index>.w - ペットの卵リストが選択された -S 01a9 <emotion>.l - ペットエモーション送信 -R 01aa <ID>.l <emotion>.l - ペットエモーション受信 - <emotion> - 33以下のとき:エモーション - 34以上のとき:発言テーブル? -R 01ac <object id>.l - アンクルの発動(≠設置)時のみ毎回出現(機能は謎) -R 01ad <len>.l <item>.w - 矢作りの作成可能ITEM表受信 -S 01ae <itemID>.w - 矢作りで使う材料送信 -S 01af <type>.w - チェンジカート(カート選択) - type=1 ノーマルカート -R 01b0 <monster id>.l <?>.b <new monster code>.l - 油のクラスチェンジ - <new monster code>はチェンジ後のコード(1001〜)をdwordで -S 01b2 <len>.w <message>.80B <flag>.B {<index>.w <amount>.w <value>.l}.8B* - 露店開設 - flag : 0=キャンセル , 1=オープン -R 01b3 <filename>.64B <type>.B - R 0145の上位互換 -R 01B6 <guildID>.l <guildLv>.l <connum>.l <定員>.l <Avl.lvl>.l <now_exp>.l <next_exp>.l <上納ポイント>.l <性向F-V>.l <性向R-W>.l <members>.l <guild name>.24B <guild master>.24B <agit?>.20B - ギルド情報 -R 01b9 <ID>.I - 被ダメ等によるIDの詠唱中断 -R 01c4 <index>.w <amount>.l <itemID>.w <item data>.12B - カプラ倉庫アイテム -R 01c8 <index>.w <item ID>.w <ID>.l <amount left>.w <type>.B - アイテム使用応答。(00a8の上位バーション?) - type=00の場合使用失敗? amountもゴミの模様 - type=01の場合成功で、amountは使用後の残り個数 -R 01c9 <dst ID>.l <src ID>.l <X>.w <Y>.w <type>.B <fail>.B ?.81b - スキル効能地作成(011fの上位バーション?) - type 0x7e:SW、0x7f:火壁、0x80 ポタ開き中、0x81 ポタ開き直前 - 0x82 聖体、0x83 サンク、0x84 マグヌス、0x85 ニューマ - 0x86 0x86 大魔法(SG/MS/LoV/GX)、0x87 ファイヤーピラ待機 - 0x88 ファイヤーピラ爆発、0x87〜0x8B 表示無し、 - 0x8c トーキーボックス(発動中)、0x8D アイスウォール - 0x8E クワグマイア、0x8f ブラストマイン、0x90 スキッド - 0x91 アンクル、0x92 ベノムダスト、0x93 ランドマイン - 0x94 ショックウェーブトラップ、0x95 サンドマン - 0x96 フラッシャー、0x97 フリージングトラップ - 0x98 クレイモアートラップ、0x99 トーキーボックス - 0x9A ボルケーノ、0x9B デリュージ、0x9C バイオレントゲイル - 0x9D ランドプロテクター、0x9E Zenyマーク、0x9F Zeny袋 - 0xA0 回る緑の輪、0xA1 ピンクの音符 (二連符有り - 0xA2 真ん中に点のある光の玉、0xA3 ピンクのスプリング - 0xA4 深淵の中に、0xA5 回る青い輪、0xA6 不協和音 - 0xA7 口笛、0xA8 夕陽のアサシンクロス、0xA9 ブラギの詩 - 0xAA イドゥンの林檎、0xAB 自分勝手なダンス、0xAC ハミング - 0xAD 私を忘れないで…、0xAE サービスフォーユー - 0xAF ピンクのスプリング、0xB0 表示無し - 0xB0 グラフィティ, - 0xB1 デモンストレーション、0xB2〜0xBF 表示無し - 0xB2 ピンクのワープポータル風 - 0xB3 小さな十字架がふよふよ - 0xB4 バジリカ、0xB5 エフェクトなし? - 0xB6 黒い×が立体的に浮かび上がる - 0xB7 クモの巣、0xB8〜 エフェクトなし? - - 他情報求む - ?.81bは謎。 -R 01cd (<sid>.l)x7 - オートスペル選択肢受信 - <sid>x7 には NB,CB,FB,LB,SS,FBL,FD の順でスキルコードがdwordで入る - まだ選択できないスキルの部分は <sid> = 0x00000000 が入る -S 01ce <sid>.l - オートスペル選択肢送信 -R 01cf <crusader id>.l <target id>.l <?>.18b - 献身状態ターゲットON/OFF。献身が切れると <target id> が 0x00000000 になる - -R 01d0 <ID>.l <num>.w - <num> : 気功の数(非Lv) -R 01d1 <monk id>.l <target monster id>.l <bool>.l - 白羽取り状態ON/OFF。<bool> は白刃取り成立時に 0x00000001 解除時に 0x00000000 が来る -R 01d2 <id>.l <delay>.l - モンクのコンボディレイ(msec) - 三段・連打は基本ディレイ1000(+300)、猛龍は基本ディレイ700(+300) -R 01d4 <ID>.l - 文字列入力窓表示(IDはNPCのIDが入る) -S 01d5 <len>.w <ID>.l <input>.?B 00 - 文字列入力内容送信(IDはNPCのIDが入る) -R 01d7 <ID>.l <equip point>.b <item id1>.w <item id2>.w - 装備グラフィック <equip point> は 02手と09足のみ確認。id2は左手 -R 01d8 <ID>.l <speed>.w <opt1>.w <opt2>.w <option>.w <class>.w <hair>.w <item id1>.w <item id2>.w <head option bottom>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.l <emblem>.l <manner>.w <karma>.B <sex>.B <X_Y_dir>.3B ?.B ?.B <sit>.B <Lv>.B ?.B - マップロード時&移動時用、向き付き用キャラ情報?(0078の上位バージョン) -R 01d9 <ID>.l <speed>.w <opt1>.w <opt2>.w <option>.w <class>.w <hair>.w <item id1>.w <item id2>.w.<head option bottom>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.l <emblem>.l <manner>.w <karma>.B <sex>.B <X_Y_dir>.3B ?.B ?.B <Lv>.B ?.B - テレポ等の表示範囲内沸きキャラ用、向き付き無しキャラ情報?(0079の上位バージョン) -R 01da <ID>.l <speed>.w <opt1>.w <opt2>.w <option>.w <class>.w <hair>.<item id1>.w <item id2>.w <head option bottom>.w <server tick>.l <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.l <emblem>.l <manner>.w <karma>.B <sex>.B <X_Y_X_Y>.5B ?.B ?.B ?.B <Lv>.B ?.B - 表示範囲内キャラ移動情報(007bの上位バージョン) -S 01db - 暗号化key要求 -R 01dc <len>.w <key>.?B - 暗号化key送付 -S 01dd <version>.l <account name>.24B <md5 binary>.16B <version2>.1B - id&暗号化済みpass送信 - 順にクライアントが01dbを送る、 - 鯖が01dcでkeyを返す、 - クライアントが"<key><password>"についてmd5計算し - <md5 binary>の所を埋めて01ddを送る。 - <passwordencrypt2>の時は - "<key><password>"に対してmd5計算としている所を - "<password><key>"と変更する -R 01de <skill ID>.w <src ID>.l <dst ID>.l <server tick>.l <src speed>.l <dst speed>.l <param1>.l <param2>.w <param3>.w <type>.B - 攻撃系スキルエフェクト@(0114の上位バーション?) - type=04 火壁で観測 type=06とほぼ同じ? - type=05 NB/FBlの分散したダメージ用? - type=06 単発もの? param1はダメージ合計、param2はlevel、param3は1固定と予想 - type=07 ダメージ表示無し? - type=08 連打もの? param1はダメージ合計、param2はlevel、param3は分割数と予想 - type=09 ダメージモーションなしにダメージだけ表示される物(インデュア)と思ったのだがダメージモーションが出る物。(機能は謎) -S 01df <ID>.| - GM右クリックによるIDのチャット禁止回数参照? -R 01e1 <ID>.l <num>.w - <num> : 気功の数(非Lv) 一度表示したら後どんなnumが来ても無視される。 -R 01e6 <partner name>.24B - 結婚スキルあなたに逢いたい使用時の叫び声 -S 01e7 - スパノビで/doridoriしたら飛んでくる。SPR回復量2倍フラグを立てるパケット -S 01e8 <party name>.24B <item1>B <item2>B - <item1>アイテム収集方法。0で個人別、1でパーティ公有 - <item2>アイテム分配方法。0で個人別、1でパーティに均等分配 - (00f9の上位バーション) -R 01ea <ID>.l - 結婚エフェクト(音楽、紙吹雪) - IDは新婦のものが入る? -S 01ed - スパノビが爆裂波動になるフラグを立てるパケット -R 01ee <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B <card>.4w}.18B* - 所有消耗品&収集品リスト - 矢の場合は?.2Bが0x8000になる - 00a3から変更 -R 01ef <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B <card>.4w}.18B* - カート内アイテム。消耗品/収集品 - 0123から変更 -R 01f0 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B <card>.4w}.18B* - カプラさんに預けてある消耗品&収集品リスト - 00a5から変更 -R 01f4 <name>.24B <trade id?>.L <LV>.w - 先方から取引要請 - 00e5から変更 -R 01f5 <result>.B <trade id?>.L <LV>.w - こちらからの取引要請に対する反応 - 00e7から変更 -S 0200 <login name>.24B - ragexeに/accountオプションをつけて起動するとログイン要求に付加されるパケット -S 0204 <?>.16B - ログイン要求に付加されるパケット。16バイトは固定? -S 020B <?>.17B - キャラクタサーバ接続要求0065に付加されるパケット。1+0204の16バイトで17バイト? diff --git a/doc/command.txt b/doc/command.txt deleted file mode 100644 index 49258b7..0000000 --- a/doc/command.txt +++ /dev/null @@ -1,40 +0,0 @@ -This file has explained some special commands. -It begins to explain the declared commands in this file. -Furthermore, many of the special command which is not stated in this file are not mounted. - - -Index - 1. mapmove - 2. b and nb - - -1. MapMove - MapMove command is a warping command which a GM can use on the server. - There is no restriction such, that presently you can use, just have GM enabled. The usage where it is possible - to use as /mm or /mapmove is as follows. - /mm <fieldname>* X Y - /mm <fieldname.gat>* X Y - /mapmove <fieldname>* X Y - /mapmove <fieldname.gat>* X Y - * means for field name type /where, please input the map name which appears in the execution time. gat is not always a necessary. - (X Y) X coordinate and the Y-coordinate of the place where you would like to go, exact coordinates. However it does - if no X or Y, it will jump randomly. - Example: - /mm payon - /mapmove prontera.gat 167 158 - -2. Broadcast - Broadcastコマンドとは実際のサーバでGMが使えるGMメッセージと同様の働きをします。 - /bもしくは/nbとして使うことができます使用方法は以下の通りです。 - /b <message> - /nb <message> - - /b - 実行したユーザ名付きでメッセージを表示します。 - /nb - 実行したユーザ名を表示せずメッセージを表示します。 - - 例: - /b テスト - /nb テスト -$Id: command.txt,v 1.1 2004/05/28 03:55:43 wizputer Exp $ diff --git a/doc/conf_ref.txt b/doc/conf_ref.txt deleted file mode 100644 index bd1e35c..0000000 --- a/doc/conf_ref.txt +++ /dev/null @@ -1,1981 +0,0 @@ -========================================================================== -eAthena dev 1.0.0 mod1004 Reference +alpha of the present conf --------------------------------------------------------------------------- - -< What this file is. > - - It is the reference of the setting method of an Athena setting file. -although it is not a HowTo, it not Those who cannot use Athena even if they see this - To give up obediently is safer. - - -< The list of conf > - - login_athena.conf A setup of login-server - char_athena.conf A setup of char-server - inter_athena.conf A setup of inter-server - map_athena.conf A setup of map-server - battle_athena.conf A setup of map-server (setup of a special rule etc.) - atcommand_athena.conf A setup of map-server (setup of the GM command or @ command) - ladmin_athena.conf A setup of ladmin ('c' version) - - -< The fundamental setting method > - -One line "key: Enter as a value." -<Example> -key: value - -Head of the sentence It will become a comment if it begins by //. -<Example> -//Since this line is a comment, it is not processed. - -< Two or more same items > - -Priority is given to what was written later unless it is written especially clearly that two or more same items are written. -login_athena.conf allow and deny -- and -- map_athena.conf map, npc, etc. -Another processing will be carried out if two or more lines are written. - -========================================================================== -1. conf/login_athena.conf --------------------------------------------------------------------------- - -< What this file is. > - - A setup of login-server (server which manages account) is described. - It mainly becomes a setup of an administrator. - - -< Explanation of a key > - -If you change one of these parameters, you must restart login-server to update. -If you repeat one parameter (except 'allow', 'deny' or 'ladminallowip') in the configuration file, only the latest will be validated. - 'Allow', 'deny' and 'ladminallowip' parameters are list parameters. Add as many 'allow', 'deny' or 'ladminallowip' as you need. - -login_port - Port to bind login-server to (always binds to all IP addresses) - It is the port used by login-server. It can be omitted and a default is 6900. - Default value: 6900. - -admin_pass - It is the administrator password used to administrate the login-server through a remote connection. - You will found some tools in the tool directory, and specially the tool - ./tool/ladmin (for Login ADMINistration), a perl software, which manages all accounts. - Void password will not work. - NOTICE: You must change this or attackers can exploit your server. - Default value: admin. CHANGES this default value to avoid hack. - -ladminallowip - It's a list parameter. To add an item in this list, just add a new line. Each line can only have 1 parameter. - This list indicates the IP that the server accepts for a remote administration. - This parameter accepts IP descriptions, like: - IP or the begining of IP: it's a characters match. Write an IP (123.456.789.012) or the begining of the IP (123.456.). - Because it's a characters match, the IP 123.4 matches with 123.4.xxx.yyy and 123.4z.xxx.yyy. So, add a final '.' to be sure of the IP. - Example: - allow: 127.0.0.1 - allow: 192.168.10. - IP with number of bits for a network: it's a logical match. Write the network like this: 123.456.789.012/<#_of_mask_bits> - Don't use the final '.', but use all four values. - Example: - allow: 127.0.0.1/32 (match only 1 IP, because 32 bits match all bits). - allow: 192.168.10/24 (matches the network begining by 192.168.10). - IP with mask of a network: it's a logical match. Write the network like this: 123.456.789.012/345.678.901.234 - Don't use the final '.', but use all four values for the IP and the mask. - Example: - allow: 127.0.0.1/255.255.255.255 (match only 1 IP). - allow: 192.168.10.0/255.255.255.0 (matches the network begining by 192.168.10). - all: matches any IP. - Example: - allow: all. - clear: clears the list at this point. Really useful for 'import' parameter, in the new configuration file. - Example: - allow: clear. - Add as many IP's as you wish. - Default value: all. - -gm_pass - It is the required password when a player wants to change its (normal) account to a GM (Game Master) account. - It is used by the @gm command. - Level of gm is set with level_new_gm parameter. - NOTICE: You should also change this one. - Default value: gm. CHANGES this default value to avoid player hack. - -level_new_gm - Level of new GM created with @gm command. (default: 60) - If you set to 0, you disable creation of new GM with @gm. - To be able to create a gm with @gm, you must: - - give a level to this value (not 0) - - enable to level 0 the @gm command (atcommand_athena.conf) (default 100) - - enable gm commands to normal player (battle_athena.conf, atcommand_gm_only parameter) - - and normal player must give correct password when he use the @gm command - Possible value: 0 to 99 - Default value: 60 - -new_account - It is whether to permit new account creation. - When allowed, the player must add _F or _M at the end of its login account to create a new account. - This extension of the account gives the sex of the new created account. - Without the _F/M, the account must have at least 4 characters. - The account will not have e-mail to protect characters against deletion. - The given password at first connection (when the account is created) is the account password. - The value can be: 1 (to allow creation) or 0 (to forbid creation). - Default value: 1. - -account_filename - It specifies the accounts save file. - Gives the accounts txt database name and path to stores accounts information. - Look into the file to have a short description of the database structure. - Can be omited, a default is save/account.txt. - Default value: save/account.txt. - -gm_account_filename - It specifies which account IDs have GM privileges, and what level they have. - We recommand to use only ID value lower than first normal player ID (2000000). - Levels ranges from 0 (no privilege/normal player) to 99 (highest privilege). - If you change a value inside this file, you must restart login-server to use the new value - or use reloadgm ladmin command. - Can be omited, a default is conf/GM_account.txt. - Default value: conf/GM_account.txt - -gm_account_filename_check_timer - Timer to check if GM_account file has been changed and reload GM account automaticaly - (in seconds) - Value: 0 (disabled), or 2 or more. - Default: 15 - -login_log_filename - Gives the log file name and path to stores logs information. - All operations done by the login-server are written in this file with a time stamp. - Default value: log/login.log - -login_log_unknown_packets_filename - Gives the file name and path of the file that logs the received unknown packets. - It's used for debug or hack check. - All information are displayed with the time stamp, the ip of the source, the packet number, - the number of received bytes and the detail of the packet with hex and text values. Example: - 01-06-2004 21:25:21.579: receiving of an unknown packet -> disconnection - parse_login: connection #5 (ip: 82.64.111.96), packet: 0x4e92 (with being read: 28). - Detail (in hex): - 92 4e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 誰.............. - 00 00 00 00 00 00 00 00 00 00 00 00 ............ - Default value: log/login_unknown_packets.log - -save_unknown_packets - It indicates if the unknown packets are saved or not. - The unknown packets received from the char-server or remote administration does not relate to this parameter, - because they are always saved. - The value can be: 1 (to save unknown packets) or 0 (to not save them). - Be careful: if you receive an attack, your hard disk can cause lag... - So, active this option with a speed hard disk or for debug only. - Default value: 0 - -display_parse_login - It indicates if you want display the parse of the packets received in a normal connection. - At all received packets in normal connection, the server display a message about the size and the value. - It's useful for debug. Possible values: 0: no (default), 1: yes. - Default value: 0 - -display_parse_admin - It's same of 'display_parse_login' parameter, but only for remote administration received packets. - It's useful for debug. Possible values: 0: no (default), 1: yes. - Default value: 0 - -display_parse_fromchar - It's same of 'display_parse_login' parameter, but only for char-server received packets. - It's useful for debug. Possible values: 0: no (default), 1: yes (without packet 0x2714), 2: all packets. - Default value: 0 - -date_format: - indicate how to display date in logs, to players, etc. - 0: 31-12-2004 23:59:59 - 1: 12-31-2004 23:59:59 - 2: 2004-31-12 23:59:59 - 3: 2004-12-31 23:59:59 - Default value: 3 - -min_level_to_connect - Indicate the minimum GM level of player that the server accepts to connection. - 0: all players (normal player are 0. it's default), or - 1-99: GM level at least with level x - Default value: 0 (any player or GM) - -add_to_unlimited_account - Give possibility to adjust (ladmin command: timeadd) the time of an unlimited account. - If set to on/1/yes..., the adjustment is be done from actual time to set the final time of the account. - If set to no/0/no..., the adjustment can not be done on an unlimited account. - You must set (ladmin command: timeset) a final time before to adjust (ladmin command: timeadd) - Default value: no - -start_limited_time - Starting additional sec from now for the limited time at creation of account - -1: new account are created with UNlimited time (default value) - 0 or more: new accounts was created by addition of the value (in sec) to the actual time (to set first limited time) - Default value: -1 - -check_ip_flag - It's to check IP of a player between login-server and char-server (part of anti-hacking system) - If player doesn't have same IP, connection is refused. - Set to 0/off/no to not check IP of player. - Set to 1/on/yes if you want to check (default) - Note: if you enable this option, be sure that your (local/lan/wan) players use correct ip (in xml file) to contact servers, - and that your LAN is correctly configured (!), and that LAN configuration of eathena is right. - if not correct, you can read list of char-servers, but not look slots of characters (rejected by server). - Default value: yes - -order - This parameter controls how the login-server must use the 'allow' and 'deny' lists. - 'Allow' and 'deny' are used to do IP lists. - 3 possibilities: - 'deny,allow': to sum it up, it's like 'allow if not deny'. The login-server only checks the 'deny' list. - If the connected IP is in the 'deny' list, the login-server refuses the connection, otherwise it accepts it. - 'allow,deny': to sum it up, it's like 'deny if not allow'. The login-server only checks the 'allow' list. - If the connected IP is in the 'allow' list, the login-server accepts the connection, otherwise it refuses it. - 'mutual-failture': to sum it up, it's like 'allow if in allow list and not in the deny list'. - The login-server checks the 'allow' list. If the connected IP is in the 'allow' list, - the login-server checks it in the 'deny' list. If the connectec IP is not in the 'deny' list, - the login-server accepts the conection, otherwise it refuses it. - In this case, a non 'allow' IP or a 'deny' IP will be never accepted. - If you don't use allow AND deny, all ip are authorised. - Default value: deny,allow. - -allow - It's a list parameter. To add an item in this list, just add a new line. Each line can only have 1 parameter. - This list depends on the 'order' parameter (read 'order' parameter to known what the login-server do with this list). - This parameter accepts IP descriptions, like: - IP or the begining of IP: it's a characters match. Write an IP (123.456.789.012) or the begining of the IP (123.456.). - Because it's a characters match, the IP 123.4 matches with 123.4.xxx.yyy and 123.4z.xxx.yyy. So, add a final '.' to be sure of the IP. - Example: - allow: 127.0.0.1 - allow: 192.168.10. - IP with number of bits for a network: it's a logical match. Write the network like this: 123.456.789.012/<#_of_mask_bits> - Don't use the final '.', but use all four values. - Example: - allow: 127.0.0.1/32 (match only 1 IP, because 32 bits match all bits). - allow: 192.168.10/24 (matches the network begining by 192.168.10). - IP with mask of a network: it's a logical match. Write the network like this: 123.456.789.012/345.678.901.234 - Don't use the final '.', but use all four values for the IP and the mask. - Example: - allow: 127.0.0.1/255.255.255.255 (match only 1 IP). - allow: 192.168.10.0/255.255.255.0 (matches the network begining by 192.168.10). - all: matches any IP. - Example: - allow: all. - clear: clears the list at this point. Really useful for 'import' parameter, in the new configuration file. - Example: - allow: clear. - It does not support the backward match of host name. - Default value: <no list>. - -deny - This list works exactly like the 'allow' list, but for the 'deny' list. - -import - Gives an other configuration file to include in. - You must write the additionnal configuration file name and path. - The mentionned file can include any parameter of the login configuration. - You can create a chain or configuration files if necessary. - Default value: <no_additional_configuration_file>. - -<Example> -login_port: 6900 -admin_pass: admin -ladminallowip: all -gm_pass: gm -level_new_gm: 60 -new_account: 1 -account_filename: save/account.txt -gm_account_filename: conf/GM_account.txt -gm_account_filename_check_timer: 15 -login_log_filename: log/login.log -login_log_unknown_packets_filename: log/login_unknown_packets.log -save_unknown_packets: 0 -display_parse_login: 0 -display_parse_admin: 0 -display_parse_fromchar: 0 -date_format: 3 -min_level_to_connect: 0 -add_to_unlimited_account: off -start_limited_time: -1 -check_ip_flag: yes -order: deny,allow -//deny: all -//allow: 127.0.0.1 -//allow: 10.0. -//allow: 172.16.0.0/16 -//allow: 192.168.0.0/255.255.255.0 -//import: import/new_login.conf - -========================================================================== -2. conf/char_athena.conf --------------------------------------------------------------------------- - -< What this file is. > - - A setup of char-server (server which manages the character data in one world) - It ???. The name of a world, the password of a world, a server's IP, - A data file name etc. is described. - - -<Explanation of a key> - -userid - It is ID which this world uses. It registers with login-server. - ID of account is specified. - And also [ it uses it for connecting to map-server used in this world ] - It is used also for discernment of the world within login-server. - It is each when registering two or more worlds into the same login-server. - It is necessary to use another ID by char-server. - -passwd - It is a password corresponding to ID which this world uses. - It is used for the time of the registration to login-server, and connecting to map-server. - -server_name - It is the name of this world. It is displayed when logged in by the client. - -wisp_server_name - Wisp name for server: used to send wisp from server to players (between 4 to 23 characters) - Default: Server - -login_ip - It is the IP address of login-server which registers a world seen from char-server. - -login_port - It is the port used by login-server. It can omit and a default is 6900. - -char_ip - It is the IP address of char-server seen from the client. - -char_port - It is the port used by char-server. It can omit and a default is 6121. - -email_creation - Option to force a player to create an e-mail. - If a player have default e-mail, and if you activate this option, the player can only connect in the game (to arrive on a map) like follow: - - Create at least 1 character - - Select 1 character - - Select DEL to enter his/her e-mail. (if OK is choosen, client says to the player: 'invalid e-mail') - - If his/her e-mail is correct, the player enter in the game (an e-mail is saved definitively). - - If his/her e-mail is incorrect, he/she have 'incorrect e-mail' and must select again DEL. - - After entering in the game (when the player arrives on a map), DEL and SEL/OK button work normaly for all next connections. - Resume: If a player have "incorrect/invalid e-mail" when he/she click on 'OK' button, - the player must click 'DEL' button and register his/her NEW e-mail to enter in the game - So, default is 0, because administrator must explain to their players before to activate this option. - -char_txt - It is the data file name which stores character data. - It is not omissible. - -char_maintenance - If it is made 1, it will be in a maintenance state. - It can omit and a default is 0. - -char_new - If it is made 1, the time (new) of being displayed on a client will stick. - It can omit and a default is 0. - -max_connect_user - It is the maximum number of the user linked to a Char-server. - If it is made 0, the maximum number restrictions will be lost. - Please use to apply restriction of the connection number. - It can omit and a default is 0. - -check_ip_flag - It's to check IP of a player between char-server and other servers (part of anti-hacking system) - If player doesn't have same IP, connection is refused. - Set to 0/off/no to not check IP of player. - Set to 1/on/yes if you want to check (default) - Note: if you enable this option, be sure that your (local/lan/wan) players use correct ip (in xml file) to contact servers, - and that your LAN is correctly configured (!), and that LAN configuration of eathena is right. - default: yes - -autosave_time - It is time to save data automatically at a file. A unit is a second. - It can omit and a default is 300 (5 minutes). - -start_point - When a new character is created, it is the place where they start. - It describes like "a map file name, X coordinates, and Y coordinates." - It can omit and is a default. It is new_1-1.gat and 53,111. - -start_weapon: - Starting weapon for new characters - default value: 1201 (Knife) - -start_armor: - Starting armor for new characters - default value: 2301 (Cotton Shirt) - -start_zeny - When new character is made, the quantity of ZENY which it has from the start is set up. - Being able to omit, a default is 500. - -unknown_char_name - The name returned when the name request of character which does not exist in a character server is carried out - It sets up. Being able to omit, a default is Unknown. - -char_log_filename - A character server's log file is specified. - Being able to omit, a default is log/char.log. - -name_ignoring_case - Allow or not identical name for characters but with a different case (upper/lower): example: Test-test-TEST-TesT - 0 (default): no character can have same name, instead of the case (no Test-TEST...) - 1: more than 1 of character can have same name if names are not using same case (one with Test, another with TEST, etc...) - -char_name_option - Manage possible letters/symbol in the name of charater. Control character (0x00-0x1f) are never accepted. Possible values are: - 0: no restriction (default) - 1: only letters/symbols in 'char_name_letters' option. - 2: Letters/symbols in 'char_name_letters' option are forbidden. All others are possibles. - default: 0. - -char_name_letters - Set the letters/symbols that you want use with the 'char_name_option' option. - Note: add 'space' between 2 others letters/symbols. - default: void. - -online_txt_filename - It sets the filename of the file which receives the online players list in text - default: online.txt - -online_html_filename - It sets the filename of the file which receives the online players list, but in html version - default: online.html - -online_sorting_option - It sets how to display online players in the txt/html files. - 0: no sorting (default) - 1: by alphabetical order of their name - 2: by number of their zenys - 3: by their base level - 4: by their job (and job level inside the same job) - 5: by alphabetical order of their actual map location - Note: sorting operation with a lot of online players can take time on a slow computer. - -online_display_option - It sets which columns that you want display in the online files. Do the addition of these values: - (if value is 0, no file is done) - 1: name (just the name, no function like 'GM') - 2: job - 4: levels - 8: map name - 16: mapname and coordonates - 32: zenys - 64: name (with 'GM' if the player is a GM) - default value: 1 (only name) - -online_gm_display_min_level - minimum GM level to display 'GM' when we want to display it. - default value: 1 (any GM) - -online_refresh_html - refresh time (in sec) of the html file in the explorer - default: 20 - -import - The line is replaced with the contents of another file. - - -< Example > -userid: s1 -passwd: p1 -server_name: eAthena -wisp_server_name: Server -login_ip: 127.0.0.1 -login_port: 6900 -char_ip: 127.0.0.1 -char_port: 6121 -email_creation: 0 -char_txt: save/athena.txt -char_maintenance: 0 -char_new: 0 -max_connect_user: 0 -check_ip_flag: yes -autosave_time: 15 -start_point: new_1-1.gat,53,111 -start_weapon: 1201 -start_armor: 2301 -start_zeny: 500 -unknown_char_name: Unknown -char_log_filename: log/char.log -name_ignoring_case: 0 -char_name_option: 0 -//char_name_letters: -online_txt_filename: online.txt -online_html_filename: online.html -online_sorting_option: 0 -online_display_option: 1 -online_gm_display_min_level: 1 -online_refresh_html: 20 -//import: import/new_char.conf - - -========================================================================== -3. conf/inter_athena.conf --------------------------------------------------------------------------- - -< What this file is. > - - A setup of inter-server (server which manages the global data in one world) - It ???. A data file name etc. is described. - (It is operating as a part of char-server in program now.) - -< Explanation of a key > - -storage_txt - It is the file name which stores warehouse data. - It can omit and is a default. It is save/storage.txt. - -party_txt - It is the file name which stores party data. - It can omit and is a default. It is save/party.txt. - -guild_txt - It is the file name which stores guild data. - It can omit and is a default. It is save/guild.txt. - -pet_txt - It is the file name which stores pet data. - It can omit and is a default. It is save/pet.txt. - -castle_txt - It is the file name which stores the castle data of a guild. - It can omit and is a default. It is save/castle.txt. - -guild_storage_txt - It is the file name which stores guild warehouse data. - Being able to omit, a default is save/g_storage.txt. - -accreg_txt - It is the file name which stores the account share variable data in a world. - It can omit and is a default. It is save/accreg.txt. - -party_share_level - The restriction level of a fair distribution party is set up. - Being able to omit, a default is 10. - -inter_log_filename - An interchange server's log file is specified. - Being able to omit, a default is log/inter.log. - -import - The line is replaced with the contents of another file. - - -< Example > -storage_txt: save/storage.txt -party_txt: save/party.txt -guild_txt: save/guild.txt -pet_txt: save/pet.txt -castle_txt: save/castle.txt -guild_storage_txt: save/g_storage.txt -accreg_txt: save/accreg.txt -party_share_level: 10 -inter_log_file: log/inter.log - - -========================================================================== -4. conf/map_athena.conf --------------------------------------------------------------------------- - -< What this file is. > - - A fundamental setup of map-server (server which manages game advance on the map in his duty) - It ???. - - -< Explanation of a key > - -userid - It is ID which this world uses. It is used for the connecting to char-server. - -passwd - It is a password corresponding to ID which this world uses. - -char_ip - map-serverからみた、このサーバーが担当するマップのワールドを管理する - char-serverのIPです。 - -char_port - マップを登録するchar-serverのポートです。省略可能でデフォルトは6121です。 - -map_ip - クライアントから見たこのmap-serverのIPです。 - -map_port - map-serverで使用するポートです。省略可能でデフォルトは5121です。 - -autosave_time - データを自動的にキャラ鯖に送る時間です。単位は秒です。 - 省略可能でデフォルトは60(1分)です。 - -water_height - 水場の高さを指定するファイルを決めます。 - 省略可能で、デフォルトはconf/water_height.txtです。 - -motd_txt - Message of the Dayファイルを指定します。 - 省略可能で、デフォルトはconf/motd.txtです。 - -help_txt - @helpで表示するファイルを指定します。 - 省略可能で、デフォルトはconf/help.txtです。 - -mapreg_txt - MAPサーバー内キャラクター共有変数を保存するファイルを指定します。 - 省略可能で、デフォルトはsave/mapreg_txtです。 - -data_grf - ROデータファイル data.grf へのパスです。 - 省略可能で、デフォルトは ./data.grf です。 - grf-files.txtがある場合そちらの設定が優先されます。 - -sdata_grf - サクライデータファイル sdata.grf へのパスです。 - 省略可能で、デフォルトは ./sdata.grf です。 - grf-files.txtがある場合そちらの設定が優先されます。 - -adata_grf - αデータファイル adata.grf へのパスです。 - 省略可能で、デフォルトは ./adata.grf です。 - grf-files.txtがある場合そちらの設定が優先されます。 - -npc - 読み込むnpcデータファイルへのパスです。 - 複数指定可能で、指定した順にロードします。 - clear を指定するとそれまでに登録したパスを全て削除します。 - -delnpc - 読み込まないnpcファイルへのパスです。 - 指定したパスはnpcで指定されたデータファイルリストから削除されます。 - all を指定すると全て削除します( npc: clear と同義)。 - -map - このマップが担当するマップファイル名です。 - 複数指定可能で、指定した順にロードします。 - 存在しないマップを指定した場合エラーになります。 - clear を指定するとそれまでに登録したファイル名を全て削除します。 - -delmap - 読み込まないマップファイルへのパスです。 - 指定したファイルはmapで指定されたリストから削除されます。 - all を指定すると全て削除します( map: clear と同義)。 - -import - その行を別ファイルの中身と置き換えます。 - -< Example > - -userid: s1 -passwd: p1 -char_ip: 127.0.0.1 -char_port: 6121 -map_ip: 127.0.0.1 -map_port: 5121 -autosave_time: 60 -nullpo_check: 1 -water_height: conf/water_height.txt -data_grf: ./data.grf -sdata_grf: ./sdata.grf -npc: conf/warp/npc_warp.txt -npc: conf/warp/npc_warp25.txt -npc: conf/warp/npc_warp3.txt -npc: conf/mob/npc_monster3J.txt -map: prontera.gat -map: prt_castle.gat -(npc、mapは多いので省略) -delnpc: conf/sample/npc_test.txt -npc: clear -delmap: prontera.gat -delmap: all - -========================================================================== -5. conf/battle_athena.conf --------------------------------------------------------------------------- - -< What this file is. > - - Battle relation of map-server (server which manages game advance on the map in his duty), - Other setup is described. - All setup can be omitted and a default value is used at the time of an abbreviation. - -< The special character sequence which can be specified to be a value > - - yes on It is processed as 1. (Effective meaning) - no off It is processed as 0. (Invalid meaning) - - -< Explanation of a key > - -warp_point_debug - ワープポイントを普通に表示するかどうかです。これをyesにすると - ワープポイントのかわりにギルドフラグがその場所に出てワープ - ポイントの名前を確認することができます。デフォルトはnoです。 - -enemy_critical - プレイヤーと同じLUKによるクリティカル判定をMOBとペットに有効にするかどうかです。 - このクリティカルはもちろん必中なので、onにすると高Fleeでも、 - LUKの高い敵の攻撃が避けづらくなります。デフォルトはnoです。 - -enemy_critical_rate - モンスターとペットのクリティカル頻度の百分率です。enemy_criticalがyesじゃないと設定しても何の意味もありません。デフォルトは100です。 - -enemy_str - モンスターのが攻撃するときのATK計算にSTRを使用するかどうかです。 - デフォルトはyesです。 - -enemy_perfect_flee - 敵が完全回避をするかどうかです。これをyesにすると敵も完全回避を - するようになります。デフォルトはnoです。 - -casting_rate - スキルの詠唱時間を百分率で調整します。 - 200にすると詠唱時間が倍になり、0にすると詠唱がなくなります。 - 0-1000程度の数値を指定してください。デフォルトは100です。 - -delay_rate - スキル使用後ディレイを百分率で調整します。 - 200にするとディレイが倍になり、0にするとディレイがなくなります。 - 0-1000程度の数値を指定してください。デフォルトは100です。 - -delay_dependon_dex - スキル使用後ディレイが詠唱時間と同じようにDEXで影響を受けるかどうかを - 指定します。デフォルトはnoです。 - -skill_delay_attack_enable - スキルディレイの間攻撃できるかどうかです。yesにすればスキルディレイの間スキルは使えないけど攻撃はできます。 - デフォルトはnoです。 - -left_cardfix_to_right - 二刀流の左手武器の種族、属性、Sizeのダメージ補正を右手武器に適用するかどうかです。これをyesにすると左手武器には種族、属性、Sizeのダメージ補正が掛からなくなります。デフォルトはnoです。 - -player_skill_add_range - プレイヤーのスキル射程から敵が離れた時どれぐらいの距離までスキルを使用可能にするかを決めます。スキルの射程+player_skill_add_rangeまでスキルが届きます。デフォルトは0ですが少しは入れた方がいいです。 - -skill_out_range_consume - スキルの射程から敵が離れてスキルが失敗した時SPやアイテムを消耗するかどうかです。デフォルトはyesです。 - -monster_skill_add_range - モンスターのスキル射程から敵が離れた時どれぐらいの距離までスキルを使用可能にするかを決めます。スキルの射程+monster_skill_add_rangeまでスキルが届きます。デフォルトは0です。 - -player_damage_delay - プレイヤーキャラがダメージを受けた時移動できないディレイを入れるかどうかです。 - yesにするとインデュアでも使わない限りダメージを受けた時 - しばらくは動きません。デフォルトはyesです。 - -player_damage_delay_rate - プレイヤーキャラがダメージを受けた時移動できないディレイを百分率で調整します。 - 200にするとディレイが倍になり、0にするとディレイがなくなります。 - player_damage_delayがyesにしてないと意味がありません。 - デフォルトは100です。 - -defunit_not_enemy - 防御ユニット(セイフティウォール/ニューマなど)がMOBに効果を - 及ぼさないようにするかどうかです。デフォルトはyesです。 - -random_monster_checklv - モンスター召還アイテムを使ったときに自分よりLVの高いモンスターを召還するかどうかです。 - yesにすると、自分よりLVの高いモンスターを召還しないようになります。 - デフォルトはyesです。 - -attribute_recover - 属性によって攻撃されても回復するかどうかです。noの場合は-属性を - 0にします。デフォルトはyesです。 - -item_auto_get - アイテム自動取得機能を使用するかどうかです。 - yesにするとアイテムドロップをモンスターに一番多くダメージを与えたキャラが - 自動でアイテムを取得するようになります。 - デフォルトはnoです。 - -flooritem_lifetime - 床に落ちたアイテムが消えるまでかかる時間です。単位はms(ミリ秒)です。 - デフォルトは60000(60秒)で最小は1000(1秒)です。1000未満ならデフォルトにセットされます。 - -item_first_get_time - モンスターに一番ダメージを多く与えたキャラ以外がそのモンスターの - ドロップアイテムを取れるようになるまでの時間です。 - 単位はms(ミリ秒)です。デフォルトは10000(10秒)です。 - -item_second_get_time - item_first_get_timeの後モンスターに二番目にダメージを多く与えた - キャラ以外がそのモンスターのドロップアイテムを取れるようになるまでの - 時間です。単位はms(ミリ秒)です。デフォルトは7000(7秒)です。 - -item_third_get_time - item_second_get_timeの後モンスターに三番目にダメージを多く与えた - ャラ以外がそのモンスターのドロップアイテムを取れるようになるまでの - 時間です。単位はms(ミリ秒)です。デフォルトは5000(5秒)です。 - -mvp_item_first_get_time - モンスターに一番ダメージを多く与えたキャラ以外がそのモンスターの - MVPアイテムを取れるようになるまでの時間です。 - 単位はms(ミリ秒)です。デフォルトは10000(10秒)です。 - -mvp_item_second_get_time - mvp_item_first_get_timeの後モンスターに二番目にダメージを多く与えた - キャラ以外がそのモンスターのMVPアイテムを取れるようになるまでの - 時間です。単位はms(ミリ秒)です。デフォルトは10000(10秒)です。 - -mvp_item_third_get_time - mvp_item_second_get_timeの後モンスターに三番目にダメージを多く与えた - キャラ以外がそのモンスターのMVPアイテムを取れるようになるまでの - 時間です。単位はms(ミリ秒)です。デフォルトは2000(2秒)です。 - -item_rate - アイテムドロップ率を百分率で調整します。 - 0-1000程度の数値を指定してください。デフォルトは100です。 - -drop_rate0item - 落下確率0のアイテム(一部モンスターにおけるリンゴ)を落下するかどうかの設定です。 - デフォルトはnoです。 - -base_exp_rate - BaseEXPの所得倍率を百分率で調整します。 - 0-1000程度の数値を指定してください。デフォルトは100です。 - -job_exp_rate - JobEXPの所得倍率を百分率で調整します。 - 0-1000程度の数値を指定してください。デフォルトは100です。 - -death_penalty_type - デスペナルティのタイプを決定します。 - 0で死んだ後リスタートする時に適用で持っているEXPの量から比率の分を減らす仕様、1で死んだ直後に適用で持っているEXPの量から比率の分を減らす仕様です。 - 2で死んだ後リスタートする時に適用で次のレベルアップまでのEXPから比率の分を減らす仕様、3で死んだ直後に適用で次のレベルアップまでのEXPから比率の分を減らす仕様です。 - デフォルトは0です。 - -death_penalty_base - デスペナルティによるBASE経験値減少率を百分率で調整します。 - あまり低すぎる値を使うと減りません。単位は0.01%です。 - デフォルトは0です。 - -death_penalty_job - デスペナルティによるJOB経験値減少率を百分率で調整します。 - あまり低すぎる値を使うと減りません。単位は0.01%です。 - デフォルトは0です。 - -zeny_penalty - 死んだ時無くなるゼニ量の比率です。単位は0.01%です。死んだ時 - 減るわけではなく死んだ後セーヴポイントに戻る時適用されます。 - デフォルトは0です。 - -restart_hp_rate - リスタートする時に回復するHP比率を百分率で調整します。単位は%です。 - デフォルトは0です。0の場合1回復になります。 - -restart_sp_rate - リスタートする時に回復するSP比率を百分率で調整します。単位は%です。 - デフォルトは0です。0の場合は回復しません。 - そしてSPが比率より高い場合も回復しません。 - -mvp_hp_rate - MVP モンスターのHPを百分率で調整します。 - 0-1000程度の数値を指定してください。デフォルトは100です。 - -mvp_item_rate - MVPアイテムの所得倍率を百分率で調整します。 - 0-1000程度の数値を指定してください。デフォルトは100です。 - -mvp_exp_rate - MVP EXPの所得倍率を百分率で調整します。 - 0-1000程度の数値を指定してください。デフォルトは100です。 - -monster_hp_rate - MVP 以外のモンスターのHPを百分率で調整します。 - 0-1000程度の数値を指定してください。デフォルトは100です。 - -monster_max_aspd - モンスターの最大攻撃速度を設定します。 - デフォルトは199です。最大は199で最小は100です。 - -atcommand_gm_only - @コマンドをGM専用にするかどうかです。デフォルトはnoです。 - -gm_all_skill - 全てのスキルを覚えられるようにするGMのレベルを設定します。 - これを0以外にすると、そのGMレベル以上のGMはJOBやスキル所得条件に関係なく全スキルが覚えられます。(クェストスキルも含めて) - デフォルトは 0 です。0の場合はGMではない全てのキャラの意味ではなく全てのGMが全てのスキルを覚えられないと言うことです。 - -gm_all_equipment - 全ての装備品を装備できるようにするGMのレベルを設定します。 - これを0以外にすると、そのGMレベル以上のGMはJOBやレベル、性別に関係なく - 全装備品を装備できるようになります。ただし、クライアント側でエラーを - 起こす組み合わせもあると思います。デフォルトは 0 です。 - 0の場合は全てのGMは通常プレイヤーと同じ判定が行われます。 - -gm_skill_unconditional - 無条件にスキルを使用できるようにするGMのレベルを設定します。 - これを0以外にすると、そのGMレベル以上のGMは装備武器や消費アイテムの有無 - などに関係なく、そして何も消費することなくスキルを使用できるように - なります。判定処理を無視するので動作に不都合がでる可能性があります。 - デフォルトは 0 です。 0の場合は全てのGMは通常プレイヤーと同じ判定が - 行われます。 - -player_skillfree - スキルツリーに関係なくスキルを上げることができるかどうかです。 - これをyesにすればプレイヤーの職業で習うことができるスキル全てを - スキルツリーに関係なく上げることができます。デフォルトはnoです。 - -player_skillup_limit - スキルリセット等をした時スキルを制限なしに上げるかどうかです。 - これをyesにすれば始めのスキルポイント9つはノービスで習うスキルにしか - 使えません。そしてその後の39は1次職業で習う物にだけ使えてその後の - ポイントは自由に使うことができます。デフォルトはnoです。 - -weapon_produce_rate - 武器製造スキルでの製造成功率を百分率で調整します。 - 0-1000程度の数値を指定してください。デフォルトは100です。 - -potion_produce_rate - ポーション製造スキルでの製造成功率を百分率で調整します。 - 0-1000程度の数値を指定してください。デフォルトは100です。 - -monster_active_enable - 先攻モンスターを先攻にするかどうかです。これをnoにすると - 先攻モンスターが非先攻になります。デフォルトはyesです。 - -monster_damage_delay_rate - モンスターがダメージを受けた時移動できないディレイを百分率で調整します。 - 200にするとディレイが倍になり、0にするとディレイがなくなります。 - デフォルトは100です。 - -monster_loot_type - ルートモンスターの行動の仕方を指定します。 - 0の場合はLOOTITEM_SIZEまでアイテムを食べてもまたアイテムを食べて、 - 前のアイテムが消える仕様。1の場合はLOOTITEM_SIZEまでアイテムを食べると - もうアイテムを食べなくなる仕様。デフォルトは0です。 - -mob_skill_use - MOBがスキルを使ってくるかどうかです。デフォルトはyesです。 - -mob_count_rate - map_athena.confで指定されたnpcデータを読み込む際、 - monsterで定義された配置MOBの数を百分率で調整します。 - 例外として、配置数1として定義されたMOBの数は変わりません。(BOSS対策) - また、配置数を下方修正したとき、1未満になった場合は1として処理します。 - 0-1000程度で指定してください。デフォルトは100です。 - -quest_skill_learn - クェストスキルを普通に習得するかどうかです。 - これをyesにするとクェストスキルが普通に表示されてスキルポイントを使って習得することができます。 - デフォルトは noです。 - -quest_skill_reset - スキルをリセットする時クェストスキルをリセットするかどうかです。 - デフォルトはyesです。 - noにしてもquest_skill_learnをyesにすればリセットされます。 - -basic_skill_check - 座り、交換、パーティ結成、チャットルーム作り等の時基本スキルをチェックするかどうかです。 - これをnoにすれば座り、交換等の基本スキルが必要な行動を基本スキルに関係なく使うことができます。 - デフォルトは yesです。 - -guild_emperium_check - ギルドを作る時エンペリウムを消費するかどうかです。これをnoにすれば - エンペリウムなしでもギルドが作れます。 - デフォルトは yesです。 - -guild_exp_limit - ギルドの役職に設定できる上納経験値の割合の上限を設定できます。 - デフォルトは50(%)です。 - -player_invincible_time - マップ移動やテレポート、復活した時の無敵時間を設定します。単囲は - ms(ミリ秒)。移動、攻撃行動、スキル使用、アイテム使用をするとこの - 時間はなくなる。(シーズモードでは時間を2倍にして適用) - デフォルトは5000(5秒)です。 - -pet_catch_rate - ペットの捕獲倍率を百分率で設定します。 - 0-1000程度の数値を指定してください。デフォルトは100です。 -pet_rename - ペットの名前を変更するかどうかを決めます。デフォルトはnoです。 - yesは何度でも名前の変更が可能。noは一度変更するともう変更不可能になる。 - -pet_friendly_rate - ペットに餌をあげた時上がる親密度の倍率です。 - 親密度が減る場合は適用されません。デフォルトは100です。 - -pet_hungry_delay_rate - ペットの腹が減る時間の倍率です。 - 倍率が高いと腹が減り難くなります。デフォルトは100です。 - -pet_hungry_friendly_decrease - ペットの腹が完全に減った時減る親密度の量です。デフォルトは5です。 - -pet_str - ペットのATK計算にSTRを適用するかどうかです。 - デフォルトはyesです。 - -pet_status_support - ペットによるステータスボーナスを適用するかどうかです。yesにすると - ペットを持ってる時ペット毎に設定されているステータスボーナスが - 付きます。デフォルトはnoです。 - -pet_attack_support -pet_damage_support - 主人がモンスターにダメージを与えたとき、受けたときに - ペットが支援攻撃をするかどうかです。yesにするとペットの親密度が - きわめて親しいの時だけ支援攻撃をしてくれます。デフォルトはnoです。 - -pet_support_rate - ペットの支援攻撃確率の倍率です。(100で通常、200で倍です) - 倍率が高いと支援攻撃よくしてくれるようになります。デフォルトは100です。 - -pet_attack_exp_to_master - ペットが与えたダメージの分の経験値を主人が収得するかどうかです。 - これをyesにするとペットの攻撃によるダメージも主人が与えた物になり - 主人が経験値を収得することができます。デフォルトはnoです。 - -pet_attack_exp_rate - ペットが与えたダメージの分の経験値を主人が収得する時の倍率です。 - デフォルトは100です。 -pet_lootitem - ペットがアイテムをルートするかどうかの設定です。 - デフォルトはnoです。 - -pet_weight - ペットにルートさせるときの重量制限です。 - デフォルトは1000です。 - -skill_min_damage - スキルを使った時ダメージが連打数より未満の場合全てミスになるか1ダメージになるかを決定します。 - デフォルトはnoです。 - -finger_offensive_type - スキル指弾の表示タイプを決定します。 - 0は本サーバー仕様で1はアテナ仕様です。デフォルトは0です。 - -heal_exp - スキル「ヒール」を使った際にもらえるジョブ経験値量の設定です。 - 100で回復した量と同量になります。 - モンスターの経験値を変更してない場合は5〜10程度が適当だと思われます。 - デフォルトは0です。 - -resurrection_exp - スキル「リザレクション」を使った際にもらえる経験値量の設定です。 - 単位は0.01%です。復活したプレイヤーが持っている経験値 * レベル差/100 * resurrection_exp/10000 分の経験が貰えます。 - デフォルトは0です。 - -shop_exp - スキルディスカウントとオーバーチャージを習得してる場合NPC利用金額に応じたJOB経験値獲得倍率です。(100で通常、200で倍になります) - 計算式はln(代金*スキルレベル) * shop_exp / 100 で買う場合はディスカウントがある時のみ適用で売る場合オーバーチャージがある時のみ適用されます。 - 計算式は適度に作った物です。 - デフォルトは0です。 - -combo_delay_rate - モンクのコンボディレイの時間の倍率です。(100で通常、200で倍になります。) - ただ注意するべきなのは高く設定するのがいいことではないことです。 - コンボディレイが長いとコンボの繋ぎはよくなりますがその長くなった - 時間の間は行動できないからです。デフォルトは100です。 - -item_check - アイテムのチェックを行うかどうかです。 - ログイン時とマップ移動時に所持アイテムに不正アイテムがないかチェックします。 - また@itemで不正アイテムを所得できなくします。 - デバグやアイテムの確認を行うときなどはoffにしてください。 - デフォルトはonです。 - -wedding_modifydisplay - タキシードとウェディングドレスを表示するかどうかです。 - 結婚キャラを表示したい場合はこれをyesにしてください。 - デフォルトはnoです。 - -natural_healhp_interval - HPが自動回復するまで掛かる時間です。単位はms(ミリ秒)です。 - デフォルトは6000でNATURAL_HEAL_INTERVAL未満にすることはできません。 - -natural_healsp_interval - SPが自動回復するまで掛かる時間です。単位はms(ミリ秒)です。 - デフォルトは8000でNATURAL_HEAL_INTERVAL未満にすることはできません。 - -natural_heal_skill_interval - スキルによって自動回復する場合掛かる時間です。単位はms(ミリ秒)です。 - デフォルトは10000でNATURAL_HEAL_INTERVAL未満にすることはできません。 - -natural_heal_weight_rate - 自動回復ができなくなる重量を設定します。単位は%です。 - 最小は50で最大は101です。最大が101なのは重量が - natural_heal_weight_rate未満の時に自動回復するからです。(つまり101なら - いつでも自動回復できます。) - デフォルトは50です。 - -item_name_override_grffile - アイテムの名前(英語以外の名前です。)を.grfファイルから読むかどうかです。 - noにするとitem_db.txtの名前を使います。 - デフォルトはyesです。 - -arrow_decrement - 弓を使う時矢を消耗するかどうかです。これをnoにすると - 矢が消耗されません。(矢を装備する必要はあります。) - デフォルトはyesです。 - -max_aspd - プレイヤーの最大攻撃速度を設定します。 - デフォルトは199です。最大は199で最小は100です。 - -max_hp - 最大HPを設定します。 - デフォルトは32500です。最大は1000000で最小は100です。 - -max_sp - 最大SPを設定します。 - デフォルトは32500です。最大は1000000で最小は100です。 - -max_parameter - プレイヤーの基本パラメータの最大値を設定します。 - デフォルトは99です。最大は10000で最小は10です。 - 基本パラメータ大きい過ぎるとクライアント落ちが起こるので - 適当な値を設定する方が良いです。 - -max_cart_weight - カートの最大重量を設定します。 - デフォルトは8000です。最大は1000000で最小は100です。 - -player_skill_log - プレイヤーのスキル使用ログを表示するかどうかです。 - デフォルトはnoです。 - -monster_skill_log - モンスターのスキル使用ログを表示するかどうかです。 - デフォルトはnoです。 - -battle_log - 戦闘関係のログを表示するかどうかです。 - デフォルトはnoです。 - -save_log - キャラの保存に関するログを表示するかどうか - デフォルトはnoです。 - -error_log - エラーログを表示するかどうかです。 - デフォルトはyesです。 - -etc_log - スキル、戦闘、キャラ保存、エラー以外のログを表示するかどうか - デフォルトはyesです。 - -save_clothcolor - 服の色を保存するかどうか、有効にすると問題があるかもしれません。 - デフォルトはnoです。 - -undead_detect_type - アンデッドを認識する方法を設定します。0で属性のみ、1で種族のみ、 - 2で属性と種族の両方のどちらでもあってる場合になります。 - デフォルトは0です。 - -player_auto_counter_type - プレイヤーのオートカウンターの仕様を設定します。0で100%クリティカル - でスキル反撃無し、1で防御無視、Hit+20、クリティカル率2倍でスキル反撃 - 無し、2で100%クリティカルでスキル反撃有り、3で防御無視、Hit+20、 - クリティカル率2倍でスキル反撃有りです。 - デフォルトは1です。 - -monster_auto_counter_type - モンスターのオートカウンターの仕様を設定します。0で100%クリティカル - でスキル反撃無し、1で防御無視、Hit+20、クリティカル率2倍でスキル反撃 - 無し、2で100%クリティカルでスキル反撃有り、3で防御無視、Hit+20、 - クリティカル率2倍でスキル反撃有りです。 - デフォルトは1です。 - -agi_penaly_type - agi_penaly_count以上の敵に攻撃された時のagiペナルティの仕様を設定します。 - 0でなし、1でagi_penaly_num%ずつ減って、2でagi_penaly_numだけ減ります。 - デフォルトは0です。 - -agi_penaly_count - agiペナルティを適用する敵の数を設定します。 - 2未満に設定することはできません。デフォルトは3です。 - -agi_penaly_num - agiペナルティによって減る回避の量を設定します。 - デフォルトは0です。 - -vit_penaly_type - vit_penaly_count以上の敵に攻撃された時のvitペナルティの仕様を設定します。 - 0でなし、1でvit_penaly_num%ずつ減って、2でvit_penaly_numだけ減ります。 - (減るのはvitによる防御のみ) - デフォルトは0です。 - -vit_penaly_count - vitペナルティを適用する敵の数を設定します。 - 2未満に設定することはできません。デフォルトは3です。 - -vit_penaly_num - vitペナルティによって減る回避の量を設定します。 - デフォルトは0です。 - -player_defense_type - プレイヤーが対象に攻撃する時のDEFの計算方法。0で本鯖仕様、1以上で減算(DEF*値)。 - -monster_defense_type - モンスターが対象に攻撃する時のDEFの計算方法。0で本鯖仕様、1以上で減算(DEF*値)。 - -pet_defense_type - ペットが対象に攻撃する時のDEFの計算方法。0で本鯖仕様、1以上で減算(DEF*値)。 - -magic_defense_type - MDEFの計算方法。0で本鯖仕様、1以上で減算(MDEF*値) - -player_skill_reiteration - プレイヤーが使う一部の地面スキルの重ね置きを許可するかどうかです。 - これをyesにするとSWやニューマ、トラップを重ねて置くことができます。 - デフォルトはnoです。 - -monster_skill_reiteration - モンスターが使う一部の地面スキルの重ね置きを許可するかどうかです。 - これをyesにするとSWやニューマ、トラップを重ねて置くことができます。 - デフォルトはnoです。 - -player_skill_nofootset - プレイヤーが使う一部の地面スキルをプレイヤーやモンスターの足元に - 置くのを禁止するかどうかです。これをyesにするとスキルを設置する時その - 効果範囲にプレイヤーやモンスターがいるとスキルを置くことができません。 - デフォルトはnoです。 - -monster_skill_nofootset - モンスターが使う一部の地面スキルをプレイヤーやモンスターの足元に - 置くのを禁止するかどうかです。これをyesにするとスキルを設置する時その - 効果範囲にプレイヤーやモンスターがいるとスキルを置くことができません。 - デフォルトはnoです。 - -player_cloak_check_type - プレイヤークローキングの仕様を設定します。 - 0は壁チェック有り、スキル使用と攻撃で解除される。 - 1は壁チェック無し、スキル使用と攻撃で解除される。 - 2はは壁チェック有り、スキル使用と攻撃で解除されない。 - 2はは壁チェック無し、スキル使用と攻撃で解除されない。 - デフォルトは0です。 - -monster_cloak_check_type - モンスタークローキングの仕様を設定します。 - 0は壁チェック有り、スキル使用と攻撃で解除される。 - 1は壁チェック無し、スキル使用と攻撃で解除される。 - 2はは壁チェック有り、スキル使用と攻撃で解除されない。 - 2はは壁チェック無し、スキル使用と攻撃で解除されない。 - デフォルトは0です。 - -gvg_short_attack_damage_rate - シーズモードで近距離物理攻撃のダメージ倍率です。デフォルトは100です。 - -gvg_long_attack_damage_rate - シーズモードで遠距離物理攻撃のダメージ倍率です。デフォルトは100です。 - -gvg_magic_attack_damage_rate - シーズモードで魔法攻撃のダメージ倍率です。デフォルトは100です。 - -gvg_misc_attack_damage_rate - シーズモードで物理攻撃と魔法攻撃以外の攻撃(鷹やトラップ等)の - ダメージ倍率です。デフォルトは100です。 - -mob_changetarget_byskill: no - 条件がskillusedのスキルをMOBがPCに使用するとき、その対象をスキル使用者にするかどうかです。 - MOBスキル使用後にタゲは戻ります。デフォルトはnoです。 - -player_attack_direction_change - プレイヤーが攻撃した時方向を変更するかどうかです。本鯖では動けない限り方向が変えらないのですがバグぽい仕様なのでデフォルトはyesです。 - noにすれば動くことだけで方向が変えるようになります。 - -monster_attack_direction_change - モンスターが攻撃した時方向を変更するかどうかです。本鯖では動けない限り方向が変えらないのですがバグぽい仕様なのでデフォルトはyesです。 - noにすれば動くことだけで方向が変えるようになります。 - -player_land_skill_limit - skill_db.txtで設定されている地面スキルの数制限をプレイヤーに - 適用するかどうかです。これをyesにすれば設定されている数以上は - 地面に設置することができなくなりますが数制限をどう変えても - MAX_SKILLUNITGROUPを越える数の設置はできません。 - デフォルトはyesです。 - -monster_land_skill_limit - skill_db.txtで設定されている地面スキルの数制限をモンスターに - 適用するかどうかです。これをyesにすれば設定されている数以上は - 地面に設置することができなくなりますが数制限をどう変えても - MAX_MOBSKILLUNITGROUPを越える数の設置はできません。 - デフォルトはyesです。 - -party_skill_penaly - 一部のパーティスキルを使用者とパーティでスキル効果が違うように - するかどうかです。これの影響を受けるスキルは今の所 - アドレナリンラッシュ、ウエポンパーフェクション、オーバートラストのみです。 - デフォルトはyesです。 - -monster_class_change_full_recover - モンスターがメタモルフォーシスとトランスフォーメーション等によって - 他のモンスターに変わった時そのモンスターのHPを最大なで回復させるか - どうかです。これをyesにすると変わったモンスターの最大HPまで - 回復します。noなら変わる前のHPと最大HPの比率の分のHPになります。 - デフォルトはnoです。 - -produce_item_name_input - 製造で作られた鉄や属性石に製造者の名前を付けるかどうかです。 - デフォルトはyesです。 - -produce_potion_name_input - 製造で作られたポーションに製造者の名前を付けるかどうかです。 - デフォルトはyesです。 - -making_arrow_name_input - 矢作成で作られた矢に製造者の名前を付けるかどうかです。 - デフォルトはyesです。 - -holywater_name_input - アクアベネディクタで作られた聖水に製造者の名前を付けるかどうかです。 - デフォルトはyesです。 - -display_delay_skill_fail - スキル使用のディレイ中に「スキル使用の後は、しばらくお待ちください」を表示するかどうかです。 - デフォルトはyesです。 - -chat_warpportal - チャット中のPCをワープポータルで飛ばせるかどうかです。 - デフォルトはnoです。 - -mob_warpportal - MOBをワープポータルで飛ばせるかどうかです。 - デフォルトはnoです。 - -dead_branch_active - 古木の枝などmonster命令でmobidを負数に指定した場合に召喚されるモンスターをアクティブにするかどうかです。 - デフォルトはnoです。 - -vending_max_value - 露店で置けるアイテム価格の最高値です。 - デフォルトは10000000です。 - -show_steal_in_same_party - スティール成功時、画面内のPTメンバー(自分含む)に - スティールしたアイテムの情報を公開するかどうかです。 - デフォルトはnoです。 - -enable_upper_class - 転生、養子職を有効にするかどうかです。 - デフォルトはnoです。 - -pet_atack_attr_none - ペットによる無属性通常攻撃を - 属性無し(属性による補正無し)にするかどうかです。 - デフォルトはnoです - -pc_atack_attr_none - プレイヤーによる無属性通常攻撃を - 属性無し(属性による補正無し)にするかどうかです。 - デフォルトはnoです - -mob_atack_attr_none - モンスターによる無属性通常攻撃を - 属性無し(属性による補正無し)にするかどうかです。 - デフォルトはyesです - -player_skill_partner_check - 聖体降福や合奏スキルを行う際にパートナーの存在をチェックするかどうかです。 - デフォルトはyes(チェックする)です。 - -hide_GM_session - GMアカウントのキャラクターを@コマンド等で表示の対象にするかどうかです。 - デフォルトはnoです -unit_movement_type - ユニット移動処理方法を選択します。 - 0で本鯖仕様(回線負荷→重、鯖処理→軽)、1でAthena仕様(回線負荷→軽、鯖処理→重) - デフォルトは0(本鯖仕様)です -invite_request_check - プレイヤーが各種要請中(PT加入、Guild加入、取引)に他の要請を受け入れるかどうかです。 - yesで本鯖仕様、noでAthena仕様(受け入れない) - デフォルトはyes(受け入れる)です。 -skill_removetrap_type - リムーブトラップの仕様を選択します。 - 0:本鯖仕様で罠1個を取得する - 1:Athena仕様で使ったアイテムを使った個数を取得する -disp_experience - 経験値を表示するかどうかです。 - yesにすると、敵を倒した時など経験値が入った時に本人にのみ表示されます。 - デフォルトはnoです。 - -night_at_start - Choose if server begin with night (yes) or day (no) - Default: No - -day_duration - Define duration in msec of the day. - Set to 0 to disable day cycle (but not @day command). - Except 0, minimum is 60000 (1 minute). - Default: 7,200,000 = 2 hours - -night_duration - Define duration in msec of the night. - Set to 0 to disable night cycle (but not @night command). - Except 0, minimum is 60000 (1 minute). - Default: 1,800,000 = 30 min - -ban_spoof_namer - Ban people that try to use an other name of its name (spoof name). - Duration of the ban, in minutes. - Value from 0 to 32767. Set to 0 to do no ban. - Default: 5 (minutes) - -hack_info_GM_level - Set here minimum level of a (online) GM that can receive all informations about any player that try to hack, spoof a name, etc. - Values are from 0 to 100. - 100: disable information - 0: send to any people, including normal players - default: 60, according to GM definition in atcommand_athena.conf - -any_warp_GM_min_level - Set here the minimum GM level to disable the nowarp (from) and nowarpto (to) flags. - This option is mainly used in AT_commands (@memo, @warp, @charwarp, @go, etc...). All GM commands used to move or set a new map check nowarp and nowarpto flags. - default: 20 (first level after normal player or super'normal' player) - -packet_ver_flag - Set here which client version do you accept. Add all values of clients: - 1: Clients before 2004-07-06 (old clients) - 2: 2004-07-06 kRO client - 4: 2004-07-13 kRO client - 8: 2004-07-26 kRO client - 16: 2004-08-09 kRO / 2004-08-16aSakray / 2004-08-17aSakray client - 32: 2004-09-06aSakray client - default value: 63 (all clients) - -import - その行を別ファイルの中身と置き換えます。 - -< Example > - -warp_point_debug: no -enemy_critical: yes -enemy_critical_rate: 100 -enemy_perfect_flee: no -casting_rate: 100 -delay_rate: 100 -delay_dependon_dex: no -skill_delay_attack_enable: no -left_cardfix_to_right: no -player_skill_add_range: 0 -skill_out_range_consume: yes -monster_skill_add_range: 0 -player_damage_delay: yes -player_damage_delay_rate: 100 -defunit_not_enemy: yes -random_monster_checklv: yes -attribute_recover: yes -item_auto_get: no -flooritem_lifetime: 60000 -item_first_get_time: 10000 -item_second_get_time: 7000 -item_third_get_time: 5000 -mvp_item_first_get_time: 10000 -mvp_item_second_get_time: 10000 -mvp_item_third_get_time: 2000 -item_rate: 100 -drop_rate0item: no -base_exp_rate: 100 -job_exp_rate: 100 -death_penalty_type: 0 -death_penalty_base: 100 -death_penalty_job: 100 -zeny_penalty: 0 -restart_hp_rate: 0 -restart_sp_rate: 0 -mvp_hp_rate: 100 -mvp_item_rate: 100 -mvp_exp_rate: 100 -monster_hp_rate: 100 -monster_max_aspd: 199 -atcommand_gm_only: Yes -gm_all_skill: 0 -gm_all_equipment: 0 -gm_skill_unconditional: 0 -player_skillfree: no -player_skillup_limit: no -weapon_produce_rate: 100 -potion_produce_rate: 100 -monster_active_enable: yes -monster_damage_delay_rate: 100 -monster_loot_type: 0 -mob_skill_use: yes -mob_count_rate: 100 -quest_skill_learn: no -quest_skill_reset: yes -basic_skill_check: yes -guild_emperium_check: yes -player_invincible_time: 5000 -pet_catch_rate: 100 -pet_rename: no -pet_friendly_rate: 100 -pet_hungry_delay_rate: 100 -pet_hungry_friendly_decrease: 5 -pet_str: yes -pet_status_support: no -pet_support: no -pet_support_rate: 100 -pet_attack_exp_to_master: no -pet_attack_exp_rate: no -pet_lootitem: no -pet_weight: 1000 -skill_min_damage: no -finger_offensive_type: 0 -heal_exp: 0 -resurrection_exp: 0 -hop_exp: 0 -combo_delay_rate: 100 -item_check: on -wedding_modifydisplay: no -natural_healhp_interval:4000 -natural_healsp_interval:8000 -natural_heal_skill_interval:10000 -natural_heal_weight_rate: 50 -item_name_override_grffile: yes -arrow_decrement: yes -max_aspd: 199 -max_hp: 32500 -max_sp: 32500 -max_parameter: 99 -max_cart_weight: 8000 -player_skill_log: off -monster_skill_log: off -battle_log: off -save_log: off -error_log: on -etc_log: on -save_clothcolor: no -undead_detect_type: 2 -player_auto_counter_type: 1 -monster_auto_counter_type: 0 -agi_penaly_type: 0 -agi_penaly_count: 3 -agi_penaly_num: 0 -vit_penaly_type: 0 -vit_penaly_count: 3 -vit_penaly_num: 0 -player_defense_type: 0 -monster_defense_type: 0 -pet_defense_type: 0 -magic_defense_type: 0 -player_skill_reiteration: no -monster_skill_reiteration: no -player_skill_nofootset: no -monster_skill_nofootset: no -player_cloak_check_type: 0 -monster_cloak_check_type: 0 -gvg_short_attack_damage_rate: 100 -gvg_long_attack_damage_rate: 100 -gvg_magic_attack_damage_rate: 100 -gvg_misc_attack_damage_rate: 100 -mob_changetarget_byskill: no -player_attack_direction_change:yes -monster_attack_direction_change:yes -player_land_skill_limit: yes -monster_land_skill_limit: yes -party_skill_penaly: yes -monster_class_change_full_recover: no -produce_item_name_input: yes -produce_potion_name_input: yes -making_arrow_name_input: yes -holywater_name_input: yes -display_delay_skill_fail: yes -chat_warpportal: no -mob_warpportal: no -dead_branch_active: no -vending_max_value: 10000000 -show_steal_in_same_party: no -enable_upper_class: no -pet_atack_attr_none: no -pc_atack_attr_none: no -mob_atack_attr_none: yes -player_skill_partner_check: yes -hide_GM_session: no -invite_request_check: yes -unit_movement_type: 0 -disp_experience: no -night_at_start: No -day_duration: 7200000 -night_duration: 1800000 -ban_spoof_namer: 5 -hack_info_GM_level: 60 -any_warp_GM_min_level: 20 -packet_ver_flag: 63 - - -========================================================================== -6. atcommand_athena.conf --------------------------------------------------------------------------- - -< What this file is. > - - GMコマンド(/mm、/nb等)や@コマンドを使うことができるGMのレベルを設定する物です。 - 設定は全て省略可能で、省略時はデフォルト値が利用されます。(デフォルトは0です。) - -command_symbol - Set here the symbol that you want to use for your commands - Only 1 character is get (default is '@'). You can set any character, - except control-character (0x00-0x1f), '%' (party chat speaking) and '/' (standard ragnarok GM commands) - With default character, all commands begin by a '@': <example> @revive - default: @ - -Sets the level of the users that can use the GM commands. -<command name>: level -// When battle_athena.conf has atcommand_gm_only set to no, -// normal players (gm level 0) can use GM commands if you set 0 to the command level. -Max GM level is 99. If you want forbid a command to all people, set it with level 100. - -broadcast - GMコマンド /nb、/b、/bb -local_broadcast - GMコマンド /lb -mapmove - GMコマンド /mm -resetstate - GMコマンド /resetstate、/resetskill -rura+ - @コマンド @rura+ -rura - @コマンド @rura -where - @コマンド @where -jumpto - @コマンド @jumpto -jump - @コマンド @jump -who - @コマンド @who -save - @コマンド @save -load - @コマンド @load -speed - @コマンド @speed -storage - @コマンド @storage -gstorage - @コマンド @gstorage -option - @コマンド @option -hide - GMコマンド /hideと@コマンド @hide -jobchange - @コマンド @jobchange -die - @コマンド @die -kill - @コマンド @kill -alive - @コマンド @alive -kami - @コマンド @kami、@kamib -heal - @コマンド @heal -item - @コマンド @item、@item2 -itemreset - @コマンド @itemreset -itemcheck - @コマンド @itemcheck -lvup - @コマンド @lvup -joblvup - @コマンド @joblvup -help - @コマンド @help、@h -gm - To become GM (need password; password is set in login_athena.conf). - special!: only a non-GM (player with gm level 0) need to have this command. - if you change the value, be sure of what you do! - To be able to create a gm with @gm, you must: - - give a level to level_new_gm (parameter of login_athena.conf) (not 0) - - enable to level 0 the @gm command (atcommand_athena.conf) (default 100) - Only level 0 can give access to this command - - enable gm commands to normal player (battle_athena.conf, atcommand_gm_only parameter) - - and normal player must give correct password when he use the @gm command (gm_pass paramter in login_athena.conf) -pvpoff - @コマンド @pvpoff -pvpon - @コマンド @pvpon -gvgoff - @コマンド @gvgoff -gvgon - @コマンド @gvgon -model - @コマンド @model -go - @コマンド @go -monster - @コマンド @monster -killmonster - @コマンド @killmonster、@killmonster2 -refine - @コマンド @refine -produce - @コマンド @produce -memo - @コマンド @memo -gat - @コマンド @gat -packet - @コマンド @packet -stpoint - @コマンド @stpoint -skpoint - @コマンド @skpoint -zeny - @コマンド @zeny -param - @コマンド @str、@agi、@vit、@int、@dex、@luk -guildlvup - @コマンド @guildlvup -makeegg - @コマンド @makeegg -petfriendly - @コマンド @petfriendly -pethungry - @コマンド @pethungry -petrename - @コマンド @petrename -recall - @コマンド @recall -charjob - @コマンド @charjob -revive - @コマンド @revive -charstats - @コマンド @charstats -charoption - @コマンド @charoption -charsave - @コマンド @charsave -charload - @コマンド @charload -night - @コマンド @night -day - @コマンド @day -doom - @コマンド @doom -doommap - @コマンド @doommap -raise - @コマンド @raise -raisemap - @コマンド @raisemap -charbaselvl - @コマンド @charbaselvl -charjlvl - @コマンド @charjlvl -kick - @コマンド @kickとGM右クリック命令「使用者強制終了」 -allskill - @コマンド @allskill -questskill - @コマンド @questskill -lostskill - @コマンド @lostskill -spiritball - @コマンド @spiritball -party - @コマンド @party -guild - @コマンド @guild -agitstart - @コマンド @agitstart -agitend - @コマンド @agitend -mapexit - @コマンド @mapexit -idsearch - @コマンド @idsearch -charchangesex - Changes the sex of an online player (all characters on the account) -ignorelist - Displays your ignore list -charignorelist - Displays ignore list of a player -inall - Allows all wispers for the player -exall - Blocks all wispers for the player -chardisguise - Changes disguise of a player -charundisguise - Cancels disguise of a player -email - To change your (own) email (characters protection) - note: this command doesn't check email itself, but check structure of the email (xxx@xxx) - if you want be sure of each e-mail disable this option (value: 100) - - -import - その行を別ファイルの中身と置き換えます。 - - -< Example > -command_symbol: @ - -broadcast: 1 -local_broadcast: 1 -mapmove: 1 -resetstate: 1 -rura+: 1 -rura: 1 -where: 1 -jumpto: 1 -jump: 1 -who: 1 -save: 1 -load: 1 -speed: 1 -storage: 1 -gstorage: 1 -option: 1 -hide: 1 -jobchange: 1 -die: 1 -kill: 1 -alive: 1 -kami: 1 -heal: 1 -item: 1 -itemreset: 1 -itemcheck: 1 -lvup: 1 -joblvup: 1 -help: 1 -gm: 100 -pvpoff: 1 -pvpon: 1 -gvgoff: 1 -gvgon: 1 -model: 1 -go: 1 -monster: 1 -killmonster: 1 -refine: 1 -produce: 1 -memo: 1 -gat: 1 -packet: 1 -stpoint : 1 -skpoint : 1 -zeny: 1 -param: 1 -guildlvup: 1 -makeegg: 60 -petfriendly: 1 -pethungry: 1 -petrename: 1 -recall: 1 -charjob: 1 -revive: 1 -charstats: 1 -charoption: 1 -charsave: 1 -charload: 1 -night: 1 -day: 1 -doom: 1 -doommap: 1 -raise: 1 -raisemap: 1 -charbaselvl: 1 -charjlvl: 1 -kick: 1 -allskill: 1 -questskill: 1 -lostskill: 1 -spiritball: 1 -party: 1 -guild: 1 -agitstart: 1 -agitend: 1 -mapexit: 1 -idsearch: 1 -charchangesex: 1 -ignorelist: 0 -charignorelist: 20 -inall: 20 -exall: 20 -chardisguise: 60 -charundisguise: 60 -email: 0 - -========================================================================== -7. conf/ladmin_athena.conf --------------------------------------------------------------------------- - -< What this file is. > - - A setup of ladmin (remote administration of the login-server) is described. - It mainly becomes a setup of an administrator. - Only 'c' version of the ladmin is concerned by this configuration file. - 'Perl' ladmin doesn't use it. - - -< Explanation of a key > - -If you change one of these parameters, you must restart ladmin to update. -If you repeat one parameter in the configuration file, only the latest will be validated. - -login_ip - IP adress to contact login-server. - It is the IP adress of the login-server. - Default value: 127.0.0.1 (same computer). - -login_port - Port to contact login-server. - It is the port used by login-server. - Default value: 6900. - -admin_pass - It is the administrator password used to administrate the login-server. - You define it in login-athena.conf. - Void password will not work. - NOTICE: You must change this or attackers can exploit your server. - Default value: admin. CHANGES this default value to avoid hack. - -passenc: - You specify here how ladmin send password to login-server. 3 values are possible: - 0: plain text - 1: use md5 key (format: key + password) - 2: use md5 key (format: password + key) (default) - default: 2 - -defaultlanguage - You can specified a language to display information and for logs. - There are 2 values: - F: Fran軋is - E: English (default) - If a displayed information isn't translated, English is used. - Default value: E - -ladmin_log_filename - Gives the log file name and path to stores logs information. - All operations done by the ladmin are written in this file with a time stamp. - Default value: log/ladmin.log - -date_format: - Indicate how to display date in logs, to players, etc. - 0: 31-12-2004 23:59:59 - 1: 12-31-2004 23:59:59 - 2: 2004-31-12 23:59:59 - 3: 2004-12-31 23:59:59 - Default value: 3 - -import - Gives an other configuration file to include in. - You must write the additionnal configuration file name and path. - The mentionned file can include any parameter of the login configuration. - You can create a chain or configuration files if necessary. - Default value: <no_additional_configuration_file>. - -<Example> -login_ip:127.0.0.1 -login_port: 6900 -admin_pass: admin -passenc: 2 -defaultlanguage: E -ladmin_log_filename: log/ladmin.log -date_format: 3 -//import: path/additional_configuration_file - - -========================================================================== -EOF --------------------------------------------------------------------------- diff --git a/doc/coredump_report.txt b/doc/coredump_report.txt deleted file mode 100644 index 4b41215..0000000 --- a/doc/coredump_report.txt +++ /dev/null @@ -1,109 +0,0 @@ -========================================================================== - サーバーが強制終了する場合のcoredumpによる詳細なバグ報告方法 --------------------------------------------------------------------------- - -< このファイルは何? > - - Athena使用中にmap-server.exeなどが突然落ちた場合に、落ちたときのスタックの - バックトレースをを開発者に伝える方法を解説する。 - バグ報告の時に併用すると開発者が喜ぶかもしれない。 - - ここでの「落ちる」はあくまでサーバーであり、クライアントではない。 - またプロセスがcore(またはstackdump)を吐く現象のことであり、 - 無限ループなどのプロセスは生きているがサーバーの機能は提供されない状態の - ことではない。 - - --------------------------------------------------------------------------- -< 目次 > - - * Cygwinでのstackdumpとcore - Cygwin上でcoreファイルを吐く方法を紹介する。 - - * coreファイルからスタックのバックトレースを得る - プログラムが吐いたcoreからバックトレースを得る方法を紹介する。 - - * 例 - 実際にとったログの例を示す。 - - --------------------------------------------------------------------------- -< Cygwinでのstackdumpとcore > - - Cygwinでプログラムが強制終了する(アクセス違反などによるもの)場合、標準では - coreではなくstackdumpを吐く。これは全くといって良いほど役に立たないため、 - stackdumpをコピペされても開発者はおそらく見ないだろう。 - - よって次の方法で、stackdumpではなくcoreを吐くようにする。 - ** 環境変数に「error_start=dumper.exe」を追加する ** - - よくわからない場合、次のように作業するといい。(Win2000でのみ確認) - * デスクトップの「マイコンピュータ」を右クリックして「プロパティ」を出す。 - * [詳細]タブを開き、[環境変数]ボタンをクリックする。 - * ユーザー環境変数、システム環境変数のどちらか「CYGWIN」という変数がないか探す - * ある場合は、選択して[編集]ボタンを押し、[変数値]に「error_start=dumper.exe」 - を追加する。既に何かの単語がある場合は、単語を区切るため、 - 追加する部分の最初に半角スペースを入れることを忘れないこと。 - * ない場合は、システム環境変数に(Administrator権限がないならユーザー環境変数) - の[新規]ボタンを押して、[変数名]に「CYGWIN」、辺数値に - 「error_start=dumper.exe」を入力する。 - * OKを押してウィンドウを閉じ、Cygwinを起動しなおせばよい - - こうしておくと、stackdumpの変わりにcoreを吐くようになる。 - サイズが大きい場合、coreを吐くのには多少時間がかかる。 - またcoreを吐いている間、dumper.exeというプログラムのウィンドウが表示される。 - - --------------------------------------------------------------------------- -< coreファイルからスタックのバックトレースを得る > - - coreを吐く場合、まず開発者はスタックのバックトレースを欲しがる。エラー個所を - 判断しやすいからだ。よって、gdbでバックトレースを取り出そう。 - まず、次のようにしてgdbを起動する。ここではmap-server.exeを例に出す。 - UNIX系OSではコアファイル名を修正する必要があるだろう。(「core」など) - - $ gdb -c map-server.exe.core - - なにやら色々英文が表示され、最後に (gdb) というプロンプトが出たはずだ。 - この直前にエラーの起こった関数やファイル名などと、その内容が表示されている - はずなので、これはコピペすべきだ。 - - また、ここで「bt」と入力すると、スタックのバックトレースが表示される。 - これもコピペするとよい。ただし、あまりにも長い場合は最初の十数行程度で - 十分だろう。 - - ちなみに、「p 変数名」のように入力すると変数を見たりも出来る。 - 関連しそうな変数の値を色々表示して一緒にコピペすると開発者が喜ぶかもしれない。 - - gdbを終了する場合は、「q」と打ち込む。 - - --------------------------------------------------------------------------- -< 例 > - - 以下はmob.cのmob_warp()関数でわざとアクセス違反を起こしてとったログである。 - エラーの場所、どういう順で呼び出されたかがわかるだろう。 - - もちろん、Athenaのパッチ番号の報告を忘れないこと。 - パッチが違うと、ソースファイルが変わるので、行番号が役に立たなくなるためだ。 - - なお以下の例では、バックトレース以外に、 - pコマンドを使って該当のMOBの名前(英語)と、マップの名前を表示している。 - (FAKE_ANGEL, gef_dun03.gat) - -#0 mob_warp (md=0x10119c88, x=-1, y=-1, type=-1) at mob.c:1845 -1845 memset(NULL,0,1); -(gdb) bt -#0 mob_warp (md=0x10119c88, x=-1, y=-1, type=-1) at mob.c:1845 -#1 0x0042609d in mob_ai_sub_lazy (key=0x68e77f5, data=0x10119c88, - app=0x22fe88 "、\"") at mob.c:1412 -#2 0x00455b54 in db_foreach (table=0x22fe88, func=0x610691f2 <select+242>) - at db.c:414 -#3 0x10119c88 in ?? () -#4 0x0022fe88 in ?? () -#5 0x610691f2 in select () -(gdb) p mob_db[md->class].name -$1 = "FAKE_ANGEL\000\203t\203F\203C\203N\203G\203\223\203" -(gdb) p map[md->bl.m].name -$2 = "gef_dun03.gat\000\000r" - diff --git a/doc/db_ref.txt b/doc/db_ref.txt deleted file mode 100644 index 4a0ea23..0000000 --- a/doc/db_ref.txt +++ /dev/null @@ -1,147 +0,0 @@ -========================================================================== - Athena dev 2.1.1 mod0659 現在のdbのリファレンス+α --------------------------------------------------------------------------- - -< このファイルは何? > - - Athenaのdbファイルの設定方法のリファレンスです。 - - -< dbのリスト > - -cast_db.txt スキルのキャスティング時間とディレイ、維持時間等を設定。 -skill_db.txt スキルのデータを設定。 -skill_require_db.txt スキル使用条件を設定。 -pet_db.txt ペットのデータを設定。 - - -========================================================================== -1. db/cast_db.txt --------------------------------------------------------------------------- - -id,cast_list,delay_list,upkeep_time,upkeep_time2 - -id: スキルのIDです。 -cast_list: スキルのキャスティング時間を設定します。レベル別に設定する場合は「:」を使います。 -delay_list: スキルのディレイ時間を設定します。レベル別に設定する場合は「:」を使います。 -upkeep_time:スキルの維持時間を設定します。レベル別に設定する場合は「:」を使います。 -upkeep_time2:スキルによって起こる状態異常の維持時間を設定します。レベル別に設定する場合は「:」を使います。(ただ速度減少はupkeep_timeを使いますので注意してください。) - -※武器の追加効果による状態異常はMG_STONECURSE(石化)、MG_FROSTDIVER(凍結)、NPC_STUNATTACK(スタン)、NPC_SLEEPATTACK(睡眠)、TF_POISON(毒)、NPC_CURSEATTACK(呪い)、NPC_SILENCEATTACK(沈黙)、NPC_BLINDATTACK(暗黒)のupkeep_time2を使います。(レベルは7で適用) -※急所攻撃の場合最大レベルは1ですがバッシュのレベルによって異常時間を変更できるので複数設定も可能です。 -※マキシマイズパワーとクローキングのupkeep_timeは維持時間ではなくSPが1減る時間です。 - - -========================================================================== -2. db/skill_db.txt --------------------------------------------------------------------------- - -id,range,hit,inf,pl,nk,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count - -id: スキルのIDです。 -range: スキルの射程距離です。レベル別に設定する場合は「:」を使います。-1はキャラの武器射程と同じと言う意味で-2ならキャラの武器射程+1、-3ならキャラの武器射程+2になります。 -hit: 連打なら8、単発なら6(スキルのヒット数じゃありません。) -inf: スキル情報です。 - 0-パッシブ、1-敵、2-場所、4-即時発動、16-味方、32-罠 - 複数の物を入れると(数値を足して)正しく動作しません。 -pl: スキルの属性です。 - 0-無 1-水 2-地 3-火 4-風 5-毒 6-聖 7-暗 8-念 9-不死 -nk: 付加 1効果 2吹き飛ばし -MaxLv: スキルの最大レベルです。 -list_num: Hit回数のリストです。レベル別に設定する場合は「:」を使います。 -castcancel: スキルがキャンセルされるかどうかを設定します。yesはキャンセルされる物でnoはキャンセルされない物です。 -cast_defence_rate: キャスティング中に低下する防御力の比率です。ボウリングバッシュやクランドクロスのようにスキルキャスティング中に防御が減るスキルの設定に使います。 -inf2: スキル情報2です。1 - クェストスキル、2 - npc スキル、4-敵、8-場所、16-即時発動、32-味方、64-罠、128-PVPモードで自分を含む全ての物にダメージが入るスキル(地面スキルのみ)、256-普通の使用で自分に必ずダメージが入るスキル(地面スキルのみ)、512-自分には使うことができないスキル、1024 - 自分か自分のパーティにしか使えないスキル。2048 - 自分か自分のギルドにしか使えないスキル、同盟ギルドチェックは無し。(4、8、16、32、64は一部のアクティブスキルが使用。今は阿修羅覇鳳拳のみ使用。) -maxcount: 地面スキルのみに適用される物でスキルを置ける最大数です。0は置けないと言う意味ではなく制限がない物と言う意味です。 -skill_type: スキルの種類を設定します。weaponは武器スキルでmagicは魔法スキル、miscは武器でも魔法でもないスキルです。noneは決め難しい物等に設定します。ただこれを変えたとしてもスキルのダメージ計算がこれに合わせて変わるわけではなくダメージの計算はプログラムレベルで行なっています。これはスペルブレイカーで詠唱中止されるかどうかを設定する為の物です。(他のスキルでこの設定を使用する可能性もありますが今の所スペルブレイカーのみです。) magicに設定するとスペルブレイカーで詠唱中止されます。 -blow_count: スキルよるノックバック距離です。レベル別に設定する場合は「:」を使います。 - - -========================================================================== -3. db/skill_require_db.txt --------------------------------------------------------------------------- - -id,list_hp,list_sp,list_hp_rate,list_sp_rate,list_zeny,list_weapon,state,spiritball,itemid1,amount1,itemid2,amount2,itemid3,amount3,itemid4,amount4,itemid5,amount5,itemid6,amount6,itemid7,amount7,itemid8,amount8,itemid9,amount9,itemid10,amount10 - -id: スキルのIDです。 -list_hp: スキル使用で減るHPの量です。レベル別に設定する場合は「:」を使います。 -list_sp: スキル使用で減るSPの量です。レベル別に設定する場合は「:」を使います。 -list_hp_rate: スキル使用で減るHPの比率です。レベル別に設定する場合は「:」を使います。(最大HPの比率ではなく現在HPの比率です。) -list_sp_rate: スキル使用で減るSPの比率です。レベル別に設定する場合は「:」を使います。(最大SPの比率ではなく現在SPの比率です。) -list_zeny: スキル使用で減るゼニの量です。レベル別に設定する場合は「:」を使います。 -list_weapon: スキルを使うことができる武器を設定します。 - 99 - 全ての武器、0 - 素手、1 - 短剣、2 - 片手剣、3 - 両手剣、4 - 片手槍、 - 5 - 両手槍、6 - 片手斧、7 - 両手斧、8 - 片手鈍器、9 - 両手鈍器、10 - ロッド、 - 11 - 弓、12 - ナックル、13 - 楽器、14 - 鞭、15 - 本、16 - カタール、 - 17~22: 二刀流 - 複数を設定する場合は「:」を使います。 -state:スキルを使用する為の条件を設定します。複数の設定はできません。 - none - 条件無し - hiding - ハイディング状態 - cloacking - クローキング状態。 - hidden: ハイディングやクロッキング状態 - riding: ペコペコに乗っている - falcon: 鷹を連れている - cart: カートを着けている - shield: シールドを持っている - sight: サイト状態 - explosionspirits: 爆裂波動状態 - recover_weight_rate: 自然回復できる重量 - move_enable: スキル使用位置が移動可能な場所 - water: 足元が水 -spiritball: スキル使用に必要な気弾の数です。レベル別に設定する場合は「:」を使います。 -itemid1: スキル使用に必要なアイテムのID、ポーションピッチャーの場合レベル別に使うことになるアイテムID -amount1: スキル使用に必要なアイテムの数(数が0の場合アイテムのIDがあるとアイテムは減らないけど触媒としてそのアイテムを持っている必要があるようになります。) ポーションピッチャーの場合レベル別に使うことになるアイテム数 -itemid2: 上同 -amount2: 上同 -itemid3: 上同 -amount3: 上同 -itemid4: 上同 -amount4: 上同 -itemid5: 上同 -amount5: 上同 -itemid6: 上同 -amount6: 上同 -itemid7: 上同 -amount7: 上同 -itemid8: 上同 -amount8: 上同 -itemid9: 上同 -amount9: 上同 -itemid10: 上同 -amount10: 上同 - - -========================================================================== -4. db/pet_db.txt --------------------------------------------------------------------------- - - MobID,Name,JName,ItemID,EggID,AcceID,FoodID,Fullness,HungryDelay ,R_Hungry,R_Full,Intimate,Die,Capture,Speed,S_Performance,talk_convert_class,attack_rate,defence_attack_rate,change_target_rate,pet_script - -MobID: モンスターIDです。 -Name: 英語名前(ダミー) -JName: 名前 -ItemID: 捕獲用のアイテムID -EggID: 卵のアイテムID -AcceID: 装備アクセサリーのアイテムID -FoodID: 餌のアイテムID -Fullness: 1回の餌での満腹度増加率% -HungryDelay: 満腹度が1%減る為にかかる時間(秒) -R_Hungry: 空腹時餌やり親密度増加量 -R_Full: とても満腹時餌やり親密度減少量 -Intimate: 捕獲時親密度 -Die: 死亡時親密度減少量 -Capture: 捕獲率(万分率) -Speed: 移動速度 -S_Performance: スペシャルパフォマンスがあるかどうか(1であり0でなし) -talk_convert_class: 台詞を他のペットの物に変更。変更したいペットのモンスターIDを入れます。0の場合変更なしでマイナスを入れるとエモーション以外の物(台詞)は全て無視されます。 -attack_rate: 支援攻撃確率。(万分率) 主人が攻撃をしかけた場合。 -defence_attack_rate: 支援攻撃確率。(万分率) 主人が攻撃を受けた場合。 -change_target_rate: 攻撃目標を変更する確率。(万分率) -pet_script: ペットを持っている時適用されるステータスボーナスを設定。 - - - -========================================================================== -EOF --------------------------------------------------------------------------- diff --git a/doc/help.txt b/doc/help.txt deleted file mode 100644 index 430574d..0000000 --- a/doc/help.txt +++ /dev/null @@ -1,453 +0,0 @@ -GM Commands Help File -By Akaru ------------------------ -To use these commands, type them inside the message window where you usually type to chat. - -<ANNOUNCEMENT COMMANDS> - -/nb <message> -@kami <message> -Lets you make a GM global announcement without a name (in yellow) - -@kamib <message> -Lets you make a GM global announcement without a name (in blue) - -/b/@broadcast <message> -Lets you make a GM global announcement with your name - -/lb/@localbroadcast <message> -Broadcasts a GM message with name of the GM (in yellow) ONLY on your map - -/nlb <message> -Broadcasts a GM message without name of the GM (in yellow) ONLY on your map - -<INFORMATION COMMANDS> - -@who [match_text] -Lists who is currently online in your server and their location -@who2 [match_text] -Lists who is currently online in your server and their job -@who3 [match_text] -Lists who is currently online in your server and their party/guild - -@whomap [map] -Display a listing of who is online and where in a specifical map -@whomap2 [map] -Display a listing of who is online and their job in a specifical map -@whomap3 [map] -Display a listing of who is online and their party/guild in a specifical map - -@whogm [match_text] -Like @who+@who2+who3, but only for GM. - -@where <char name> -Tells you the location of a character - -@charstatsall -Displays stats of all characters. - -@charitemlist <char name> -Displays all items of a player. - -@charstoragelist <char name> -Displays all items of a player's storage. - -@charcartlist <char name> -Displays all items of a player's cart. - -@time/@date/@server_date/@serverdate/@server_time/@servertime -Display the date/time of the server - -@idsearch <part_of_item_name> -Search all items that name have part_of_item_name - -@ignorelist -Displays your ignore list - -@mapinfo [<1-3> [map]] -Give information about a map (general info +: 0: no more, 1: players, 2: NPC, 3: shops/chat). - -<CONTROL COMMANDS> - -@die -Kill yourself :) - -@alive -Revive yourself from death - -@kill <char name> -Kills specified character name -Example: -@kill TestChar -> The character named TestChar is dead - -@nuke <char name> -Kills specified character (nuclear effect). - -@save -Sets save point as current location - -@load -Warps you to your save point (a.k.a. butterfly wing) - -@warp <map name> <x> <y> -@rura <map name> <x> <y> -@mapmove <map name> <x> <y> -/mm <map name> <x> <y> -/mapmove <map name> <x> <y> -Warps you to the selected position -Example: -@warp morocc 150 160 -> Warps you to Morroc (X:150, Y:160) -@rura prontera 50 80 -> Warps you to Prontera (X:50, Y:80) - -@jump [x [y]] -Teleports you randomly in the map (a.k.a. fly wing) - -/shift/@jumpto/@warpto/@goto <char name> -Warps you to selected character -Example: -@jumpto TestChar -> You are warped to TestChar's current location - -@go <number/city_name> -Warps you to a set city: - -3: (Memo point 2) 1: morocc 5: izlude 9: yuno 13: niflheim - -2: (Memo point 1) 2: geffen 6: aldebaran 10: amatsu 14: louyang - -1: (Memo point 0) 3: payon 7: xmas (lutie) 11: gonryun 15: start point - 0: prontera 4: alberta 8: comodo 12: umbala 16: prison/jail - -/hide/@hide -GM Hide. Perfect hide that's totally invinsible. - -@heal [<HP> <SP>] - Heals the desired amount of HP and SP. No value specified will do a full heal. -@storage - Opens storage - -/recall/@recall <char name> - Warps target character to you. -@recallall - Recalls everyone on the server to you. -@guildrecall <guild_name/id> - Warps all online character of a guild to you. -@partyrecall <party_name/id> - Warps all online character of a party to you. -@revive <char name> - Revives target character. - -<SPAWNING COMMANDS> - -/item <item_name> - Gives you 1 of the desired item. -@item <item name or ID> <quantity> - Gives you the desired item. - -/monster <monster_name> - Spawns 1 of the desired monster. -@spawn/@monster/@summon <monster_name_or_monster_ID> [<number to spawn> [<desired_monster_name> [<x coord> [<y coord>]]]] -@monster2 <desired_monster_name> <monster_name_or_monster_ID> [<number to spawn> [<x coord> [<y coord>]]] -@spawn/@monster/@summon/@monster2 "desired monster name" <monster_name_or_monster_ID> [<number to spawn> [<x coord> [<y coord>]]] -@spawn/@monster/@summon/@monster2 <monster_name_or_monster_ID> "desired monster name" [<number to spawn> [<x coord> [<y coord>]]] - Spawns the desired monster with any desired name. - -<MAP OPTIONS COMMANDS> - -@pvpon - Turns pvp on on the current map -@pvpoff - Turns pvp off on the current map -@gvgon - Turns gvg on on the current map -@gvgoff - Turns gvg off on the current map - -<CHARACTER CONTROL COMMANDS> -@baselvlup <number of levels> - Raises your base level the desired number of levels. The max is 99 -@joblvlup <number of levels> - Raises your job level the desired number of levels. The max is 50 - -@job/@jobchange <job ID> -Changes your job to the job assigned to the ID - 0 Novice 7 Knight 14 Crusader 22 Formal - 1 Swordman 8 Priest 15 Monk 23 Super Novice - 2 Mage 9 Wizard 16 Sage - 3 Archer 10 Blacksmith 17 Rogue - 4 Acolyte 11 Hunter 18 Alchem - 5 Merchant 12 Assassin 19 Bard - 6 Thief 13 Knight2 20 Dancer - 21 Crusader2 - 24 Novice High 31 Lord Knight 38 Paladin - 25 Swordman High 32 High Priest 39 Monk - 26 Mage High 33 High Wizard 40 Professor - 27 Archer High 34 Whitesmith 41 Stalker - 28 Acolyte High 35 Sniper 42 Creator - 29 Merchant High 36 Assassin Cross 43 Clown - 30 Thief High 37 Peko Knight 44 Gypsy - 45 Paladin2 - -@option <param1> <param2> <param3> -Changes options for your character - <param1> <param2> (Stackable) <param3> (Stackable) - 01 Petrified 01 Poison 01 Sight - 02 Frozen 02 Cursed 02 Hide - 03 Stunned 04 Silenced 04 Cloak - 04 Sleeping 08 ??? 08 Level 1 Cart - 06 darkness 16 darkness 16 Falcon - 32 Peco Peco riding - 64 GM Perfect Hide - 128 Level 2 Cart - 256 Level 3 Cart - 512 Level 4 Cart - 1024 Level 5 Cart - 2048 Orc Head - 4096 Wedding Sprites - 8192 Ruwach - -@speed <1-1000> -Changes you walking speed. -1(Fastest)<---140(Default)----------------->1000(Slowest) - -@disguise <monster_name_or_monster_ID> -Change your appearence to other players to a mob. - -@undisguise -Restore your normal appearance. - -@model <hair ID> <hair color> <clothes color> -Changes your characters appearance (Hair type, Hair Colour and/or Clothes Colour) - - Hair ID (0-17) Hair Colour (0-8) Clothes Colour (0-4) - 0 Default 0 Default - 1 Blonde 1 Red - 2 Purple 2 Green - 3 Brown 3 White - 4 Green 4 Brown - 5 Blue - 6 White - 7 Black - 8 Red - -@effect <effect_id> [flag] -Give an efect to your character. - -@stpoint <number of points> -Gives you the desired number of stat points. - -@skpoint <number of points> -Gives you the desired number of skill points. - -@zeny <amount> -Gives you desired amount of Zeny. - -@str <amount> -@agi <amount> -@vit <amount> -@int <amount> -@dex <amount> -@luk <amount> -Adds desired amount to any stat. For example "@str 10" raises your str by 10 - -@spiritball <number> -Number = 1-1000 -Gives you monk "spirit spheres" like from the skill "Call Spirits" -(If the number you use is > 1000, your server may become instable or crash) - -@memo [memo_position] -set/change a memo location (no position: display memo points). - -@questskill <id> -Gives you the specified quest skill - -@lostskill <id> -Takes away the specified quest skill from you - -Quest Skill ID: - Novice - 142 = Emergency Care - 143 = Act dead - Swordsman - 144 = Moving HP Recovery - 145 = Attack Weak Point - 146 = Auto Berserk - Magician - 157 = Energy Coat - Archer - 147 = Arrow Creation - 148 = Charge Arrows - Acolyte - 156 = Holy Light - Merchant - 153 = Cart Revolution - 154 = Change Cart - 155 = Crazy Uproar/Loud Voice - Thief - 149 = Throw Sand - 150 = Back Sliding - 151 = Take Stone - 152 = Stone Throw - -<GUILD CONTROL COMMANDS> - -@guildlvup/@guildlvlup <# of levels> - Raise Guild by desired number of levels - -<EQUIPMENT COMMANDS> - -@refine <position> <+/-amount> -Upgrades equipment at the position specified (Stackable) -0 - All -1 - Lower Head -2 - Right Hand -4 - Robe/Garment -8 - Left Accessory -16 - Body/Armor -32 - Left Hand -64 - Feet -128 - Right Accessory -256 - Top Head -512 - Mid Head - -Example: -@refine 34 10 - Refines a 2 handed weapon to +10 -@refine 16 4 - Refines the body/armor to +4 - -@produce <equip name or equip ID> <element> <# of very's> -Element: 0=None 1=Ice 2=Earth 3=Fire 4=Wind -# of very's: 0=None 1=Very Strong 2=Very Very Strong 3=Very Very Very Strong - -Example: @produce 1163 3 3 - Produces a Very Very Very Strong (Your Nick)'s Fire Claymore - -<Q-PET/cutePET COMMANDS> -@hatch - Create a pet from your inventory eggs list. -@makeegg <ID> - Gives pet egg for monster ID in pet DB -@petfriendly <#> - Set pet friendly amount (0-1000) 0 = Min, 1000 = Max -@pethungry <#> - Set pet hungry amount (0-100) 0 = Min, 100 = Max -@petrename - Re-enable pet rename - -<REMOTE CHAR COMMANDS> -@charwarp <map name> <x> <y> <char name> -Warps character to location of choice -Example: -@charwarp morocc 150 160 TestChar -> Warps TestChar to Morroc (X:150, Y:160) - -@charstats <char name> -Displays the character's stats. - -@charignorelist <char name> -Displays ignore list of the player - -@inall <char name> -Allows all wispers for the player - -@exall <char name> -Blocks all wispers for the player - -@charoption <param1> <param2> <param3> <char name> -Does the same as the @option command only to target character. - -@charmountpeco <charname> -Give/remove to a player a peco (Class is required, but not skill). - -@charpetrename <charname> -Re-enable pet rename to a player. - -@charsave <map> <x> <y> <char name> -Changes the target player's respawn point. - -@charbaselvl <#> <char name> -Change a character's base level. - -@charjlvl <#> <char name> -Change a character's job level. - -@charjob/@charjobchange <job ID> <char name> -Changes target character's job. - -@charzeny <amount> <char name> -Give/take a player's Zeny - -@charstpoint <amount> <char name> -Give/take a player's stat points - -@charskpoint <amount> <char name> -give/take a player's skill points - -@charquestskill <#> <charname> -Gives to a player the specified quest skill. - -@charlostskill <#> <charname> -Takes away the specified quest skill from the player. - -@chardelitem <item_name_or_ID> <quantity> <player> -Remove items from a character - -@charmodel <hair type> <hair color> <clothes color> <char name> -Changes a player's model - -@chardisguise <monster_name_or_monster_ID> <char name> -Changes disguise of a player - -@charundisguise <char name> -Cancels disguise of a player - -@charchangesex <name> -Changes sex of a player (all characters of the account) - -@charblock/@block <name> -Blocks definitively a account - -@charunblock/@unblock <name> -Unblocks a account - -@charban/@ban/@banish/@charbanish <time> <name> -Ban temporarily a account - time usage: adjustement (+/- value) and element (y/a, m, d/j, h, mn, s) - Example: @ban +1m-2mn1s-6y testplayer - -@charunban/@unban/@unbanish/@uncharbanish <name> -Unban a account - -@jail <char_name> -Sends specified character in jails - -@unjail/@discharge <char_name> -Discharges specified character/prisoner - -<MASS CONTROL COMMANDS> -@night -All characters are in darkness - -@day -@option 00 00 00 are used on all characters - -@doom -Kills all NON GM chars on the server. - -@doommap -Kills all non GM characters on the map. - -@raise -Resurrects all characters on the server. - -@raisemap -Resurrects all characters on the map. - -@kick <charname> -Kicks specified character off the server - -@kickall -Kick all characters off the server - -<OTHER COMMANDS> - -@gat ---- デバッグ用(周辺gatを調べる) -@packet ---- デバッグ用(パケット色々) - -@mapexit -Kick all players and shut down map-server. - -@reloaditemdb -Reload item database (admin command) - -@reloadmobdb -Reload monster database (admin command) - -@reloadskilldb -Reload skills definition database (admin command) - -@reloadscript -Reload all scripts (admin command) - -@reloadgmdb -Reload GM levels (admin command) - -@enablenpc <NPC_name> -Enable a NPC (admin command) - -@disablenpc <NPC_name> -Disable a NPC (admin command) - -@email <actual@email> <new@email> -to change your e-mail (characters protection) diff --git a/doc/help1.txt b/doc/help1.txt deleted file mode 100644 index 865738d..0000000 --- a/doc/help1.txt +++ /dev/null @@ -1,398 +0,0 @@ - ______ __ __ - /\ _ \/\ \__/\ \ - __\ \ \L\ \ \ ,_\ \ \___ __ ___ __ - /'__`\ \ __ \ \ \/\ \ _ `\ /'__`\/' _ `\ /'__`\ -/\ __/\ \ \/\ \ \ \_\ \ \ \ \/\ __//\ \/\ \/\ \L\.\_ -\ \____\\ \_\ \_\ \__\\ \_\ \_\ \____\ \_\ \_\ \__/.\_\ - \/____/ \/_/\/_/\/__/ \/_/\/_/\/____/\/_/\/_/\/__/\/_/ - _ _ _ _ _ _ _ _ _ _ _ _ _ - / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ -( e | n | g | l | i | s | h ) ( A | t | h | e | n | a ) - \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ - --------------------------------------------------------------- -GM COMMANDS ---------------------------------------------------------------------------------- -Note: - To use these commands, type them inside the message window where you usually - type to chat. ---------------------------------------------------------------------------------- -<> = type of parameter that the command need to have -[] = optionnal parameter ---------------------------------------------------------------------------------- - -@h/@help = display commands help inside the game. - -================================================================================= -ANNOUNCEMENT COMMANDS -================================================================================= -/b/@broadcast <message> = Broadcasts a GM message with name of the GM - (in yellow) -/nb/@kami <message> = Broadcasts a GM message without name of the GM - (in yellow) -@kamib <message> = Broadcasts a GM message without name of the GM - (in blue) -/lb/@localbroadcast <message> = Broadcasts a GM message with name of the GM - (in yellow) ONLY on your map -/nlb <message> = Broadcasts a GM message without name of the GM - (in yellow) ONLY on your map - -================================================================================= -INFORMATION COMMANDS -================================================================================= -@who [match_text] = Lists which characters are currently online in your - server and their location. [match_text] is a parameter - to search only characters that have this text in their - name. -@who2 [match_text] = Lists which characters are currently online in your - server and their job. [match_text] is a parameter to - search only characters that have this text in their - name. -@who3 [match_text] = Lists which characters are currently online in your - server and their party/guild. [match_text] is a - parameter to search only characters that have this text - in their name. -@whomap [map] = Displays a listing of which characters are online and - where they are in a specifical map. If [map] isn't - specified, you display characters on your map. -@whomap2 [map] = Displays a listing of which characters are online and - their job in a specifical map. If [map] isn't specified, - you display characters on your map. -@whomap3 [map] = Displays a listing of which characters are online and - their party/guild in a specifical map. If [map] isn't - specified, you display characters on your actual map. -@whogm [match_text] = Like @who+@who2+who3, but only for GM. -@where [char name] = Tells you the location of a character. If [char name] - isn't specified, you display your own location. -@charstatsall = Displays stats of all characters. -@charitemlist <char name> = Displays all items of a player. -@charstoragelist <char name> = Displays all items of a player's storage. -@charcartlist <char name> = Displays all items of a player's cart. -@ignorelist = Displays your ignore list -@mapinfo [<0-3> [map]] = Give information about a map (general info +: - 0: no more, 1: players, 2: NPC, 3: shops/chat). - -@time/@date/@server_date/@serverdate/@server_time/@servertime = Display the date/ - time of the server - -@guildspy <guild_name/id> = You will receive all messages of the specified guild - channel -@partyspy <party_name/id> = You will receive all messages of the specified party - channel - -================================================================================= -(YOURSELF-)CONTROL COMMANDS -================================================================================= -MOVE COMMANDS -------------- -/hide/@hide = GM Hide. Perfect hide that's totally - invisible. Type @hide again become - visible. -@save = Sets save point as current location -@load/@return = Warps you to your save point (like - butterfly wing) -/mm <mapname> <xpos> <ypos> = Warps you to the selected position -/mapmove <map_name> <x> <y> = Warps you to the selected position -@warp/@rura/@mapmove <mapname> <x> <y> = Warps you to the selected position - Example: @warp morocc 150 160 -> Warps - you to Morroc (X:150, Y:160) -@jump [x [y]] = Teleports you randomly in the map (like - fly wing) -/shift/@jumpto/@warpto/@goto <charname> = Warps you to selected character - Example: @jumpto TestChar -> You are - warped to TestChar's current - location -@go <number/city_name> = Warps you to a set city: - -3=(Memo point 2) 4=Alberta 11=Gon Ryun - -2=(Memo point 1) 5=Izlude 12=Umbala - -1=(Memo point 0) 6=Al de Baran 13=Niflheim - 0=Prontera 7=Lutie 14=Lou Yang - 1=Morroc 8=Comodo 15=Start point - 2=Geffen 9=Yuno 16=Prison - 3=Payon 10=Amatsu - -HEALTH COMMANDS ---------------- -@die = Kill yourself :) (suicide) -@alive = Revives yourself from death -@heal [<HP> <SP>] = Heals the desired amount of HP and SP. No value specified - will do a full heal. - -OTHER COMMANDS ---------------- -/resetstatus = Resets all status points for you to reuse. -/resetskill = Resets all skill points for you to reuse. -@job/@jobchange <job> = Changes your job to the job assigned to the ID: - 0 Novice 7 Knight 14 Crusader 22 Formal - 1 Swordman 8 Priest 15 Monk 23 Super Novice - 2 Mage 9 Wizard 16 Sage - 3 Archer 10 Blacksmith 17 Rogue - 4 Acolyte 11 Hunter 18 Alchem - 5 Merchant 12 Assassin 19 Bard - 6 Thief 13 Knight2 20 Dancer - 21 Crusader2 - 24 Novice High 31 Lord Knight 38 Paladin - 25 Swordman High 32 High Priest 39 Monk - 26 Mage High 33 High Wizard 40 Professor - 27 Archer High 34 Whitesmith 41 Stalker - 28 Acolyte High 35 Sniper 42 Creator - 29 Merchant High 36 Assassin Cross 43 Clown - 30 Thief High 37 Peko Knight 44 Gypsy - 45 Paladin2 -@lvup/@blevel/@baselvlup <number of levels> = Raises your base level the - desired number of levels. The max - is 99/255 (User Defined). -@joblvup/@jlevel/@joblvlup <number of levels> = Raises your job level the desired - number of levels. The max is 50 - For Basic Classes. For Super - Novice and Advanced Classes it is - 70. -@allskill/@allskills/@skillall/@skillsall = Give you all skills. -@option <param1> <param2> <param3> = Changes options of your character - Example: @option 0 0 16 - would give falcon - <param1> <param2> <param3> <param3> - 01 Petrified 01 Poison 01 Sight 128 Level 2 Cart - 02 Frozen 02 Cursed 02 Hide 256 Level 3 Cart - 03 Stunned 04 Silenced 04 Cloak 512 Level 4 Cart - 04 Sleeping 08 ??? 08 Level 1 Cart 1024 Level 5 Cart - 06 darkness 16 darkness 16 Falcon 2048 Orc Head - 32 Peco Peco riding 4096 Wedding Sprites - 64 GM Perfect Hide 8192 Ruwach -@mountpeco = Give/remove you a peco. (Class is required, but not skill) -@disguise <monster_name/monster_ID/NPC_ID> = Change your appearence to a mob or npc. - If using NPC ID 104 Will become an effect. - Speed of player will determine effect, be very careful with this ID - it can create client crashes with improper ids and can easily lag players - off of the server. -@undisguise = Restore your normal appearance. -@model <hair ID: 0-17> <hair color: 0-8> <clothes color: 0-4> - = Changes your characters appearance - (Hair type/colour and/or Clothes colour) - Hair ID (0-17) Hair Colour (0-8) Clothes Colour (0-4) - 0 Default 0 Default - 1 Blonde 1 Red - 2 Purple 2 Green - 3 Brown 3 White - 4 Green 4 Brown - 5 Blue - 6 White - 7 Black - 8 Red -@dye/@ccolor <clothes color: 0-4> = Changes your characters appearence - (only clothes color). -@hairstyle/@hstyle <hair ID: 0-17> = Changes your characters appearence - (only hair style). -@haircolor/@hcolor <hair color: 0-8> = Changes your characters appearence - (only hair color). -@speed <1-1000> = Changes you walking speed (1 being the - fastest & 1000 the slowest. Default 150. -@effect <effect_id> [flag] = Give an efect to your character. -@stpoint <number of points> = Gives you the desired number of stat - points. -@skpoint <number of points> = Gives you the desired number of skill - points. -@zeny <amount> = Gives you desired amount of Zeny. -@str,@agi,@vit,@int,@dex,@luk <amount> = Adds desired amount to any stat. For - example "@str 10" raises your str by 10. -@statall/@statsall/@allstats/@allstat [value] = Adds value in all stats (maximum - if no value). -@memo [memo_position] = set/change a memo location. - (no position: display memo points). -@spiritball <number: 1-1000> = Gives you monk "spirit spheres" like - from the skill "Call Spirits" (If the - number you use is > 1000, your server - may become instable or crash) -@questskill <id> = Gives you the specified quest skill -@lostskill <id> = Takes away the specified quest skill - from you - Novice Archer Swordsman - 142 = Emergency Care 147 = Arrow Creation 144 = Moving HP Recovery - 143 = Act dead 148 = Charge Arrows 145 = Attack Weak Point - Thief 146 = Auto Berserk - 149 = Throw Sand Merchant - 150 = Back Sliding 153 = Cart Revolution - 151 = Take Stone 154 = Change Cart - 152 = Stone Throw 155 = Crazy Uproar/Loud Voice - Acolyte Magician - 156 = Holy Light 157 = Energy Coat - -================================================================================= -MONSTERS COMMANDS -================================================================================= -/monster <monster_name> = Spawns 1 of the desired monster. -@spawn/@monster/@summon <monster_name_or_monster_ID> [<number to spawn> [<desired_monster_name> [<x coord> [<y coord>]]]] - = Spawns the desired monster with any desired name, - quantity and x and y location (if specified). -@monster2 <desired_monster_name> <monster_name_or_monster_ID> [<number to spawn> [<x coord> [<y coord>]]] - = Spawns the desired monster with any desired name. -@spawn/@monster/@summon/@monster2 "desired monster name" <monster_name_or_monster_ID> [<number to spawn> [<x coord> [<y coord>]]] -@spawn/@monster/@summon/@monster2 <monster_name_or_monster_ID> "desired monster name" [<number to spawn> [<x coord> [<y coord>]]] - = There 2 last forms can use spaces for desired names. -@killmonster [map] = kill all monsters of the map (they drop items) -@killmonster2 = kill all monsters of your map (without drops) - -================================================================================= -ITEMS COMMANDS -================================================================================= -@storage = Opens storage -@gstorage = Opens guild storage -/item <item_name> = Gives you 1 of the desired item. -@item <item name or ID> [quantity] = Gives you the desired item. -@item2 <item name or ID> <quantity> <Identify_flag> <refine> <attribut> <Card1> <Card2> <Card3> <Card4> - = Gives you the desired item. -@itemreset = Remove all your items. -@itemcheck = Check your items with authorised items. -@idsearch <part_of_item_name> = search all items that name have - part_of_item_name -@refine <equip position> <+/- amount> = Upgrades equipment at the position - specified (Stackable) - 0 - All - 1 - Lower Head - 2 - Right Hand - 4 - Robe/Garment - 8 - Left Accessory - 16 - Body/Armor - 32 - Left Hand - 64 - Foot Gear - 128 - Right Accessory - 256 - Top Head - 512 - Mid Head - Example: @refine 34 10 - Refines a 2 handed weapon to +10 - @refine 16 4 - Refines the body/armor to +4 -@produce <equip name or equip ID> <element> <# of very's> - Element: 0=None 1=Ice 2=Earth 3=Fire 4=Wind - It has separately with fragment 3 of the attribute + stars, you can apply. - # of very's: 0=None 1=Very Strong 2=Very Very Strong 3=Very Very Very Strong - Example: @produce 1163 3 3 - Produces a Very Very Very Strong (Your Nick)'s - Fire Claymore -@repairall = Repair all items of your inventory - -================================================================================= -PVP COMMANDS -================================================================================= -@pvpon = Turns pvp on on the current map -@pvpoff = Turns pvp off on the current map -@gvgon/@gpvpon = Turns gvg on on the current map -@gvgoff/@gpvpoff = Turns gvg off on the current map -@agitstart = Starts Guild Wars (War of Emperium) -@agitend = End Guild Wars (War of Emperium) - -================================================================================= -GROUPS COMMANDS -================================================================================= -@party <party_name> = Create a party -@guild <guild_name> = Create a guild. -@guildlvup/@guildlvlup <# of levels> = Raise Guild by desired number of levels -@guildrecall <guild_name/id> = Warps all online character of a guild to you. -@partyrecall <party_name/id> = Warps all online character of a party to you. - -================================================================================= -PETS COMMANDS -================================================================================= -@hatch = Create a pet from your inventory eggs list. -@makeegg <ID> = Gives pet egg for monster ID in pet DB -@petfriendly <#> = Set pet friendly amount (0-1000) 0 = Min, 1000 = Max -@pethungry <#> = Set pet hungry amount (0-100) 0 = Min, 100 = Max -@petrename = Re-enable pet rename - -================================================================================= -REMOTE CHARACTERS COMMANDS -================================================================================= -@kill <char name> = Kills specified character name - Example: @kill TestChar -> The character named - TestChar is dead -@jail <char_name> = Sends specified character in jails -/recall/@recall <char name> = Warps target character to you. -@recallall = Warps every character online to you. -@unjail/@discharge <char_name> = Discharges specified character - or prisoner -@charwarp/@rura+ <mapname> <x> <y> <char name> = Warps character to location of - choice: Example: - @charwarp morocc 150 160 testet -@revive <char name> = Revives target character. -@charstats <char name> = Displays the character's stats. -@charignorelist <char name> = Displays ignore list of the player -@inall <char name> = Allows all wispers for the player -@exall <char name> = Blocks all wispers for the player -@charoption <param1> <param2> <param3> <char name> = Does the same as the @option - command only to target - character. -@charmountpeco <charname> = Give/remove to a player a peco (Class is - required, but not skill). -@charpetrename <charname> = Re-enable pet rename to a player. -@charsave <map> <x> <y> <char name> = Changes the target player's respawn point. -@charbaselvl <#> <char name> = Change a character's base level. -@charjlvl <#> <char name> = Change a character's job level. -@charjob/@charjobchange <job ID> <char name> = Changes target character's job. -@charzeny <amount> <char name> = Give/take a player's Zeny -@charstpoint <amount> <char name> = Give/take a player's stat points -@charskpoint <amount> <char name> = Give/take a player's skill points -@charskreset <charname> = Reset skills of a character. -@charstreset <charname> = Reset stats of a character. -@charreset <charname> = Reset stats AND skills of a character. -@charquestskill <#> <charname> = Gives to a player the specified quest skill. -@charlostskill <#> <charname> = Takes away the specified quest skill from - the player. -@chardelitem <item_name_or_ID> <quantity> <player> = Remove items from a character -@charmodel <hair type> <hair color> <clothes color> <char name> = Changes a - player's model -@chardisguise <monster_name/ID> <char name> = Changes disguise of a player -@charundisguise <char name> = Cancels disguise of a player -@charchangesex <name> = Changes sex of a player (all characters of - the account) -@charblock/@block <name> = Blocks definitively a account -@charunblock/@unblock <name> = Unblocks a account -@charban/@ban/@banish/@charbanish <time> <name> = Ban temporarily a account - Time usage: adjustement - (+/- value) and element - (y/a, m, d/j, h, mn, s) - Example: - @ban +1m-2mn1s-6y testplayer -@charunban/@unban/@unbanish/@uncharbanish <name> = Unban a account -@kick <charname> = Kicks specified character off the server -@kickall = Kick all characters off the server -@mapexit = Kick all players and shut down map-server. -@doom = Kills all NON GM chars on the server. -@doommap = Kills all non GM characters on the map. -@raise = Resurrects all characters on the server. -@raisemap = Resurrects all characters on the map. - -================================================================================= -ENVIRONMENT COMMANDS -================================================================================= -@night = Uses @option 00 16 00 on all characters. All characters are in darkness -@day = Uses @option 00 00 00 on all characters. - -================================================================================= -MAIL SYSTEM (SQL Only) -================================================================================= -@checkmail = Checks # of messages in your mailbox. -@listmail = Lists all the messages in your mailbox. -@listnewmail = Lists all new messages in your mailbox. -@readmail <#> = Reads a message in your mailbox. -@deletemail <#> = Deletes a message in your mailbox. - -@sendmail <name> <message> = Sends a message to another player. Use quotes if - the player has spaces in their name. - -@sendprioritymail <name> <message> = Send priority mail to a player. - -Use * for name to send to all players. -================================================================================= -ADMINISTRATION COMMANDS -================================================================================= -@reloaditemdb = Reload item database (admin command) -@reloadmobdb = Reload monster database (admin command) -@reloadskilldb = Reload skills definition database (admin command) -@reloadscript = Reload all scripts (admin command) -@reloadgmdb = Reload GM levels (admin command) -@enablenpc <NPC_name> - Enable a NPC (admin command) -@disablenpc <NPC_name> - Disable a NPC (admin command) - -@gat = For debugging (you inspect around gat) -@packet = For debugging (packet variety) - -@GM <password> = it becomes GM! -@email <actual@email> <new@email> = to change your e-mail (characters protection) - -@refreshonline = Rechecks to make sure online column is correct (SQL Only)
\ No newline at end of file diff --git a/doc/history.txt b/doc/history.txt deleted file mode 100644 index a6653d9..0000000 --- a/doc/history.txt +++ /dev/null @@ -1,173 +0,0 @@ -Version 1.4.4 -=========================================================== -- Fixed a bug that caused the drop chance for all MVP drops - to become 0 when the "View Mob" option was used in the - Mob Drop List. (This was forgotten in the previous - update.) -- Finally updated the "item_descriptions.txt" file. - -Version 1.4.3 -=========================================================== -- Fixed a bug that caused the drop chance for all drops to - become 0 when the "View Mob" option was used in the Mob - Drop List. -- Fixed a bug that caused other mob entries to show up when - searching for a specific mob with an ID that can be found - as a string subset within the other mob's entry. -- Fixed a bug that caused all new entries to go into the - "item_db2.txt" or "mob_db2.txt" files. -- Tweaked some of the code for the Mob Skill Editor's - interface to better help with editing/creating skill - entries. - -Version 1.4.2 -=========================================================== -- Corrected the labels on the Mob Location Editor window. - Thanks to ShadowLady for pointing this out. - -Version 1.4.1 -=========================================================== -- Added functionality to the "Locations" button in the Mob - View. It will now open up the Mob Location Editor window. -- Added a list of map names with a brief description to the - "ID Helper.txt" file to be used with the Map Helper. -- Added a new option in the "ADE.ini" file that points to - the location of the files with the mobs' spawn points. -- Fixed a bug with the Drop List feature that would keep - the window open till it was closed by the cancel button - or the window's close button. -- Fixed a bug that caused the selected entry to not - properly update when saved. Thanks to Taike for reporting - this bug. -- Redid the code for handling backups. So now when you - restore the backup files, it won't reload both the item - and mob related files, it only restores the backups for - item related files while using the Item View and mob - related files for the Mob View, and it will no longer - rename files as a backup file if they have no backup to - replace them with. - -Version 1.4.0 -=========================================================== -- Added the Mob Skill Editor feature to ADE. It is - available through the Skills button in the Mob View. - This adds handling of the "mob_skill_db.txt" file. -- Fixed a bug with the Mob's Mode ID Helper that caused - the value to keep increasing everytime it was opened - beyond the first time. Thanks to Lupus for pointing this - out. -- Changed the font to Microsoft Sans Serif from MS Sans - Serif to better support the garbled text some items, - mobs, or other things may have. - -Version 1.3.2 -=========================================================== -- Edited the print functions related to the the following - DB files: "item_bluebox.txt", "item_cardalbum.txt", - "item_giftbox.txt", "item_violetbox.txt", and - "mob_branch.txt". Thanks to ShadowLady for pointing out - this problem, as well as mentioning the label change - mentioned below. -- Edited a label for Mob Modes in ID Helper from - "Detects Hidden (Sensor)" to "Detects Hidden". -- Redid some of the code in the data processing subroutine - for the Item and Mob DB files. This should prevent any - overflow/invalid index errors. Thanks to Cheex for - pointing this out. -- Fixed a bug that caused ADE to crash if any of the files - it would normally create backups of weren't there. This - is more common among eAthena 1.0 RCx Text installs, due - to their lack of an "item_db2.txt" file. (This occured - while trying to save changes.) - -Version 1.3.1 -=========================================================== -- Added an ID Helper for the Mob Mode ID section. -- You can now see a list of all mobs that drop the selected - item in ADE's Item View by clicking on the button in the - upper right corner that's labeled "Mob Drop List". - -Version 1.3.0 -=========================================================== -- Added support for handling five more of the server's DB - files. ADE now handles: "item_bluebox.txt", - "item_cardalbum.txt", "item_giftbox.txt", - "item_violetbox.txt", and "mob_branch.txt". -- Added a "Restore Backup Files" option in the File menu. -- Changed "Revert" to "Revert to Last Save". -- ADE now inserts a blank comment line after the initial - header line and the last line for most of the server - files. -- ADE will automatically set the compatability mode to - support higher jobs, if it reads in a job ID for any such - jobs while set for low jobs only. -- Fixed a couple of minor bugs and tweaked some of the code. - -Version 1.2.0 -=========================================================== -- Added support for generating the item files related to - card labels. The files are "cardpostfixnametable.txt" and - "cardprefixnametable.txt". The file "card_labels.txt" is - used to hold the card labels. (To create it, just copy - any "cardprefixnametable.txt" file to the DB folder being - used and rename it to "card_labels.txt".) -- Fixed a bug found by Solid that caused the program to end - when a Mob's entry had an invalid Race ID or Element ID. - Also applied this same fix to some of the other IDs that - were vunerable. -- Resized the maximum entries allowed for both Items and - Mobs. Items now have a current max of 15,000 entries and - Mobs have a max of 1,000. Both used to have 10,000. -- Included a minimum ID and max ID allowed when dealing - with either Items or Mobs. The new Item ID range is 501 - to 15000, and the new Mob ID range is 1001 to 2000. Any - entries with IDs out of the range won't be kept. -- Slightly redid some of the code with printing the headers - of all files made with the program. - -Version 1.1.1 -=========================================================== -- Fixed a bug that caused the duplicate scan process to be - used again during adding and removing entries. -- Replaced the text box for the Item's Sex ID with a combo - box. (The Item's Sex ID is used to determine if the item - is limited to a character's sex or can be used by all.) -- Added the ID Helper for the Item View ID text box, and - included a file called "Item Helper.txt" that contains - the data for it. -- Fixed a bug that caused the "Allow High Jobs" option for - compatibility to be turned on when even with it set to - being off by default. -- Added a small bit of code to print "All Low Jobs" for - the description files for any items that only allow - characters with low jobs only to use the item. -- Added a temp fix for any forms that can get stuck behind - the main window by allowing them to show up in the - taskbar. - -Version 1.1.0 -=========================================================== -- Added support for higher jobs like Knight Lord, Assassin - Cross, High Priest, etc. -- Added duplication scanning for the DB entries. This will - remove duplicates found. (An entry is considered a - duplicate if the ID or DBName is the same.) -- Fixed a bug that would cause the program to keep loading - if you closed the progress bar during startup. - -Version 1.0.1 -=========================================================== -- Fixed a bug that caused a null mob DB entry. -- Added some code to let the program load even if it didn't - find the files used for loading. -- Redid small portions of the code to increase performance. - -Version 1.0.0 -=========================================================== -- Merged the previous programs. -- Added a mob DB file editor. - -Version 0.X -=========================================================== -- Created Stand-alone Item Database Editor. -- Created Stand-alone Item File Generator. diff --git a/doc/inter_server_packet.txt b/doc/inter_server_packet.txt deleted file mode 100644 index 4e6dabf..0000000 --- a/doc/inter_server_packet.txt +++ /dev/null @@ -1,204 +0,0 @@ -S map鯖=>inter鯖 -R inter鯖=>map鯖 - -パケット長リスト -R 3800-388f - -1,-1,27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 35,-1,11,15, 34,29, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, - 10,-1,15, 0, 79,17, 7,-1, 0,-1,-1,-1, 14,67,186,-1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -S 3000-308f - -1,-1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 72, 6,52,14, 10,29, 6,-1, 34, 0, 0, 0, 0, 0, 0, 0, - -1, 6,-1, 0, 55,17, 6,-1, 14,-1,-1,-1, 14,19,186,-1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48,14,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - - -S 3000 <len>.w <message>.?B - GMメッセージ送信要求 -R 3800 <len>.w <message>.?B - GMメッセージ -S 3001 <len>.w <src-nick>.24B <dst-nick>.24B <message>.?B - Wis送信要求 -R 3801 <len>.w <wis-id>.l <src-nick>.24B <dst-nick>.24B <message>.?B - Wisデータ受信 - wis-id=inter鯖内部のWis-id:map鯖では3002で送信するためだけに使う -S 3002 <wis-id>.l <flag>.B - このmap鯖でのWisの送信結果 - flag=0 送信完了(このmap鯖にいたので、送信した) - flag=1 送信失敗(このmap鯖にはそんな人いません) - flag=2 送信終了(このmap鯖にいるが、ignoreされている) -R 3802 <src-nick>.24B <flag>.B - 全map鯖でのWis送信結果 - flag=0 送信完了 - flag=1 送信失敗(どのmap鯖にもそんな人いません) - flag=2 送信失敗(ignoreされた) -S 3010 <account_id>.l - 倉庫データ要求 -R 3810 <len>.w <account_id>.l <storage>.?B - 倉庫データ受信 -S 3011 <len>.w <account_id>.l <storage>.?B - 倉庫データ送信&保存要求 -R 3811 <account_id>.l <flag>.b - 倉庫データ保存終了 - flag=0 成功(現在の仕様では必ず0なので、返信を待たなくてもいい) - -S 3020 <account_id>.l <party_name>.24B <nick_name>.24B <map_name>.16B <level>.w - パーティ作成要求 -R 3820 <account_id>.l <fail>.B <party_id>.l <party_name>.24B - パーティ成功可否(自分のマップ鯖のみ) - fail=00 パーティ作成成功 - fail=01 失敗(party_id,pary_nameはゴミ) -S 3021 <party_id>.l - パーティ情報要求 -R 3821 <len>.w <struct party>.?B - (struct partyの最初4バイトはparty_id) - len=8 パーティは存在しない(受信したら該当キャラを未所属に変更する) - len>8 パーティ情報(受信したらクライアントに送ること) - (要求してきたマップ鯖へ) -S 3022 <party_id>.l <account_id>.l <nick>.24B <map_name>.16B <level>.w - パーティ追加要求 -R 3822 <party_id>.l <account_id>.l <fail>.B - パーティ追加通知(要求してきたマップ鯖へ) - fail=00で成功、fail=01で失敗 - (成功時はこの直後に全鯖にパーティ情報が送られる) -S 3023 <party_id>.l <account_id>.l <exp>.w <item>.w - パーティ設定変更要求 -R 3823 <party_id>.l <account_id>.l <exp>.w <item>.w <fail>.B - パーティ設定変更通知(成功の場合全マップ鯖へ通知) - fail=0x00 パーティ設定変更完了 - fail=0x01 expの変更失敗 - fail=0x10 itemの変更失敗 -S 3024 <party_id>.l <account_id>.l - パーティ脱退要求 -R 3824 <party_id>.l <account_id>.l <nick>.24B - パーティ脱退通知(全マップ鯖へ) -S 3025 <party_id>.l <account_id>.l <map_name>.16B <online>.B <level>.w - パーティマップ更新/オンライン要求 -R 3825 <party_id>.l <account_id>.l <map_name>.16B <online>.B <level>.w - パーティマップ更新通知(全マップ鯖へ) -S 3026 <party_id>.l - パーティ解散要求(送られることはないと思われる) -R 3026 <party_id>.l <fail>.B - パーティ解散 - fail=00 パーティは解散された(今のところ必ず00) - (map鯖内の不要データ削除のためだけに使われる) -S 3027 <len>.w <party_id>.l <account_id>.l <message>.?B - パーティ内発言要求 -R 3827 <len>.w <party_id>.l <account_id>.l <message>.?B - パーティ内発言通知(全マップ鯖へ) -S 3028 <party_id>.l <account_id>.l <nick>.24B - 別パーティに所属していないかチェック<party_id>は本来の所属 - - -S 3030 <len>.w <account_id>.l <guild_name>.24B <struct guild_member>.?B - ギルド作成要求 -R 3830 <account_id>.l <guild_id>.l - ギルド作成可否(guild_id=0で失敗) -S 3031 <guild_id>.l - ギルド情報要求 -R 3831 <len>.w <struct guild>.?B - ギルド情報 - len=8 ギルドは存在しない - len>8 ギルド情報 -S 3032 <len>.w <guild_id>.l <struct guild_member>.?B - ギルドメンバ追加要求 -R 3832 <guild_id>.l <account_id>.l <charactor_id>.l <fail>.B - ギルド追加メンバ通知 - fail=0で成功,1で失敗 -S 3034 <guild_id>.l <account_id>.l <charactor_id>.l <flag>.B <mes>.40B - ギルド脱退/追放要求 - flag=0 脱退 / 1 追放 -R 3834 <guild_id>.l <account_id>.l <charactor_id>.l <flag>.B <mes>.40B <nick>.24B - ギルド脱退/追放通知 -S 3035 <guild_id>.l <account_id>.l <charactor_id>.l <online>.B <lv>.w <class>.w - ギルドメンバ情報更新要求 -R 3835 <guild_id>.l <account_id>.l <charactor_id>.l <online>.B <lv>.w <class>.w - ギルドメンバ情報更新通知 -S 3036 <guild_id>.l - ギルド解散要求 -R 3836 <guild_id>.l <fail>.B - ギルド解散通知 - flag=00 解散成功 / 01 失敗 -S 3037 <len>.w <guild_id>.l <account_id>.l <message>.?B - ギルド発言要求 -R 3837 <len>.w <guild_id>.l <account_id>.l <message>.?B - ギルド発言通知 -S 3038 <guild_id>.l <account_id>.l <charactor_id>.l - 別ギルドに所属していないかチェック -S 3039 <len>.w <guild_id>.l <type>.w <data>.?B - 各種基本情報更新要求 -R 3839 <len>.w <guild_id>.l <type>.w <data>.?B - 各種基本情報更新通知 -S 303A <len>.w <guild_id>.l <account_id>.l <char_id>.l <type>.w <data>.?B - 各種ギルドメンバ情報更新要求 -R 383A <len>.w <guild_id>.l <account_id>.l <char_id>.l <type>.w <data>.?B - 各種ギルドメンバ情報更新通知 -S 303B <len>.w <guild_id>.l <position>.l <struct guild_position>.?B - ギルド役職変更要求 -R 383B <len>.w <guild_id>.l <position>.l <struct guild_position>.?B - ギルド役職変更通知 -S 303C <guild_id>.l <skill_num>.l <account_id>.l - ギルドスキル割り振り -R 383C <guild_id>.l <skill_num>.l <account_id>.l - ギルドスキル割り振り(skill_num==0で失敗) -S 303D <guild_id1>.l <guild_id2>.l <account_id1>.l <account_id2>.l <flag>.B - ギルド同盟/敵対要求 - flag=0 同盟 / 1 敵対 / 8 同盟解除 / 9 敵対解除 -R 383D <guild_id1>.l <guild_id2>.l <account_id1>.l <account_id2>.l <flag>.B <name1>.24B <name2>.24B - ギルド同盟/敵対通知 - flag=0 同盟 / 1 敵対 - flag=0x10 同盟失敗 / 0x11 敵対失敗 -S 303E <guild_id>.l <message1>.60B <message2>.120B - ギルド告知設定要求 -R 383E <guild_id>.l <message1>.60B <message2>.120B - ギルド告知設定通知 -S 303F <len>.w <guild_id>.l <dummy>.l <emblem_data>.?B - ギルドエンブレム変更要求 dummyは0固定 -R 383F <len>.w <guild_id>.l <dummy>.l <emblem_data>.?B - ギルドエンブレム変更通知 -(以下、ギルド系追加予定) - -S 3080 <account_id>.l <char_id>.I <pet_type>.w <pet_lv>.w <pet_egg_id>.w - <pet_equip>.w <pet_intimate>.w <pet_hungry>.w <rename_flag>.B <incuvate>.B - <pet_name>.24B - ペット生成要求 -R 3880 <account_id>.l <fail>.B <pet_id>.l - ペット生成成功可否 - fail=00 ペット生成成功 - fail=01 失敗(pet_idはゴミ) -S 3081 <account_id>.l <char_id>.I <pet_id>.l - ペットデータ要求 -R 3881 <len>.w <account_id>.l <fail>.B <struct s_pet>.?B - ペットデータ受信 - fail=00 ペットデータ転送 - fail=01 ペットのデータがないかもしくはaccount_idかchar_idが合わないので - 失敗(s_petはゴミ) -S 3082 <len>.w <account_id>.l <struct s_pet>.?B - ペットデータ送信&保存要求 -R 3882 <account_id>.l <flag>.b - ペットデータ保存終了 - flag=0 成功(現在の仕様ではメモリ不足以外には必ず0なので、返信を - 待たなくてもいい) - flag=1 失敗 -S 3083 <pet_id>.l - ペットデータ削除要求 -R 3883 <flag>.b - ペットデータ削除終了 - flag=0 成功(現在の仕様では既にデータがいない場合以外は必ず0なので、 - 返信を待たなくてもいい) - flag=1 失敗(pet_idに当たるデータがない場合の物ですが既にデータが - いないと言うことは削除する必要がないことにもなりますので - 意味はありません) - diff --git a/doc/item.txt b/doc/item.txt deleted file mode 100644 index 0629364..0000000 --- a/doc/item.txt +++ /dev/null @@ -1,1451 +0,0 @@ -ID Ename - -0 Default -501 Red Potion -502 Orange Potion -503 Yellow Potion -504 White Potion -505 Blue Potion -506 Green Potion -507 Red Herb -508 Yellow Herb -509 White Herb -510 Blue Herb -511 Green Herb -512 Apple -513 Banana -514 Grape -515 Carrot -516 Sweet Potato -517 Meat -518 Honey -519 Milk -520 Hinalle Leaflet -521 Aloe Leaflet -522 Mastela Fruit -523 Holy Water -525 Panacea -526 Royal Jelly -528 Monster's Feed -529 Candy -530 Candy Cane -531 Apple Juice -532 Banana Juice -533 Grape Juice -534 Carrot Juice -535 Pumpkin -536 Ice Cream -537 Pet Food -538 Well-baked Cookie -539 Piece of Cake -540 Falcon food -541 Pecopeco food -542 Festive Cookie -543 Festive Rainbow Cake -544 Raw Fish -545 Red Potion Bottle -546 Yellow Potion Bottle -547 White Potion Bottle -548 Cheese -549 Hot Potato -550 Rice Popper -551 Sushi -552 Ketupat -553 Dumpling -554 Mochi -555 ?? -556 ?????? -557 ??????_???_?????? -558 Chocolate -559 Hand-made Chocolate -601 Fly Wing -602 Butterfly Wing -603 Old Blue Box -604 Branch of Dead tree -605 Anodyne -606 Aloevera -607 Yggdrasilberry -608 Yggdrasil Seed -609 Amulet -610 Yggdrasil Leaf -611 Magnifier -612 Mini Furnace -613 Iron Hammer -614 Golden Hammer -615 Oridecon Hammer -616 Old Card Album -617 Old Violet Box -618 Worn Out Scroll -619 Unripe Apple -620 Orange Juice -621 Bitter Herb -622 Rainbow Carrot -623 Earthworm the Dude -624 Rotten Fish -625 Rusty Iron -626 Monster Juice -627 Sweet Milk -628 Well Dried Bone -629 Singing Flower -630 Dew Laden Moss -631 Deadly Noxious Herb -632 Fatty Chubby Earthworm -633 Baked Yam -634 Tropical Banana -635 Horror of Tribe -636 No Recipient -637 Old Broom -638 Silver Knife of Chastity -639 Armlet of Obedience -640 Shining Stone -641 Contracts in Shadow -642 Book of Devil -643 Pet Incubator -644 Gift Box -645 Concentration Potion -656 Awakening Potion -657 Berserk Potion -658 Tribal Solidarity -659 Her Heart -660 Red Candle -661 Sky Apron -663 Rice Cake -664 Gift Box -665 Gift Box -666 Gift Box -667 Gift Box -668 Angpow -669 ??????_??????_???? -670 ???? -671 ?? -672 ???? -673 ?? -674 ????? -675 ?? -676 ???? -677 ??? -678 ?? -679 ??? -701 Ora Ora -702 Animal Gore -703 Hinalle -704 Aloe -705 Clover -706 Four-Leaf Clover -707 Singing Plant -708 Ment -709 Izidor -710 Illusion Flower -711 Shoot -712 Flower -713 Empty Bottle -714 Emperium -715 Yellow Gemstone -716 Red Gemstone -717 Blue Gemstone -718 Garnet -719 Amethyst -720 Aquamarine -721 Emerald -722 Pearl -723 Ruby -724 Cursed Ruby -725 Sardonyx -726 Sapphire -727 Opal -728 Topaz -729 Zircon -730 1 Carat Diamond -731 2 Carat Diamond -732 3 Carat Diamond -733 Cracked Diamond -734 Red Frame -735 Chung Jah -736 China -737 Black Ladle -738 Pencil Case -739 Rouge -740 Puppet -741 Poring Doll -742 Chonchon Doll -743 Spore Doll -744 Bouquet -745 Wedding Bouquet -746 Glass Bead -747 Crystal Mirror -748 Witherless Rose -749 Frozen Rose -750 Baphomet Doll -751 Osiris Doll -752 Grasshopper Doll -753 Yoyo Doll -754 Raccoon Doll -756 Rough Oridecon -757 Rough Elunium -901 Danggie -902 Tree Root -903 Reptile Tongue -904 Scorpion Tail -905 Stem -906 Pointed Scale -907 Resin -908 Spawn -909 Jellopy -910 Garlet -911 Scell -912 Zargon -913 Tooth of Bat -914 Fluff -915 Chrysalis -916 Feather of Birds -917 Talon -918 Sticky Webfoot -919 Animal Skin -920 Wolf Claw -921 Mushroom Spore -922 Orc's Fang -923 Evil Horn -924 Powder of Butterfly -925 Bill of Birds -926 Snake Scale -928 Insect Feeler -929 Immortal Heart -930 Rotten Bandage -931 Orcish Voucher -932 Skel-Bone -934 Memento -935 Shell -936 Scale Shell -937 Venom Canine -938 Sticky Mucus -939 Bee Sting -940 Grasshopper's Leg -941 Nose Ring -942 Yoyo Tail -943 Solid Shell -944 Horseshoe -945 Raccoon Leaf -946 Snail's Shell -947 Horn -948 Bear's Footskin -949 Feather -950 Heart of Mermaid -951 Fin -952 Cactus Needle -953 Stone Heart -954 Shining Scale -955 Worm Peeling -956 Gill -957 Decayed Nail -958 Horrendous Mouth -959 Stinky Scale -960 Nipper -961 Conch -962 Tentacle -963 Sharp scale -964 Crap Shell -965 Clam Shell -966 Clam Flesh -967 Turtle Shell -968 Heroic Emblem -969 Gold -970 Alchol -971 Detrimindexta -972 Karvodailnirol -973 Counteragent -974 Mixture -975 Scarlet Dyestuffs -976 Lemon Dyestuffs -978 Cobaltblue Dyestuffs -979 Darkgreen Dyestuffs -980 Orange Dyestuffs -981 Violet Dyestuffs -982 White Dyestuffs -983 Black Dyestuffs -984 Oridecon -985 Elunium -986 Anvil -987 Oridecon Anvil -988 Golden Anvil -989 Emperium Anvil -990 Red Blood -991 Crystal Blue -992 Wind of Verdure -993 Green Live -994 Flame Heart -995 Mystic Frozen -996 Rough Wind -997 Great Nature -998 Iron -999 Steel -1000 Star Crumb -1001 Star Dust -1002 Iron Ore -1003 Coal -1004 Chivalry Emblem -1005 Hammer of Blacksmith -1006 Old Magic Book -1007 Necklace of Wisdom -1008 Necklace of Oblivion -1009 Hand of God -1010 Phracon -1011 Emveretarcon -1012 Frill -1013 Rainbow Shell -1014 Ant Jaw -1015 Tongue -1016 Rat Tail -1017 Mole Whiskers -1018 Mole Claw -1019 Trunk -1020 Black Hair -1021 Dokkaebi Horn -1022 Nine Tails -1023 Fish Tail -1024 Squid ink -1025 Cobweb -1026 Acorn -1027 Porcupine Quill -1028 Mane -1029 Tiger Skin -1030 Tiger's Footskin -1031 Mantis Scythe -1032 Maneater Blossom -1033 Maneater Root -1034 Blue Hair -1035 Dragon Canine -1036 Dragon Scale -1037 Dragon Tail -1038 Little Evil Horn -1039 Little Evil Wing -1040 Elder Pixie's Moustache -1041 Lantern -1042 Bug Leg -1043 Orc Claw -1044 Zenorc's Fang -1045 Cultish Masque -1046 Scorpion Nipper -1047 Dead Medusa -1048 Horrendous Hair -1049 Skirt of Virgin -1050 Tendon -1051 Detonator -1052 Single Cell -1053 Ancient Tooth -1054 Ancient Lips -1055 Earthworm Peeling -1056 Grit -1057 Moth Dust -1058 Moth Wings -1059 Fabric -1060 Golden Hair -1061 Witched Starsand -1062 Jack o' Pumpkin -1063 Fang -1064 Reins -1065 Trap -1066 Fine-grained Trunk -1067 Solid Trunk -1068 Barren Trunk -1069 Orange Net Mushroom -1070 Orange Gooey Mushroom -1071 Unknown Testtube -1072 DEL Message -1073 Voucher -1074 Voucher -1075 Voucher -1076 Voucher -1077 Voucher -1078 Voucher -1079 Voucher -1080 Voucher -1081 DEL Box -1082 DEL Box -1083 DEL Box -1084 Kapra Pass -1085 Unknown Testtube -1086 Unknown Testtube -1087 Unknown Testtube -1088 Morocc Solution -1089 Payon Solution -1090 Unknown Testtube -1091 DEL Box -1092 Empty Testtube -1093 Empty Potion Bottle -1094 Short Daenggie -1095 Needle of Alarm -1096 Round Shell -1097 Worn Out Page -1098 Manacles -1099 Worn-out Prison Uniform -1101 Sword -1102 Sword -1103 Sword -1104 Falchion -1105 Falchion -1106 Falchion -1107 Blade -1108 Blade -1109 Blade -1110 Rapier -1111 Rapier -1112 Rapier -1113 Scimiter -1114 Scimiter -1115 Scimiter -1116 Katana -1117 Katana -1118 Katana -1119 Tsurugi -1120 Tsurugi -1121 Tsurugi -1122 Ring Pommel Saber -1123 Haedonggum -1124 Orcish sword -1125 Ring Pommel Saber -1126 Saber -1127 Saber -1128 Haedonggum -1129 Flamberge -1130 Nagan -1131 Ice Falchon -1132 Edge -1133 Fire Brand -1134 Caesar's Sword -1135 Cutlas -1136 Solar Sword -1137 Excalibur -1138 Mysteltainn -1139 Talefing -1140 Byeollungum -1141 Immaterial Sword -1142 Crystal Sword -1143 Gaia Sword -1144 Sashimi -1145 Holy Avenger -1151 Slayer -1152 Slayer -1153 Slayer -1154 Bastard Sword -1155 Bastard Sword -1156 Bastard Sword -1157 Two-handed Sword -1158 Two-handed Sword -1159 Two-handed Sword -1160 Broad Sword -1161 Balmung -1162 Broad Sword -1163 Claymore -1164 Muramasa -1165 Masamune -bonus bStr -bonus bAspd -bonus bDefRate -bonus bDef2Rate - } -1166 Dragon Slayer -1167 Schweizersabel -1168 Zweihander -1169 Executioner -1170 Katzbalger -1201 Knife -1202 Knife -1203 Knife -1204 Cutter -1205 Cutter -1206 Cutter -1207 Main Gauche -1208 Main Gauche -1209 Main Gauche -1210 Dirk -1211 Dirk -1212 Dirk -1213 Dagger -1214 Dagger -1215 Dagger -1216 Stiletto -1217 Stiletto -1218 Stiletto -1219 Gladius -1220 Gladius -1221 Gladius -1222 Damascus -1223 Fortune Sword -1224 Swordbreaker -1225 Mailbreaker -1226 Damascus -1227 Weeder Knife -1228 Combat Knife -1229 Mama's Knife -1230 House Auger -1231 Bazerald -1232 Assasin Dagger -1233 Excorcise -1234 Walgwanggum -1235 Azoth -1236 Sucsamad -1237 Grimtooth -1238 Zeny Knife -1239 Poison Knife -1240 Princess Knife -1241 Cursed Knife -1242 Counter Knife -1243 Novice's Main Gauche -1250 Jur -1251 Jur -1252 Katar -1253 Katar -1254 Jamadhar -1255 Jamadhar -1256 Katar of Cold Icicle -1257 Katar of Dusty Thornbush -1258 Katar of Raging Blaze -1259 Katar of Piercing Wind -1260 Sharppened Legbone of Gh -1261 Infiltrator -1301 Axe -1302 Axe -1303 Axe -1304 Orcish Axe -1305 Cleaver -1306 War Axe -1351 Battle Axe -1352 Battle Axe -1353 Battle Axe -1354 Hammer -1355 Hammer -1356 Hammer -1357 Buster -1358 Buster -1359 Buster -1360 Two-handed Axe -1361 Two-handed Axe -1362 Two-handed Axe -1363 Bloody Axe -1364 Great Axe -1365 Sabbath -1366 Light Epsilon -1367 Slaughter -1368 Tomahawk -1369 Guillotine -1401 Javelin -1402 Javelin -1403 Javelin -1404 Spear -1405 Spear -1406 Spear -1407 Pike -1408 Pike -1409 Pike -1410 Lance -1411 Lance -1412 Lance -1413 Gungnir -1414 Gelerdria -1415 Brocca -1416 Tjungkuletti -1417 Pole Axe -1451 Guisarme -1452 Guisarme -1453 Guisarme -1454 Glaive -1455 Glaive -1456 Glaive -1457 Partizan -1458 Partizan -1459 Partizan -1460 Trident -1461 Trident -1462 Trident -1463 Halberd -1464 Halberd -1465 Halberd -1466 Crescent Scythe -1467 Bill Guisarme -1468 Zephyrus -1469 Longinus's Spear -1470 Brionac -1471 Hellfire -1472 Soul Staff -1473 Wizardy staff -1501 Club -1502 Club -1503 Club -1504 Mace -1505 Mace -1506 Mace -1507 Smasher -1508 Smasher -1509 Smasher -1510 Flail -1511 Flail -1512 Flail -1513 Morning Star -1514 Morning Star -1515 Morning Star -1516 Sword Mace -1517 Sword Mace -1518 Sword Mace -1519 Chain -1520 Chain -1521 Chain -1522 Stunner -1523 Spike -1524 Golden Mace -1525 Long Mace -1526 Slash -1527 Quadrille -1528 Grand Cross -1529 Iron Driver -1530 Mjollnir -1531 Spanner -1550 Book -1551 Bible -1552 Tablet -1553 Book of Billows -1554 Book of Mother Earth -1555 Book of Blazing Sun -1556 Book of Gust of Wind -1557 Book of the Apocalypse -1558 Girl's Diary -1599 Angra Manyu -1601 Rod -1602 Rod -1603 Rod -1604 Wand -1605 Wand -1606 Wand -1607 Staff -1608 Staff -1609 Staff -1610 Arc Wand -1611 Arc Wand -1612 Arc Wand -1613 Mighty Staff -1614 Wand of Occult -1615 Bone Wand -1701 Bow -1702 Bow -1703 Bow -1704 Composite Bow -1705 Composite Bow -1706 Composite Bow -1707 Great Bow -1708 Great Bow -1709 Great Bow -1710 Cross Bow -1711 Cross Bow -1712 Cross Bow -1713 Arbalest -1714 Gakkung -1715 Arbalest -1716 Gakkung -1718 Hunter Bow -1719 Roguemaster's Bow -1720 Rudra's Bow -1721 Repeating Crossbow -1722 Ballista -1750 Arrow -1751 Silver Arrow -1752 Fire Arrow -1753 Steel Arrow -1754 Crystal Arrow -1755 Arrow of Wind -1756 Stone Arrow -1757 Immaterial Arrow -1758 Stun Arrow -1759 Freeze Arrow -1760 Flash Arrow -1761 Curse Arrow -1762 Rusted Arrow -1763 Poison Arrow -1764 Sharp Arrow -1765 Oridecon Arrow -1766 Arrow of Counter Evil -1767 Shadow Arrow -1768 Sleep Arrow -1769 Mute Arrow -1770 Iron Arrow -1801 Waghnakh -1802 Waghnakh -1803 Knuckle Duster -1804 Knuckle Duster -1805 Hora -1806 Hora -1807 Fist -1808 Fist -1809 Claw -1810 Claw -1811 Finger -1812 Finger -1813 Kaiser Knuckle -1814 Berserk -1901 Violin -1902 Violin -1903 Mandolin -1904 Mandolin -1905 Lute -1906 Lute -1907 Guitar -1908 Guitar -1909 Harp -1910 Harp -1911 Guhmoongoh -1912 Guhmoongoh -1950 Rope -1951 Rope -1952 Line -1953 Line -1954 Wire -1955 Wire -1956 Rante -1957 Rante -1958 Tail -1959 Tail -1960 Whip -1961 Whip -1962 Lariat -1963 Rapture Rose -1964 Chemeti -2101 Guard -2102 Guard -2103 Buckler -2104 Buckler -2105 Shield -2106 Shield -2107 Mirror Shield -2108 Mirror Shield -2109 Book of Summoning -2110 Holy Guard -2111 Evangelist -2112 Novice Guard -2199 Ahura Mazda -2201 Sunglasses -2202 Sunglasses -2203 Glasses -2204 Glasses -2205 Diver's Goggles -2206 Wedding Veil -2207 Fancy Flower -2208 Ribbon -2209 Ribbon -2210 Hair Band -2211 Bandana -2212 Eye Patch -2213 Kitty Band -2214 Bunny Band -2215 Flower Band -2216 Biretta -2217 Biretta -2218 Flu Mask -2219 Flu Mask -2220 Hat -2221 Hat -2222 Turban -2223 Turban -2224 Goggle -2225 Goggle -2226 Cap -2227 Cap -2228 Helm -2229 Helm -2230 Gemmed Sallet -2231 Gemmed Sallet -2232 Circlet -2233 Circlet -2234 Tiara -2235 Crown -2236 Santa's Hat -2237 Bandit Beard -2238 Moustache -2239 Single Glass -2240 Beard -2241 Granpa Beard -2242 Purple Glasses -2243 Geek Glasses -2244 Big Ribbon -2245 Sweet Gent -2246 Golden Gear -2247 Romantic Gent -2248 Western Grace -2249 Coronet -2250 Cute Ribbon -2251 Monk Hat -2252 Wizard Hat -2253 Sunflower -2254 Angel Wing -2255 Evil Wing -2256 Majestic Goat -2257 Snow Horn -2258 Spiky Band -2259 Mini Propeller -2260 Mini Glasses -2261 Army Cap -2262 Pierrot Nose -2263 Zoro Masque -2264 Munak Hat -2265 Ganster Mask -2266 Iron Cane -2267 Cigar -2268 Pipe -2269 Romantic Flower -2270 Romantic Leaf -2271 Jack a Dandy -2272 Stop Post -2273 Doctor Band -2274 Ghost Bandana -2275 Red Bandana -2276 Eagle Eyes -2277 Nurse Cap -2278 Mr. Smile -2279 Bomb Wick -2280 Sakkat -2281 Opera Masque -2282 Heaven Ring -2283 Ear Mufs -2284 Antler -2285 Apple o' Archer -2286 Elven Ears -2287 Pirate Bandana -2288 Mr. Scream -2289 Poo Poo Hat -2290 Funeral Hat -2291 Masquerade -2292 Welding Mask -2293 Pretend Murdered -2294 Stellar -2295 Blinker -2296 Binoculars -2297 Goblini Mask -2298 Green Feeler -2299 Orc Helm -2301 Cotton Shirt -2302 Cotton Shirt -2303 Leather Jacket -2304 Leather Jacket -2305 Adventurer's Suit -2306 Adventurer's Suit -2307 Mantle -2308 Mantle -2309 Coat -2310 Coat -2311 Mink Coat -2312 Padded Armor -2313 Padded Armor -2314 Chain Mail -2315 Chain Mail -2316 Full Plate -2317 Full Plate -2318 Lord's Clothes -2319 Glittering Jacket -2320 Formal Suit -2321 Silk Robe -2322 Silk Robe -2323 Scapulare -2324 Scapulare -2325 Saint's Robe -2326 Saint's Robe -2327 Holy Robe -2328 Wooden Mail -2329 Wooden Mail -2330 Tights -2331 Tights -2332 Silver Robe -2333 Silver Robe -2334 Mage Coat -2335 Thief Clothes -2336 Thief Clothes -2337 Ninja Suit -2338 Wedding Dress -2339 Pantie -2340 Novice Breastplate -2341 Full Plate Armor -2342 Full Plate Armor -2343 Casting Robe -2344 Fire Armor -2345 Fire Armor -2346 Water Armor -2347 Water Armor -2348 Wind Armor -2349 Wind Armor -2350 Earth Armor -2351 Earth Armor -2352 Novice Armor -2401 Sandals -2402 Sandals -2403 Shoes -2404 Shoes -2405 Boots -2406 Boots -2407 Crystal Pumps -2408 Ball'n'Chain -2409 Highheals -2410 Sleipnir -2411 Greaves -2412 Greaves -2413 Safety Shoes -2414 Novice Sandal -2501 Hood -2502 Hood -2503 Muffler -2504 Muffler -2505 Manteau -2506 Manteau -2507 Cape of Old Marquess -2508 Ragamuffin Manteau -2509 Manteau of Life -2510 Novice Hood -2601 Ring -2602 Earring -2603 Necklace -2604 Glove -2605 Brooch -2607 Clip -2608 Rosary -2609 Skull Ring -2610 Gold Ring -2611 Silver Ring -2612 Flower Ring -2613 Diamond Ring -2614 Eye of Dullahan -2615 Safety Ring -2616 Critical Ring -2617 Celebrant's Mitten -2618 Matyr's Leash -2619 Bow Thimble -2620 Rogue's Treasure -2621 Ancient Ring -2622 Ancient Earring -2623 Ancient Necklace -2624 Ancient Glove -2625 Ancient Brooch -2626 Ancient Rosary -2627 Ancient Belt -2628 Novice Armlet -2629 Magingiorde -2630 Brysinggamen -2631 Pebble Ring -2634 Wedding Ring -2635 Wedding Ring -2636 Gold Christmas Ring -2637 Silver Christmas Ring -4001 Poring Card -4002 Fabre Card -4003 Pupa Card -4004 Drops Card -4005 Poring Card -4006 Lunatic Card -4007 Pecopeco Egg Card -4008 Picky Card -4009 Chonchon Card -4010 Wilow Card -4011 Picky Card -4012 Thief Bug Egg Card -4013 Andre Egg Card -4014 Roda Frog Card -4015 Condor Card -4016 Thief Bug Card -4017 Savage Babe Card -4018 Andre Larva Card -4019 Hornet Card -4020 Farmiliar Card -4021 Rocker Card -4022 Spore Card -4023 Desert Wolf Babe Card -4024 Plankton Card -4025 Skeleton Card -4026 Thief bug Female Card -4027 Kukre Card -4028 Tarou Card -4029 Wolf Card -4030 Mandragora Card -4031 Pecopeco Card -4032 Ambernite Card -4033 Poporing Card -4034 Worm Tail Card -4035 Hydra Card -4036 Muka Card -4037 Snake Card -4038 Zombie Card -4039 Stainer Card -4040 Creamy Card -4041 Coco Card -4042 Steel Chonchon Card -4043 Andre Card -4044 Smokie Card -4045 Horn Card -4046 Martin Card -4047 Ghostring Card -4048 Poison Spore Card -4049 Vadon Card -4050 Thief bug Male Card -4051 Yoyo Card -4052 Elder Wilow Card -4053 Vitata Card -4054 Angeling Card -4055 Marina Card -4056 Dustiness Card -4057 Metaller Card -4058 Thara Frog Card -4059 Soldier Andre Card -4060 Goblin Card -4061 Cornutus Card -4062 Anacondaq Card -4063 Caramel Card -4064 Zerom Card -4065 Kaho Card -4066 Orc Warrior Card -4067 Megalodon Card -4068 Scorpion Card -4069 Drainliar Card -4070 Eggyra Card -4071 Orc Zombie Card -4072 Golem Card -4073 Pirate Skeleton Card -4074 BigFoot Card -4075 Argos Card -4076 Magnolia Card -4077 Phen Card -4078 Savage Card -4079 Mantis Card -4080 Flora Card -4081 Hode Card -4082 Desert Wolf Card -4083 Rafflesia Card -4084 Marine Sphere Card -4085 Orc Skeleton Card -4086 Soldier Skeleton Card -4087 Giearth Card -4088 Frilldora Card -4089 Swordfish Card -4090 Munak Card -4091 Kobold Card -4092 Skel Worker Card -4093 Obeaune Card -4094 Archer Skeleton Card -4095 Marse Card -4096 Zenorc Card -4097 Matyr Card -4098 Dokebi Card -4099 Pasana Card -4100 Sohee Card -4101 Sandman Card -4102 Whisper Card -4103 Horong Card -4104 Requiem Card -4105 Marc Card -4106 Mummy Card -4107 Verit Card -4108 Myst Card -4109 Jakk Card -4110 Ghoul Card -4111 Strouf Card -4112 Marduk Card -4113 Marionette Card -4114 Argiope Card -4115 Hunter Fly Card -4116 Isis Card -4117 Sidewinder Card -4118 Petit Card -4119 Bathory Card -4120 Petit Card -4121 Phreeoni Card -4122 Deviruchi Card -4123 Eddga Card -4124 Medusa Card -4125 Deviace Card -4126 Minorous Card -4127 Nightmare Card -4128 Golden Bug Card -4129 Baphomet Card -4130 Scorpion King Card -4131 Moonlight Flower Card -4132 Mistress Card -4133 Raydric Card -4134 Dracula Card -4135 Orc Lord Card -4136 Khalitzburg Card -4137 Drake Card -4138 Anubis Card -4139 Joker Card -4140 Knight Of Abyss Card -4141 Evil Druid Card -4142 Doppelganger Card -4143 Orc Hero Card -4144 Osiris Card -4145 Berzebub Card -4146 Maya Card -4147 Baphomet Card -4148 Pharaoh Card -4149 Bon Gun Card -4150 Orc Archer Card -4151 Mimic Card -4152 Wraith Card -4153 Alarm Card -4154 Arclouse Card -4155 Rideword Card -4156 Skel Prisoner Card -4157 Zombie Prisoner Card -4158 Dark Priest Card -4159 Punk Card -4160 Zherlthsh Card -4161 Mysteltainn Card -4162 Tirfing Card -4163 Executioner Card -4164 Anolian Card -4165 Sting Card -4166 Wander Man Card -4167 Cramp Card -4168 Filamentous Card -4169 Brilight Card -4170 Iron Fist Card -4171 High Orc Card -4172 Choco Card -4173 Stem Worm Card -4174 Penomena Card -4175 Marin Card -4176 Sasquatch Card -4177 Antonio Card -4178 Cruiser Card -4179 Mystcase Card -4180 Chepet Card -4181 Knight Of Windstorm Card -4182 Garm Card -4183 Gargoyle Card -4184 Raggler Card -4185 Neraid Card -4186 Pest Card -4187 Injustice Card -4188 Goblin Archer Card -4189 Gryphon Card -4190 Dark Frame Card -4191 Wind Ghost Card -4192 Merman Card -4193 Cookie Card -4194 Aster Card -4195 Carat Card -4196 Bloody Knight Card -4197 Clock Card -4198 C Tower Manager Card -4199 Alligator Card -4200 Dark Lord Card -4201 Orc Lady Card -4202 Megalith Card -4203 Alice Card -4204 Raydric Archer Card -4205 Greatest General Card -4206 Stalactic Golem Card -4207 Tri Joint Card -4208 Steam Goblin Card -4209 Sage Worm Card -4210 Kobold archer Card -4211 Chimera Card -5001 Headset -5002 Jewel Crown -5003 Joker Jester -5004 Oxygen Mask -5005 Gas Mask -5006 Machoman's Glasses -5007 Grand Circlet -5008 Puppy Love -5009 Safety Helmet -5010 Indian Fillet -5011 Aerial -5012 Ph.D Hat -5013 Lord Kaho's Horn -5014 Fin Helm -5015 Egg Shell -5016 Boys Cap -5017 Bone Helm -5018 Feather Bonnet -5019 Corsair -5020 Kafra Band -5021 Money Loser's Grief -5022 Solar God Helm -5023 Parcel Hat -5024 Cake Hat -5025 Angel Helm -5026 Chef's Hat -5027 Magic Instructor's Hat -5028 Candle -5029 Spore Hat -5030 Panda Cap -5031 Miner's Helmet -5032 Sunday Hat -5033 Smokie Hat -5034 Lightbulb Hairband -5035 Poring hat -5036 Cross Hairband -5037 Apple Hat -5038 Deviruchi Hat -5039 Spotted Eggshell -5040 Innocence of Maiden -5041 Heart Hairpin -5042 Dumpling Decoration -5043 Opera Ghost Mask -5044 Wing's of Demon -5045 Magic Hat -5046 Bongun hat -5047 Fashion Sunglasses -5048 Cresent Hairpin -5049 Striped Bandana -5050 Mysterious Apple Hat -5051 Bell of Pussycat -5052 Blue Bandana -5053 Sphinx Hat -5054 Assassin Mask -5055 Novice Eggshell -5056 ??? -7001 Mould Powder -7002 Ogre Tooth -7003 Anolian Skin -7004 Mud Lump -7005 Skull -7006 Wing of Red Bat -7007 Claw of Rat -7008 Stiff Horn -7009 Glitter Shell -7010 Tail of Steel Scorpion -7011 Claw of Monkey -7012 Tough Scalelike Stem -7013 Coral Reef -7014 Old Portrait -7015 Bookclip in Memory -7016 Spoon Stub -7017 Executioner's Mitten -7018 Young Twig -7019 Loki's Whispers -7020 Mother's Nightmare -7021 Foolishness of the Blind -7022 Old Hilt -7023 Blade Lost in Darkness -7024 Bloody Edge -7025 Lucifer's Lament -7026 Key of Clock Tower -7027 Key of Underground -7028 Invite for Duel -7029 Admission for Duel -7030 Claw of Desert Wolf -7031 Old Frying Fan -7032 Piece of Egg Shell -7033 Poison Spore -7034 Red Socks with Holes -7035 Matchstick -7036 Fang of Garm -7037 Coupon -7038 Yarn -7039 Novice Nametag -7040 Megaphone -7041 Fine Grit -7042 Leather Bag of Infinity -7043 Fine Sand -7044 Vigorgra -7045 Magic Paint -7046 Cart Parts -7047 Alice's Apron -7048 Talon of Griffon -7049 Stone -7050 Cotton Mat -7051 Silk Mat -7052 Wasted Magazine -7053 Cyfar -7054 Brigan -7055 Animal Poop -7056 Payment Statement for Ka -7057 Gallar Horn -7058 Gullraifnir -7059 Free Ticket for Kafra St -7060 Free Ticket for Kafra Tr -7061 Free Ticket for the Cart -7062 Broken Turtle Shell -7063 Soft Feather -7064 Wing of Dragonfly -7065 Sea Otter Fur -7066 Ice Cubes -7067 Piece of Rock -7068 Half Burnt Log -7069 Broken Armor Piece -7070 Broken Shell -7071 Tattered Clothes -7072 Old Shuriken -7073 Freyja's Jewel -7074 Thor's Guntlet -7075 Iron Maiden -7076 Wheel of the Unknown -7077 Silver Ornament -7078 Wrath of Valkyrie -7079 Feather of Angel Wing -7080 Footprints of Cat -7081 Woman's Moustache -7082 Root of Stone -7083 Spirit of Fish -7084 Saliva of Bird -7085 Tendon of Bear -7086 Solar Bead -7087 Breath of Soul -7088 Snow Crystal -7089 Omen of Tempest -7090 Ripple -7091 Billow -7092 Drifting Air -7093 Metal Wheel -7094 Cabinet Chip -7095 Tooth Fragment -7096 Hardened Lava -7097 Burning Heart -7098 Fire Seed -7099 Old Magical Circle -7100 Sharpened Leaf -7101 Peco's Feather -7102 Nightmare -7103 Yellwo Liquid Bottle -7104 Imitation Angel's Wing -7105 Imitation Soul's Band -7106 Horn of Goat -7107 Fur of Goat -7108 Broken Shield -7109 Shiny Spear Tip -7110 Sharp Sword -7111 String Paper -7112 Transparent Paper -7113 Onion Wand -7114 Sphinx Mask -7115 Blood Feather -7116 Tooth of Lowblood -7117 Torn Spell Book -7118 Torn Scroll -7119 Hypha Body -7120 Burning Horseshoe -7121 Honey Jar -7122 Hot Feather -7123 Dragon's Skin -7124 Sand Lump -7125 Crab Shot -7126 Large Jellopy -7127 Alcohol Making Book -7128 Fire Bottle Making Book -7129 Acid Bottle Making Book -7130 Plant Bottle Making Book -7131 Mine Bottle Making Book -7132 Coating Wax Making Book -7133 Slim Potion Making Book -7134 Medicine Bowl -7135 Fire Bottle -7136 Hydrobolic Acid Bottle -7137 Water Bottle -7138 Mine Bottle -7139 Coating Wax -7140 Seed of Life -7141 Water Flow -7142 Ancient Life -7143 Seperation Tubes -7144 Potion Making Book -7145 Ragnarok T-Shirt -7146 Vacation Ticket -7147 Jasmine -7148 Mother's Letter -7149 Yellow Plate -7150 Bamboo Trunk -7151 Oiled Paper -7152 Glossy Hair -7153 Old Kimono -7154 Poison Powder -7155 Poisonous Toad's Skin -7156 Broken Shuriken -7157 Black Mask -7158 Broken Liquor Bottle -7159 Demon's Nose -7160 Passport From King -7161 Skin of the Black Bear -7162 Piece of Cloud -7163 Hard Antennae -7164 Very Hard Peach -7165 Etherial Winged Clothing -7166 Soft Silk Fabric -7167 Strange Piece of Iron -7168 Big Wing of Butterfly -7169 Tae Guk Tablet -7170 Tuxedo -7171 Skin of Panther -7172 Claw of Panther -7173 Bun Buster Bag -7174 Wrapping Thread -7175 Wrapper -7176 King's Proof Document -7177 ?????_?????_???? -7178 ?????_????? -7179 ????_??????? -7180 0 -7181 0 -7182 Cacao -7183 ???? -7184 ?????? -7185 ?????? -7186 ??? -7187 ????? -7188 ???? -7189 ???? -7190 ???? -7191 ? -7192 ???? -7193 ????? -7194 ???????? -7195 ???? -7196 ???? -7197 ???????? -7198 ?????? -7199 20 -7200 ??? -7201 ?? -7202 ???????? -7203 ????? -7204 ?? -9001 Poring Egg -9002 Drops Egg -9003 Poporing Egg -9004 Lunatic Egg -9005 Picky Egg -9006 Chonchon Egg -9007 Steel Chonchon Egg -9008 Hunter Fly Egg -9009 Savage Babe Egg -9010 Baby Desert Wolf Egg -9011 Rocker Egg -9012 Spore Egg -9013 Poison Spore Egg -9014 PecoPeco Egg -9015 Smokie Egg -9016 Yoyo Egg -9017 Orc Warrior Egg -9018 Munak Egg -9019 Dokkaebi Egg -9020 Sohee Egg -9021 Isis Egg -9022 Green Petite Egg -9023 Deviruchi Egg -9024 Bapho Jr. Egg -9025 Bongun Egg -9026 Alice Egg -9027 Zherlthsh Egg -9028 Test Egg -9029 Test Egg -10001 Skull Helm -10002 Monster Oxygen Mask -10003 Transparent Headgear -10004 Pacifier -10005 Wig -10006 Queen's Hair Ornament -10007 Silk Ribbon -10008 Punisher -10009 Wild Flower -10010 Battered Pot -10011 Stellar Hairpin -10012 Tiny Egg Shell -10013 Backpack -10014 Rocker Glasses -10015 Green Lace -10016 Golden Bell -10017 Bark Shorts -10018 Monkey Circlet -10019 Red Muffler -10020 Sword of Chinese Exorcis diff --git a/doc/item_bonus.txt b/doc/item_bonus.txt deleted file mode 100644 index 30202ee..0000000 --- a/doc/item_bonus.txt +++ /dev/null @@ -1,137 +0,0 @@ -skill n,x; skill n of level x - -bonus bStr,n; STR + n -bonus bAgi,n; AGI + n -bonus bVit,n; VIT + n -bonus bInt,n; INT + n -bonus bDex,n; DEX + n -bonus bLuk,n; LUK + n - -bonus bMaxHP,n; MAXHP + n -bonus bMaxSP,n; MAXSP + n -bonus bMaxHPrate,n; MAXHP + n% -bonus bMaxSPrate,n; MAXSP + n% -bonus bAtk,n; ATK + n -bonus bAtk2,n; ATK2 + n -bonus bAtkRate attack power + n% -bonus bBaseAtk,n; Basic attack power + n -bonus bMatk,n; Magical attack power 1 + n and magical attack power 2 + n -bonus bMatk1,n; Magical attack power 1 + n -bonus bMatk2,n; Magical attack power 2 + n -bonus bMatkRate,n; Magical attack power + n% -bonus bMdef,n; Magical defensive power + n -bonus bDef,n; DEF + n -bonus bHit,n; On-target hit power + n -bonus bCritical,n; Critical + n -bonus bCriticalRate,n; Critical ratio + n% -bonus bFlee,n; Evasion power + n -bonus bFlee2,n; Perfection evasion + n -bonus bSpeed,n; Drift speed + n -bonus bAspd,n; Attack speed + n -bonus bSpeedRate,n; Drift speed + n% (just high ones application) -bonus bAspdRate,n; Attack speed + n% (just high ones application) -bonus bSpeedAddRate drift speed + n% -bonus bAspdAddRate attack speed + n% -bonus bAtkRange,n; Attack Range + n -bonus bCastrate,n; Cast rate + n% -bonus bUseSPrate,n; SP consumption + n% -bonus bHPrecovRate,n; HP automatic recovery ratio + n% (you exclude the recovery with skill) -bonus bSPrecovRate,n; SP automatic recovery ratio + n% (you exclude the recovery with skill) -bonus bDoubleRate,n; attack probability n% (with weapon disregard just high ones application) -bonus bDoubleAddRate,n; Double attack probability + n% (weapon disregard) -bonus bPerfectHitRate,n; On-target impact attack probability n% (just high ones application) -bonus bPerfectHitAddRate,n; On-target impact attack probability +n% -bonus bGetZenyNum,n; When pushing down the monster with physical attack, rand () ゼニ of %n+1 is obtained, (as for n just high ones application) -bonus bAddGetZenyNum,n; When pushing down the monster with physical attack, rand () ゼニ of %n+1 is obtained, (n is done +) -bonus bCriticalDef,n; Critical 喰 and others the trap it is, probability + n% -bonus bNearAtkDef,n; The damage of short-range attack n% reduction (magic and the trap, the 鷹 is excluded) -bonus bLongAtkDef,n; damage of stand off attack n% reduction (magic and the trap, the 鷹 is excluded) -bonus bMagicAtkDef the damage of magical attack n% reduction -bonus bMiscAtkDef MISC attack (the trap and ?) the damage n% reduction - -bonus bIgnoreDefRace,n Defense disregard of enemy of n race - 0,Intangibility 1,Immortality 2,Animal 3,Plant 4,Insect 5,Fish and shellfish 6,Demon 7,Human 8,Angel 9,Dragon family 10:Boss monster 11:Other than (normal monster) boss monster -bonus bIgnoreDefEle,n; Defense disregard of enemy of n attribute - 0,Nothing 1,Water 2,Earth 3,Fire 4,Wind 5,Poison 6,Saint 7,Darkness 8,Sense 9,Immortality -bonus bIgnoreMDefRace n race the magical defensive power disregard damage - 0,Intangibility 1,Immortality 2,Animal 3,Plant 4,Insect 5,Fish and shellfish 6,Demon 7,Human 8,Angel 9,Dragon family 10:Boss monster 11:Other than boss monster (normal monster) -bonus bIgnoreMDefEle n attribute the magical defensive power disregard damage - 0,Nothing 1,Water 2,Earth 3,Fire 4,Wind 5,Poison 6,Saint 7,Darkness 8,Sense 9,Immortality -bonus bDefRatioAtkRace,n; n race if defensive power is high the high extent big damage is given, (defense disregard) - 0,Intangibility 1,Immortality 2,Animal 3,Plant 4,Insect 5,Fish and shellfish 6,Demon 7,Human 8,Angel 9,Dragon family 10:Boss monster 11:Other than boss monster (normal monster) -bonus bDefRatioAtkEle,n; n attribute if defensive power is high the high extent big damage is given, (defense disregard) - 0,Nothing 1,Water 2,Earth 3,Fire 4,Wind 5,Poison 6,Saint 7,Darkness 8,Sense 9,Immortality -bonus bAtkEle,n; Attack with element n - 0,Nothing 1,Water 2,Earth 3,Fire 4,Wind 5,Poison 6,Saint 7,Darkness 8,Sense 9,Immortality -bonus bDefEle,n; Guard against element n - 0,Nothing 1,Water 2,Earth 3,Fire 4,Wind 5,Poison 6,Saint 7,Darkness 8,Sense 9,Immortality -bonus bHitRate,n; on-target hit ratio +n% -bonus bFleeRate,n; evasion ratio +n% -bonus bFlee2Rate,n; complete evasion ratio +n% -bonus bDefRate,n; earned-run average +n% (equipment) -bonus bDef2Rate,n; earned-run average +n% (those due to vit) -bonus bMdefRate,n; magical earned-run average +n% (equipment) -bonus bMdef2Rate,n; magical earned-run average +n% (those due to int) -bonus bSplashRange n; damage is given to the peripheral n cell of the target with usual weapon attack, if (as for n just high ones application, 1 if the 3*3, 2 the 5*5) -bonus bSplashAddRange n; damage is given to the peripheral n cell of the target with usual weapon attack, (range + n) - -bonus bInfiniteEndure,n; Unlimited Endure (n is meaningless) -bonus bRestartFullRecover,n; When reviving, HP and SP all recoveries (non mind there is no n) -bonus bNoCastCancel,n; The casting is not cancelled (non mind there is no n) -bonus bNoCastCancel2,n; The casting is not cancelled (is not cancelled even with GVG, n is meaningless) -bonus bNoSizeFix,n; The attack revision with the size of the monster is not received, (non mind there is no n) -bonus bNoWeaponDamage,n; The damage is not received to physical attack, (non mind there is no n) -bonus bNoMagicDamage,n; The damage is not received to magic, (including also the heel, non mind there is no n) -bonus bNoGemStone,n; When using skill, the gemstone is not consumed (non mind there is no n) - - -bonus2 bAddEff,Eff_Blind,n; With the establishment of n% dark grant -bonus2 bAddEff,Eff_Sleep,n; With the establishment of n% sleep grant -bonus2 bAddEff,Eff_Poison,n; With the establishment of n% poison grant -bonus2 bAddEff,Eff_Freeze,n; With the establishment of n% freezing grant -bonus2 bAddEff,Eff_Silence,n; With the establishment of n% silence grant -bonus2 bAddEff,Eff_Stan,n; With the establishment of n% stun grant -bonus2 bAddEff,Eff_Curse,n; You curse with the establishment of n%, grant -bonus2 bAddEff,Eff_Confusion,n; With the establishment of n% confusion grant -bonus2 bAddEff,Eff_Stone,n; With the establishment of n% petrochemical grant - -bonus2 bResEff,Eff_Blind,n; Dark tolerance + n% -bonus2 bResEff,Eff_Sleep,n; Sleep tolerance + n% -bonus2 bResEff,Eff_Poison,n; Poison tolerance + n% -bonus2 bResEff,Eff_Freeze,n; Freezing tolerance + n% -bonus2 bResEff,Eff_Silence,n; Silence tolerance + n% -bonus2 bResEff,Eff_Stan,n; Stun tolerance + n% -bonus2 bResEff,Eff_Curse,n; Cursing tolerance + n% -bonus2 bResEff,Eff_Confusion,n; Confusion tolerance + n% -bonus2 bResEff,Eff_Stone,n; Petrochemical tolerance + n% - -bonus2 bAddSize,n,x; In n size the damage addition of x% - 0,Small size 1,Medium size 2,Large size -bonus2 bAddRace,n,x; In n race the damage addition of x% - 0,Intangibility 1,Immortality 2,Animal 3,Plant 4,Insect 5,Fish and shellfish 6,Demon 7,Human 8,Angel 9,Dragon family 10:Boss monster 11:Other than boss monster (normal monster) -bonus2 bSubRace,n,x; Damage x% reduction from n race - 0,Intangibility 1,Immortality 2,Animal 3,Plant 4,Insect 5,Fish and shellfish 6,Demon 7,Human 8,Angel 9,Dragon family 10:Boss monster 11:Other than boss monster (normal monster) -bonus2 bMagicAddRace,n,x; In n race the damage addition of x% (only magical attack) - 0,Intangibility 1,Immortality 2,Animal 3,Plant 4,Insect 5,Fish and shellfish 6,Demon 7,Human 8,Angel 9,Dragon family 10:Boss monster 11:Other than boss monster (normal monster) -bonus2 bMagicSubRace,n,x; Magical damage x% reduction from n race - 0,Intangibility 1,Immortality 2,Animal 3,Plant 4,Insect 5,Fish and shellfish 6,Demon 7,Human 8,Angel 9,Dragon family 10:Boss monster 11:Other than boss monster (normal monster) -bonus2 bAddEle,n,x; In n attribute the damage addition of x% - 0,Nothing 1,Water 2,Earth 3,Fire 4,Wind 5,Poison 6,Saint 7,Darkness 8,Sense 9,Immortality -bonus2 bMagicAddEle,n,x; In n attribute the damage addition of x% (only magical attack) - 0,Nothing 1,Water 2,Earth 3,Fire 4,Wind 5,Poison 6,Saint 7,Darkness 8,Sense 9,Immortality -bonus2 bSubEle,n,x; Damage x% reduction from n attribute - 0,Nothing 1,Water 2,Earth 3,Fire 4,Wind 5,Poison 6,Saint 7,Darkness 8,Sense 9,Immortality -bonus2 bAddDamageClass,n,x; In monster of class n the damage addition of x% (only physical attack), in case of prayer in n occupation the damage addition of x% -bonus2 bAddMagicDamageClass,n,x; In monster of class n in case of the magical damage addition and prayer of x% in n occupation the magical damage addition of x% -bonus2 bAddDefClass,n,x; In monster of class n the damage reduction of x% (only physical attack), in case of prayer in n occupation the damage reduction of x% -bonus2 bAddMDefClass,n,x; In monster of class n in case of the magical damage reduction and prayer of x% in n occupation the magical damage reduction of x% -bonus2 bHPDrainRate,n,x; it obtained to the enemy -- ? ME ? JI -- n % probability -- x % -- HP -- absorption (+ n and x are carried out) -bonus2 bSPDrainRate,n,x; it obtained to the enemy -- ? ME ? JI -- n % probability -- x % -- SP -- absorption (+ n and x are carried out) - - -bonus3 bAddMonsterDropItem,n,x; When pushing down the monster with physical attack, the probability which drops item n +x% (the item which the monster drops unrelated ones) - 0,Intangibility 1,Immortality 2,Animal 3,Plant 4,Insect 5,Fish and shellfish 6,Demon 7,Human 8,Angel 9,Dragon family 10:Boss monster 11:Other than boss monster (normal monster) -bonus3 bAutoSpell,n,x,y; Auto Spell casting of spell n at level x with y% chance - -// bAddDamageClass, bAddMagicDamageClass and bAddMonsterDropItem it is setting possible up to 10. Those which exceed 10 are ignored. -// those which can be used with the arrow are only bCritical, bAtkEle, bHit, bAddEle, bAddRace, bAddSize and bAddEff. The other things are ignored. diff --git a/doc/spell-language b/doc/old-spell-language index 5f70f89..5f70f89 100644 --- a/doc/spell-language +++ b/doc/old-spell-language diff --git a/doc/packet_table_en.txt b/doc/packet_table_en.txt deleted file mode 100644 index 3b72ba3..0000000 --- a/doc/packet_table_en.txt +++ /dev/null @@ -1,1325 +0,0 @@ -here is a translation for "packet_table.txt". -i leave original japanese sentenses and write translation below that. - - -詳しくは知りませんが、GMはアカウントID=704554付近を指定すると -クライアントがGMだと認識して表示するみたいです。 -数字が半端なのは気にしないで・・・ - -i don't know for sure, but if you set account id around 704554, -the ro client recognizes you as GM ( i don't know about other client like -iro or something. this is talking about jro.) - - -パケット長リスト。-1はパケット種別の直後に長さがあるパケット - -list of packet length. "-1" means a packet that have its packet length -just after the packet number. - - 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,108, 3, 2, - 3, 28, 19, 11, 3, -1, 9, 5, 52, 51, 56, 58, 41, 2, 6, 6, - - 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0, - 7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6, - 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6, - 8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3, - - 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 3, 2, 27, - 3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1, - 30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2, - 3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10, - - - 2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1, - 10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16, - 6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1, - 6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26, - - 22, 14, 6, 10, 23, 19, 6, 39, 6, 7, 6, 27, -1, 2, 6, 6, - 110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42, - -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14,186,182, - 14, 30, 10, 3, -1, 6,106, -1, 4, 5, 4, -1, 6, 7, -1, -1, - - 6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6, - 90, 86, 24, 6, 30,102, 8, 4, 8, 4, 14, 10 - -S クライアントから見て送信 -S means a packet that will be sent from client. - -R クライアントから見て受信 -R means a packet that will be received by client. - -B バイト -B means a byte. - -w ワード=2B -w means word( 2 bytes) - -l ロングワード=4B -l means long word(4bytes) - -* 0個以上くりかえし -* means repeat - - -S 0064 <version>.l <account name>.24B <password>.24B <version2>.B - アカウントID&パスワード送信 - send account id & password -S 0065 <account ID>.l <login ID1>.l <login ID2>.l ?.2B <sex>.B - キャラセレ鯖接続要求 - request connection to character select server -S 0066 <charactor number>.B - キャラクタ選択要求 - request to select character -S 0067 <charactor name>.24B <param etc>.11B - キャラクタ作成要求 - request to create new character -S 0068 <charactor ID>.l <mail address>.40B - キャラクタ削除要求 - request to delete character -R 0069 <len>.w <login ID1>.l <account ID>.l <login ID2>.l ?.32B <sex>.B {<IP>.l <port>.w <server name>.20B <login users>.l ?.2B}.32B* - login成功&鯖情報 - information about a success of login to login server -R 006a <error No>.B - login失敗 - fail to login to login server -R 006b <len>.w <charactor select data>.106B* - キャラセレ鯖接続成功&キャラクタデータ - information about a success of connection to character select server & character server - <charactor select data> = <charactor ID>.l <base exp>.l <zeny>.l <job exp>.l <job level>.l ?.8B <option>.l <karma>.l <manner>.l ?.2B <HP>.w <MaxHP>.w <SP>.w <MaxSP>.w <speed>.w <class>.w <hair>.w <weapon>.2w <base level>.w <skill point>.w <head_bottom>.w <sheild>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <name>.24B <STR>.B <AGI>.B <VIT>.B <INT>.B <DEX>.B <LUK>.B <charactor number>.B ?.B -R 006c <error No>.B - キャラクタ選択失敗 - fail to select character -R 006d <charactor select data>.106B - キャラクタ作成成功 - success to create new character -R 006e <error No>.B - キャラクタ作成失敗 - fail to create new character -R 006f - キャラクタ削除成功 - success to delete character -R 0070 <error No>.B - キャラクタ削除失敗 - fail to delete character -R 0071 <charactor ID>.l <map name>.16B <ip>.l <port>.w - キャラクタ選択成功&マップ名&ゲーム鯖IP/port - success to select character & map name and ip/port number for game server -S 0072 <account ID>.l <charactor ID>.l <login ID1>.l <login ID2>.l <sex>.b - ゲーム鯖接続要求 - request connection to game server -R 0073 <server tick>.l <coordidate>.3B ?.2B - ゲーム鯖接続成功&サーバ側1ms時計&出現位置 - success to connect to game server & server time & spawn point -R 0078 <ID>.l <speed>.w ?.w ?.w <option>.w <class>.w <hair>.w <weapon>.w <head option bottom>.w <sheild>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.w ?.w ?.w <manner>.w <karma>.w ?.B <sex>.B <X_Y_dir>.3B ?.B ?.B <sit>.B - マップロード時&移動時用、向き付き用キャラ情報? - a packet for map load or moving, infermation about a direction for character? -R 0079 <ID>.l <speed>.w ?.w ?.w <option>.w <class>.w <hair>.w <weapon>.w <head option bottom>.w <sheild>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.w ?.w ?.w <manner>.w <karma>.w ?.B <sex>.B <X_Y_dir>.3B ?.B ?.B - テレポ等の表示範囲内沸きキャラ用、向き付き無しキャラ情報? - information about characters in a range of a skill like teleport, no infor about direction for character? -R 007b <ID>.l <speed>.w ?.w ?.w <option>.w <class>.w <hair>.w <weapon>.w <head option bottom>.w <server tick>.l <sheild>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.w ?.w ?.w <manner>.w <karma>.w ?.B <sex>.B <X_Y_X_Y>.5B ?.B ?.B ?.B - 表示範囲内キャラ移動情報 - character information about walking in a range of the character can see -R 007c <ID>.l <speed>.w ?.6w <class>.w ?.7w <X_Y>.3B ?.2B - NPC用表示範囲内キャラ情報 - character information for npc in a range the character can see -S 007d - mapロード終り - end of load -S 007e <client tick>.l - クライアント側1msタイマ送信 - send 1ms timer at client -R 007f <server tick>.l - サーバ側1msタイマ送信 - send 1ms timer at server -R 0080 <ID>.l <type>.B - type=00 キャラ消滅 (画面外移動。死体消滅等?) - character disappear( walk out of screen. died and disappear?) - type=01 キャラ死亡 - character died - type=02 キャラ消滅 (テレポ,蝿,蝶,logout等?) - character disappear( teleport, fly's wing, butterfly's wing, logout?) -R 0081 <type>.B - type=03 speed hack - speed hack - type=08 2重ログイン - duplicated login -S 0085 <X_Y>.3B - 移動要求 - request to walk -R 0087 <server tick>.l <X_Y_X_Y>.5B ?.B - 移動応答 - response to the request to walk -R 0088 <ID>.l <X>.w <Y>.w - 移動途中停止 - stop walking -S 0089 <target ID>.l <type>.B - type=00 targetを1回殴る - hit target once - type=02 座る - sit down - type=03 立ち上る - stand up - type=07 targetを殴り続ける - continue to hit target -R 008a <src ID>.l <dst ID>.l <server tick>.l <src speed>.l <dst speed>.l <param1>.w <param2>.w <type>.B <param3>.w - type=00 param1=0 miss - param1=0 miss - type=00 param1:ダメージ(の合計?) param2:分割数 param3:アサシン2刀流逆手ダメージ - param1:damage(of total?) param2:number of division param3:damage of assasin's left hand - NPCからの攻撃の場合、param2,param3はゴミデータ - if the attack was by npc, param2 and param3 are not used - speedはPCの場合内部ASPDと一致 - speed match the aspd if it's player character - type=01 itemを拾う ID*2以外ゴミ - pick up item, unused data except ID*2 - type=02 座る src ID以外ゴミ - sit down, unused data except src ID - type=03 立つ src ID以外ゴミ - stand up, unused data except src ID - type=08 複数攻撃 - multiple attack - type=0a クリティカル - critical attack - type=0b 完全回避 - perfect evade -R 008c <len>.w <str>.?B - 通常発言送信。チャット中はチャット内発言用になる - send normal speech. it become a speech for chat during a chat - 先頭の"<nick> : "の部分はクライアント側で付ける事 - client adds "<nick> : " part. -R 008d <len>.w <ID>.l <str>.?B - IDさんの発言受信。チャット中はチャット内発言用になる - receive a speech by ID. it become speech for chat during a chat -R 008e <len>.w <str>.?B - 自分の発言受信。チャット中はチャット内発言用になる - receive my character's speech. it become speech for chat during a chat -S 0090 <ID>.l <type?>.B - NPCに話しかける。typeは01しか見た事無し - talk to npc. i havent seen type setted to 01. -R 0091 <map name>.16B <X>.w <Y>.w - 鯖内マップ間移動、テレポ,蝿等用 - map change in the same server, for instance, teleport, fly's wing... -R 0092 <map name>.16B <X>.w <Y>.w <IP>.l <port>.w - 鯖間移動 - map change to the other server -R 0093 - 8月中に1回だけ観測。謎 - this packet observed in august once. i dont know what it is. -S 0094 <ID>.l - IDのキャラ名等要求。0095か0195の返答があるはず - request a character name for ID. 0095 or 0195 response is expected. -R 0095 <ID>.l <nick>.24B - NPC,ギルド未所属PCの0094への返答 - response for 0094 request from npc or player character without guild. - 0193 <charID>.l で問い合わせて - request by <charID>.l - 0194 <charID>.l <name>.24B の応答で得てます。 - get response by <charID>.l <name>.24B - -S 0096 <len>.w <nick>.24B <message>.?B - wis送信 - send wisper -R 0097 <len>.w <nick>.24B <message>.?B - wis受信 - receive wisper -R 0098 <type>.B - type=00 wis送信成功 - success to send wisper - type=01 wis相手がloginしてない? - target character is not loged in? - type=02 wis相手からignoreされてる? - ignored by target -R 009a <len>.w <message>.?B - GMからの天の声 - GM announce -S 009b <head dir>.w <dir>.B - 体&頭の方向変更要求。クライアントへの応答は無い模様 - request a change of head and body direction. no response to client. - dirは00〜07で体の向き。00で北から反時計回りに45°単位で07まで - dir can be 00-07 and it's for body direction. 00 means north and go counter-clockwise upto 07 by 45 degrees. - head dirは00,01,02で頭の向き。00で体と同じ、01が右、02が左 - head dir can be 00,01,02. 00 means the same direction of body, 01 means right, 02 menas left. -R 009c <ID>.l <head dir>.w <dir>.B - IDの体&頭の方向変更 - change body and head direction for ID. -R 009d <ID>.l <item ID>.w <identify flag>.B <X>.w <Y>.w <amount>.w <subX>.B <subY>.B - 移動等で床アイテムが画面内に入ってきた時 - when the item on the floor will appear on the screen by walking etc. -R 009e <ID>.l <item ID>.w <identify flag>.B <X>.w <Y>.w <subX>.B <subY>.B <amount>.w - item drop。何故か009dとマス目内位置&個数が入れ変っている - item drop. coordinate and amount is different from 009d. -S 009f <ID>.l - IDの床アイテムを拾う - pick up item on the floor. -R 00a0 <index>.w <amount>.w <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w <equip type>.w <type>.B <fail>.B - fail=02 取得失敗? - fail to pick up? - fail=06 ルート権無し。取得失敗 - no right to pick up. fail to pick up. -R 00a1 <ID>.l - IDの床アイテム消去 - disappear the floor item -S 00a2 <index>.w <amount>.w - 所有アイテムを落す - drop inventory item. -R 00a3 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B}.10B* - 所有消耗品&収集品リスト - list of consumptive item and collecter item that you have -R 00a4 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <equip type>.w <equip point>.w <attribute?>.B <refine>.B <card>.4w}.20B* - 所有装備リスト - list of equipments that you have -R 00a5 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B}.10B* - カプラさんに預けてある消耗品&収集品リスト - list of consumptive item and collecter item that you leave with capra. -R 00a6 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <equip type>.w <equip point>.w <attribute?>.B <refine>.B <card>.4w}.20B* - カプラさんに預けてある装備リスト - list of equipments that you leave with capra. -S 00a7 <index>.w <ID>.l - 所持アイテムindexを使用する。IDは自分のみ? - use index item. ID can be only myself? -R 00a8 <index>.w <amount>.w <type>.B - アイテム使用応答。type=00の場合使用失敗? amountもゴミの模様 - response to use item. type=00 means failed. amount is unused. - type=01の場合成功で、amountは使用後の残り個数 - type=01 means success to use item, amount is a number of rest of the item. -S 00a9 <index>.w <equip type>.w - アイテム装備 - equip item. -R 00aa <index>.w <equip point>.w <type>.B - アイテム装備応答。type=00の場合装備失敗? equip pointもゴミの模様 - response to equip item. type=00 means fail. equip point is unused. -S 00ab <index>.w - 装備解除 - take off equipment. -R 00ac <index>.w <equip point>.w <type>.B - 装備解除応答。type=00の場合失敗? equip pointもゴミの模様 - response to take off equipment. type=00 means fail? equip point is unused. -R 00af <index>.w <amount>.w - アイテム数減少。amount個だけ減らす - decrease number of item by amount. -R 00b0 <type>.w <val>.l - 色々な能力値の更新。以下type:対応する数値を列挙 - update values of various status. - 0000:speed 0003:悪行値 0004:マナーポイント 0005:HP 0006:MaxHP - 0000:speed 0003:carma 0004:manner point 0005:HP 0006: MaxHP - 0007:SP 0008:MaxSP 0009:ステータスポイント 000b:ベースレベル - 0007:SP 0008:MaxSP 0009:status point 000b: base level - 000c:スキルポイント 0018:重量(表示されてる数字の10倍) - 000c:skil point 0018:weight(this number must be 10 times greater than it's been diplayed.) - 0019:最大重量(表示されてる数字の10倍) - 0019:max weight(this number must be 10 times greater than it's been diplayed.) - 0029:ATK前 002a:ATK後 002b:MATK前 002c:MATK後 - 0029:attack in front 002a:attack in back 002b:matk in front 002c:matk in back - 002d:DEF前 002e:DEF後 002f:MDEF前 0030:MDEF後 - 002d:deffence in front 002e:deffence in back 002f:mdef in front 0030:mdef in back - 0031:HIT 0032:FLEE前 0033:FLEE後 0034:クリティカル - 0031:hit 0032:flee in front 0033:flee in back 0034: critical - 0035:ASPD(2ms単位の時間?) 0037:ジョブレベル - 0035:aspd(time by 2ms?) 0037:job level - 0082:謎 ATK後と同じ数字? - 0082:unknown. is it the same number as atk in back? -R 00b1 <type>.w <val>.l - 色々な能力値の更新。以下type:対応する数値を列挙 - update valies of various status. below is the list of corresponding type and value. - 0001:ベース側経験値 0002:ジョブ側経験値 0014:zeny - 0001:base experience 0002:job experience 0014:zeny - 0016:ベース側必要経験値 0017:ジョブ側必要経験値 - 0016:base experience that needed to level up 0017:job experience that needed to level up - β1では00b0はvalがshort、00b1はvalがlongという使い分けがあったんだけど - 今となっては差が無くなって、盲腸みたいなもの? - in beta1, value of 00b0 was short and value of 00b1 was long, - but not there are no difference. -S 00b2 <type>.B - type=00 死亡時リスタート - restart game when character died - type=01 キャラセレ要求 - request character select -R 00b3 <type>.B - type=01 キャラセレ応答 - response to character select -R 00b4 <len>.w <ID>.l <str>.?B - IDのNPCからのメッセージ - message from npc id -R 00b5 <ID>.l - IDのNPCとのメッセージウィンドウに"NEXT"アイコンを出す - display the "NEXT" icon to npc message window -R 00b6 <ID>.l - IDのNPCとのメッセージウィンドウに"CLOSE"アイコンを出す - display the "CLOSE" icon to npc message window -R 00b7 <len>.w <ID>.l <str>.?B - IDのNPCの会話で選択項目表示。各項目は':'で区切られる - display select options in npc message window. each options devided by ":". -S 00b8 <ID>.l <select>.B - IDのNPCの会話の選択。各項目に順に1〜が振られる。ffでキャンセル? - select options in ncp message window. number starts from 1 for each options. cancel for ff? -S 00b9 <ID>.l - IDのNPCとの会話。NEXTボタンを押した - "NEXT" button clicked in ncp message window. -S 00bb <type>.w <amount>.B - ステータスup要求。typeは000dから0012が順にSTR,AGI,VIT,INT,DEX,LUKに対応 - request update status. type can be 000d for STR, 000e for AGI, 000f for VIT, 0010 for INT, 0011 for DEX, 0012 for LUK. -R 00bc <type>.w <fail>.B <val>.B - ステータスup応答。fail=01なら成功。typeは00bbと同じ。valは上った後の数字 - respnse to update status. it's successeeded if fail=01. type is the same value as packet number 00bb. val is a value of increase. - 失敗例は見た事無いので謎。ステータスポイントが足りない状態で - 00bbを発行できるクライアントが有れば、fail=00になるのではないかと予想 - it's unknown when it's failed because i havent ever seen. i think it will be fail=00 when it's failed. -R 00bd <status point>.w <STR>.B <STRupP>.B <AGI>.B <AGIupP>.B <VIT>.B <VITupP>.B <INT>.B <INTupP>.B <DEX>.B <DEXupP>.B <LUK>.B <LUKupP>.B <ATK>.w <ATKbonus>.w <MATKmax>.w <MATKmin>.w <DEF>.w <DEFbonus>.w <MDEF>.w <MDEFbonus>.w <HIT>.w <FLEE>.w <FLEEbonus>.w <critical>.w ?.w - まとめてステータス情報を送るパケット - packet of information for various status. -R 00be <type>.w <val>.B - 必要ステータスポイント更新パケット。typeは0020〜0025が順にSTR〜LUKに対応 - packet to update required status point. type can be 0020-0025 for STR-LUK.( see packet number 00bb for detals.) -S 00bf <type>.B - エモーションを出す。typeは00-0c(,0d)がALT+1〜ALT+9,ALT+0,チョキ,グー,パー(,韓国旗)に対応 - display emotion. type can be 00-0c(,0d) for ALT+1-ALT+9,ALT+0,CTRL+-,CTRL++,CTRL+\(,korean flag). -R 00c0 <ID>.l <type>.B - IDの人がエモーションを出した。typeは00bfと同じ - emotion by ID. type is the same as 00bf. -S 00c1 - login人数問い合わせ - request to ask loged in people. -R 00c2 <val>.l - login人数応答 - response to asking loged in people. -R 00c3 <ID>.l <type>.B <val>.B - 見た目変更。typeは00で本体(転職時等)、02が武器、03が頭(下)、04が頭(上)、05が頭(中)、08が盾 - change looks. type=00 means body(by jobs), 02 is weapon, 03 is head(lower), 04 is head(upper), 05 is head(middle), 08 is shield. -R 00c4 <ID>.l - 話かけたNPCが商人だったのでbuy/sell選択窓出 - display "BUY" or "SELL" window by npc ID -R 00c5 <ID>.l <type>.B - buy/sell選択。type=00ならbuy。type=01ならsell - select "BUY" or "SELL". type=00 is buy, type=01 is sell. -R 00c6 <len>.w {<value>.l <DCvalue>.l <type>.B <item ID>.w}.11B* - NPCのお店buy選択時。DCvalueは商人DC後の値段 - list of marchandizes when clicked "BUY". DCvalue is a value of Discount Skill applied. -R 00c7 <len>.w {<index>.w <value>.l <OCvalue>.l}.10B* - NPCのお店sey選択時。OCvalueは商人OC後の値段 - list of items when clicked "SELL". OCvalue is a value of Over Charge Skill applied. -S 00c8 <len>.w {<amount>.w <item ID>.w}.4B* - NPCのお店から買う - buy item from npc shop. -S 00c9 <>.w {<index>.w <amount>.w}.4B* - NPCのお店に売る - sell item to npc shop. -R 00ca <type>.B - NPCから購入終了。type=00成功 - response for buying item. type=00 meanse successetion. -R 00cb <type>.B - NPCへ売却終了。type=00成功 - response for selling item. type=00 means success. -S 00cf <nick>.24B <type>.B - type=00 nickからの発言受け付け拒否 (/ex nick) - deny speech from nick(/ex nick). - type=01 nickからの発言受け付け許可 (/in nick) - allow speech from nick(/in nick) -S 00d0 <type>len.B - type=00 全ての発言受け付け拒否 (/exall) - deny all speech(/exall) - type=01 全ての発言受け付け許可 (/inall) - allow all speech(/inall) -R 00d1 <type>.B <fail>.B - fail=00 発言受け付け拒否成功 - success to deny speech - fail=01 発言受け付け拒否失敗 - fail to deny speech -R 00d2 <type>.B <fail>.B - fail=00 全発言受け付け拒否成功 - seccess to allow speech - fail=01 全発言受け付け拒否失敗 - fail to alloe speech -S 00d5 <len>.w <limit>.w <pub>.B <passwd>.8B <title>.?B - チャット立て。ここからチャット関係が続くけど調べが甘いので補完よろ - create chat room.(from now on, im not sure for packets about chat.) -R 00d6 <fail>.B - チャット立て応答 - response to create chat room. -R 00d7 <len>.w <owner ID>.l <chat ID>.l <limit>.w <users>.w <pub>.B <title>.?B - 画面内チャット情報 - information for chat room in the screen. -R 00d8 <chat ID>.l - チャット消去 - delete chat room. -S 00d9 <chat ID>.l <passwd>.8B - チャット参加要請 - request to join the chat. -R 00da <fail>.B - チャット参加失敗 - fail to join the chat. -R 00db <len>.w <chat ID>.l {<index>.l <nick>.24B}.28B* - チャット参加者リスト - list of people in the chat room. -R 00dc <users>.w <nick>.24B - チャットへの参加者追加(?) - add person to the chat room. -R 00dd <index>.w <nick>.24B <fail>.B - チャットから参加者抜け - leave the chat room. -S 00de <len>.w <limit>.w <pub>.B <passwd>.8B <title>.?B - チャットステータス変更 - change chat room status. -R 00df <len>.w <owner ID>.l <chat ID>.l <limit>.w <users>.w <pub>.B <title>.?B - チャットステータス変更成功 - success to change chat room status. -S 00e0 ?.l <nick>.24B - チャットルーム所有者変更要求? - request to change owner of the chat room? -R 00e1 <index>.l <nick>.24B - チャット参加者番号付け直し? - re-number people in the chat room? -S 00e2 <nick>.24B - チャットkick - kick nick from chat room. -S 00e3 - チャット抜け - leave chat room. -S 00e4 <ID>.l - 取り引き要求 - request trade. -R 00e5 <nick>.24B - 取り引き要請受け - recieve a request to trade. -S 00e6 <type>.B - type=03 取り引き要請ok - trade ok. - type=04 取り引き要請キャンセル - trade canceled. -R 00e7 <fail>.B - 取り引き要求応答 - response to requesting trade. - fail=00 距離が遠過ぎ - too far. - fail=03 要請受けてくれた - allowed the trade. - fail=04 キャンセルされた? - trade canceled? -S 00e8 <index>.w <amount>.l - アイテム追加。index=0でzeny追加。正規クライアントではzenyは00ebの直前のみ - add item. index=0 means adding zeny. for official client, zeny can be added only in packet number 00eb. -R 00e9 <amount>.l <type ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w - 相手方からのアイテム追加 - added item from other character. -R 00ea <index>.w <fail>.B - fail=00 アイテム追加成功 - success to add item. - fail=01 追加失敗。相手側重量オーバ - fail to add item. the player was over weighted. -S 00eb - アイテム追加完了(ok押し) - completed adding item.(cliecked OK) -R 00ec <fail>.B - fail=00 自分からのok受領 - recieved "OK" from myself - fail=01 相手からのok受領 - recieved "OK" from the other. -S 00ed - 取り引きキャンセル - trade canceled. -R 00ee - 取り引きがキャンセルされました - message of "trade canceled" -S 00ef - 取り引き許諾(trade押し) - trade OKed. (cliecked Trade) -R 00f0 - 取り引き完了 - trade completed. -R 00f2 <num>.w <limit>.w - カプラさん許容アイテム個数&現状 - number of item that capra can stock and number of item that capra stocks now. -S 00f3 <index>.w <amount>.l - カプラさん倉庫にアイテム放り込み - put item to capra's warehouse. -R 00f4 <index>.w <amount>.l <type ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w - カプラさん倉庫のアイテム追加 - add item to capra's warehouse. -S 00f5 <index>.w <amount>.l - カプラさん倉庫からアイテム取り出し - take out item from capra's warehouse. -R 00f6 <index>.w <amount>.l - カプラさん倉庫のアイテム削除 - delete item in the capra's warehouse. -S 00f7 - カプラさん倉庫閉じ - request to close capra's warehouse. -R 00f8 - カプラさん倉庫閉じ応答 - response to close capra's warehouse. -S 00f9 <party name>.24B - パーティ作成 - create party. -R 00fa <fail>.B - fail=00 作成成功 - success to create party. -R 00fb <len>.w <party name>.24B {<ID>.l <nick>.24B <map name>.16B <leader>.B <offline>.B}.46B* - パーティ情報まとめて送り - packet for various information about party. -S 00fc <ID>.l - パーティ勧誘する - invate player to the party. -R 00fd <nick>.24B <fail>.B - fail=00 相手は既にパーティに入っていた - the player is already in other party. - fail=01 相手に拒否された - invitaion was denied. - fail=02 勧誘成功 - success to invite, -R 00fe <ID>.l <party name>.24B - パーティに誘われた - invited to party. -S 00ff <ID>.l <fail>.l - パーティに誘われた時の返答。fail=1 ok返答? - response when player was invited to party. fail=1 means OK? -R 0100 - ? パーティ関連? - unknown. related to party? -S 0101 <exp>.w <item?>.w - パーティ設定変更 - change party setting. -R 0102 <exp>.w <item?>.w - パーティ設定現状? exp=2の場合は公平配分設定失敗? - party setting status. when exp=2, fail to set "equality for experience"? -R 0104 <ID>.l ?.l <X>.w <Y>.w <offline>.B <party name>.24B <nick>.24B <map name>.16B - パーティ1人分情報更新 - information about a one player in th party. -R 0105 <ID>.l <nick>.24B <fail>.B - nickさんがパーティから離脱 - nick leaves the party. -R 0106 <ID>,l <HP>.w <MaxHP>.w - パーティメンバHP更新 - update HP of party members. -R 0107 <ID>.l <X>.w <Y>.w - パーティメンバ位置更新 - update coordinates of party members. -S 0108 <len>.w <message>.?B - パーティ内発言 - send speech for party memebers. -R 0109 <len>.w <ID>.l <message>.?B - パーティ内発言受信 - receive speech for party memebers. -R 010a <type ID>.w - MVPアイテム取得 - get MVP item. -R 010b <exp>.l - MVP経験値取得 - get MVP experience. -R 010c <ID>.l - MVPキャラ表示 - display MVP character. -R 010e <skill ID>.w <lv>.w <sp>.w <range>.w <up>.B - スキル情報更新。spは未使用? - update skill sinformation. sp is unused? -R 010f <len>.w {<skill ID>.w <target type>.w ?.w <lv>.w <sp>.w <range>.w <skill name>.24B <up>.B}.37B* - スキル情報の塊。skill nameは一部流れて来ない物がある>AL_PNEUMA,PR_SLOWPOISON等 - bunch of information about skill. some of skill name is not send (AL_PNEUMA, PR_SLOWPOISON etc). - target typeは0-パッシブ、1-敵、2-場所、4-即時発動、16-味方 - target type is 0 for novice skill, 1 for enemy, 2 for place, 4 for immediate invoke, 16 for party member - lv=0 up=0の場合はリストに出してない? - it will not be on list when lv=0 up=0? -R 0110 <skill ID>.w <basic type>.w ?.w <fail>.B <type>.B - fail=00の時にスキル利用失敗? - fail to use skill when fail=00? - type 00:basic typeの方 01:SP不足 02:HP不足 03:memo無し 04:delay中 - type 00:basic type 01:lack of SP, 02:lack of HP, 03:no memo, 04:in delay - 05:お金無し(めまー) 06:武器がよろしくない 07:赤ジェム無し 08:青ジェム無し 09:謎 - 05:lack of money, 06:weapon does not satisfy, 07:no red jewel, 08:no blue jewel, 09:unkown - basic type 00:取り引き 01:emotion 02:座り 03:チャット 04:パーティ - basic type 00:trade 01:emotion 02:sit down, 03:chat, 04:party - 05:shout? 06:PK 07:マナーポイント - 05:shout? 06:PK, 07:manner point -R 0111 <skill ID>.w <target type>.w ?.w <lv>.w <sp>.w <range>.w <skill name>.24B <up>.B - 010fの1つ分。β2だと未使用? - just one skill information. not used in beta2? -S 0112 <skill ID>.w - スキルlvup要求 - request to skill level up. -S 0113 <level>.w <skill ID>.w <ID>.l - IDをターゲットにskillを使う - use skill to the target. -R 0114 <skill ID>.w <src ID>.l <dst ID>.l <server tick>.l <src speed>.l <dst speed>.l <param1>.w <param2>.w <param3>.w <type>.B - 攻撃系スキルエフェクト@ - skill effect for attack. - type=04 火壁で観測 type=06とほぼ同じ? - rtpe=04 observed when firewall was used. is that the almost same as type=06? - type=06 単発もの? param1はダメージ合計、param2はlevel、param3は1固定と予想 - type=06 skill for just one hit? param1 is total damage, param2 is level, param3 will always stay 1. - type=08 連打もの? param1はダメージ合計、param2はlevel、param3は分割数と予想 - type=08 skill for multiple hits? param1 is totak damage, param2 is level, param3 will be a number of hit. -R 0115 <skill ID>.w <src ID>.l <dst ID>.l <server tick>.l <src speed>.l <dst speed>.l <X>.w <Y>.w <param1>.w <param2>.w <param3>.w <type>.B - 弾き飛ばし有り攻撃系スキルエフェクト - blow up type skill effect. - type=05 ダメージ&弾き飛ばし。param1はダメージ合計、param2はlevel、param3は分割数と予想 - type=05 damage and blow up. param1 is total damage, param2 is level, param3 will be a number of hit. - type=06 爆心地? 少なくともparam1はゴミの模様 - type=06 a point of explorsion? param1 is unused at least. -S 0116 <level>.w <skill ID>.w <X>.w <Y>.w - (X,Y)をターゲットにskillを使う - use skill at (X,Y). -R 0117 <skill ID>.w <src ID>.l <val>.w <X>.w <Y>.w <server tick>.l - 場所相手のスキルエフェクト表示。valはレベルか、一部固さ?(氷壁) - display skill effect at (X,Y). is val level? or how hard it is (like ice wall)? -S 0118 - 攻撃キャンセル - cancel to attack -R 0119 <ID>.l <param1>.w <param2>.w <param3>.w ?.B - 見た目変更 - change looks. - param1=02 フロストダイバで凍り漬け? - param1=02 flozen diva? - param2=01 毒? - param2=01 poison? - param2=20 ANGELUS状態? - param2=20 ANGELUS? - param3=01 サイトかルワッチ? - param3-01 site or ruwatch? (i dont know skill names in english :() - param3=0b ハイディング状態? - param3=0b hiding? - param3=0b クローキング状態? - param3-0b cloking? - param3=0d カート付き - param3=0d with cart - param3=0e 鷹付き - param3-0e with hawk - param3=0f ペコペコ乗り - param3=0f with pekopeko - -R 011a <skill ID>.w <val>.w <dst ID>.l <src ID>.l <fail>.B - 非ダメージ系スキル表示。ヒールの場合valは回復量 - display no-damage skill effect. val is an amount of HP cured when it's heal. - fail=00の場合失敗ぽいが、スチール以外では見た事無し - fail=00 must mean fail, but i havent seend it except steal. -S 011b <skill ID>.w <map name>.16B - 011cへの応答。使わない場合"cancel"を送る - response to packet number 011c. send "cancel" for no-use. -R 011c <skill ID>.w <map1>.16B <map2>.16B <map3>.16B <map4>.16B - テレポ/ポタの場所選択。 - select place for teleport or portal warp. - テレポの場合、Random/セーブ場所、ポタの場合、セーブ場所/memo1/memo2/memo3となる - マップ名のみ送られる - in case of teleport, Ramdom/save point will be sent, - in case of portal warp, save point/memo1/memo2/memo3 will be sent. - only map name wil be sent. -S 011d - 現在居る所をメモ要求 - request to take a memo at this point. -R 011e <fail>.B - fail=00 メモ成功 - success to take memo. - fail=01 メモ失敗 - fail to take memo. -R 011f <dst ID>.l <src ID>.l <X>.w <Y>.w <type>.B <fail>.B - スキル効能地作成 - create ground effect for skills like firewall. - type 7e:SW 7f:火壁 80:ポタ発動中 81:ポタ発動前 83:サンク 85:フニューマ - type 7e:SW, 7f:firewall, 80:portal warp(invoking), 81:portal warp(before invoking), 83:sank, 85:funewma( i really don know skill names :() - 86:バーミリオン 8c:トーキーボックス発動時 8d:氷壁 8e:くあぐまいやー 91:あんくるすねあ - 86: bermillion, 8c:talky box(invoked), 8d:frost diva, 8e:kuagumire, 91:uncle snear - 93:らんどまいん 97:?? 99:トーキーボックス発動前 - 93:land mine, 97:??, 99:talky box(befor invoked) - 他情報求む -R 0120 <ID>.l - スキル効能地消去 - delete ground effect. -R 0121 <num>.w <num limit>.w <weight>.l <weight limit>l - カートの種類&重さの現在値&上限 - kind of cart, weight and max weight. -R 0122 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <equip type>.w <equip point>.w <attribute?>.B <refine>.B <card>.4w}.20B* - カート内アイテム。装備品 - equipments in cart. -R 0123 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B}.10B* - カート内アイテム。消耗品/収集品 - cunsumptive and collector items in cart. -R 0124 <index>.w <amount>.l <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w - カートにアイテム追加 - add item to cart. -R 0125 <index>.w <amount>.l - カートからアイテム削除 - delete item in cart. -S 0126 <index>.w <amount>.l - カートにアイテムを入れる - put item to cart. -S 0127 <index>.w <amount>.l - カートからアイテムを取り出す - take out item from cart. -S 0128 <index>.w <amount>.l - カプラさんからカートへアイテムを移す - move item from capra's warehouse to cart. -S 0129 <index>.w <amount>.l - カートからカプラさんへアイテムを移す - move item from cart to capra's warehouse. -R 012c <fail>.B - fail=00 重量制限を越えてカートにアイテムを入れられませんでした? - fail=00 over the weight and could not add item to cart. -R 012d <num>.w - 露店開設。アイテムリスト要求。numは置ける最大数 - create shop (marchant skill). request item list. num is a number of kind of item that can be sell. -S 012e - 露店閉鎖 - close shop. -S 012f <len>.w <message>.80B {<index>.w <amount>.w <value>.l}.8B* - 露店開設、露店名&アイテム,値段リスト - create shop, shop name, item, price list. -S 0130 <ID>.l - 露店アイテムリスト要求 - request item list for shop( not npc shop). -R 0131 <ID>.l <message>.80B - 露店看板表示 - display shop name tag. -R 0132 <ID>.l - 露店看板消去 - delete shop name tag. -R 0133 <len>.w <ID>.l {<value>.l <amount>.w <index>.w <type>.B <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w}.22B - 露店アイテムリスト - item list for shop(not npc shop). -S 0134 <len>.w <ID>.l {<amount>.w <index>.w}.4B* - 露店アイテム購入 - buy item from shop (not npc). -R 0135 <index>.w <amount>.w <fail>.B - 露店アイテム購入失敗。failは原因 - fail to buy item from non npc shop. fail tells you reasons. -R 0136 <len>.w <ID>.l {<value>.l <index>.w <amount>.w <type>.B <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w}.22B* - 露店開設成功 - success to create non-npc-shop. -R 0137 <index>.w <amount>.w - 露店アイテム販売報告 - report of selling item. -R 0139 <ID>.l <X>.w <Y>.w <X2>.w <Y2>.w <range>.w - IDの敵は(X,Y)に居て自分は(X2,Y2)に居るので攻撃が届きませんでした - the enemy at(X,Y) was too far to attack from my coordinate (X2,Y2). - 攻撃可能距離はrangeなので、近寄って下さい? - possible range to attack enemy is "range", so be closer? -R 013a <val>.w - 攻撃射程 - attack range. -R 013b <type>.w - 各種メッセージ表示。3=矢が装備できました - various message. 3="arrow has been equiped" -R 013c <ID>.w - 装備された矢のItemID。0で、未装備状態。 - item id of equiped arrow. 0 means no arrow is equiped. -R 013d <type>.w <val>.w - HP回復スキル/SP回復スキルによる回復 - recovery of HP/SP by HP/SP recovery skill. - type=5ならHP type=7ならSP - type=5 is HP, type=7 is SP. -R 013c <index>.w - 装備している矢 - id of equiped arrow. - -R 013e <src ID>.l <dst ID>.l <X>.w <Y>.w <lv?>.w ?.w <wait>.l - スキル詠唱中。PC/NPCが相手の場合は(X,Y)は0。場所がターゲットの場合はdst IDは0になる - skill has been casting. (X,Y) will be 0 when target is player character or NPC. dst ID will be 0 when target is place. - - 0x013e の offset+16(dword) はスキル属性です(調査済)。 - offset+16(dword) in packet number 0x013e is skill attribute. - - 00:無 01:水 02:地 03:火 04:風 05:毒 06:聖 07:暗 08:念 09:死 - 00:none, 01:water, 02:ground, 03:fire, 04:wind, 05:poinson, 06:holly, 07:dark, 08:spirit(i don know how to translate.), 09:death - 将来的に、詠唱中のエフェクトが属性で変わるのかと。 - casting effect might differ by skill attribute in the future. - - waitはms単位かな? - wait in mili second? -R 0141 <type>.l <base>.l <bonus>.l - ステータス情報。typeは0dから12が順にSTR,AGI,VIT,INT,DEX,LUKに対応 - information for status. type is 0d-12 for STR,AGI,VIT,INT,DEX,LUK. - base+bonusと表示される - base+bonus will be displayed. -R 0144 <ID>.l <type>.l <X>.l <Y>.l <point ID>.B <color>.3B ?.B - 案内員用、マップ上アイコン表示パケット - for guid npc, packet for display icon on map. - type=1 アイコンを表示 - display icon. - type=2 アイコンを消去 - delete icon. -R 0145 <file name>.16B <type>.B - (今の所)カプラさんcutin表示 - display capra picture(at this time). - type=02 表示 - display. - type=ff 消去 - delete. -S 0146 <ID>.l - IDのNPCとの会話。CLOSEボタンを押した。ack無しにNPCメッセージウィンドを同時に閉じる - talk to npc with ID. Clicked CLOSE button. -R 0147 <skill ID>.w <target type>.w ?.w <lv>.w <sp>.w <range>.w <skill name>.24B <up>.B - アイテム利用の結果一時的に得られたスキル情報 - effect for skill by using item. -S 0148 <ID>.l - リザレクションの相手決め? @ β1 - decide target of a skill rezarection? in beta1. -S 0149 <ID>.l <type>.B - IDにマナーポイントを与える。type=00 プラス type=01 マイナス - give manner point to ID. type=00 is plus, type=01 is minus. -R 014a <fail>.l - マナーポイントを与えた結果。fail=0 成功 fail=1 失敗 - result of giving manner point. fail=0 is success, fail=1 is fail. -R 014b <type>.B <nick>.24B - マナーポイントを貰った。type=00 プラス type=01 マイナス - get manner point. type=00 is plus, type-01 is minus. -R 014C <len>.w (<type>.l <guildID>.l <guild name>.24B).* - 同盟・敵対ギルド表示 - display alliance and opposition guild. - type=0 同盟 - alliance. - type=1 敵対 - opposition. -S 014D - ギルド情報表示開始? - start of guild information? -R 014E <type?>.l - type=0x57 一般ギルド団員 - normal guild member. - type=0xD7 ギルドマスター - guild master. -S 014F <page>.l - ギルド表示タブ送信 - send packet for guild "DISPLAY" tab. -R 0150 <guildID>.l <guildLv>.l <connum>.l <定員>.l <Avl.lvl>.l ?.l <next_exp>.l ?.16B <guild name>.24B <guild master>.24B ?.16B - ギルド情報 - guild info. -S 0151 <guild ID>.l - エンブレム要求 - request for guild emblem. -R 0152 <len>.w <guild ID>.l <emblem ID?>.l <emblem data>.?B - エンブレムイメージ送付 - return emblem image. -R 0154 <len>.w {<accID>.l <charactorID>.l <髪型>.w <髪の色>.w <性別?>.w <job>.w <lvl?>.w <上納経験値>.l <online>.l <Position>.l ?.50B <nick>.24B}* - ギルドメンバリスト? - guild member list? -S 0159 <guildID>.l <accID>.l <charID>.l <mess>.40B - ギルド脱退送信 - send packet for leaving guild. -R 015A <nic>.24B <mess>.40B - ギルド脱退(全員)受信 - receive packet for leaving guild(all members). -S 015B <guildID>.l <accID>.l <charID>.l <mess>.40B - ギルド追放送信 - send packet for kicking member out of the guild. -R 015C <nick>.24B <mess>.40B <アカウントID>.24B - ギルド追放(全員)受信 - receive packet for kicking member out of the guild.(all member) -R 0163 <len>.w <nick>.24B <accountID>.24B <kicking reason>.40B - -S 0165 <myaccID>.l <guild name>.24B - ギルド作成 - create guild -R 0166 <len>.w ?.28B* - 役職名リスト? - list for roll of members? -R 0167 <type>.b - ギルド作成合否 - response to vreating guild. - type = 0 ギルド作成成功 - success. - type = 2 同名のギルドがある - there is a guild with the same name. -S 0168 <TargetAccID>.l <sourceAccID>.l <myCharactorID>.l - ギルド勧誘 - invite to the guild. -R 0169 <type>.B - ギルド勧誘拒否された - invitation denied. -R 016A <guild ID>.l <guild name>.24B - ギルド勧誘された - invited to the guild. -S 016B <guild ID>.l <type>.l - ギルド勧誘返信 - response to invitaion for joining to guild. - type=0 拒否する - deny. - type=1 許諾する - OK. -R 016c <guild ID>.l ?.13B <guild name>.24B - login時ギルド情報 - guild information when loged in. -R 016d <ID>.l <charactor ID>.l <online>.l - ギルドメンバがloginした抜けた等 - information about guild member loged in or loged out etc. -R 016f <message>.180B - ギルドお題目? - guild message? -S 016E <guildID>.l <mess1>.60B <mess2>.120B - ギルド告知設定 - set guild announcement. -R 016F <mess1>.60B <mess2>.120B - ギルド告知 - guild announcement. -S 0170 <TargetAccID>.l <sourceAccID>.l <myCharactorID>.l - 同盟要請勧誘 - invite the guild to be alliance. -R 0171 <SorceAccID>.l <guild name>.24B - 同盟要請勧誘された - invited to be a alliance. -S 0172 <SorceAccID>.l <type>.l - 同盟要請返信 - response for invitiation to be alliance. - type=0 拒否する - deny. - type=1 許諾する - OK. -R 0173 <type>.B - type = 0 すでに同盟関係 - the guild is already alliance. - type = 1 同盟拒否された - denied to be alliance. - type = 2 同盟成功 - success to invite to be alliance. -R 0177 <len>.w <index>.w* - 鑑定可能アイテムリスト - list of items that need to be judge( i mean unkown items.) -S 0178 <index>.w - アイテム鑑定 - judge item. -R 0179 <index>.w <fail>.B - アイテム鑑定結果。fail=00で成功。fail=01ってあるのか? - response to judging item. fail=00 is success. is there fail=01? -S 017A <index>.w - カードWクリック - card is double clicked. -R 017B <len>.w {<index>.w}* - カード挿入できるアイテムIndex番号 - item index number for items that can be inserted card. -S 017C <SrcIndex>.w <DescIndex>.w - Src をDescに突っ込む - insert Src to Desc. -R 017D <DescIndex>.w <SrcIndex>.w <fail>.b - Src をDescに突っ込み<fail> 0=成功 1=失敗? - response to insert Src to Desc. fail=0 is success, fail=01 is fail? -S 017e <len>.w <message>.?B - ギルド内メッセージ発言 - send speach for guild members. -R 017f <len>.w <message>.?B - ギルド内メッセージ受信 - receive guild message. -R 0182 <accID>.l <charactorID>.l <hair type>.w <hair color>.w <sex?>.w <job>.w <lvl?>.w <experience?>.l <online>.l <Position>.l ?.50B <nick>.24B - -R 0187 <account ID>.l - alive信号? - alive signal? -R 0188 <fail?>.w <index>.w <val>.w - 武器精錬。結果+val武器に - weapon refiling. result+val to weapon -R 0189 ?.w - 謎。テレポ失敗? - unknown. fail to teleport? -S 018a ?.w - ゲーム終了 - game quited. -R 018b <fail>.w - ゲーム終了/キャラセレ応答。fail=0成功。fail=1失敗? - game quited/character select sever response. fail=0 is success, fail=1 is fail? -R 018C <MonsID>.w <class>.w <size>.w <HP>.w <?>.w <deffence>.w <kind of monster>.w <magic deffence>.w <attribute>.w <anti-attribute?>.9b - wizの敵のセンス結果 - response to sense skill by wizard. - 0 小型 - small - 1 中型 - middle - 2 大型 - big -R 0191 <ID>.l <message>.80B - トーキーボックスのメッセージ - message of talky box. -S 0193 <ID>.l - ギルドメンバ名前引き? - name search for guild member? -R 0194 <ID>.l <nick>.24B - ギルドメンバ名前引き応答? - response to name search for guild member? -R 0195 <ID>.l <nick>.24B <party name>.24B <guild name>.24B <class name>.24B - ギルド所属PCの場合の0094返答 - response to packet number 0094 that if the player joined guild. -R 0196 <type>.w <ID>.l - 増強系スキル使用時のメッセージ色々。IDはtargetと思われるが自分相手のみしか来ない? - various message of skill that effect status. ID must be target, but only m ID and other's ID are sent? - type=00 2HQ付与「攻撃速度が増加しました。」 - 2HQ casted. "attack speed insreased." - type=01 2HQ解除「攻撃速度が減少しました。」 - 2HQ ended. "attack speed decreased." - type=02 IMPOSITIO付与「武器の攻撃力が増加しました。」 - IMPOSITIO casted. "power of the weapon increased." - type=03 IMPOSITIO解除「武器の攻撃力が減少しました。」 - IMPOSITIO ened. "power of the weapon decreased." - type=04 「スキル使用ディレイが減少しました。」 - "casting delay become short" - type=05 「スキル使用ディレイが元に戻りました。」 - "casting delay return to defailt" - type=06 「武器に毒属性が付与されました。」 - "attribute of poison is given to the weapon" - type=07 ASPERSIO付与「武器に聖属性が付与されました。」 - ASPERSIO casted. "attribute of holly is given to the weapon" - type=08 ASPERSIO解除「武器の属性が元に戻りました。」 - ASPERSIO ended. "attribute of weapon return to default" - type=09 「防具に聖属性が付与されました。」 - "armor got holly attribute" - type=0a 「防具の属性が元に戻りました。」 - "armor's attribute return to default" - type=0b KYRIE付与「バリア状態になりました。」 - KYRIE casted. "barrier" - type=0c KYRIE解除「バリア状態が解除されました。」 - KYRIE ended. "barrier end" - type=0d 「ウェポンパーフェクションモードになりました。」 - "became weapon ferfection mode" - type=0e 「ウェポンパーフェクションモードが解除されました。」 - "end weapon perfection mode" - type=0f 「オーバートラストモードになりました。」 - "became over trust mode" - type=10 「オーバートラストモードが解除されました。」 - "end over trust mode" - type=11 「マキシマイズパワーモードになりました。」 - "became maximize power mode" - type=12 「マキシマイズパワーモードが解除されました。」 - "end maximize power mode" -S 0197 <type>.w - type=0 /resetstate - type=1 /resetskill - 効能は無し? - no effect? -R 019b <ID>.l <type>.l - 他人のlvupや武器精錬等の表示? - display other's level up effect or weapon refiling? - type=0 base lvup? - type=1 job lvup? - type=3 武器精錬 - weapon refiling -R 0199 <type>.w - type=1 pvpモード開始? - start pvp mode? -R 019a <ID>.l <rank>.l <num>.l - pvp順位 rank/num - pvp rank rank/num -R 019b <ID>.l <type>.l - 他人のlvupや武器精錬等の表示? - type=0 base lvup? - type=1 job lvup? - type=2 武器精錬失敗 - type=3 武器精錬成功 - -R 019d <?>.4B - GMコマンド/hide - -S 00CC <ID>.l - GM用右クリックメニュー「(name)使用者強制終了」使用 - use special right click menu for GM "(name) force to quit" - -S 0149 <ID>.l <type>.B <time>.w - GM用右クリックメニュー「チャット禁止時間を下げる(解ける)」使用 → type=00 - use special right click menu for GM "decrease prohibited time to create chat room". type=00 - GM用右クリックメニュー「チャット禁止時間を上げる(掛ける)」使用 → type=01 - use special right click menu for GM "increase prohibited time to create chat room". type=01 - timeは分単位です(確か - unit is minute (maybe - -R 019e - 捕獲モンスター決め -S 019f <ID>.l - 捕獲モンスター指定 -R 01a0 <fail>.B - 捕獲判定 - fail=01で成功、00で失敗 -S 01a1 <param>.1B - <param> - 0x00:ペット状態表示 - 0x01:餌を与える - 0x02:パフォーマンス - 0x03:卵に戻す - 0x04:アクセサリ解除 -R 01a2 <pet name>.24B <name flag>.B <lv>.w <hungry>.w <friendly>.w <accessory>.w - ペットの状態 - name flag:00=名前未設定 01=名前設定済み(変更不可) - lv=ペットのレベル、hungry=満腹度(0~100)、friendly=親密度(初期値250?)、accessory=アクセサリのItemID -R 01a3 <fail>.B <itemID>.w - <fail> - 0x00:餌やり失敗 - 0x01:餌やり成功 -R 01a4 <type>.B <ID>.l <val>.l - ペット関連通知 - type=00,val=00 ペット孵化時に送られてくる。ペット認識用? - type=01 親密度変化 - type=02 満腹度変化 - type=03 アクセサリ変化(0で未装備) - type=04 パフォーマンス 確認されたval=1~3 - (4はスペシャルパフォーマンス?) - type=05 ?確認されたval=0x14 -S 01a5 <pet name>.24B - ペットの名前決め -R 01a6 <len>.w <index>.w* - ペットの卵リスト -S 01a7 <index>.w - ペットの卵リストが選択された -S 01a9 <emotion>.l - ペットエモーション送信 -R 01aa <ID>.l <emotion>.l - ペットエモーション受信 - <emotion> - 33以下のとき:エモーション - 34以上のとき:発言テーブル? -R 01ac <object id>.l - アンクルの発動(≠設置)時のみ毎回出現(機能は謎) -R 01ad <len>.l <item>.w - 矢作りの作成可能ITEM表受信 -S 01ae <itemID>.w - 矢作りで使う材料送信 -S 01af <type>.w - チェンジカート(カート選択) - type=1 ノーマルカート -R 01b0 <monster id>.l <?>.b <new monster code>.l - 油のクラスチェンジ - <new monster code>はチェンジ後のコード(1001〜)をdwordで -S 01b2 <len>.w <message>.80B <flag>.B {<index>.w <amount>.w <value>.l}.8B* - 露店開設 - flag : 0=キャンセル , 1=オープン -R 01b3 <filename>.64B <type>.B - R 0145の上位互換 -R 01B6 <guildID>.l <guildLv>.l <connum>.l <定員>.l <Avl.lvl>.l <now_exp>.l <next_exp>.l <上納ポイント>.l <性向F-V>.l <性向R-W>.l <members>.l <guild name>.24B <guild master>.24B <agit?>.20B - ギルド情報 -R 01b9 <ID>.I - 被ダメ等によるIDの詠唱中断 -R 01c4 <index>.w <amount>.l <itemID>.w <item data>.12B - カプラ倉庫アイテム -R 01c8 <index>.w <item ID>.w <ID>.l <amount left>.w <type>.B - アイテム使用応答。(00a8の上位バーション?) - type=00の場合使用失敗? amountもゴミの模様 - type=01の場合成功で、amountは使用後の残り個数 -R 01c9 <dst ID>.l <src ID>.l <X>.w <Y>.w <type>.B <fail>.B ?.81b - スキル効能地作成(011fの上位バーション?) - type 0x7e:SW、0x7f:火壁、0x80 ポタ開き中、0x81 ポタ開き直前 - 0x82 聖体、0x83 サンク、0x84 マグヌス、0x85 ニューマ - 0x86 0x86 大魔法(SG/MS/LoV/GX)、0x87 ファイヤーピラ待機 - 0x88 ファイヤーピラ爆発、0x87〜0x8B 表示無し、 - 0x8c トーキーボックス(発動中)、0x8D アイスウォール - 0x8E クワグマイア、0x8f ブラストマイン、0x90 スキッド - 0x91 アンクル、0x92 ベノムダスト、0x93 ランドマイン - 0x94 ショックウェーブトラップ、0x95 サンドマン - 0x96 フラッシャー、0x97 フリージングトラップ - 0x98 クレイモアートラップ、0x99 トーキーボックス - 0x9A ボルケーノ、0x9B デリュージ、0x9C バイオレントゲイル - 0x9D ランドプロテクター、0x9E Zenyマーク、0x9F Zeny袋 - 0xA0 回る緑の輪、0xA1 ピンクの音符 (二連符有り - 0xA2 真ん中に点のある光の玉、0xA3 ピンクのスプリング - 0xA4 深淵の中に、0xA5 回る青い輪、0xA6 不協和音 - 0xA7 口笛、0xA8 夕陽のアサシンクロス、0xA9 ブラギの詩 - 0xAA イドゥンの林檎、0xAB 自分勝手なダンス、0xAC ハミング - 0xAD 私を忘れないで…、0xAE サービスフォーユー - 0xAF ピンクのスプリング、0xB0 表示無し - 0xB0 グラフィティ, - 0xB1 デモンストレーション、0xB2〜0xBF 表示無し - 0xB2 ピンクのワープポータル風 - 0xB3 小さな十字架がふよふよ - 0xB4 バジリカ、0xB5 エフェクトなし? - 0xB6 黒い×が立体的に浮かび上がる - 0xB7 クモの巣、0xB8〜 エフェクトなし? - - 他情報求む - ?.81bは謎。 -R 01cd (<sid>.l)x7 - オートスペル選択肢受信 - <sid>x7 には NB,CB,FB,LB,SS,FBL,FD の順でスキルコードがdwordで入る - まだ選択できないスキルの部分は <sid> = 0x00000000 が入る -S 01ce <sid>.l - オートスペル選択肢送信 -R 01cf <crusader id>.l <target id>.l <?>.18b - 献身状態ターゲットON/OFF。献身が切れると <target id> が 0x00000000 になる - -R 01d0 <ID>.l <num>.w - <num> : 気功の数(非Lv) -R 01d1 <monk id>.l <target monster id>.l <bool>.l - 白羽取り状態ON/OFF。<bool> は白刃取り成立時に 0x00000001 解除時に 0x00000000 が来る -R 01d2 <id>.l <delay>.l - モンクのコンボディレイ(msec) - 三段・連打は基本ディレイ1000(+300)、猛龍は基本ディレイ700(+300) -R 01d4 <ID>.l - 文字列入力窓表示(IDはNPCのIDが入る) -S 01d5 <len>.w <ID>.l <input>.?B 00 - 文字列入力内容送信(IDはNPCのIDが入る) -R 01d7 <ID>.l <equip point>.b <item id1>.w <item id2>.w - 装備グラフィック <equip point> は 02手と09足のみ確認。id2は左手 -R 01d8 <ID>.l <speed>.w <opt1>.w <opt2>.w <option>.w <class>.w <hair>.w <item id1>.w <item id2>.w <head option bottom>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.l <emblem>.l <manner>.w <karma>.B <sex>.B <X_Y_dir>.3B ?.B ?.B <sit>.B <Lv>.B ?.B - マップロード時&移動時用、向き付き用キャラ情報?(0078の上位バージョン) -R 01d9 <ID>.l <speed>.w <opt1>.w <opt2>.w <option>.w <class>.w <hair>.w <item id1>.w <item id2>.w.<head option bottom>.w <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.l <emblem>.l <manner>.w <karma>.B <sex>.B <X_Y_dir>.3B ?.B ?.B <Lv>.B ?.B - テレポ等の表示範囲内沸きキャラ用、向き付き無しキャラ情報?(0079の上位バージョン) -R 01da <ID>.l <speed>.w <opt1>.w <opt2>.w <option>.w <class>.w <hair>.<item id1>.w <item id2>.w <head option bottom>.w <server tick>.l <head option top>.w <head option mid>.w <hair color>.w ?.w <head dir>.w <guild>.l <emblem>.l <manner>.w <karma>.B <sex>.B <X_Y_X_Y>.5B ?.B ?.B ?.B <Lv>.B ?.B - 表示範囲内キャラ移動情報(007bの上位バージョン) -S 01db - 暗号化key要求 -R 01dc <len>.w <key>.?B - 暗号化key送付 -S 01dd <version>.l <account name>.24B <md5 binary>.16B <version2>.1B - id&暗号化済みpass送信 - 順にクライアントが01dbを送る、 - 鯖が01dcでkeyを返す、 - クライアントが"<key><password>"についてmd5計算し - <md5 binary>の所を埋めて01ddを送る。 - <passwordencrypt2>の時は - "<key><password>"に対してmd5計算としている所を - "<password><key>"と変更する -R 01de <skill ID>.w <src ID>.l <dst ID>.l <server tick>.l <src speed>.l <dst speed>.l <param1>.l <param2>.w <param3>.w <type>.B - 攻撃系スキルエフェクト@(0114の上位バーション?) - type=04 火壁で観測 type=06とほぼ同じ? - type=05 NB/FBlの分散したダメージ用? - type=06 単発もの? param1はダメージ合計、param2はlevel、param3は1固定と予想 - type=07 ダメージ表示無し? - type=08 連打もの? param1はダメージ合計、param2はlevel、param3は分割数と予想 - type=09 ダメージモーションなしにダメージだけ表示される物(インデュア)と思ったのだがダメージモーションが出る物。(機能は謎) -S 01df <ID>.| - GM右クリックによるIDのチャット禁止回数参照? -R 01e1 <ID>.l <num>.w - <num> : 気功の数(非Lv) 一度表示したら後どんなnumが来ても無視される。 -R 01e6 <partner name>.24B - 結婚スキルあなたに逢いたい使用時の叫び声 -S 01e7 - スパノビで/doridoriしたら飛んでくる。SPR回復量2倍フラグを立てるパケット -S 01e8 <party name>.24B <item1>B <item2>B - <item1>アイテム収集方法。0で個人別、1でパーティ公有 - <item2>アイテム分配方法。0で個人別、1でパーティに均等分配 - (00f9の上位バーション) -R 01ea <ID>.l - 結婚エフェクト(音楽、紙吹雪) - IDは新婦のものが入る? -S 01ed - スパノビが爆裂波動になるフラグを立てるパケット -R 01ee <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B <card>.4w}.18B* - 所有消耗品&収集品リスト - 矢の場合は?.2Bが0x8000になる - 00a3から変更 -R 01ef <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B <card>.4w}.18B* - カート内アイテム。消耗品/収集品 - 0123から変更 -R 01f0 <len>.w {<index>.w <item ID>.w <type>.B <identify flag>.B <amount>.w ?.2B <card>.4w}.18B* - カプラさんに預けてある消耗品&収集品リスト - 00a5から変更 -R 01f4 <name>.24B <trade id?>.L <LV>.w - 先方から取引要請 - 00e5から変更 -R 01f5 <result>.B <trade id?>.L <LV>.w - こちらからの取引要請に対する反応 - 00e7から変更 -S 0200 <login name>.24B - ragexeに/accountオプションをつけて起動するとログイン要求に付加されるパケット -R 0201 ?.1B<Flag?>.1B (?.8B <Character Name>.24B)x20 - Flag seems to need to be 1 to function. - 8 unknown bytes and 24 bytes for name need to be repeated for each friend. -S 0202 <Character name>.24B - Character name to add to friend list (for server-side friend list enabled clients) -S 0204 <?>.16B - ログイン要求に付加されるパケット。16バイトは固定? -S 020B <?>.17B - キャラクタサーバ接続要求0065に付加されるパケット。1+0204の16バイトで17バイト? -S 020C <account id>.L, <ip address>.L - IP address in network byte order for a player account in response to a charname request [MadCamel] - -パケット長の追加。019e〜01aaが増えてるので、0190〜を切り抜き -added packet lenth. 019e-01aa is a new, so here is a packet length table from 0190. - - 90, 86, 24, 6, 30,102, 8, 4, 8, 4, 14, 10, -1, 6, 2, 6, - 3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10 diff --git a/doc/readme.html b/doc/readme.html deleted file mode 100644 index 3f87c20..0000000 --- a/doc/readme.html +++ /dev/null @@ -1,163 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> -<head> - <title>eAthena 1.0 RC5 Readme</title> - <meta http-equiv="expires" content="-1"> - <meta http-equiv="pragma" content="no-cache"> - <meta name="author" content="eAthena Development Team"> - <meta name="description" content="eAthena, ro server emulator"> - <meta name="keywords" - content="eathena, ro, ragnarok online, server emulator, server software"> - <link href="./readme/rc5.css" media="screen" rel="stylesheet" - type="text/css"> -</head> -<body> -<table class="wrapper"> - <tbody> - <tr class="topbanner"> - <td class="topnav"><b><a href="./readme.html">Intro</a></b></td> - <td class="topnav"><b><a href="./readme/changelog.html">Changelog</a></b></td> - <td class="topnav"><b><a href="./readme/features.html">Features</a></b></td> - <td class="topnav"><b><a href="./readme/Npcfeatures.html">Npc Features</a></b></td> - <td class="topnav"><b><a href="./readme/settingup.html">Setting Up</a></b></td> - <td class="topnav"><b><a href="./readme/gmcommands.html">GM Commands</a></b></td> - <td class="topnav"><b><a href="./readme/faq.html">FAQ</a></b></td> - <td class="topnav"><b><a href="./readme/support.html"> Support</a></b></td> - </tr> - <tr> - <td class="banner" colspan="8"> - <div align="right"><img src="./readme/midbanner.jpg" border="0"></div> - </td> - </tr> - <tr> - <td class="omgspacer"><br> - </td> - </tr> - <tr> - <td colspan="8" align="center"> - <table class="content"> - <tbody> - <tr> - <td class="contenttitle"><b>Thank you for downloading -eAthena 1.0.0 RC5</b></td> - </tr> - <tr> - <td class="contentbg">eAthena is an emulator for Ragnarok -Online servers. -It's written in C, and is -cross-platform. The officially supported platforms are Win32 and Linux. - <p>We hope you enjoy using it!</p> - <p>eAthena is licensed under the GPL, meaning it's open -source :) There -is no public CVS provided, however.</p> - </td> - </tr> - </tbody> - </table> - </td> - </tr> - <tr> - <td class="omgspacer"><br> - </td> - </tr> - <tr> - <td colspan="8" align="center"> - <table class="content"> - <tbody> - <tr> - <td class="contenttitle"><b>The eAthena Development Team</b></td> - </tr> - <tr> - <td class="contentbg">eAthena is based on the original -Athena, by the -Japanese Development Team.<br> -A big thanks to them for working hard on Athena.<br> - <br> -Valaris<br> -Mugendai<br> -fritz<br> -Wizputer<br> -Evera<br> -Nana<br> -Shinigami<br> -Darkchild<br> -Lupus<br> -moonsoul<br> -MouseJstr<br> -kobra_k88<br> -Codemaster<br> -Davidsiaw<br> -Mass Zero<br> -MC_Cameri<br> -Spira<br> -Lord<br> - <p></p> - </td> - </tr> - </tbody> - </table> - </td> - </tr> - <tr> - <td class="omgspacer"><br> - </td> - </tr> - <tr> - <td colspan="8" align="center"> - <table class="content"> - <tbody> - <tr> - <td class="contenttitle"><b>Special Thanks</b></td> - </tr> - <tr> - <td class="contentbg">The eAthena development team would -like to specially -thank:<br> - <br> -The Japanese Development Team. A big thanks to them for -working hard on Athena which eAthena is based on.<br> - <br> -RoVeRT, our ex-developer. eAthena wouldn't have this many -features without him!<br> - <br> -sara-chan, who had also contributed alot to the development -of eAthena! Thanks!<br> - <br> -AppleGirl, who lead the team and contributed alot of work.<br> - <br> -yor, for his work he did on login and char servers, not to mention -ladmin.<br> - <br> -Gravity, for making Ragnarok Online. eAthena wouldn't even -exist if it wasn't for them!<br> - <br> -ASB for hosting our forum section :)<br> - <br> -DeltaAnime for hosting our official forums among other things :)<br> - <br> -Ketonom for putting together a nice Win32 installer for the noobs and -converting mob and item databases to sql.<br> - <br> - <br> - <br> - <br> - <br> -And others who gave continuously endless support to eAthena!<br> - </td> - </tr> - </tbody> - </table> - </td> - </tr> - <tr> - <td class="spaceromg"><br> - </td> - </tr> - <tr> - <td class="copyright" colspan="8">© Copyright 2004 eAthena -Development Team<br>Design © Copyright 2004 Evera</td> - </tr> - </tbody> -</table> -</body> -</html> diff --git a/doc/readme.txt b/doc/readme.txt deleted file mode 100644 index 797d338..0000000 --- a/doc/readme.txt +++ /dev/null @@ -1,122 +0,0 @@ -*************************** NOTICE *************************** -************************************************************** - -This program is free to use for any non-commercial private RO -server running an Athena based server, and is povided as-is. -The author of this program is only responsible for errors -that occur only to this program while it is in operation, -provided the program has not been modified in any way. If you -come across any errors or would like to leave comments and/or -suggestions about this program, please feel free to notify the -author of this program at spamrat42@gmail.com. - -Please make sure to create a backup of your current database -files and your data folder prior to using this program. - -============================================================== - -This package contains the following files... - -ADE.ini -Athena Database Editor.exe -history.txt -ID Helper.txt -readme.txt - -sample data (empty folder) - -sample db (folder) - card_labels.txt - item_descriptions.txt - -sample mobs (empty folder) - -============================================================== -= NOTE: All packages from 1.4.1 and newer will not include the -= files from the latest eAthena server distribution. So -= make sure to copy your current files from your server -= into the appropriate folders listed above, or set the -= correct paths in the ADE.ini file. -============================================================== - -Thank you for downloading this tool I wrote for the eAthena -817 Text based server, but it should work even with the more -recent versions like eAthena 1.0 RC5. I hope you find this -tool to be useful. - -The files in the db folder that come with this program are -custom files that are to be used with ADE. To change the -directory that this program looks in when opening or saving -files, open the ADE.ini file and enter the full or relative -path. The ADE.ini when first installed will already be -pointing to the relative folders listed above. You can also -simply copy your current db files to those folders, allowing -you to edit them without editing the db files you're -currently using. - -All entries that have been commented out will not be read, -and won't be carried over into the new DB files. So please -make sure to back them up before using this program for the -first time. I will eventually add support for handling -commented lines in future versions. - -One of the main features of this program will let you create -updated files for the client's data folder as well as update -the other relative db files for the server. When using this -feature, the following files will be created... - -DB Folder - Server Files -================================ -class_equip_db.txt -item_value_db.txt - -Data Folder - Client Files -================================ -cardpostfixnametable.txt -cardprefixnametable.txt -idnum2itemdesctable.txt -idnum2itemdisplaynametable.txt -itemslotcounttable.txt -num2itemdesctable.txt -num2itemdisplaynametable.txt - -Note: There is a checkbox that will say to click it if the - descriptions are garbled. Please only check after - trying the default description files it produces. - -If there are any files you think that were left out -that should have been updated as well for the client's -data folder, please let me know at the email address -provided above. - -The item_descriptions.txt file is where all of the -descriptions are stored. Please note if you're manually -changing something in it, that you should the サ character -for a new line. (Use ALT + 175 to type it.) It should -currently have the majority of the basic descriptions. -You won't need to add how much defense or the attack -power of equipment, as it will automatically be added -when the files are created. (It gets the values directly -from the item db files.) - -The card_labels.txt file is where all the card labels are -stored. If you already have a custom set of card labels, -just copy the cardprefixnametable.txt file from your data -folder into the db folder and rename it to card_labels.txt. -Any missing labels will or blank labels will result in the -default label of "Carded" as a prefix. - -I will eventually try to update this program to try -including other db files as well as to help make sure -it works with all versions of the eAthena text based -server from 817 to the current version. I'll also try -to add more support for other files that are also needed -to be generated for the client's data folder. - -============================================================== -= NOTE 2: The item_descriptions.txt file that comes with this -= package has incorrect and blank entries. Please make -= sure to go over all the descriptions if you plan on -= using it to generate description files for your -= server's data folder. -============================================================== diff --git a/doc/readme/changelog.html b/doc/readme/changelog.html deleted file mode 100644 index 4cae56a..0000000 --- a/doc/readme/changelog.html +++ /dev/null @@ -1,115 +0,0 @@ -<html> -<head><title>eAthena 1.0 RC5 Readme</title> -<meta http-equiv="expires" content="-1" /> -<meta http-equiv="pragma" content="no-cache" /> -<meta name="author" content="eAthena Development Team" / -<meta name="description" content="eAthena, ro server emulator" /> -<meta name="keywords" content="eathena, ro, ragnarok online, server emulator, server software" /> -<link href="./rc5.css" media="screen" rel="stylesheet" type="text/css"> -</head> -<body> -<table class="wrapper"> - <tr class="topbanner"> - <td class="topnav"><b><a href="../readme.html">Intro</a></b></td> - <td class="topnav"><b><a href="./changelog.html">Changelog</a></b></td> - <td class="topnav"><b><a href="./features.html">Features</a></b></td> - <td class="topnav"><b><a href="./Npcfeatures.html">Npc Features</a></b></td> - <td class="topnav"><b><a href="./settingup.html">Setting Up</a></b></td> - <td class="topnav"><b><a href="./gmcommands.html">GM Commands</a></b></td> - <td class="topnav"><b><a href="./faq.html">FAQ</a></b></td> - <td class="topnav"><b><a href="./support.html"> Support</a></b></td> - </tr> - <tr> - <td class="banner" colspan="8"> - <div align="right"><img src="./midbanner.jpg" border="0"></div> - </td> - </tr> - <tr> - <td class="omgspacer"></td> - </tr> - <tr> - <td align="middle" colspan="8"> - <table class="content"> - <tr> - <td class="contenttitle"><b>eAthena Changelog</b></td> - </tr> - <tr> - <td class="contentbg"> -This is what has changed from eAthena 1.0.0 RC1 -> -eAthena 1.0.0 RC5 -</td> - </tr> - </table> - </td> - </tr> - <tr> - <td class="omgspacer"></td> - </tr> - <tr> - <td align="middle" colspan="8"> - <table class="content"> - <tr> - <td class="contenttitle"><b>Detailed Changelog</td> - </tr> - <tr> - <td class="contentbg"> -<font face="Courier New" size="2"> -<pre> .ZWBBBBBBBBBBBBBBBB0WWWWWWWWW@@@WW@WWWWW@M00Wi - 2MMMWBBBBBBBBWWWWWWWM@@WBBB808Z8ZZZ8Z88Z88Z800WMM; - MMMWBBBWBWWWW@BBW0088088aZZ888W00B0B0888ZZ8Z80800@MX - WMMWWWWWW@@WB08aZZZ80WM0ZMMM@WWW@@M@WW@W@@W@@WW088880MW - :MMM@@@WB08Zaa80BW@M@W@M0riSMMWBWBBM;MMW0WWB@B0WW@@WMMW0@M - 7MMWB0ZZZZZ8BW@WWWBW0WBM0SZ; 2MM@BBBM@ @MW0B0WMB0BW0W0MMMMM@ - 7M@Z888Z80BWMWWBBB@WWWB@M.M7 ;@M@WBWM0 BM@BB0MMW8BBW0@@WWMM0 - M@800Z0W@WWBWBWWB@M7MW@Mr:M . WMMWWWM MMMB0WM@@0WB0B@@WW@Mr - MM880W@WWBBBW@0BBBM2;MBMBX.W ,, .MMWBMZ :ZMMB@8@M@BMB8B@WWWMM. - 2M80BWWWWWBB@ZWBBB@M ;MWMra M .,,,. MMMMM X8MM@@2MMWWMB0@W@WWMM - MMW@WBWWBBBBMiM0WBMB 7MM0r M .,,,.,.; rMMM; XMMM;MMW@@@BBW@WW@M2 - MMWBBB@BWWW@8:M@WMMr iMMWr M .,,,,,. ;MM0 2MMi MMW@WW@WWWWWMM. - M@BWBB@0WBBMZZM0WM7 MMi M, ,..,,,., MMMMMMMMMX rM@WWWW@WW@WWMM - MBBBBBWBBBMM. MBMZ MM . 7S ,,,,,,,, MMMMMMMMa,MMM 2MWWWW@WWWWWWMM - SMBBBBBWBWBMS MWM0MMMMMM ,.:W ,,:,,,,: M@BBBB@M8 MMMiMM@MWWW@WWWWWMB - MMWBBWBWBW@M, MMZWMMWMMW ,. . :.,,,,., .M0WWWBBWMS aM;MZM@WW@WW@WWMMi - M@BBWB0MBBMB MMMaMWB0BWM ,,,.,.,,,,,,: BM0@@@WWBMM aMM;MM@W@W@WWWWMM. - MBWBWB0MWWM ;M2 MMBBWWBBMM .,,,,,,,.,,,i BM0W@@MWWBM@ MZ ZMWWWWWWWWWWMM - M0WBBB0M8WM.MZ MWWWM@MWBM :,.,,.:,,,.: iM0W@W@@BWMM M2 ZM@WWW@WWW@WWMM - M0WBBB0MB0MMM MBBWMBBW0MM ::,,:.,.,,,, MM@MM@@BWMM MX.a@M@WWWWBWWWW@Mi - M0BBWB0@M MMZ MWWWMWW@0MM :,..,.,,,,,,, MMMMMM@a8MM M2:ZiMMWWWWWWWWWWMM - MBWBWBBBM MZ MMMMMM@M0@M i:,,,.,,,.,,: M88MMi M 7MrWMWWWWWWWWWWWW - MWBBB0BBM, MM MM,,:MMW8MM :.,,,.,,,,,,.: 2;.SM0@M8 20ZrMMWWWWWWWWW@W - M@BBWBW0MM MM .@8aMB ,,..,.,,,..,,,. XMMMMMM. i:, .2BM.MMWWWWWWWWWWW - MMBBW0B0@M MM :MMMMMMMMr ,,,,,. .,,..,. .,, a@7:rMW@WWWWWWWWW - WMBB0BWB0Mi X ZMMMM2 .,,.. aS: .,,..,..,...,.,,,, 2@r;.M0MWWWWWWWWW - ,MBBBBBB0MM ,:, i ..,,,,, B78r..:,.,,.,,,,,...,...aMi,0Ma@WWWWWWWWW - MWBBBBBB@M .,,,.. .....,,,,,. ..,,.,,.,.,,,,::,, .Z@ ZMM8B@WWWWWWWW - M@BBB000BMB ,,.,.....,,.,.,,,....,..,,....,..,,,.,,.,:. :a28MM@W0@@WWWWWWW - MMWBBBWB8MM ..,.,:,...,:..,,,,,..,,...;:.,,,.,:.,,.., iWMM@W@@0B@WWWWWWW - 0M0BBBBBBBM; .,,.,,.,,,,,..,,,. eAthena .,,,,,,,,,.,. iaMMWWW@MB8@@WWWWWW - MWBBBBBB0MM .,.,,.,,,,,.,,.,,. 1.0.0 ..,.,,,,.,:, iBMMWWWWW@WBBMWWWWWW - MM0WBBBBBBM@ .,,,,,..,,,.,,,,, RC5,.,.:,,,,:,., 8MMMWWWWW@WW00@WWWWWW - ZM0WBBBBBZMMM ...,,,,.,,,,,..,.,,,.:,.,:. ZMMMWBW@WWWWWMW8W@@WWWW - M@WBWBBB0WMMMMM, ,..,.,,,,,,,,,,,,,,,. .MMMM@W@@WW@@W@BW@0B@@WWWW - 8MBWBBWBB0@W@MMMMMB: ..,,i.,,:,,,... rMMMMWWWWW@@WWWWMBMMB8W@@@WW - MMBBWBBWBW@WWWW@MMMMMW; .,.,.. WMM,MWWW@WWWMWWM@@@@W@W0BMBWWW - 8MB0@B0WB0@@@W@B@W@@MMMMMMM2. BMMZ7r,MWW@@W@BWMXMM@@WWW@B0MW@WW - MM0WM00W8W@@B@WWWWWWWWMM SWMMMMWBW0MM877XSSiMW@WWWWWWM2 MMWWWW@00WWWWW - 2@B0MWBWB0WWWWWWWWWWWWWMS77rrXX222SX7XXSSSX;MB@WW@WWWMM MWWWW@WBB@WWW</pre> -</font> -<br> -<br> -<iframe src="../Changelog.txt" name="Changelog" - title="eAthena Changelog" marginwidth="10" marginheight="10" border="0" - allowtransparency="true" frameborder="0" height="500" width="100%"></iframe></font> -</td> - </tr> - </table> - </td> - </tr> - <tr> - <td class="spaceromg"></td> - </tr> - <tr> - <td class="copyright" colspan="8">© Copyright 2004 eAthena Development Team<br>Design © Copyright 2004 Evera</td> - </tr> -</table> -</body>
\ No newline at end of file diff --git a/doc/readme/faq.html b/doc/readme/faq.html deleted file mode 100644 index 2cc1a2c..0000000 --- a/doc/readme/faq.html +++ /dev/null @@ -1,146 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> -<head> - <title>eAthena 1.0 RC5 Readme</title> - <meta http-equiv="expires" content="-1"> - <meta http-equiv="pragma" content="no-cache"> - <meta name="author" content="eAthena Development Team"> - <meta name="description" content="eAthena, ro server emulator"> - <meta name="keywords" - content="eathena, ro, ragnarok online, server emulator, server software"> - <link href="./rc5.css" media="screen" rel="stylesheet" type="text/css"> -</head> -<body> -<table class="wrapper"> - <tbody> - <tr class="topbanner"> - <td class="topnav"><b><a href="../readme.html">Intro</a></b></td> - <td class="topnav"><b><a href="./changelog.html">Changelog</a></b></td> - <td class="topnav"><b><a href="./features.html">Features</a></b></td> - <td class="topnav"><b><a href="./Npcfeatures.html">Npc Features</a></b></td> - <td class="topnav"><b><a href="./settingup.html">Setting Up</a></b></td> - <td class="topnav"><b><a href="./gmcommands.html">GM Commands</a></b></td> - <td class="topnav"><b><a href="./faq.html">FAQ</a></b></td> - <td class="topnav"><b><a href="./support.html"> Support</a></b></td> - </tr> - <tr> - <td class="banner" colspan="8"> - <div align="right"><img src="./midbanner.jpg" border="0"></div> - </td> - </tr> - <tr> - <td class="omgspacer"><br> - </td> - </tr> - <tr> - <td colspan="8" align="center"> - <table class="content"> - <tbody> - <tr> - <td class="contenttitle"><b>Frequently Asked Questions</b></td> - </tr> - <tr> - <td class="contentbg"><span style="font-weight: bold;">Q</span>: -I get the error message -"This application has failed to start because cygwin1.dll was not -found. Re-installing the application may fix this problem."<br> - <span style="font-weight: bold;">A</span>: You're missing -the cygwin -dlls. Please get the latest dll at: http://www.cygwin.com/snapshot. If -you're unsure, asking around in our IRC chatroom will get you around -too, but always remember - use common sense and search before asking.<br> - <br> - <span style="font-weight: bold;">Q</span>: My map-server -won't load! It -appears to be loading things before it dissapeared suddenly! HELP!<br> - <span style="font-weight: bold;">A</span>: Use command line -to load -map-server. It should tell you the error. If you're missing a map, -update your kRO Sakray or comment the map from map_athena.conf. If you -have an errornous NPC, fix it or comment it off. Anything other than -that, feel free to ask around.<br> - <br> - <span style="font-weight: bold;">Q</span>: My map-server -failed to load -'adata.grf'! Where do I find this adata.grf? My map-server won't load -without it!<br> - <span style="font-weight: bold;">A</span>: The error that -caused the -map-server to not load is not the adata.grf. adata.grf is NOT a -requirement for the map-server to load. The error is probably related -to something else.<br> - <br> - <span style="font-weight: bold;">Q</span>: All 3 of the -servers are -loaded, but I am still having problems accessing it! What do I do?<br> - <span style="font-weight: bold;">A</span>: First, check the -IPs in -map_athena.conf and char_athena.conf. If those are correct, check the -ports to make sure they match. If that's correct too, you probably -cannot handle the server load. Lower the monster spawning rate using -mob_count in battle_athena.conf and it should be fine.<br> - <br> - <span style="font-weight: bold;">Q</span>: How do I start -Guild -Wars/War of Emperium??? HELP!!!<br> - <span style="font-weight: bold;">A</span>: Read the GM -Command page for -full list of commands that GMs can use, including the command for this.<br> - <br> - <span style="font-weight: bold;">Q</span>: My Ragnarok -Online crashed -while playing with eAthena! What do I do now?<br> - <span style="font-weight: bold;">A</span>: Well, if your -Ragnarok -crashes, it's most probably not anything to do with eAthena. Something -is wrong with your Ragnarok installation. Try reinstalling or updating.<br> - <br> - <span style="font-weight: bold;">Q</span>: Is eAthena -compatible with -mySQL? Can I use mySQL as the DB instead of using text files?<br> - <span style="font-weight: bold;">A</span>: Yes, eAthena is -compatible -with mySQL. A tutorial on how to setup this is coming soon.<br> - <br> - <span style="font-weight: bold;">Q</span>: Is eAthena -compatible with -msSQL? Can I use msSQL as the DB instead of using text files?<br> - <span style="font-weight: bold;">A</span>: No, eAthena is -not -compatible with msSQL. You cannot use msSQL with eAthena.<br> - <br> - <span style="font-weight: bold;">Q</span>: I found a bug! -Where do I -report it?<br> - <span style="font-weight: bold;">A</span>: Drop the -developers a line -at the IRC chatroom. Or just post it in the bug report forum. We check -them out too. :)<br> - <br> - <span style="font-weight: bold;">Q</span>: I know alot of C -and I'm -able to help improve eAthena and add new features. How can I join your -development team?<br> - <span style="font-weight: bold;">A</span>: Try talking to -one of the -current developers in the eAthena channel.<span - style="font-weight: bold;"></span><span style="font-weight: bold;"></span><br> - </td> - </tr> - </tbody> - </table> - </td> - </tr> - <tr> - <td class="spaceromg"><br> - </td> - </tr> - <tr> - <td class="copyright" colspan="8">© Copyright 2004 eAthena -Development Team<br> -Design © Copyright 2004 Evera</td> - </tr> - </tbody> -</table> -</body> -</html> diff --git a/doc/readme/features.html b/doc/readme/features.html deleted file mode 100644 index 8a448bd..0000000 --- a/doc/readme/features.html +++ /dev/null @@ -1,239 +0,0 @@ -<html> -<head><title>eAthena 1.0 RC5 Readme</title> -<meta http-equiv="expires" content="-1" /> -<meta http-equiv="pragma" content="no-cache" /> -<meta name="author" content="eAthena Development Team" / -<meta name="description" content="eAthena, ro server emulator" /> -<meta name="keywords" content="eathena, ro, ragnarok online, server emulator, server software" /> -<link href="./rc5.css" media="screen" rel="stylesheet" type="text/css"> -</head> -<body> -<table class="wrapper"> - <tr class="topbanner"> - <td class="topnav"><b><a href="../readme.html">Intro</a></b></td> - <td class="topnav"><b><a href="./changelog.html">Changelog</a></b></td> - <td class="topnav"><b><a href="./features.html">Features</a></b></td> - <td class="topnav"><b><a href="./Npcfeatures.html">Npc Features</a></b></td> - <td class="topnav"><b><a href="./settingup.html">Setting Up</a></b></td> - <td class="topnav"><b><a href="./gmcommands.html">GM Commands</a></b></td> - <td class="topnav"><b><a href="./faq.html">FAQ</a></b></td> - <td class="topnav"><b><a href="./support.html"> Support</a></b></td> - </tr> - <tr> - <td class="banner" colspan="8"> - <div align="right"><img src="./midbanner.jpg" border="0"></div> - </td> - </tr> - <tr> - <td class="omgspacer"></td> - </tr> - <tr> - <td align="middle" colspan="8"> - <table class="content"> - <tr> - <td class="contenttitle"><b>eAthena Completed Features</b></td> - </tr> - <tr> - <td class="contentbg"> -<ul> - <li> PvP (Player VS Player)</li> - <li> GvG (Guild VS Guild)</li> - <li> qPets (Cute Pets)</li> - <li> Monster skills</li> - <li> 2-2 Jobs (Alternate 2nd Jobs)</li> - <li> SuperNovice (Alternate 1st Job)</li> - <li> WoE (War of Emperium)</li> - <li> Remote administration of accounts (ladmin softwares)</li> - <li> Weddings</li> - <li> Pet equipped mobs.<br> - </li> - <li> Management of day/night.</li> - <li> Mob Disguises</li> - <li> Weather and other special effects.<br> - </li> -</ul> -eAthena 1.0.0 RC5 -</td> - </tr> - </table> - </td> - </tr> - <tr> - <td class="omgspacer"></td> - </tr> - <tr> - <td align="middle" colspan="8"> - <table class="content"> - <tr> - <td class="contenttitle"><b>eAthena Features - Estimated completion rate (Detailed) </b></td> - </tr> - <tr> - <td class="contentbg"> -<ul> - <li>Novice Skills - 100% (3/3)</li> - <li>1st Job Skills - 100%</li> - <ul> - <li> Swordsman - 100% (10/10)</li> - </ul> - <ul> - <li> Acolyte - 100% (16/16)</li> - </ul> - <ul> - <li> Archer - 100% (7/7)</li> - </ul> - <ul> - <li> Magician - 100% (14/14)</li> - </ul> - <ul> - <li> Merchant - 100% (10/10)</li> - </ul> - <ul> - <li> Thief - 100% (10/10)</li> - </ul> - <li>2-1 Skills (2nd Job Skills) - 100%</li> - <ul> - <li> Knight - 100% (10/10)</li> - </ul> - <ul> - <li> Priest - 100% (18/18)</li> - </ul> - <ul> - <li> BlackSmith - 100% (21/21)</li> - </ul> - <ul> - <li> Wizard - 100% (13/13)</li> - </ul> - <ul> - <li> Assassin - 100% (10/10)</li> - </ul> - <ul> - <li> Hunter - 100% (17/17)</li> - </ul> - <li>2-2 Skills (Alternate 2nd Job Skills) - 91%</li> - <ul> - <li> Crusader - 100% (18/18)</li> - </ul> - <ul> - <li> Monk - 100% (15/15)</li> - </ul> - <ul> - <li> Alchemist - 63% (14/22)</li> - </ul> - <ul> - <li> Sage - 100% (20/20)</li> - </ul> - <ul> - <li> Rogue - 80% Complete:(12/15) Incomplete:(3/15)</li> - </ul> - <ul> - <li> Bard - 100% (16/16)</li> - </ul> - <ul> - <li> Dancer - 100% (16/16)</li> - </ul> - <li>2-1-1 Skills (Advanced 2-1 Job Skills) - 80.5%</li> - <ul> - <li> Lord Knight - 94% - Complete:(7/8) -Incomplete:(1/8)</li> - </ul> - <ul> - <li> High Priest - 66% - Complete:(1/3) -Incomplete:(2/3)</li> - </ul> - <ul> - <li> High Wizard - 100% (4/4)</li> - </ul> - <ul> - <li> Whitesmith - 75% (3/4)</li> - </ul> - <ul> - <li> Sniper - 88% - Complete:(3/4) Incomplete:(1/4)</li> - </ul> - <ul> - <li> Assassin Cross - 60% (3/5)</li> - </ul> - <li>2-2-1 Skills (Advanced 2-2 Job Skills) - 47%</li> - <ul> - <li> Paladin - 65%</li> - </ul> - <ul> - <li> Champion - 100%</li> - </ul> - <ul> - <li> Professor - 100%</li> - </ul> - <ul> - <li> Stalker - 65%</li> - </ul> - <ul> - <li> Creator - 0%</li> - </ul> - <ul> - <li> Clown - 0%</li> - </ul> - <ul> - <li> Gypsy - 0%</li> - </ul> - <li>Pet Skills - 95%</li> - <ul> - <li> Loot Skills - 100%</li> - </ul> - <ul> - <li> Buff Skills - 100%</li> - </ul> - <ul> - <li> Attack Skills - 90%</li> - </ul> - <ul> - <li> Assist Skills - 100%</li> - </ul> - <li>Equipment Breaking System - 80%</li> - <ul> - <li> Weapon Breaking - 95%</li> - </ul> - <ul> - <li> Armor Breaking - 95%</li> - </ul> - <ul> - <li> Equipment Repair - 50%</li> - </ul> - <li>PK Server Mode - ??%</li> - <ul> - <li> Need more info on this mode to be called complete.</li> - </ul> -</ul> -</td> - </tr> - </table> - </td> - </tr> - <tr> - <td class="omgspacer"></td> - </tr> - <tr> - <td align="middle" colspan="8"> - <table class="content"> - <tr> - <td class="contenttitle"><b>eAthena Incomplete Features</b></td> - </tr> - <tr> - <td class="contentbg"> -<ul> - <li>Advanced Classes (Upper Jobs)</li> - <li>Baby Classes (Baby Jobs)</li> - <li>PK Server Mode<font face="Courier New" size="2"></font></li> -</ul> -eAthena 1.0.0 RC5 -</td> - </tr> - </table> - </td> - </tr> - <tr> - <td class="spaceromg"></td> - </tr> - <tr> - <td class="copyright" colspan="8">© Copyright 2004 eAthena Development Team<br>Design © Copyright 2004 Evera</td> - </tr> -</table> -</body>
\ No newline at end of file diff --git a/doc/readme/gmcommands.html b/doc/readme/gmcommands.html deleted file mode 100644 index 80a938c..0000000 --- a/doc/readme/gmcommands.html +++ /dev/null @@ -1,692 +0,0 @@ -<html> -<head><title>eAthena 1.0 RC5 Readme</title> -<meta http-equiv="expires" content="-1" /> -<meta http-equiv="pragma" content="no-cache" /> -<meta name="author" content="eAthena Development Team" / -<meta name="description" content="eAthena, ro server emulator" /> -<meta name="keywords" content="eathena, ro, ragnarok online, server emulator, server software" /> -<link href="./rc5.css" media="screen" rel="stylesheet" type="text/css"> -</head> -<body> -<table class="wrapper"> - <tr class="topbanner"> - <td class="topnav"><b><a href="../readme.html">Intro</a></b></td> - <td class="topnav"><b><a href="./changelog.html">Changelog</a></b></td> - <td class="topnav"><b><a href="./features.html">Features</a></b></td> - <td class="topnav"><b><a href="./Npcfeatures.html">Npc Features</a></b></td> - <td class="topnav"><b><a href="./settingup.html">Setting Up</a></b></td> - <td class="topnav"><b><a href="./gmcommands.html">GM Commands</a></b></td> - <td class="topnav"><b><a href="./faq.html">FAQ</a></b></td> - <td class="topnav"><b><a href="./support.html"> Support</a></b></td> - </tr> - <tr> - <td class="banner" colspan="8"> - <div align="right"><img src="./midbanner.jpg" border="0"></div> - </td> - </tr> - <tr> - <td class="omgspacer"></td> - </tr> - <tr> - <td align="middle" colspan="8"> - <table class="content"> - <tr> - <td class="contenttitle"><b>eAthena GM Commands</b></td> - </tr> - <tr> - <td class="contentbg"> -The following is a list of all GM Commands in eAthena. -To use them, just type @ in front of the command into the message -window where you usually type to chat. -<p> The @ can be changed by the server admin to another character. -</td> - </tr> - </table> - </td> - </tr> - <tr> - <td class="omgspacer"></td> - </tr> - <tr> - <td align="middle" colspan="8"> - <table class="content"> - <tr> - <td class="contenttitle"><b>GM Command List</b></td> - </tr> - <tr> - <td class="contentbg"> -<font face="Verdana"><span class="GMCommandTitle">ANNOUNCEMENT COMMANDS</span> -<span class="GMCommand">/b <message><br>@broadcast <message></span> -Lets you make a GM global announcement with your name - -<span class="GMCommand">/nb <message><br>@kamu <message></span> -Lets you make a GM global announcement withouth your name - -<span class="GMCommand">@kamib <message><br>/bb <message></span> -Lets you make a GM global announcement withouth your name in blue - -<span class="GMCommandTitle">INFORMATION COMMANDS</span> -<span class="GMCommand">@who [match_text]</span> <br>Lists who is currently online in your server and their location. [match_text] is optional <br><br><span - class="GMCommand">@who2 [match_text] </span> -Lists who is currently online in your server and their job. [match_text] is optional - -<span class="GMCommand">@who3 [match_text]</span> <br>Lists who is currently online in your server and their party/guild. [match_text] is optional<br><br><span - class="GMCommand">@whomap [map]</span> <br>Display a listing of who is online and where in a specifical map<br><br><span - class="GMCommand">@whomap2 [map]</span> <br>Display a listing of who is online and their job in a specifical map<br><br><span - class="GMCommand">@whomap3 [map]</span> <br>Display a listing of who is online and their party/guild in a specifical map<br><br><span - class="GMCommand">@whogm [match_text]</span> <br>Like @who+@who2+who3, but only for GM. [match_text] is optional <br><br><span - class="GMCommand">@where <char name></span> -Tells you the location of a character - -<span class="GMCommand">@charstatsall</span> - Displays stats of all characters. - -<span class="GMCommand">@charitemlist <char name></span> - Displays all items of a player. - -<span class="GMCommand">@charstoragelist <char name></span> - Displays all items of a player's storage. - -<span class="GMCommand">@charcartlist <char name></span> - Displays all items of a player's cart. - -<span class="GMCommand">@time<br>@date<br>@server_date<br>@serverdate<br>@server_time<br>@servertime</span> -Display the date/time of the server - -<span class="GMCommand">@idsearch <part_of_item_name></span> -Search all items that name have part_of_item_name - -<span class="GMCommand">@ignorelist</span> -Displays your ignore list - -<span class="GMCommand">@mapinfo [<1-3> [map]]</span> -Give information about a map (general info +: 0: no more, 1: players, 2: NPC, 3: shops/chat). - -<span class="GMCommandTitle">CONTROL COMMANDS</span> -<span class="GMCommand">@die</span> -Kill yourself :) - -<span class="GMCommand">@alive</span> -Revive yourself from death - -<span class="GMCommand">@kill <char name></span> -Kills specified character name - -<span class="GMCommand"></span><span class="GMCommand">@save</span> -Sets save point as current location - -<span class="GMCommand">@load</span> -Warps you to your save point (a.k.a. butterfly wing) - -<span class="GMCommand">@warp <map name> <x> <y><br>@rura <map name> <x> <y><br>@mapmove <map name> <x> <y><br>/mm <map name> <x> <y><br>/mapmove <map name> <x> <y></span> -Warps you to the selected position -Example: -@warp morocc 150 160 -> Warps you to Morroc (X:150, Y:160) -@rura prontera 50 80 -> Warps you to Prontera (X:50, Y:80) - - -<span class="GMCommand">@rura+ <map name> <x> <y> <char name><br>@charwarp <map name> <x> <y> <char name><br>#banish <map name> <x> <y> <char name></span> -Warps the selected character to the selected position -Example: -@charwarp morocc 150 160 Sora -> Warps the character 'Sora' to Morroc (X:150, Y:160) -@rura+ prontera 50 80 Haley -> Warps the character 'Haley' to Prontera (X:50, Y:80) - -<span class="GMCommand">@jump [x [y]]</span> -Teleports you randomly in the map (a.k.a. fly wing). Or to the specified location with x and y. - -<span class="GMCommand">/shift <char name><br>@jumpto <char name><br>@warpto <char name><br>@goto <char name></span> -Warps you to selected character - -<span class="GMCommand">@go <number/city_name></span> -Warps you to a set city:</font></pre> -<table id="table1" border="1" width="90%"> - <tbody> - <tr> - <td width="25%"><font face="Verdana" size="2">-3: (Memo Point 2)</font></td> - <td width="25%"><font face="Verdana" size="2">2: Geffen</font></td> - <td width="25%"><font face="Verdana" size="2">7: Lutie</font></td> - <td width="25%"><font face="Verdana" size="2">12: Umbala</font></td> - </tr> - <tr> - <td width="25%"><font face="Verdana" size="2">-2: (Memo Point 1)</font></td> - <td width="25%"><font face="Verdana" size="2">3: Payon </font> </td> - <td width="25%"><font face="Verdana" size="2">8: Comodo</font></td> - <td width="25%"><font face="Verdana" size="2">13: Niflheim</font></td> - </tr> - <tr> - <td width="25%"><font face="Verdana" size="2">-1: (Memo Point 0)</font></td> - <td width="25%"><font face="Verdana" size="2">4: Alberta</font></td> - <td width="25%"><font face="Verdana" size="2">9: Yuno</font></td> - <td width="25%"><font face="Verdana" size="2">14: Louyang</font></td> - </tr> - <tr> - <td width="25%"><font face="Verdana" size="2">0: Prontera</font></td> - <td width="25%"><font face="Verdana" size="2">5: Izlude</font></td> - <td width="25%"><font face="Verdana" size="2">10: Amatsu</font></td> - <td width="25%"><font face="Verdana" size="2">15: Start Point</font></td> - </tr> - <tr> - <td width="25%"><font face="Verdana" size="2">1: Morroc</font></td> - <td width="25%"><font face="Verdana" size="2">6: Al de Baran</font></td> - <td width="25%"><font face="Verdana" size="2">11: Gon Ryun</font></td> - <td width="25%"><font face="Verdana" size="2">16: Prison/Jail</font></td> - </tr> - </tbody> -</table> -<pre class="style1"><font face="Verdana"><span class="GMCommand">/hide<br>@hide</span> -GM Hide. Perfect hide that's totally invisible. - -<span class="GMCommand">@heal [<HP> <HP>]</span> -Heals the desired amount of HP and SP. No value specified will do a full heal. - -<span class="GMCommand">@storage </span> -Opens storage - -<span class="GMCommand">/recall <char name><br>@recall <char name></span> -Recalls target character to you. - -<span class="GMCommand">@recallall</span> -Recalls everyone on the server to you. - -<span class="GMCommand">@guildrecall <guild_name/id></span> -Warps all online character of a guild to you. - -<span class="GMCommand">@partyrecall <party_name/id></span> -Warps all online character of a party to you. - -<span class="GMCommand">@revive <char name></span> -Revives target character. - -<span class="GMCommand">@killmonster</span> -Kills all spawned monsters on maps - -<span class="GMCommandTitle">SPAWNING COMMANDS</span> -<span class="GMCommand">/item <item_name><br></span>Gives you 1 of the desired monster<span - class="GMCommand"> - -@item <item name or ID> <quantity></span> -Gives you the desired item with the desired quantity - -<span class="GMCommand">/monster <monster_name></span><span - class="faqlist"> -Spawns 1 of the desired monster - -</span><span class="GMCommand"><font size="2">@spawn <monster_name_or_monster_ID> [<quantity> [<desired_monster_name> [<x coord> [<y coord>]]]]<br>@monster <monster_name_or_monster_ID> [<quantity> [<desired_monster_name> [<x coord> [<y coord>]]]]<br>@summon <monster_name_or_monster_ID> [<quantity> [<desired_monster_name> [<x coord> [<y coord>]]]]</font></span><font - size="2"><span class="faqlist"> -</span><span class="GMCommand">@monster2 <desired_monster_name> <monster_name_or_monster_ID> [<quantity> [<x coord> [<y coord>]]]<br>OR<br>@spawn "desired monster name" <monster_name_or_monster_ID> [<quantity> [<x coord> [<y coord>]]]<br>@monster "desired monster name" <monster_name_or_monster_ID> [<quantity> [<x coord> [<y coord>]]]<br>@summon "desired monster name" <monster_name_or_monster_ID> [<quantity> [<x coord> [<y coord>]]]<br>@monster2 "desired monster name" <monster_name_or_monster_ID> [<quantity> [<x coord> [<y coord>]]]<br>OR<br>@spawn <monster_name_or_monster_ID> "desired monster name" [<quantity> [<x coord> [<y coord>]]]<br>@monster <monster_name_or_monster_ID> "desired monster name" [<quantity> [<x coord> [<y coord>]]]<br>@summon <monster_name_or_monster_ID> "desired monster name" [<quantity> [<x coord> [<y coord>]]]<br>@monster2 <monster_name_or_monster_ID> "desired monster name" [<quantity> [<x coord> [<y coord>]]]</span> -</font> -Spawns the desired monster with any desired name, quantity and x and y location (if specified). -There 2 last forms can use spaces for desired names (between the ""). - -<span class="GMCommandTitle">MAP OPTIONS COMMANDS</span> - -<span class="GMCommand">@pvpon</span> -Turns pvp on on the current map -<span class="GMCommand">@pvpoff</span> -Turns pvp off on the current map -<span class="GMCommand">@gvgon</span> -Turns gvg on on the current map. This does NOT enable War of Emperium. -<span class="GMCommand">@gvgoff </span> -Turns gvg off on the current map. This does NOT disable War of Emperium. - -<span class="GMCommandTitle">CHARACTER CONTROL COMMANDS</span> -<span class="GMCommand">@baselvlup <number of levels></span> -<span class="GMCommand">@lvup <number of levels><br>@blevel <number of levels></span> -Raises your base level the desired number of levels. The max is 99 (unless you change it in battle_athena.conf). - -<span class="GMCommand">@joblvlup <number of levels></span> -<span class="GMCommand">@joblvup <number of levels><br>@jlevel <number of levels></span> -Raises your job level the desired number of levels. The max is 50 for 1st and 2nd class, and 70 for advanced classes. - -<span class="GMCommand">@job <job ID><br>@jobchange <job ID></span> -Changes your job to the job assigned to the ID</font></pre> -<table id="table2" border="1" width="90%"> - <tbody> - <tr> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">0: -Novice</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">6: -Thief</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">12: -Assassin</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">18: -Alchemist</font></td> - </tr> - <tr> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">1: -Swordsman</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">7: -Knight</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">13: -Knight w/ Peco</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">19: -Bard</font></td> - </tr> - <tr> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">2: -Mage</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">8: -Priest</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">14: -Crusader</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">20: -Dancer</font></td> - </tr> - <tr> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">3: -Archer</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">9: -Wizard</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">15: -Monk</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">21: -Crusader w/ Peco</font></td> - </tr> - <tr> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">4: -Acolyte</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">10: -Blacksmith</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">16: -Sage</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">22: -Wedding</font></td> - </tr> - <tr> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">5: -Merchant</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">11: -Hunter</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">17: -Rogue</font></td> - <td width="25%"><font style="font-size: 11pt;" face="Verdana">23: -Super Novice</font></td> - </tr> - </tbody> -</table> -<table id="table3" border="1" width="90%"> - <tbody> - <tr> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">24/4001: -Novice High</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">31/4007: -Thief High</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">40/4013: -Assassin Cross</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">46/4019: -Creator</font></td> - </tr> - <tr> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">25/4002: -Swordsman High</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">35/4008: -Lord Knight</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">41/4014: -Lord Knight w/ Peco</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">47/4020: -Clown</font></td> - </tr> - <tr> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">26/4003: -Mage High</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">36/4009: -High Priest</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">42/4015: -Paladin</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">48/4021: -Gypsy</font></td> - </tr> - <tr> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">28/4004: -Archer High</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">37/4010: -High Wizard</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">43/4016: -Champion</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">49/4022: -Paladin w/ Peco</font></td> - </tr> - <tr> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">29/4005: -Acolyte High</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">38/4011: -Whitesmith</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">44/4017: -Professor</font></td> - <td width="25%"> </td> - </tr> - <tr> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">30/4006: -Merchant High</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">39/4012: -Sniper</font></td> - <td width="25%"><font style="font-size: 9pt;" face="Verdana">45/4018: -Stalker</font></td> - <td width="25%"> </td> - </tr> - </tbody> -</table> -<pre class="style1"><font face="Verdana"><span class="GMCommand">@option <param1> <param2> <param3></span> -Changes options for your character - <param1> <param2> (Stackable) <param3> (Stackable) - 01 Petrified 01 Poison 01 Sight - 02 Frozen 02 Cursed 02 Hide - 03 Stunned 04 Silenced 04 Cloak - 04 Sleeping 08 ??? 08 Level 1 Cart - 06 ??? 16 Darkness 16 Falcon - 32 (Depreciated) - 64 GM Perfect Hide - 128 Level 2 Cart - 256 Level 3 Cart - 512 Level 4 Cart - 1024 Level 5 Cart - 2048 Orc Head - 4096 Wedding Sprites - 8192 Ruwach - -<span class="GMCommand">@mountpeco</span> -Will (un)mount on a peco. (Class is required, but not skill) - -<span class="GMCommand">@speed <1-1000></span> -Changes you walking speed. -1(Fastest)<---140(Default)----------------->1000(Slowest) - -<span class="GMCommand">@disguise <monster_name_or_monster_ID></span> -Change your appearence to other players to a mob. - -<span class="GMCommand">@undisguise</span> -Restore your normal appearance. - -<span class="GMCommand">@model <hair ID> <hair color> <clothes color></span> -Changes your characters appearance (Hair type, Hair Colour and/or Clothes Colour) - Hair ID (0-17) Hair Colour (0-8) Clothes Colour (0-4) - 0 Default 0 Default - 1 Blonde 1 Red - 2 Purple 2 Green - 3 Brown 3 White - 4 Green 4 Brown - 5 Blue - 6 White - 7 Black - 8 Red - -<span class="GMCommand">@effect <effect_id> [flag]</span> - Give an efect to your character. - -<span class="GMCommand">@stpoint <number of points></span> -Gives you the desired number of stat points. - -<span class="GMCommand">@skpoint <number of points></span> -Gives you the desired number of skill points. - -<span class="GMCommand">@zeny <amount></span> -Gives you desired amount of Zeny. - -<span class="GMCommand">@str <amount><br>@agi <amount><br>@vit <amount><br>@int <amount><br>@dex <amount><br>@luk <amount></span> -Adds desired amount to any stat. For example "@str 10" raises your str by 10 - -<span class="GMCommand">@spiritball <number></span> -Number 1-1000 -Gives you monk "spirit spheres" like from the skill "Call Spirits" -(If the number you use is > 1000, your server may become instable or crash). 1000 Lags Your Client - -<span class="GMCommand">@memo [memo_position]</span> -set/change a memo location (no position: display memo points). - -<span class="GMCommand">@questskill <id></span> -Gives you the specified quest skill - -<span class="GMCommand">@lostskill <id></span> -Takes away the specified quest skill from you - -Quest Skill ID: - Novice - 142 Emergency Care - 143 Act dead - Swordsman - 144 Moving HP Recovery - 145 Attack Weak Point - 146 Auto Berserk - Archer - 147 Arrow Creation - 148 Charge Arrows - Thief - 149 Throw Sand - 150 Back Sliding - 151 Take Stone - 152 Stone Throw - Merchant - 153 Cart Revolution - 154 Change Cart - 155 Crazy Uproar/Loud Voice - Acolyte - 156 Holy Light - Magician - 157 Energy Coat - -<span class="GMCommand">@email <actual@email> <new@email></span> -to change your e-mail (characters protection) - -<span class="GMCommandTitle">GUILD/WoE CONTROL COMMANDS</span> -<span class="GMCommand">@guildlvup/@guildlvlup <# of levels></span> -Raise Guild by desired number of levels - -<span class="GMCommand">@guild <Desired Guild Name></span> -Creates a guild with the disered name (Spaces are allow, no need to use "") - -<span class="GMCommand">@agitstart</span> -Starts Guild Wars (War of Emperium) - -<span class="GMCommand">@agitend</span> -Ends Guild Wars (War of Emperium) - -<span class="GMCommandTitle">EQUIPMENT COMMANDS</span> -<span class="GMCommand">@refine <position> <+/-amount></span> -Upgrades equipment at the position specified (Stackable) -0 - All -1 - Lower Head -2 - Right Hand -4 - Robe/Garment -8 - Left Accessory -16 - Body/Armor -32 - Left Hand -64 - Feet -128 - Right Accessory -256 - Top Head -512 - Mid Head - -Example: -@refine 34 10 - Refines a 2 handed weapon to +10 -@refine 16 4 - Refines the body/armor to +4 - -<span class="GMCommand">@produce <equip name or equip ID> <element> <# of very's></span> -Element: 0 None 1 Ice 2 Earth 3 Fire 4 Wind -# of very's: 0 None 1 Very Strong 2 Very Very Strong 3 Very Very Very Strong - -Example: @produce 1163 3 3 - Produces a Very Very Very Strong (Your Nick)'s Fire Claymore - -<span class="GMCommandTitle">PET COMMANDS</span> -<span class="GMCommand">@makeegg <ID></span> -Gives pet egg for monster ID in pet DB - -<span class="GMCommand">@petfriendly <#></span> -Set pet friendly amount (0-1000) 0 Min, 1000 Max - -<span class="GMCommand">@pethungry <#></span> -Set pet hungry amount (0-100) 0 Min, 100 Max - -<span class="GMCommand">@petrename</span> -Re-enable pet rename - -<span class="GMCommand">@hatch</span> -Brings up the hatch pet menu - -<span class="GMCommandTitle">REMOTE CHAR COMMANDS</span> -<span class="GMCommand">@charwarp <map name> <x> <y> <char name></span> -Warps character to location of choice -Example: -@charwarp morocc 150 160 TestChar -> Warps TestChar to Morroc (X:150, Y:160) - -<span class="GMCommand">@charstats <char name></span> -Displays the character's stats. - -<span class="GMCommand">@charignorelist <char name></span> -Displays ignore list of the player - -<span class="GMCommand">@inall <char name></span> -Allows all wispers for the player - -<span class="GMCommand">@exall <char name></span> -Blocks all wispers for the player - -<span class="GMCommand">@charoption <param1> <param2> <param3> <char name></span> -Does the same as the @option command only to target character. - -<span class="GMCommand">@charmountpeco <charname></span> -Give/remove to a player a peco (Class is required, but not skill). - -<span class="GMCommand">@charpetrename <charname></span> -Re-enable pet rename to a player. - -<span class="GMCommand">@charsave <map> <x> <y> <char name></span> -Changes the target player's respawn point. - -<span class="GMCommand">@charbaselvl <#> <char name></span> -Change a character's base level. - -<span class="GMCommand">@charjlvl <#> <char name></span> -Change a character's job level. - -<span class="GMCommand">@charjob <job ID> <char name><br>@charjobchange <job ID> <char name></span> -Changes target character's job. - -<span class="GMCommand">@charzeny <amount> <char name></span> -Give/take a player's Zeny - -<span class="GMCommand">@charstpoint <amount> <char name></span> -Give/take a player's stat points - -<span class="GMCommand">@charskpoint <amount> <char name></span> -give/take a player's skill points - -<span class="GMCommand">@charquestskill <#> <char name></span> -Gives to a player the specified quest skill. - -<span class="GMCommand">@charlostskill <#> <char name></span> -Takes away the specified quest skill from the player. - -<span class="GMCommand">@chardelitem <item_name_or_ID> <quantity> <char name></span> -Remove items from a character - -<span class="GMCommand">@charmodel <hair type> <hair color> <clothes color> <char name></span> -Changes a player's model - -<span class="GMCommand">@chardisguise <monster_name_or_monster_ID> <char name></span> -Changes disguise of a player - -<span class="GMCommand">@charundisguise <char name></span> -Cancels disguise of a player - -<span class="GMCommand">@charreset <char name></span> -Resets the character - -<span class="GMCommand">@chardyeclothes <#> <char name></span> -Changes a player's clothes colour - -<span class="GMCommand">@chardyehair <#> <char name></span> -Changes a player's hair colour - -<span class="GMCommand">@charstylehair <#> <char name></span> -Changes a player's hair style - -<span class="GMCommand">@charchangesex <name></span> -Changes sex of a player (all characters of the account) - -<span class="GMCommand">@charblock <name></span> -Blocks definitively a account - -<span class="GMCommand">@charunblock <name></span> -<span class="GMCommand">@unblock <name></span> -Unblocks a account - -<span class="GMCommand">@charban <time> <name></span> -Ban temporarily a account - time usage: adjustement (+/- value) and element (y/a, m, d/j, h, mn, s) - Example: @ban +1m-2mn1s-6y testplayer - -<span class="GMCommand">@charunban <name><br>@unban <name><br>@unbanish <name><br>@uncharbanish <name></span> -Unban a account - -<span class="GMCommand">@jail <char_name></span> -Sends specified character in jails - -<span class="GMCommand">@unjail <charname><br>@discharge <char_name></span> -Discharges specified character/prisoner - -<span class="GMCommandTitle">MASS CONTROL COMMANDS</span> -<span class="GMCommand">@night</span> -All characters are in darkness - -<span class="GMCommand">@day</span> -@option 00 00 00 are used on all characters - -<span class="GMCommand">@doom</span> -Kills all NON GM chars on the server. - -<span class="GMCommand">@doommap</span> -Kills all non GM characters on the map. - -<span class="GMCommand">@raise</span> -Resurrects all characters on the server. - -<span class="GMCommand">@raisemap</span> -Resurrects all characters on the map. - -<span class="GMCommand">@kick <charname></span> -Kicks specified character off the server - -<span class="GMCommand">@kickall</span> -Kick all characters off the server - -<span class="GMCommandTitle">OTHER COMMANDS</span> -<span class="GMCommand">@gat<br>@packet</span> -Unknown - -<span class="GMCommandTitle">Server Control Commands</span> -<span class="GMCommand">@reloadscript<br></span>Reloads all the scripts for the server<span - class="GMCommand"> - -@reloaditemdb</span> -Reloads the itemdb - -<span class="GMCommand">@reloadgmdb</span> -Reload GM levels - -<span class="GMCommand">@mapexit</span> -Kick all players and shut down map-server. - -<span class="GMCommand">@reloadmobdb</span> -Reload monster database - -<span class="GMCommand">@reloadskilldb</span> -Reload skills definition database - -<span class="GMCommand">@enablenpc <NPC_name></span> -Enable a NPC - -<span class="GMCommand">@disablenpc <NPC_name></span> -Disable a NPC</font> -</pre> -</td> - </tr> - </table> - </td> - </tr> - <tr> - <td class="spaceromg"></td> - </tr> - <tr> - <td class="copyright" colspan="8">© Copyright 2004 eAthena Development Team<br>Design © Copyright 2004 Evera</td> - </tr> -</table> -</body>
\ No newline at end of file diff --git a/doc/readme/midbanner.jpg b/doc/readme/midbanner.jpg Binary files differdeleted file mode 100644 index d928dfc..0000000 --- a/doc/readme/midbanner.jpg +++ /dev/null diff --git a/doc/readme/npcfeatures.html b/doc/readme/npcfeatures.html deleted file mode 100644 index a2e52ec..0000000 --- a/doc/readme/npcfeatures.html +++ /dev/null @@ -1,143 +0,0 @@ -<html> -<head><title>eAthena 1.0 RC5 Readme</title> -<meta http-equiv="expires" content="-1" /> -<meta http-equiv="pragma" content="no-cache" /> -<meta name="author" content="eAthena Development Team" / -<meta name="description" content="eAthena, ro server emulator" /> -<meta name="keywords" content="eathena, ro, ragnarok online, server emulator, server software" /> -<link href="./rc5.css" media="screen" rel="stylesheet" type="text/css"> -</head> -<body> -<table class="wrapper"> - <tr class="topbanner"> - <td class="topnav"><b><a href="../readme.html">Intro</a></b></td> - <td class="topnav"><b><a href="./changelog.html">Changelog</a></b></td> - <td class="topnav"><b><a href="./features.html">Features</a></b></td> - <td class="topnav"><b><a href="./Npcfeatures.html">Npc Features</a></b></td> - <td class="topnav"><b><a href="./settingup.html">Setting Up</a></b></td> - <td class="topnav"><b><a href="./gmcommands.html">GM Commands</a></b></td> - <td class="topnav"><b><a href="./faq.html">FAQ</a></b></td> - <td class="topnav"><b><a href="./support.html"> Support</a></b></td> - </tr> - <tr> - <td class="banner" colspan="8"> - <div align="right"><img src="./midbanner.jpg" border="0"></div> - </td> - </tr> - <tr> - <td class="omgspacer"></td> - </tr> - <tr> - <td align="middle" colspan="8"> - <table class="content"> - <tr> - <td class="contenttitle"><b>eAthena Npc Scripts</b></td> - </tr> - <tr> - <td class="contentbg"> -<ul> -<li>Town Npcs (11/13)</li> -<ul><li> Prontera - 100%</li></ul> -<ul><li> Morocc - 100%</li></ul> -<ul><li> Geffen - 100%</li></ul> -<ul><li> Izlude - 100%</li></ul> -<ul><li> Alberta - 100%</li></ul> -<ul><li> Al de Baran - 100%</li></ul> -<ul><li> Lutie - 100%</li></ul> -<ul><li> Amatsu - 100%</li></ul> -<ul><li> Comodo - 100%</li></ul> -<ul><li> Niflheim - 100%</li></ul> -<ul><li> Umbala - 100%</li></ul> -<ul><li> Gonryun - 60%</li></ul> -<ul><li> Payon(New Maps) - 50%</li></ul> -<li>Job Quests (16/33)</li> -<ul><li> Novice Class (2/2)</li></ul> -<ul><ul><li> Novice - 100%</li></ul></ul> -<ul><ul><li> Super Novice - 100%</li></ul></ul> -<ul><li> 1-1 Class (6/6)</li></ul> -<ul><ul><li> Swordman - 100%</li></ul></ul> -<ul><ul><li> Mage - 100%</li></ul></ul> -<ul><ul><li> Archer - 100%</li></ul></ul> -<ul><ul><li> Acolyte - 100%</li></ul></ul> -<ul><ul><li> Merchant - 100%</li></ul></ul> -<ul><ul><li> Thief - 100%</li></ul></ul> -<ul><li> 2-1 Class (6/6)</li></ul> -<ul><ul><li> Knight - 100%</li></ul></ul> -<ul><ul><li> Priest - 100%</li></ul></ul> -<ul><ul><li> Wizard - 100%</li></ul></ul> -<ul><ul><li> Blacksmith - 100%</li></ul></ul> -<ul><ul><li> Hunter - 100%</li></ul></ul> -<ul><ul><li> Assassin - 100%</li></ul></ul> -<ul><li> 2-2 Class (2/7)</li></ul> -<ul><ul><li> Crusader - 0%</li></ul></ul> -<ul><ul><li> Monk - 0% (Soon)</li></ul></ul> -<ul><ul><li> Sage - 0% (Soon)</li></ul></ul> -<ul><ul><li> Rogue - 100%</li></ul></ul> -<ul><ul><li> Alchemist - 100%</li></ul></ul> -<ul><ul><li> Bard - 0%</li></ul></ul> -<ul><ul><li> Dancer - 100%</li></ul></ul> -<ul><li> 2-1-1 Class (0/6)</li></ul> -<ul><li> 2-2-1 Class (0/6)</li></ul> -<li>Kafras - 100%</li> -<li>Guides - 100%</li> -<li> War Of Emperium (4/5)</li> -<ul><li> Prontera - 100%</li></ul> -<ul><li> Geffen - 100%</li></ul> -<ul><li> Payon - 100%</li></ul> -<ul><li> Al De Baran - 100%</li></ul> -<ul><li> Novice - 0%</li></ul> -<li>Quests (24/25)</li> -<ul><li> Skill Quests (7/7)</li></ul> -<ul><ul><li> Novice - 100%</li></ul></ul> -<ul><ul><li> Swordman - 100%</li></ul></ul> -<ul><ul><li> Mage - 100%</li></ul></ul> -<ul><ul><li> Archer - 100%</li></ul></ul> -<ul><ul><li> Acolyte - 100%</li></ul></ul> -<ul><ul><li> Merchant - 100%</li></ul></ul> -<ul><ul><li> Thief - 100%</li></ul></ul> -<ul><li>Town Quests (9/10)</li></ul> -<ul><ul><li> Prontera - 100%</li></ul></ul> -<ul><ul><li> Morocc - 100%</li></ul></ul> -<ul><ul><li> Geffen - 100%</li></ul></ul> -<ul><ul><li> Izlude - 100%</li></ul></ul> -<ul><ul><li> Alberta - 100%</li></ul></ul> -<ul><ul><li> Al De Baran - 100%</li></ul></ul> -<ul><ul><li> Yuno - 100%</li></ul></ul> -<ul><ul><li> Lutie - 100%</li></ul></ul> -<ul><ul><li> Comodo - 100%</li></ul></ul> -<ul><ul><li> Payon - 20%</li></ul></ul> -<ul><li>Other Quests (8/8)</li></ul> -<ul><ul><li> Dye - 100%</li></ul></ul> -<ul><ul><li> MrSmile - 100%</li></ul></ul> -<ul><ul><li> Juice Making - 100%</li></ul></ul> -<ul><ul><li> Doomed Swords - 100%</li></ul></ul> -<ul><ul><li> Bongun Taming - 100%</li></ul></ul> -<ul><ul><li> Munak Taming - 100%</li></ul></ul> -<ul><ul><li> Tamking - 100%</li></ul></ul> -<ul><ul><li> Bongun Sword - 100%</li></ul></ul> -<ul><li>Other (7/10)</li></ul> -<ul><ul><li> Card Remover - 100%</li></ul></ul> -<ul><ul><li> PvP (old) - 100%</li></ul></ul> -<ul><ul><li> Time Arena - 100%</li></ul></ul> -<ul><ul><li> Bank - 100%</li></ul></ul> -<ul><ul><li> Wedding - 80%</li></ul></ul> -<ul><ul><li> Valkyrie - 10%</li></ul></ul> -<ul><ul><li> Gefenia - 10%</li></ul></ul> -<ul><ul><li> Heal Npc - 100%</li></ul></ul> -<ul><ul><li> Warp Npc - 100%</li></ul></ul> -<ul><ul><li> Jobchange - 100%</li></ul></ul> - </li> -</ul> -</td> - </tr> - </table> - </td> - </tr> - <tr> - <td class="spaceromg"></td> - </tr> - <tr> - <td class="copyright" colspan="8">© Copyright 2004 eAthena Development Team<br>Design © Copyright 2004 Evera</td> - </tr> -</table> -</body>
\ No newline at end of file diff --git a/doc/readme/rc5.css b/doc/readme/rc5.css deleted file mode 100644 index e6c0809..0000000 --- a/doc/readme/rc5.css +++ /dev/null @@ -1,68 +0,0 @@ - A {color: #000; text-decoration: none; background-color : inherit;} - A:link {color: #000; text-decoration: none; background-color : inherit;} - A:visited { color: #000; text-decoration: none; background-color : inherit;} - A:active { color: #000; text-decoration: none; background-color : inherit;} - A:hover { color: #8282AE; text-decoration: underline; background-color : inherit;} - -body { - margin: 0px; - font-size: 11px; - font-family: Lucila, Arial, Helvetica; - background: #E1E1F4; - color: #9999CD; -} - -.wrapper { - width: 100%; - padding: 0px; - margin: 0px; -} - -.topbanner { - background: #FFF; - height: 25px; -} - -.topnav { - border-top: 1px solid #ADADD8; - border-left: 1px dotted #ADADD8; - border-right: 1px dotted #ADADD8; - width: 12.5%; -} - -.banner { - border-bottom: 1px solid #000; - border-top: 1px solid #000; - background: #9999CD; - height: 136px; -} - -.omgspacer { - height: 10px; -} - -.content { - width: 75%; - padding: 3px; - border: 1px dashed #ADADD8; -} - -.contenttitle { - font-size: 20px; - background: #D3D3EB; - color: #8282AE; -} - -.contentbg { - font-size: 15px; - background: #F1F1FA; -} - -.spaceromg { - height: 20px; -} - -.copyright { - background: #BDBDE0; - height: 10px; - color: #000;
\ No newline at end of file diff --git a/doc/readme/settingup.html b/doc/readme/settingup.html deleted file mode 100644 index b35f4d8..0000000 --- a/doc/readme/settingup.html +++ /dev/null @@ -1,126 +0,0 @@ -<html> -<head><title>eAthena 1.0 RC5 Readme</title> -<meta http-equiv="expires" content="-1" /> -<meta http-equiv="pragma" content="no-cache" /> -<meta name="author" content="eAthena Development Team" / -<meta name="description" content="eAthena, ro server emulator" /> -<meta name="keywords" content="eathena, ro, ragnarok online, server emulator, server software" /> -<link href="./rc5.css" media="screen" rel="stylesheet" type="text/css"> -</head> -<body> -<table class="wrapper"> - <tr class="topbanner"> - <td class="topnav"><b><a href="../readme.html">Intro</a></b></td> - <td class="topnav"><b><a href="./changelog.html">Changelog</a></b></td> - <td class="topnav"><b><a href="./features.html">Features</a></b></td> - <td class="topnav"><b><a href="./Npcfeatures.html">Npc Features</a></b></td> - <td class="topnav"><b><a href="./settingup.html">Setting Up</a></b></td> - <td class="topnav"><b><a href="./gmcommands.html">GM Commands</a></b></td> - <td class="topnav"><b><a href="./faq.html">FAQ</a></b></td> - <td class="topnav"><b><a href="./support.html"> Support</a></b></td> - </tr> - <tr> - <td class="banner" colspan="8"> - <div align="right"><img src="./midbanner.jpg" border="0"></div> - </td> - </tr> - <tr> - <td class="omgspacer"></td> - </tr> - <tr> - <td align="middle" colspan="8"> - <table class="content"> - <tr> - <td class="contenttitle"><b>How to setup eAthena</b></td> - </tr> - <tr> - <td class="contentbg"> -<ol> - <li>Edit motd.txt, grf-files.txt & .conf files as neccessary.</li> - <li>If you want to add a user, run adduser.exe in the main eAthena -directory before starting the -server.<br> - </li> - <li>Run the login-server.exe, char-server.exe and map-server.exe in -the main eAthena directory.</li> - <li>You're done!<br> - </li> -</ol> -</td> - </tr> - </table> - </td> - </tr> - <tr> - <td class="omgspacer"></td> - </tr> - <tr> - <td align="middle" colspan="8"> - <table class="content"> - <tr> - <td class="contenttitle"><b>Upgrading eAthena</b></td> - </tr> - <tr> - <td class="contentbg"> - <span style="font-weight: bold;"> -<br> -From a release newer than 953 or 817:</span><br> -<ol> - <li>Transfer your old /save/ folder contents (Athena.txt, -Account.txt, Storage.txt, etc.) to the new /save/ folder.</li> - <li>Transfer/Edit grf-files.txt, gm-account.txt and motd.txt as -neccessary.</li> - <li>Transfer any extra custom NPCs to the /npc/ folder and edit if -neccessary.</li> - <li>Edit .conf files to setup your server.</li> - <li>You're done!</li> -</ol> - <span style="font-style: italic;">NOTE</span>: -It is not recommended to transfer your DB files<br> - as the DB files are constantly -updated by the eAthena/jAthena<br> - team. Just readd your changes to -the new DB files instead of<br> - replacing the new DB file with -your old one.<br> -<br> -<span style="font-weight: bold;"><br> -From a release older than 670:</span><br> -<ol> - <li>Transfer your old /save/ folder contents (Athena.txt, -Account.txt, Storage.txt, etc.) to the new /save/ folder.</li> - <li>Transfer/Edit grf-files.txt, gm-account.txt and motd.txt as -neccessary.</li> - <li>Transfer any extra custom NPCs to the /npc/ folder and edit if -neccessary.</li> - <li>Edit .conf files to setup your server.</li> - <li>You're done!</li> -</ol> - <span style="font-style: italic;">NOTE</span>: -It is not recommended to transfer your .conf files from<br> - your old eAthena setup to this -new one because there are always<br> - changes and new additions to -these .conf files all the time<br> -<br> - <span style="font-style: italic;">NOTE -2</span>: It is also not recommended to transfer your DB files<br> - as the DB files are constantly -updated by the eAthena/jAthena<br> - team. Just readd your changes to -the new DB files instead of<br> - replacing the new DB file with -your old one.<br> -</td> - </tr> - </table> - </td> - </tr> - <tr> - <td class="spaceromg"></td> - </tr> - <tr> - <td class="copyright" colspan="8">© Copyright 2004 eAthena Development Team<br>Design © Copyright 2004 Evera</td> - </tr> -</table> -</body>
\ No newline at end of file diff --git a/doc/readme/support.html b/doc/readme/support.html deleted file mode 100644 index b0cb6a9..0000000 --- a/doc/readme/support.html +++ /dev/null @@ -1,65 +0,0 @@ -<html> -<head><title>eAthena 1.0 RC5 Readme</title> -<meta http-equiv="expires" content="-1" /> -<meta http-equiv="pragma" content="no-cache" /> -<meta name="author" content="eAthena Development Team" / -<meta name="description" content="eAthena, ro server emulator" /> -<meta name="keywords" content="eathena, ro, ragnarok online, server emulator, server software" /> -<link href="./rc5.css" media="screen" rel="stylesheet" type="text/css"> -</head> -<body> -<table class="wrapper"> - <tr class="topbanner"> - <td class="topnav"><b><a href="../readme.html">Intro</a></b></td> - <td class="topnav"><b><a href="./changelog.html">Changelog</a></b></td> - <td class="topnav"><b><a href="./features.html">Features</a></b></td> - <td class="topnav"><b><a href="./Npcfeatures.html">Npc Features</a></b></td> - <td class="topnav"><b><a href="./settingup.html">Setting Up</a></b></td> - <td class="topnav"><b><a href="./gmcommands.html">GM Commands</a></b></td> - <td class="topnav"><b><a href="./faq.html">FAQ</a></b></td> - <td class="topnav"><b><a href="./support.html"> Support</a></b></td> - </tr> - <tr> - <td class="banner" colspan="8"> - <div align="right"><img src="./midbanner.jpg" border="0"></div> - </td> - </tr> - <tr> - <td class="omgspacer"></td> - </tr> - <tr> - <td align="middle" colspan="8"> - <table class="content"> - <tr> - <td class="contenttitle"><b>Forums:</b></td> - </tr> - <tr> - <td class="contentbg"> -<a - href="http://eathena.deltaanime.net">http://eathena.deltaanime.net</a> -Our Official Webpage.<br> -<a href="http://forum.asb-sakray.net">http://forum.asb-sakray.net</a> Aegis -Support Board.<br> -<a href="http://www.evera-aura.net">http://www.evera-aura.net</a> Evera's Site<br> -<a href="http://eathena.systeminplace.net">eathena.systeminplace.net</a> Valaris's Site<br> -<br> -<span style="font-weight: bold;">IRC Channel:<br> -<span style="font-weight: bold;"></span></span>irc.deltaanime.net -#athena (Please make sure to check both forums before coming into the -channel to ask questions, or else you may not be answered and possibly -ridiculed.)<span style="font-weight: bold;"><span - style="font-weight: bold;"><span style="font-weight: bold;"></span></span><br> -</span><br> -</td> - </tr> - </table> - </td> - </tr> - <tr> - <td class="spaceromg"></td> - </tr> - <tr> - <td class="copyright" colspan="8">© Copyright 2004 eAthena Development Team<br>Design © Copyright 2004 Evera</td> - </tr> -</table> -</body>
\ No newline at end of file diff --git a/doc/script_ref.txt b/doc/script_ref.txt deleted file mode 100644 index 3a0ccfe..0000000 --- a/doc/script_ref.txt +++ /dev/null @@ -1,1485 +0,0 @@ -AthenaNPCScript - -- Table of contents - 0. Introduction - 1. Definition of NPC - 2. Explanation of Script, and Fundamental Rule - 3. Imperative Sentence, Function, and Constant Label - 4. Error Message - 5. Postscript - -0. Introduction - The function and form which are contained in this text refer to npc_sample.txt contained in the newest snapshot, and are described. - The convenience of the editor which shows this text is considered, <tab> is written and <n> etc. is written. [ a tab character ] [ arbitrary values ]. - Although it is a coordinate system, please make a lower figure reference. - The increase in ?Y - ( 0,200)--(200,200) - | | - | | - | | - | | - | | - ( 0, 0)--(200, 0)-> the increase in X - -1. Definition of NPC - if it is below an athena directory -- anywhere -- being good (if it being able to do below athena/npc) -- please create txt for the time being - The NPC describes first what is shown (a way of speaking called NPC depending on the case is unsuitable). - - * Warp point : perform movement between MAP. - <gatname>,<x>,<y><tab>warp<tab><displayname><tab><dx>,<dy>,<destination_gatname>,<destination_x>,<destination_y> - - gatname The MAP file name on which a warp point is put is specified. Please do not forget gat. - x The horizontal coordinates on which a warp point is put are specified. - y The vertical coordinates on which a warp point is put are specified. - displayname It is a warp point discernment child. You may overlap. It uses by debugging. - dx It is the horizontal effect range of a warp point. - dy It is the vertical effect range of a warp point. Probably I do not write a circle but think that it is a region. - Example of dx and dy (- is x and y) : - 0,0 1,0 2,2 - *@*- *-*-*-*-*- *-*-*-*-*-*-*- - *-*?*- *-*-*?*-*- *-*-*-*-*-*-*- - *@*- *-*-*-*-*- *-*-*-*-*-*-*- - *@ *-*-*-*?*-*-*- - *@ *-*-*-*-*-*-*- - *@ *-*-*-*-*-*-*- - *@ *-*-*-*-*-*-*- - *@ - * I hear that and it will leap if the cell of - is stepped on. - *@ - destination_gatname It is a warp place. . Even if there is gat and there is not, don't care about it. - destination_x They are warp place horizontal coordinates. - destination_y They are warp place vertical coordinates. - - Notes : - A warp point displays only that plurality is described to be at the end when located on this position. - When the coordinates of a warp place are move prohibition cells, it leaps to somewhere in the MAP. - - * Monster : manage the spawning(aka apperance in japanese.) of a monster. - <gatname>,<x>,<y>,<xs>,<ys><tab>monster<tab><displayname><tab><npcid>,<number>,<spawn_delay1>,<spawn_delay2>[,<event>] - - gatname The appearing MAP file name is specified. - x The appearing horizontal coordinates are specified. Random at 0. - y The appearing vertical coordinates are specified. Random at 0. - xs The appearing horizontal range is specified. - ys The appearing vertical range is specified. - Example of xs and ys (- is x and y) : - 0,0 2,1 - *@*? *-*-*-*-*- - *@ *-*-*?*-*- - *@ *-*-*-*-*- - *@ - * And a monster appears from the cell of -. - - displayname It is the display name of the appearing monster. - npcid Please refer to mob_db.txt. id of the monster made to appear is specified. - number It is the number of the maximum appearances in the MAP and the appearance range. - spawn_delay1 After appearing, if specified the amount of time in milliseconds before it re-appears. - spawn_delay2 After dying, if specified the amount of time in milliseconds before it re-appears. - event The specified event is generated. An abbreviation is possible. - - Notes: - spawn_delay1 and spawn_delay2 judge and give priority to whether it re-appears having been based the latest [ direction ] on which as a result. - - * Store : sell an item. - <gatname>,<x>,<y>,<direction><tab>shop<tab><displayname><tab><npcid>,<item_id>:<price>,<item_id>:<price>,<item_id>:<price> - - gatname The MAP file name to arrange is specified. - x The horizontal coordinates to arrange are specified. - y The vertical coordinates to arrange are specified. - direction Direction is specified. - Details of direction : - 7 0 1 - 6 2 - 5 4 3 - - displayname The display name of the store to arrange is specified. - npcid The display sprite ID of the store to arrange is specified. - item_id The item ID put on the store to arrange is specified. Please refer to item_db. - price The price of the item specified by item_id is set up. - each <item_id>:<price> is divided by a comma (,), and more than one can be specified. - example: - item_id:price,item_id2,price2 - - * Script : create NPC. - <gatname>,<x>,<y>,<direction><tab>script<tab><displayname><tab><npcid>,<xs>,<ys>,{ <script> ... } - - gatname The MAP file name to arrange is specified. - x The horizontal coordinates to arrange are specified. - y The vertical coordinates to arrange are specified. - direction Direction is specified. - displayname The display name of NPC to arrange is specified. It becomes an event name when npcid is -1. - When making said display name another operation event, it can be described as a display name::discernment child. - npcid The display sprite ID of NPC to arrange is specified. If -1 is specified, it will become an event in map. - xs The horizontal range which performs a script automatically is specified. - ys The vertical range which performs a script automatically is specified. It is the same as a warp. - - Explanation about the inside of {} (inside parenthesis). - Collecting by the party cannot recommend you. If it can do - gatname etc, - { - //comment - script; - label: - script; - } - Let's write by the said touch. Comment out is //and comment area is /* and */. - The ? which does not leave; (semicolon) in the script ending. - - 「<gatname>,<x>,<y>,<direction><tab>」の部分を、「-<tab>」とすることで、 - マップサーバー内には存在していても、実際のマップには配置されないNPCを作成できます。 - これは後述のデュプリケートスクリプトでコピー元として使用します。 - - *デュプリケートスクリプト:既存のNPC(のスクリプト)をコピーします。 - <gatname>,<x>,<y>,<direction><tab>duplicate(<source>)<tab><displayname><tab><npcid>,<xs><ys> - - source以外のパラメータは通常のスクリプトと同じです。 - sourceにはコピー元となるNPCの識別名を入力します。 - - コピー元のNPCがマップ上に配置されている場合、同じマップである必要があります。 - マップ上に配置されていない場合は、どのマップへもコピー可能です。 - - *ユーザー定義関数スクリプト:スクリプトから呼び出されるユーザー定義関数を作成します。 - function<tab>script<tab><name><tab>{ <script> ... } - - callfunc命令で呼び出すことの出来る関数を作成します。 - 関数の最後には必ずreturn命令を入れてください。 - - *マップフラグ:MAPのルールを管理します。 - <gatname><tab>mapflag<tab><const> - - gatname ルールを設定するMAPファイル名を指定します。 - const ルールの内容を指定します。 - - constの一覧。 - nosave<tab><gatname>,<x>,<y> - リログインした際<gatname>の座標<x>,<y>に移動します。 - nomemo<tab>dummy - メモを取ることを禁止します。 - notereport<tab>dummy - SavePointまたはRandomを指定したwarp文、ワープポータル、テレポートを禁止します。 - nobranch<tab>dummy - 古木の枝の使用を禁止します。 - pvp<tab>dummy - PVP可能MAPになります。 - nopenalty<tab>dummy - デスペナルティ無しになります。 - pvp_noparty<tab>dummy - PVPにおいて、同パーティー攻撃不可になります。 - pvp_noguild<tab>dummy - PVPにおいて、同ギルド攻撃不可になります。 - gvg<tab>dummy - シーズモードになります。 - gvg_noparty<tab>dummy - シーズモードにおいて、同パーティー攻撃不可になります。 - -2.スクリプトの説明と基本的な規則 - *数字 - 符号付の整数と16進数表記整数を使用することができます。 - 符合付整数は半角数字で123456等と記述します。 - 16進数表記整数は0x12等0xを付けて記述します。 - - *文字列 - "(ダブルクォーテーション)で囲んだ文字は文字列として評価されます。 - "(ダブルクォーテーション)記号を扱いたい場合は\"と記述します。 - \記号を扱いたい場合は\\と記述します。 - なお表示関係の物に関しては^000000等の色変更を使うことができます。 - 変数 + "文字列"といった文字列結合もできます。 - - *単項演算子 - 以下の数値専用の単項演算子が用意されています。 - - 符号逆転(2の補数) - ~ ビット論理否定(1の補数) - ! 論理否定 - - *2項演算子 - 以下2項演算子は数値と文字列で動作が異なります。 - + 加算/結合 - 数値どうしの場合は加算します。 - それ以外の場合は文字列とみなして結合します。 - - 以下の2項演算子は数値専用です。 - - 減算 - * 乗算 - / 除算 - % 剰余 - & ビット論理積 - | ビット論理和 - ^ ビット排他的論理和 - && 論理積 - || 論理和 - - 以下の2項演算子は数値どうし、または文字列どうしの比較を行います。 - これらの関係演算子は関係が成り立つと1、成り立たないと0を返します。 - == 等しい - != 等しくない - > より大きい - >= より大きいか等しい(以上) - < より小さい(未満) - <= より小さいか等しい(以下) - - *変数 - 半角英数字を使用することができます。 - 変数のスコープとライフタイムはプレフィックスにより指定します。 - 小文字のエルはプレフィックスとして扱われるので注意してください。 - (小文字のエルは今後の動作を保障されないので使用しないで下さい) - - プレフィックス スコープ ライフタイム - (なし) キャラクター 永続的 - @ キャラクター 一時的 - l 同上 同上(推奨されない) - $ マップサーバー 永続的 - $@ マップサーバー 一時的 - # アカウント 永続的 - ## アカウント(全ワールド) 永続的 - - つまり、普通の一時的な変数は@, 保存する必要のある変数は - プレフィックスなし、全てのキャラクターで共有すべき変数は $、 - 同一アカウントで共有すべき変数は # や ## を使用することになります。 - - また、変数の型はポストフィックスにより指定します。 - ただし、文字列型はキャラクター一時変数、および、 - 永続的/一時的マップサーバー変数でのみ使用できます。 - (プレフィックス @、$、$@ ) - - ポストフィックス 型 - (なし) 整数 - $ 文字列 - - <例> @hoge$ 文字列型一時的キャラクター変数 - hoge 数値型永続的キャラクター変数 - $hoge 数値型永続的全キャラクター共有変数 - - 一時的でない変数は多用すべきではありません。 - 保存する必要のないものは極力一時変数で済ませるべきです。 - 保存する必要があるのかないのかはよく考慮してください。 - 特に永続的なキャラクター/アカウント変数は、数に制限があります。 - 使用が終わって二度と使用することがないとわかっている変数は - 値を0に設定することで削除することが出来ます。 - - *配列変数 - 変数名の後に括弧 [ ] で括った式を指定することで配列変数になります。 - 変数名と"["の間に空白文字を入れることはできません。 - - <例> hoge[10] fuga[ @temp ] - - 配列の要素番号は0〜127が指定できますが、番号0は同名の変数と - 値を共有します。たとえば、hoge[0] と hoge は同じ変数です。 - - 配列変数は一時的キャラクター変数、一時的/永続的マップサーバー変数で使用できます。 - 変数の型は数値、文字列両方とも利用できます。 - - *ラベル - 半角英数およびアンダーバーが使用できます。 - 変数や命令などと区別するため L_ を先頭につけることが推奨されます。 - L_hoge: といった風に使用します。 - if文やmenu文のジャンプ先に指定されます。 - - *定数 - athenaはdb/const.txtに準拠した定数を提供します。 - スクリプト内でのみ使用可能です。 - - *埋め込み変数 - 話かけたプレイヤーのステータスなどを参照できます。 - db/const.txtに記述されています。 - スクリプト内でのみ使用可能です。 - なお、一部を除いて値の代入はできません。 - - *式 - 命令文の引数が数値だった場合、そこで利用することができます。 - スペースは要らないようですがあった方が見易いです。 - 比較演算子及び論理演算子は値が真であったとき数値の1、偽であったとき0を返します。 - - *イベント - 形を持たないスクリプトです。 - タイムアタックなどの作成に使います。 - イベント名を記述する部分では、イベント名::ラベル名とすることでそのイベントの指定したラベルから - スクリプトを開始させることができます。 - - *命令構文 - 引数は半角スペースを空けて記述してください。 - -3.命令文及び関数及び定数ラベル - *命令文 - mes命令 - mes <string>; - - string 文字列 - - <string>に記述された文字列をメッセージウィンドウに出力します。 - - next命令 - next; - - メッセージウィンドウにnextボタンを表示し、待機します。 - - close命令 - close; - - メッセージウィンドウにcloseボタンを表示し、スクリプトを終了します。 - - menu命令 - menu <string1>,<label1>[,<stringN>,<labelN>...]; - - stringN 文字列 - labelN ラベル - - メニューを表示します。<stringN>に記述された文字列を選択すると<labelN>からスクリプトを開始します。 - また、選ばれたラベルの番号は変数@menuに代入されます。 - (l15にも代入されますが、こちらは今後動作が保障されないのでl15は使用しないで下さい) - - goto命令 - goto <label>; - - label ラベル - - <label>からスクリプトを開始します。 - - cutin命令 - cutin <filename>,<position>; - - filename 文字列 - position 数値 - - カプラ職員などのカットインを表示します。<filename>は表示したいファイル名、<position>は表示位置を指定します。 - position:0,左下、1,中央下、2,右下、255,カットイン消去 - - jobchange命令 - jobchange <job>[, <upper>]; - - job 数値 - upper 数値 - - 職業を変更します。<job>はdb/const.txtを参照してください。 - <upper>は0=通常,1=転生,2=養子,-1 or 無し=現在の<upper>になります。 - jobLvは自動で1になります。 - バードとダンサーには注意してください。 - - input命令 - input [<variable>]; - - variable 変数、省略可 - - 入力ウィンドウを開き、入力データを<variable>に代入します。 - 変数の型が文字列型のときは文字列入力ウィンドウ、整数型のときは数値入力ウィンドウになります。 - <variable>を省略した場合には数値入力ウィンドウを出し、データは変数l14 (小文字のエル+14)に代入されます。 - (l14は今後の動作が保障されないので、引数は省略しないで下さい) - - warp命令 - warp <gatname>,<x>,<y>; - - gatname 文字列 - x,y 数値 - - <gatname>に指定されたMAPの座標<x>,<y>にワープします。 - <gatname>をSavePointにした場合、セーブポイントに移動します。 - Randomにした場合、そのMAP内のどこかに移動します。即ち<x><y>は無視。 - - setlook命令 - setlook <n1>,<n2>; - - n1,n2 数値 - - 外見を変更します。<n1>は部品を、<n2>は種類を指定します。 - n1:1,髪型、2,武器、3,頭上段、4,頭中段、5,頭下段、6,髪色、7,服色、8,盾 - 装備品は変更されません。アサシン男とローグ男に関しては服の色がありません。 - - - set命令 - set <variable>,<n>; - - variable 変数 - n 数値/文字列 - - <variable>に<n>を代入します。 - 文字列型を使用するときは変数名にポストフィックスを忘れないで下さい。 - - setarray命令 - setarray <variable>[,<n0>[,<n1>…]]; - - variable 変数 - nx 数値/文字列 - - 配列<variable>に値<n0>,<n1>,…のリストを代入します。 - <variable>は配列名を指定すると最初から、要素番号も指定すれば途中から代入できます。 - <例> setarray @hoge[2],16,24,32; @hogeの要素2から4までを16,24,32にする。 - - cleararray命令 - cleararray <variable>,<n>,<count>; - - variable 変数 - n 数値/文字列 - count 数値 - - 配列<variable>に値<n>を<count>個分代入します。 - <variable>は配列名を指定すると最初から、要素番号も指定すれば途中から代入できます。 - <例> cleararray @hoge[3],0,6; @hogeの要素3から8までを0にセットする - - copyarray命令 - copyarray <var1>,<var2>,<n>; - - <var1>,<var2> 変数 - n 個数 - - 配列<var1>に配列<var2>の要素<n>個をコピーします。 - <var1>,<var2>は配列名を指定すると最初から、要素番号も指定すれば途中からコピーできます。 - - deletearray命令 - - deletearray <variable>,<n>; - - variable 変数 - n 数値 - - 配列<variable>から<n>個の要素を削除し、後ろの要素を前に詰める - <variable>は配列名を指定すると最初から、要素番号も指定すれば途中から削除できます。 - - if命令 - if (<cond>) goto <label>; - - cond 数値 - label ラベル - - <cond>が0以外の場合、<label>からスクリプトを開始します。 - - getitem命令 - getitem <itemid>,<num>; - - itemid 数値または文字列 - num 数値 - - <itemid>に指定されたアイテムIDを持つアイテムを<num>個分入手します。 - <itemid>が文字列の場合、その名前(name,jname)を持つアイテムのIDを使用します。 - ただし、アイテム名はitem_db.txtなどに依存するため、テスト目的以外では使用すべきではありません。 - - getitem2命令 - getitem <itemid>,<num>,<identify>,<refine>,<attribute>,<card1>, - <card2>,<card3>,<card4> - - itemid 数値または文字列 - num,identify,refine,attribute,card1,card2,card3,card4 数値 - - <itemid>に指定されたアイテムIDを持つアイテムを<num>個分入手します。 - <identify> 鑑定状態(0で未鑑定、1で鑑定) - <refine> 精錬値 - <attribute> アイテムの状態 - <card1> 差さているカード、製造武器なら255で装備以外のアイテムでキャラの名前を入れたい時は254 - <card2> 差さているカード、製造武器なら属性と星のかけらの数を設定。星のかけらの数(範囲:0~3)*5*256 + 属性(無:0、火:3、水:1、風:4、土:2) - <card3> 差さているカード、製造武器やキャラの名前が入るアイテムはキャラIDの下の2バイト - <card4> 差さているカード、製造武器やキャラの名前が入るアイテムはキャラIDの上の2バイト - - <itemid>が文字列の場合、その名前(name,jname)を持つアイテムのIDを使用します。 - ただし、アイテム名はitem_db.txtなどに依存するため、テスト目的以外では使用すべきではありません。 - - delitem命令 - delitem <itemid>,<num>; - - itemid_num 数値 - - <itemid>に指定されたアイテムIDを持つアイテムを<num>個分失います。 - - getexp命令 - getexp <base_exp>,<job_exp>; - - base_exp 数値 - job_exp 数値 - - <base_exp>に指定された数だけBaseに経験値が入ります。 - <job_exp>に指定された数だけJobに経験値が入ります。 - マイナスの数字は適応されません。 - - makepet命令 - makepet <petid>; - - petid 数値 - - <petid>に指定されたアイテムIDを持つペットの卵を作成します。 - - viewpoint命令 - viewpoint <type>,<x>,<y>,<id>,<color>; - - type,x,y,id 数値 - color 不明 - - 資料不足なので詳しい説明はできませんが、ミニMAPに点滅する点を表示、削除します。 - type:1,表示、2,削除 - - heal命令 - heal <hp>,<sp>; - - hp,sp 数値 - - <hp>分HPを、<sp>分SPを回復します。 - - itemheal命令 - itemheal <hp>,<sp>; - - hp,sp 数値 - - <hp>分HPを、<sp>分SPを回復します。healとは違い回復するHPとSPの量にVIT(SPの場合INT)とスキルによる補正が付きます。 - - end命令 - end; - - スクリプトの実行を終了します。 - - setoption命令 - setoption <string>; - - string 文字列 - - 引用: - PCに以下で示す付属品(?)を付けます。 - 0x0000 - 付属品削除 - 0x0001 - ? - 0x0002 - ハイド(影付き) - 0x0004 - ?? - 0x0008 - カート - 0x0010 - 鷹 - 0x0020 - ペコペコ(ナイト,クルセイダーの時のみ有効) - 0x0040 - ハイド(影無し) - 0x0080 - カート2 - 0x0100 - カート3 - 0x0200 - カート4 - 0x0400 - カート5 - 0x0800 - 頭がオーク(Sageのスキル、リバースオーキッシュがかかった状態になる) - - 一端すべて消されてから付け直すので、複数指定したい場合には合計を指定してください。 - - savepoint命令 - savepoint <gatname>,<x>,<y>; - - gatname 文字列 - x,y 数値 - - <gatname>の座標<x>,<y>をセーブポイントに設定します。 - - openstorage命令 - openstorage; - - 倉庫を開きます。 - - setcart命令 - setcart; - - カートを付けます。 - - successrefitem命令 - successrefitem <n>; - - n 数値 - - 精錬成功エフェクトを表示します。 - n:1,頭装備、2,鎧、3,左手、4,右手、5,かけるもの、6,靴、7,アクセ1、8,アクセ2、9,頭中段、10,頭下段 - - failedrefitem命令 - failedrefitem <n>; - - n 数値 - - 精錬失敗エフェクトを表示します。 - n:1,頭装備、2,鎧、3,左手、4,右手、5,かけるもの、6,靴、7,アクセ1、8,アクセ2、9,頭中段、10,頭下段 - - setfalcon命令 - setfalcon; - - 鷹を付けます。 - - setriding命令 - setriding; - - ペコペコに乗ります。 - - monster命令 - monster <gatname>,<x>,<y>,<mobname>,<mobid>,<num>[,<event>]; - - gatname,mobname 文字列 - x,y,mobid,num 数値 - event 文字列、省略可 - - <gatname>の座標<x>,<y>に<mobname>を持つ<mobid>に指定されたIDを持つモンスターを<num>体出現させます。 - <gatname>がthisの場合スクリプトを実行したプレイヤーがいるMAP、 - <x><y>が-1の場合、スクリプトを実行したプレイヤーの座標、 - <mobname>が--en--の場合英語名、--ja--の場合日本語名、<mobid>が-1の場合ランダム。 - そのモンスターを倒したとき<event>を開始します。 - - announce命令 - announce <string>,<flag>; - - string 文字列 - flag 数値 - - <string>をGMアナウンスで表示します。 - <flag>は以下に示す通りです。 - エリアフラグ - 0x00 すべてのMAPに送信 - 0x01 同じMAP - 0x02 画面内 - 0x03 自分のみ - 0x04 同じMAP鯖 - 色フラグ - 0x00 黄色 - 0x10 青色 - 特殊フラグ - 0x00 特に無し - 0x08 イベント用 - - エリアフラグと色フラグと特殊フラグの合計を指定してください。 - - killmonster命令 - killmonster <gatname>[,<event>]; - - gatname 文字列 - event 文字列、省略可 - - <gatname>に存在するモンスターをすべて殺します。 - <event>によって呼び出されたモンスターのみ殺すことも可能です。<event>をAllにするとそのマップにある一時的に召喚されたモンスターを全て殺します。 - - killmonsterall命令 - killmonsterall <gatname> - - gatname 文字列 - - <gatname>に存在するモンスターをすべて殺します。killmonsterとは違ってそのマップに始めから配置されていたモンスターまで全て殺すことができます。 - - - addtimer命令 - addtimer <ms>,<event>; - - ms 数値 - event 文字列 - - 現在のプレイヤーに、<ms>ミリ秒経過した後<event>を開始するタイマーを作成します。 - このタイマーによって実行されるイベントは、このプレイヤーの情報にアクセスできます。 - プレイヤーがログアウトするとタイマーは無効になるため注意してください。 - アリーナマップなどで使用する場合はこれではなくNPCタイマーを使用してください。 - - deltimer命令 - deltimer <event>; - - event 文字列 - - 現在のプレイヤーの<event>を開始するタイマーを消去します。 - - addtimercount命令 - addtimercount <event>,<ms>; - - event 文字列 - ms 数値 - - 現在のプレイヤーの<event>を開始するタイマーの開始までの時間を<ms>ミリ秒追加します。 - - initnpctimer命令 - initnpctimer [<name>]; - - <name>で指定されたNPCが持つNPCタイマーの値を0にし、カウントを開始します。 - nameを省略すると、命令を実行したNPCが対象になります。 - - このNPCタイマーはミリ秒単位でOnTimerXXXXというラベルイベントを実行します。 - <例> OnTimer1000: <= 1秒後, OnTimer30000: <= 30秒後 - - stopnpctimer命令 - stopnpctimer [<name>]; - - <name>で指定されたNPCが持つNPCタイマーのカウントを停止します。 - nameを省略すると、命令を実行したNPCが対象になります。 - - startnpctimer命令 - stopnpctimer [<name>]; - - <name>で指定されたNPCが持つNPCタイマーのカウントを再開します。 - nameを省略すると、命令を実行したNPCが対象になります。 - こちらはinitnpctimerと違い、カウントを0にリセットしません。 - stopnpctimerとセットで使用します。 - - setnpctimer命令 - setnpctimer <tick>[,<name>] - - <name>で指定されたNPCが持つNPCタイマーのカウントを変更します。 - nameを省略すると、命令を実行したNPCが対象になります。 - getnpctimerを利用すれば、カウントを増減できます。 - - disablenpc命令 - disablenpc <npcname>; - - npcname 文字列 - - <npcname>を無効にします。 - - enablenpc命令 - enablenpc <npcname>; - - npcname 文字列 - - <npcname>を有効にします。 - - mapannounce命令 - mapannounce <gatname>,<string>,<flag>; - - gatname,string 文字列 - flag 数値 - - <gatname>全体に<string>をGMアナウンスで表示します。 - flag:0,黄色文字、16,青文字 - - areaannounce命令 - areannounce <gatname>,<x0>,<y0>,<x1>,<y1>,<string>,<flag>; - - gatname,string 文字列 - x0,y0,x1,y1,flag 数値 - - <gatname>の<x0>,<y0>から<x1>,<y1>の範囲内に対し<string>をGMアナウンスで表示します。 - flag:0,黄色文字、16,青文字 - - areawarp命令 - areawarp <gatname>,<x0>,<y0>,<x1>,<y1>,<gatname2>,<x>,<y>; - - gatname,gatname2 文字列 - x0,y0,x1,y1,x,y 数値 - - <gatname>の<x0>,<y0>から<x1>,<y1>の範囲内にいるPCを<gatname2>の座標<x>,<y>に移動させます。 - - areamonster命令 - areamonster <gatname>,<x0>,<y0>,<x1>,<y1>,<mobname>,<mobid>,<num>[,<event>]; - - gatname,mobname 文字列 - x0,y0,x1,y1,mobid,num 数値 - event 文字列、省略可 - - <gatname>の<x0>,<y0>から<x1>,<y1>の範囲内に<mobname>を持つ<mobid>に指定されたIDを持つモンスターを<num>体出現させます。 - <gatname>がthisの場合スクリプト実行MAP、<x><y>が-1の場合ランダム座標、 - <mobname>が--en--の場合英語名、--ja--の場合日本語名、<mobid>が-1の場合ランダム。 - そのモンスターを倒したとき<event>を開始します。 - - percentheal命令 - percentheal <hp>,<sp>; - - hp,sp 数値 - - HPとSPを<hp>%、<sp>%分回復します。 - - resetstatus命令 - resetstatus; - - ステータスポイントをリセットします。 - - resetskill命令 - resetskill; - - スキルポイントをリセットします。 - - statusup命令 - statusup <st>; - - st 数値 - - <st>で指定された基本ステータス値を、ステータスポイントを消費して1上げる。 - <st>は bStr, bVit, bInt, bAgi, bDex, bLuk で指定する。 - - statusup2命令 - statusup2 <st>,<n>; - - st,n 数値 - - <st>で指定された基本ステータス値を、ステータスポイントを消費せずに<n>上げる。 - <st>は bStr, bVit, bInt, bAgi, bDex, bLuk で指定する。 - - skill命令 - skill <skillid>,<skilllv>,<flag>; - - skillid,skilllv,flag 数値 - - <skillid>に指定されたIDを持つLV<skilllv>スキルを習得します。 - flag:0,恒久的なスキル取得(スキルツリーにない物は無効)、1,一時的(範囲は不明)な取得、 - <skilllv>を0にするとこでそのスキルを忘れさせることも可能です。 - - waitingroom命令 - waitingroom <title>,<limit>[,<event>[,<trigger>]]; - - title 文字列 - limit 数値 - event 文字列、省略可 - trigger 数値、省略可 - - <title>をタイトルとしてチャットルームを表示させます。 - <trigger>を満たしたとき、<event>を動作させることが可能です。 - <trigger>を省略すると<limit>の数値が使用されます。 - - delwaitingroom命令 - delewaitingroom [<name>] - - name 文字列、省略可 - - 指定したNPCのチャットルームを閉じます。 - <name>を省略すると、命令を実行したNPCが対象になります。 - - disablewaitingroomevent命令 - disablewaitingroomevent [<name>] - - name 文字列、省略可 - - <name>で指定したNPCのチャットルームのイベントを無効にします。 - <name>を省略すると、命令を実行したNPCが対象になります。 - - enablewaitingroomevent命令 - enablewaitingroomevent [<name>] - - name 文字列、省略可 - - <name>で指定したNPCのチャットルームのイベントを有効にします。 - <name>を省略すると、命令を実行したNPCが対象になります。 - また、既にイベントが起こる人数に達している場合、 - 即座にイベントを実行します。 - - warpwaitingnpc命令 - warpwaitingnpc <gatname>,<x>,<y>[,<num>]; - - gatname 文字列 - x,y,num 数値 - - 命令を実行したNPCのチャットルームに入っているPCのうち、 - <num>で指定した人数を、<gatname>の座標<x>,<y>に移動させます。 - <num>を省略すると waitingroomの<trigger>で指定した人数を使用します。 - - ワープさせた人数を $@warpwaitingpcnum に、ワープさせた人のアカウントIDを - 配列 $@warpwaitingpc にセットします(先頭から人数分)。 - - - emotion命令 - emotion <n>; - - n 数値 - - <n>エモーションを出します。 - - setmapflag命令 - setmapflag <gatname>,<flag>; - - gatname 文字列 - flag 数値 - - <gatname>のmapflagを追加します。 - <flag>はdb/const.txtを参照してください。 - - removemapflag命令 - removemapflag <gatname>,<flag>; - - gatname 文字列 - flag 数値 - - <gatname>のmapflagを消去します。 - <flag>はdb/const.txtを参照してください。 - - pvpon命令 - pvpon <gatname>; - - gatname 文字列 - - <gatname>をPVP可能MAPにします。 - - pvpoff命令 - pvpoff <gatname>; - - gatname 文字列 - - <gatname>をPVP不可MAPにします。 - - gvgon命令 - gvgon <gatname>; - - gatname 文字列 - - <gatname>をシーズモードにします。 - - gvgoff命令 - gvgoff <gatname>; - - gatname 文字列 - - <gatname>を非シーズモードにします。 - - setmapflagnosave命令 - setmapflagnosave <gatname>,<savegatname>,<x>,<y>; - - gatname,nosavegat 文字列 - x,y 数値 - - <gatname>のmapflagにnosave、引数として<savegatname>,<x>,<y>を設定します。 - - detachrid命令 - detachrid; - - NPCにアタッチされているIDをクリアします。 - 以後、キャラクター情報を必要とする命令が実行できなくなります。 - - doevent命令 - doevent <name>; - - name 文字列 - - プレイヤー主体のイベントを起こします。<name>にはイベント名を指定します。 - プレイヤーが他のNPCと会話中などで実行できない場合、キューに入り、実行可能になるまで待って実行されます。 - キューのサイズはとても小さいので、連続で起こるとイベントが無視されるかもしれません。 - ラベル付きイベントも指定できますが、NPC名を省略できないので注意してください。 - - donpcevent命令 - donpcevent <name>; - - name 文字列 - - プレイヤーがアタッチされていない(NPC主体の)イベントを起こします。 - <name>にはイベント名を指定します。イベントは即座に実行されます。 - ラベル付きイベントも指定でき、NPC名を省略することで、イベントをブロードキャストできます。 - (複数のNPCの同じ名前のラベルを実行できる。 例>"::OnEvent") - - callsub命令 - callsub <label> - - label ラベル - - 同一スクリプト内のラベル<label>をサブルーティンとして実行します。 - サブルーティンから復帰するときはreturn命令を使用してください。 - この命令はreturn命令の実行状況によっては関数として使用することも出来ます。 - - callfunc命令 - callfunc <func> - - func 文字列 - - <func>で定義されたユーザー定義関数を実行します。 - ユーザー定義関数から復帰するときはreturn命令を使用してください。 - この命令はreturn命令の実行状況によっては関数として使用することも出来ます。 - - return命令 - return <retval> - - retval 数値または文字列、省略可 - - 直ちにサブルーティンもしくはユーザー定義関数を抜け、呼び出し元に戻ります。 - <retval>は戻り値で、callsubまたはcallfuncが関数として呼び出されているとき、この戻り値が使用されます。 - callsubまたはfuncが命令として呼ばれているときは、<retval>は省略してください。 - - *関数 - rand関数 - rand(<n1>[,<n2>]) - - n1 数値 - n2 数値、省略可 - - <n1>のみ指定されていた場合、0から<n1>-1までの数値をランダムに選んで返します。 - <n2>を指定した場合、<n1>から<n2>までの数チをランダムに選んで返します。 - - getitemname関数 - getitemname(<itemid>) - - itemid 数値 - - <itemid>に指定されたIDを持つアイテムのjnameを文字列で返します。 - なお、アイテム名はitem_db.txtを参照します - - countitem関数 - countitem(<itemid>) - - itemid 数値または文字列 - - <itemid>に指定されたIDを持つアイテムの所持数を返します。 - <itemid>が文字列の場合、その名前(name,jname)を持つアイテムのIDを使用します。 - ただし、アイテム名はitem_db.txtなどに依存するため、テスト目的以外では使用すべきではありません。 - - checkweight関数 - checkweight(<itemid>,<num>) - - itemid 数値または文字列 - num 数値 - - <itemid>に指定されたIDを持つアイテムを<num>個持つことができるのならば1を、 - できなければ0を返します。 - <itemid>が文字列の場合、その名前(name,jname)を持つアイテムのIDを使用します。 - ただし、アイテム名はitem_db.txtなどに依存するため、テスト目的以外では使用すべきではありません。 - - strcharinfo関数 - strcharinfo(<n>) - - n 数値 - - キャラ情報を返します。 - n:0,キャラ名、1,パーティー名、2,ギルド名 - - getequipname関数 - strcharinfo(<n>) - - n 数値 - - 装備品名を返します。 - n:1,頭装備、2,鎧、3,左手、4,右手、5,かけるもの、6,靴、7,アクセ1、8,アクセ2、9,頭中段、10,頭下段 - - getequipisequiped関数 - getequipisequiped(<n>) - - n 数値 - - 装備していたら1、していなかったら0を返します。 - n:1,頭装備、2,鎧、3,左手、4,右手、5,かけるもの、6,靴、7,アクセ1、8,アクセ2、9,頭中段、10,頭下段 - - getequipisenableref関数 - getequipisenableref(<n>) - - n 数値 - - 精錬できる場合は1、できない場合は0を返します。 - n:1,頭装備、2,鎧、3,左手、4,右手、5,かけるもの、6,靴、7,アクセ1、8,アクセ2、9,頭中段、10,頭下段 - - getequipisidentify関数 - getequipisidentify(<n>) - - n 数値 - - 鑑定済みの場合1、未鑑定の場合0を返します。 - n:1,頭装備、2,鎧、3,左手、4,右手、5,かけるもの、6,靴、7,アクセ1、8,アクセ2、9,頭中段、10,頭下段 - - getequiprefinerycnt関数 - getequiprefinerycnt(<n>) - - n 数値 - - 精錬の度合いを返します。 - n:1,頭装備、2,鎧、3,左手、4,右手、5,かけるもの、6,靴、7,アクセ1、8,アクセ2、9,頭中段、10,頭下段 - - getequipweaponlv関数 - getequipweaponlv(<n>) - - n 数値 - - 武器LVを返します。防具の場合には0、あとは武器LVに対応します。 - n:1,頭装備、2,鎧、3,左手、4,右手、5,かけるもの、6,靴、7,アクセ1、8,アクセ2、9,頭中段、10,頭下段 - - getequippercentrefinery関数 - getequippercentrefinery(<n>) - - n 数値 - - 精錬成功率を返します。 - n:1,頭装備、2,鎧、3,左手、4,右手、5,かけるもの、6,靴、7,アクセ1、8,アクセ2、9,頭中段、10,頭下段 - - getusers関数 - getusers(<n>) - - n 数値 - - 人数を返します。 - n:0,PCのいるMAPの総人数、1,全MAPの総人数(即ちログイン人数)、8,NPCの存在するMAPの総人数 - - getmapusers関数 - getmapusers(<gatname>) - - gatname 文字列 - - <gatname>に存在する総人数を返します。 - - getareausers関数 - getareausers(<gatname>,<x0>,<y0>,<x1>,<y1>) - - gatname 文字列 - x0,y0,x1,y1 数値 - - <gatname>の<x0>,<y0>から<x1>,<y1>の範囲内にいる人数を返します。 - - getskilllv関数 - getskilllv(<skillid>) - - skillid 数値 - - <skillid>で指定したIDを持つスキルのLVを返します。習得していない場合は0を返します。 - - getcharid関数 - getcharid(<n>) - - n 数値 - - キャラ情報をIDで返します。 - n=0 キャラID - n=1 パーティー - n=2 ギルド - n=3 アカウントID - - getpartyname関数 - getpartyname(<n>) - - n 数値 - - <n>で指定したIDを持つパーティー名を返します。 - - getguildname関数 - getguildname(<n>) - - n 数値 - - <n>で指定したIDを持つギルド名を返します。 - - getguildmaster関数 - getguildname(<n>) - - n 数値 - - <n>で指定したIDを持つギルドのマスターの名前を返します。 - - getguildmasterid関数 - getguildmasterid(<n>) - - n 数値 - - <n>で指定したIDを持つギルドのマスターのキャラクターIDを返します。 - - basicskillcheck関数 - basicskillcheck(0); - - battle_athena.confのbasic_skill_checkの設定値を返します。0は意味はありませんが何も入れなかった場合エラーになります。 - basic_skill_checkとカプラの倉庫利用を合わせる為に作った物でそれ以外の機能はありません。戻った数値が0ならbasic_skill_checkがno、1ならyesです。 - - getgmlevel関数 - getgmlevel(0); - - プレイヤーのGMレベルを返します。 - - guildopenstorage関数 - guildopenstorage(0); - - ギルド倉庫を開きます。 - 返た数値が2ならギルドに所属してないキャラと言う意味で - 1なら他のギルドメンバーが倉庫を使用中の意味です。 - 0なら成功的にギルド倉庫が開いたとのことです。 - - getwaitingroomstate関数 - getwaitingroomstate(<num>,[<name>]) - - num 数値 - name 文字列、省略可 - - <name>で指定したNPCのチャットルームの状態を返します。 - <name>を省略すると、命令を実行したNPCが対象になります。 - <num>で得たい情報を指定します。 - - num=0 現在チャットルームに入っている人数(数値) - num=1 チャットルームの限界人数(数値) - num=2 チャットルームのイベントを起こす人数(数値) - num=3 チャットルームのイベントが有効かどうか(数値) - num=4 チャットルームのタイトル(文字列) - num=5 チャットルームのパスワード(文字列) - num=16 チャットルームのイベント名(文字列) - num=32 チャットルームが満員かどうか(数値) - num=33 チャットルームでイベントが起こる人数かどうか(数値) - - getnpctimer関数 - getnpctimer(<num>[,<name>]) - - num 数値 - - <name>で指定されたNPCが持つNPCタイマーの情報を得ます。 - nameを省略すると、命令を実行したNPCが対象になります。 - <num>で得たい情報を指定します。 - - num=0 現在のNPCタイマーのカウント値 - num=1 現在NPCタイマーが動作しているかどうか - num=2 指定NPCのタイマーイベントラベルの総数 - - attachrid関数 - attachrid(<num>) - - num 数値 - - <num>で指定されたIDのキャラクターを実行したスクリプトにアタッチします。 - 以後、キャラクターに関する命令や関数/変数などは全て新しいキャラクターが対象になります。 - これはスクリプトが終了/中断する(close,end,menu,next,inputなどの実行)まで有効です。 - 主にイベントで起動されたスクリプト内でマップ変数を使って別キャラクターを - アタッチするのに使用します。getcharid(3)で所得したアカウントIDを使ってください。 - なお、デタッチにはdetachrid命令を使います。 - - 注意すべき点としては、この命令でPCをアタッチした場合、mes,menu,nextなどの - ウィンドウ(やボタン)が出る命令を実行してはいけません。 - 相手が他のNPCと会話中の場合、これらの命令は正しく動作しません。 - 情報所得命令などだけで済ませるべきです。 - - この関数はアタッチに成功したかどうかを返します。 - 偽(0)が返って来た場合は、該当キャラクターが存在していません。 - - isloggedin関数 - isloggedin(<num>) - - num 数値 - - <num>で指定されたIDのキャラクターがこのマップサーバーに - ログインしているかどうか調べます。 - - getarraysize関数 - getarraysize(<variable>) - - variable 変数 - - 配列<variable>の有効なサイズを調べます。 - ここでのサイズは要素が0(文字列変数では"")でない、 - 最大の要素番号+1 になります。 - 配列名ではなく要素番号付きで指定すると、 - 少なくともその要素までは全て有効であると仮定します。 - <例> 配列@hogeが 1,2,3,4,5 だとすると、 - getarraysize(@hoge)=5, getarraysize(@hoge[10])=10; - - callsub関数 - callsub <label> - - callsub命令を関数として実行します。詳しくはcallsub命令を見てください。 - - callfunc関数 - callfunc <func> - - callfunc命令を関数として実行します。詳しくはcallfunc命令を見てください。 - - sc_check関数 - sc_check <status-change> - - Detects whether a given status change is active. - * ステタスけすもに探し当てます。 - - getspellinvocation関数 - getspellinvocation <spellname> - - Retrieves a spell's invocation string. - * スペルの呪文(援用)に見付けます。 - - getanchorinvocation関数 - getanchorinvocation <anchor-label> - - Retrieves the invocation for a teleport anchor - * (fixme) - - getpartnerid関数 - Retrieves the RID of the player's partner, or 0 if not married. - - * (fixme) - - misceffect <id> <name> - Shows the effect with id on name. if name is omitted show on NPC. - - getskilllist - Computes the set of all skills that the player has access to. - Results are written into @skilllist_id[], @skilllist_lv[], @skilllist_flag[], - which have a total of @skilllist_count entries. - - getpoolskilllist - Same as getskilllist, but only list pool skills, and also set set - @skilllist_name$[] to the skills' names. - Note that flag & 1 here indicates that the spell is activated. - - getactivatedpoolskilllist - Same as getpoolskilllist, but only list activated pool skills. - - poolskill (skill_nr) - Moves the specified skill into the skill pool, if possible - - unpoolskill (skill_nr) - Moves the specified skill out of the skill pool, if possible - - checkpoolskill (skill_nr) - Checks whether the specified skill is in the skill pool (returns nonzero if so) - - *定数ラベル - -ラベル - if文やmenu文で使用します。次の行からスクリプトを開始します。 - - OnInitラベル - MAPがロードされたときスクリプトを開始します。 - - OnInterIfInitラベル - MAPサーバーがInterサーバーに接続したときに実行します。 - - OnCharIfInitラベル - MAPサーバーがCharサーバーに接続したときに実行します。 - - OnMinuteXXラベル - 毎時XX分に実行します。数値は十進数2桁です。 - - OnClockXXXXラベル - 毎日XX時XX分に実行します。数値は十進数4桁です。 - - OnHourXXラベル - 毎日XX時00分に実行します。数値は十進数2桁です。 - - OnDayXXラベル - 毎月XX日00時00分に実行します。数値は十進数2桁です。 - - OnTimerXラベル - NPCタイマーのカウントがXになったときに実行されます。 - このXはミリ秒単位です。桁数は関係ありません。 - - OnAgitInitラベル - ギルド城データと占拠ギルド情報がマップサーバー内に - 所得されたときに実行されます。 - ギルド城関係のNPCの初期化に使用します。 - - OnAgitStartラベル - ギルド攻城戦が始まったときに実行されます。 - - OnAgitEndラベル - ギルド攻城戦が終わったときに実行されます。 - - OnAgitBreakラベル - エンペリウムを破壊したときに実行されます。 - このラベルは破壊したプレイヤーを主体にして実行されます。 - - OnAgitEliminateラベル - エンペリウム破壊後、ギルドの所有者が書き換わるときに - 呼ばれます。 - - OnPCKilledEventラベル - Invoked when a PC is killed in PVP. - Set @killerrid to the RID of the killer, @victimrid to the RID of the - victim, and @victimlvl to the experience level of the victim. This - is called in the RID context of the victim. - * PVP人殺しの時に呼出す。 @killerridはキラーのRIDに代入されます、 - @victimridは虜のRID、@victimlvlは虜のレベル。虜のRID属性に呼出す。 - - OnPCKillEventラベル - Same as the OnPCKilledEvent, except that it is invoked in the RID - context of the killer. - *OnPCKilledEventの同じですけど、RID属性はキラーのです。 - - *注意事項 - 文字列と説明されている引数は""で囲ってください。 - -4. Error Message - - * Make an error at the time of compile (it is a thing at the time of map server starting). - A place is displayed for the line number of an error. - - unexpected expr end - It is the end of an unexpected formula. - ', ', and';' are in the beginning of a formula. - - unmatch ')' - ')' does not match. - Correspondence of parenthesis'('')' is amusing. - - unexpected newline @ string - It is the new-line which is not expected in a character sequence. - There is a new-line in the middle of a character sequence (surrounded by '"'). - Probably it is a failure of '"' to close. - - unexpected eof @ string - It is the file terminus which is not expected in a character sequence. - The file finished in the middle of the character sequence. - Probably it is a failure of '"' to close. - - unexpected character - unexpected char - It is an unexpected character. - It is thought that the variable etc. is not following a naming rule. - - l14 and l15 is DEPRECATED. use @menu instead of l15. - l14 and l15 are not recommended. Please use @menu instead of l15. - - prefix 'l' is DEPRECATED. use prefix '@' instead. - Prefix'l' is not recommended. Please use '@' instead. - - unmatch ']' - ']' does not carry out an interval. - Correspondence of parenthesis']' is missing. - - expect function - 関数を期待していました - 関数呼び出し演算子'('の前に関数以外のシンボルがあります。 - おそらく関数名を間違えています。 - - expect ',' or ')' at func params - 関数の引数において','か')'を期待していました - おそらく引数区切りの','か')'を忘れています。 - - func request '(' ')' - 関数呼び出しの括弧対応問題 - おそらく引数の数が128を超えました。 - - illeagal number of parameters - パラメータの数が不正です - 関数/命令パラメータの個数が異なります。 - 引数の個数を確認してください。 - エラー位置は全ての引数の後になります。 - - expect command - 命令を期待していました - 命令以外のシンボルが突然出現しています。 - おそらく命令名を間違えています。 - - expect ',' or ';' at cmd params - 命令の引数において','か';'を期待していました - おそらく引数区切りの','か';'を忘れています。 - - need ';' - ';'が必要です - おそらく引数の数が128を超えました。 - - 実行時のエラー - fatal error ! player not attached! - 致命的エラー!プレイヤーがアタッチされていません! - - キャラクターを特定できないイベントで実行されている - スクリプトの中でキャラクター情報が必要な命令や関数、 - 変数へアクセスしました。attachrid関数を使うか、 - キャラクター情報が不要な命令を使用してください。 - もしくは、attachrid関数で設定された情報が不正です。 - なお、このエラーが起こると直後にコアを吐くと思われます。 - - NPC主体イベントでannounceしたときにフラグ0x08を指定していない - 場合もこのエラーがでます。 - - - illeagal scope string variable. - 文字列変数のスコープが不正です。 - 未対応のプレフィックスで文字列変数が使用されました。 - プレフィックスを確認してください。 - - illeagal scope - スコープが不正です。配列変数未対応のプレフィックスを - 持つ変数に配列変数系の命令を実行した場合など。 - - not label ! - goto/menu命令でラベルが指定されるべきところに - ラベル以外のシンボルが指定されています。 - もしくは、ラベル名と変数名がバッティングしています。 - - buildin_set: not name - set命令で第一引数が変数名ではありません。 - - getelementofarray (operator[]): param2 illeagal number - 配列変数で[]内の値が不正です - []内の値が0未満か128以上になりました - - getelementofarray (operator[]): param1 not name - 配列変数で[]の前のシンボルが変数名ではありません。 - - op_2: int&str, str&int not allow. - 関係演算子(比較演算子)で、数値と文字列、もしくは - 文字列と数値が指定されました。 - - infinity loop ! - スクリプトの実行命令数か、goto/menu命令実行回数が - 多すぎるので、無限ループと判断しました。 - スクリプトの実行は強制的に中断されました。 - - not function and command ! - 関数実行/命令実行部分で、関数でも命令でもない - シンボルがありました。 - if文のなかである可能性が高いです。 - - return without callfunc or callsub ! - callfuncやcallsubされていないのにreturn命令を実行しました。 - - stack.sp(?) != default(?) - スタックポインタが基準スタックポインタと異なっています。 - 命令を実行した結果、スタックポインタが狂いました。 - 関数を命令として実行した可能性があります。 - - -5. Postscript - NPC contained in snapshot was made reference in creating this text. - I appreciate people which created NPC. - -It corrects based on text by asong (2004/3/1). - - diff --git a/eathena.sh b/eathena.sh deleted file mode 100755 index 98384e5..0000000 --- a/eathena.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -# $Id: eathena.sh,v 1.5 2006/03/10 21:41:09 Platyna Exp $ -#---------------------------------------------------------------------- -# Description: Simple script to control eAthena locally. -# Author: Zuzanna K. Filutowska <platyna@platinum.linux.pl> -# Created at: Fri Feb 17 18:23:56 CET 2006 -# License: GPL -# Copyright (c) 2006 Zuzanna K. Filutowska All rights reserved. -# -#---------------------------------------------------------------------- -# Configure section: -PATH=$PATH:. -SRVHOMEDIR=$HOME/tmwserver -#---------------------------------------------------------------------- -# main() - -ulimit -u 10 - -cd ${SRVHOMEDIR} - -eathena_start() { - if [ -x ${SRVHOMEDIR}/eathena-monitor ]; - then echo "Starting eathena monitor..." - ${SRVHOMEDIR}/eathena-monitor ${SRVHOMEDIR}/conf/eathena-monitor.conf - else echo "Eathena monitor binary is not executable or not found." - fi -} - -eathena_stop() { - echo "Shutting down eathena monitor..." - killall eathena-monitor -} - -eathena_restart() { - eathena_stop - echo "Waiting for all eathena processes to end..." - sleep 1 - eathena_start -} - -case "$1" in -'start') - eathena_start - ;; -'stop') - eathena_stop - ;; -'restart') - eathena_restart - ;; -*) - echo "usage $0 start|stop|restart" -esac diff --git a/etc/tmwa/shared.conf b/etc/tmwa/shared.conf new file mode 100644 index 0000000..a05b6cb --- /dev/null +++ b/etc/tmwa/shared.conf @@ -0,0 +1 @@ +// This file is used for common config between all servers diff --git a/include/tmwa/shared.hpp b/include/tmwa/shared.hpp new file mode 100644 index 0000000..c624e54 --- /dev/null +++ b/include/tmwa/shared.hpp @@ -0,0 +1,28 @@ +#pragma once +// tmwa/shared.hpp - Public header to ensure install is working. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <cstdbool> + + +namespace tmwa +{ + __attribute__((visibility("default"))) + void check_paths(); +} // namespace tmwa diff --git a/share/tmwa/shared.data b/share/tmwa/shared.data new file mode 100644 index 0000000..f30511f --- /dev/null +++ b/share/tmwa/shared.data @@ -0,0 +1 @@ +// This file is used for common data between all servers diff --git a/src/admin/fwd.hpp b/src/admin/fwd.hpp new file mode 100644 index 0000000..46674c8 --- /dev/null +++ b/src/admin/fwd.hpp @@ -0,0 +1,27 @@ +#pragma once +// admin/fwd.hpp - list of type names for admin client +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +// meh, add more when I feel like it +} // namespace tmwa diff --git a/src/admin/ladmin.cpp b/src/admin/ladmin.cpp index 9bbd710..9dae089 100644 --- a/src/admin/ladmin.cpp +++ b/src/admin/ladmin.cpp @@ -1,4 +1,4 @@ -#include <arpa/inet.h> +#include "ladmin.hpp" // ladmin.cpp - Local administration tool. // // Copyright © ????-2004 Athena Dev Teams @@ -26,30 +26,37 @@ #include <cassert> +#include <algorithm> + #include "../strings/mstring.hpp" #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" #include "../strings/vstring.hpp" -#include "../generic/md5.hpp" - #include "../io/cxxstdio.hpp" #include "../io/read.hpp" #include "../io/tty.hpp" #include "../io/write.hpp" +#include "../net/ip.hpp" +#include "../net/packets.hpp" + +#include "../proto2/any-user.hpp" +#include "../proto2/login-admin.hpp" + #include "../mmo/config_parse.hpp" #include "../mmo/core.hpp" #include "../mmo/human_time_diff.hpp" #include "../mmo/mmo.hpp" -#include "../mmo/socket.hpp" #include "../mmo/utils.hpp" #include "../mmo/version.hpp" #include "../poison.hpp" +namespace tmwa +{ static int eathena_interactive_session; #define Iprintf if (eathena_interactive_session) PRINTF @@ -68,9 +75,9 @@ IP4Address login_ip = IP4_LOCALHOST; // IP of login-server static int login_port = 6900; // Port of login-server static -AccountPass admin_pass = stringish<AccountPass>("admin"); // Administration password +AccountPass admin_pass = stringish<AccountPass>("admin"_s); // Administration password static -AString ladmin_log_filename = "log/ladmin.log"; +AString ladmin_log_filename = "log/ladmin.log"_s; //------------------------------------------------------------------------- // LIST of COMMANDs that you can type at the prompt: // To use these commands you can only type only the first letters. @@ -259,17 +266,19 @@ static TString parameters; // needs to be global since it's passed to the parse function // really should be added to session data static -int list_first, list_last, list_type, list_count; // parameter to display a list of accounts +AccountId list_first, list_last; +static +int list_type, list_count; // parameter to display a list of accounts static int already_exit_function = 0; // sometimes, the exit function is called twice... so, don't log twice the message -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-noreturn" +DIAG_PUSH(); +DIAG_I(missing_noreturn); void SessionDeleter::operator()(SessionData *) { - assert(false && "ladmin does not have sessions"); + assert(false && "ladmin does not have sessions"_s); } -#pragma GCC diagnostic pop +DIAG_POP(); //------------------------------ // Writing function of logs file @@ -285,13 +294,14 @@ void ladmin_log(XString line) log_with_timestamp(logfp, line); } -static +static __attribute__((noreturn)) void delete_fromlogin(Session *) { + login_session = nullptr; { - PRINTF("Impossible to have a connection with the login-server [%s:%d] !\n", + PRINTF("Impossible to have a connection with the login-server [%s:%d] !\n"_fmt, login_ip, login_port); - LADMIN_LOG("Impossible to have a connection with the login-server [%s:%d] !\n", + LADMIN_LOG("Impossible to have a connection with the login-server [%s:%d] !\n"_fmt, login_ip, login_port); exit(0); } @@ -352,315 +362,315 @@ void display_help(ZString param) XString command = param.xislice_h(std::find(param.begin(), param.end(), ' ')); if (command.startswith('?')) - command = "help"; + command = "help"_s; - LADMIN_LOG("Displaying of the commands or a command.\n"); + LADMIN_LOG("Displaying of the commands or a command.\n"_fmt); - if (command == "help") + if (command == "help"_s) { - PRINTF("help/?\n"); - PRINTF(" Display the description of the commands\n"); - PRINTF("help/? [command]\n"); - PRINTF(" Display the description of the specified command\n"); + PRINTF("help/?\n"_fmt); + PRINTF(" Display the description of the commands\n"_fmt); + PRINTF("help/? [command]\n"_fmt); + PRINTF(" Display the description of the specified command\n"_fmt); } - else if (command == "add") + else if (command == "add"_s) { - PRINTF("add <account_name> <sex> <password>\n"); - PRINTF(" Create an account with the default email (a@a.com).\n"); - PRINTF(" Concerning the sex, only the first letter is used (F or M).\n"); - PRINTF(" The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail.\n"); - PRINTF(" When the password is omitted,\n"); - PRINTF(" the input is done without displaying of the pressed keys.\n"); - PRINTF(" <example> add testname Male testpass\n"); + PRINTF("add <account_name> <sex> <password>\n"_fmt); + PRINTF(" Create an account with the default email (a@a.com).\n"_fmt); + PRINTF(" Concerning the sex, only the first letter is used (F or M).\n"_fmt); + PRINTF(" The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail.\n"_fmt); + PRINTF(" When the password is omitted,\n"_fmt); + PRINTF(" the input is done without displaying of the pressed keys.\n"_fmt); + PRINTF(" <example> add testname Male testpass\n"_fmt); } - else if (command == "ban") + else if (command == "ban"_s) { - PRINTF("ban yyyy/mm/dd hh:mm:ss <account name>\n"); - PRINTF(" Changes the final date of a banishment of an account.\n"); - PRINTF(" Like banset, but <account name> is at end.\n"); + PRINTF("ban yyyy/mm/dd hh:mm:ss <account name>\n"_fmt); + PRINTF(" Changes the final date of a banishment of an account.\n"_fmt); + PRINTF(" Like banset, but <account name> is at end.\n"_fmt); } - else if (command == "banadd") + else if (command == "banadd"_s) { - PRINTF("banadd <account_name> <modifier>\n"); - PRINTF(" Adds or substracts time from the final date of a banishment of an account.\n"); - PRINTF(" Modifier is done as follows:\n"); - PRINTF(" Adjustment value (-1, 1, +1, etc...)\n"); - PRINTF(" Modified element:\n"); - PRINTF(" a or y: year\n"); - PRINTF(" m: month\n"); - PRINTF(" j or d: day\n"); - PRINTF(" h: hour\n"); - PRINTF(" mn: minute\n"); - PRINTF(" s: second\n"); - PRINTF(" <example> banadd testname +1m-2mn1s-6y\n"); - PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"); - PRINTF(" and 6 years at the same time.\n"); - PRINTF("NOTE: If you modify the final date of a non-banished account,\n"); - PRINTF(" you fix the final date to (actual time +- adjustments)\n"); + PRINTF("banadd <account_name> <modifier>\n"_fmt); + PRINTF(" Adds or substracts time from the final date of a banishment of an account.\n"_fmt); + PRINTF(" Modifier is done as follows:\n"_fmt); + PRINTF(" Adjustment value (-1, 1, +1, etc...)\n"_fmt); + PRINTF(" Modified element:\n"_fmt); + PRINTF(" a or y: year\n"_fmt); + PRINTF(" m: month\n"_fmt); + PRINTF(" j or d: day\n"_fmt); + PRINTF(" h: hour\n"_fmt); + PRINTF(" mn: minute\n"_fmt); + PRINTF(" s: second\n"_fmt); + PRINTF(" <example> banadd testname +1m-2mn1s-6y\n"_fmt); + PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"_fmt); + PRINTF(" and 6 years at the same time.\n"_fmt); + PRINTF("NOTE: If you modify the final date of a non-banished account,\n"_fmt); + PRINTF(" you fix the final date to (actual time +- adjustments)\n"_fmt); } - else if (command == "banset") + else if (command == "banset"_s) { - PRINTF("banset <account_name> yyyy/mm/dd [hh:mm:ss]\n"); - PRINTF(" Changes the final date of a banishment of an account.\n"); - PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"); - PRINTF("banset <account_name> 0\n"); - PRINTF(" Set a non-banished account (0 = unbanished).\n"); + PRINTF("banset <account_name> yyyy/mm/dd [hh:mm:ss]\n"_fmt); + PRINTF(" Changes the final date of a banishment of an account.\n"_fmt); + PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"_fmt); + PRINTF("banset <account_name> 0\n"_fmt); + PRINTF(" Set a non-banished account (0 = unbanished).\n"_fmt); } - else if (command == "block") + else if (command == "block"_s) { - PRINTF("block <account name>\n"); - PRINTF(" Set state 5 (You have been blocked by the GM Team) to an account.\n"); - PRINTF(" This command works like state <account_name> 5.\n"); + PRINTF("block <account name>\n"_fmt); + PRINTF(" Set state 5 (You have been blocked by the GM Team) to an account.\n"_fmt); + PRINTF(" This command works like state <account_name> 5.\n"_fmt); } - else if (command == "check") + else if (command == "check"_s) { - PRINTF("check <account_name> <password>\n"); - PRINTF(" Check the validity of a password for an account.\n"); - PRINTF(" NOTE: Server will never sends back a password.\n"); - PRINTF(" It's the only method you have to know if a password is correct.\n"); - PRINTF(" The other method is to have a ('physical') access to the accounts file.\n"); + PRINTF("check <account_name> <password>\n"_fmt); + PRINTF(" Check the validity of a password for an account.\n"_fmt); + PRINTF(" NOTE: Server will never sends back a password.\n"_fmt); + PRINTF(" It's the only method you have to know if a password is correct.\n"_fmt); + PRINTF(" The other method is to have a ('physical') access to the accounts file.\n"_fmt); } - else if (command == "create") + else if (command == "create"_s) { - PRINTF("create <account_name> <sex> <email> <password>\n"); - PRINTF(" Like the 'add' command, but with e-mail moreover.\n"); - PRINTF(" <example> create testname Male my@mail.com testpass\n"); + PRINTF("create <account_name> <sex> <email> <password>\n"_fmt); + PRINTF(" Like the 'add' command, but with e-mail moreover.\n"_fmt); + PRINTF(" <example> create testname Male my@mail.com testpass\n"_fmt); } - else if (command == "delete") + else if (command == "delete"_s) { - PRINTF("delete <account name>\n"); - PRINTF(" Remove an account.\n"); - PRINTF(" This order requires confirmation. After confirmation, the account is deleted.\n"); + PRINTF("delete <account name>\n"_fmt); + PRINTF(" Remove an account.\n"_fmt); + PRINTF(" This order requires confirmation. After confirmation, the account is deleted.\n"_fmt); } - else if (command == "email") + else if (command == "email"_s) { - PRINTF("email <account_name> <email>\n"); - PRINTF(" Modify the e-mail of an account.\n"); + PRINTF("email <account_name> <email>\n"_fmt); + PRINTF(" Modify the e-mail of an account.\n"_fmt); } - else if (command == "getcount") + else if (command == "getcount"_s) { - PRINTF("getcount\n"); - PRINTF(" Give the number of players online on all char-servers.\n"); + PRINTF("getcount\n"_fmt); + PRINTF(" Give the number of players online on all char-servers.\n"_fmt); } - else if (command == "gm") + else if (command == "gm"_s) { - PRINTF("gm <account_name> [GM_level]\n"); - PRINTF(" Modify the GM level of an account.\n"); - PRINTF(" Default value remove GM level (GM level = 0).\n"); - PRINTF(" <example> gm testname 80\n"); + PRINTF("gm <account_name> [GM_level]\n"_fmt); + PRINTF(" Modify the GM level of an account.\n"_fmt); + PRINTF(" Default value remove GM level (GM level = 0).\n"_fmt); + PRINTF(" <example> gm testname 80\n"_fmt); } - else if (command == "id") + else if (command == "id"_s) { - PRINTF("id <account name>\n"); - PRINTF(" Give the id of an account.\n"); + PRINTF("id <account name>\n"_fmt); + PRINTF(" Give the id of an account.\n"_fmt); } - else if (command == "info") + else if (command == "info"_s) { - PRINTF("info <account_id>\n"); - PRINTF(" Display complete information of an account.\n"); + PRINTF("info <account_id>\n"_fmt); + PRINTF(" Display complete information of an account.\n"_fmt); } - else if (command == "kami") + else if (command == "kami"_s) { - PRINTF("kami <message>\n"); - PRINTF(" Sends a broadcast message on all map-server (in yellow).\n"); + PRINTF("kami <message>\n"_fmt); + PRINTF(" Sends a broadcast message on all map-server (in yellow).\n"_fmt); } - else if (command == "kamib") + else if (command == "kamib"_s) { - PRINTF("kamib <message>\n"); - PRINTF(" Sends a broadcast message on all map-server (in blue).\n"); + PRINTF("kamib <message>\n"_fmt); + PRINTF(" Sends a broadcast message on all map-server (in blue).\n"_fmt); } - else if (command == "list") + else if (command == "list"_s) { - PRINTF("list/ls [start_id [end_id]]\n"); - PRINTF(" Display a list of accounts.\n"); - PRINTF(" 'start_id', 'end_id': indicate end and start identifiers.\n"); - PRINTF(" Research by name is not possible with this command.\n"); - PRINTF(" <example> list 10 9999999\n"); + PRINTF("list/ls [start_id [end_id]]\n"_fmt); + PRINTF(" Display a list of accounts.\n"_fmt); + PRINTF(" 'start_id', 'end_id': indicate end and start identifiers.\n"_fmt); + PRINTF(" Research by name is not possible with this command.\n"_fmt); + PRINTF(" <example> list 10 9999999\n"_fmt); } - else if (command == "itemfrob") + else if (command == "itemfrob"_s) { - PRINTF("itemfrob <source-id> <dest-id>\n"); - PRINTF(" Translates item IDs for all accounts.\n"); - PRINTF(" Any items matching the source item ID will be mapped to the dest-id.\n"); - PRINTF(" <example> itemfrob 500 700\n"); + PRINTF("itemfrob <source-id> <dest-id>\n"_fmt); + PRINTF(" Translates item IDs for all accounts.\n"_fmt); + PRINTF(" Any items matching the source item ID will be mapped to the dest-id.\n"_fmt); + PRINTF(" <example> itemfrob 500 700\n"_fmt); } - else if (command == "listban") + else if (command == "listban"_s) { - PRINTF("listban [start_id [end_id]]\n"); - PRINTF(" Like list/ls, but only for accounts with state or banished.\n"); + PRINTF("listban [start_id [end_id]]\n"_fmt); + PRINTF(" Like list/ls, but only for accounts with state or banished.\n"_fmt); } - else if (command == "listgm") + else if (command == "listgm"_s) { - PRINTF("listgm [start_id [end_id]]\n"); - PRINTF(" Like list/ls, but only for GM accounts.\n"); + PRINTF("listgm [start_id [end_id]]\n"_fmt); + PRINTF(" Like list/ls, but only for GM accounts.\n"_fmt); } - else if (command == "listok") + else if (command == "listok"_s) { - PRINTF("listok [start_id [end_id]]\n"); - PRINTF(" Like list/ls, but only for accounts without state and not banished.\n"); + PRINTF("listok [start_id [end_id]]\n"_fmt); + PRINTF(" Like list/ls, but only for accounts without state and not banished.\n"_fmt); } - else if (command == "memo") + else if (command == "memo"_s) { - PRINTF("memo <account_name> <memo>\n"); - PRINTF(" Modify the memo of an account.\n"); - PRINTF(" 'memo': it can have until 253 characters (with spaces or not).\n"); + PRINTF("memo <account_name> <memo>\n"_fmt); + PRINTF(" Modify the memo of an account.\n"_fmt); + PRINTF(" 'memo': it can have until 253 characters (with spaces or not).\n"_fmt); } - else if (command == "name") + else if (command == "name"_s) { - PRINTF("name <account_id>\n"); - PRINTF(" Give the name of an account.\n"); + PRINTF("name <account_id>\n"_fmt); + PRINTF(" Give the name of an account.\n"_fmt); } - else if (command == "password") + else if (command == "password"_s) { - PRINTF("password <account_name> <new_password>\n"); - PRINTF(" Change the password of an account.\n"); - PRINTF(" When new password is omitted,\n"); - PRINTF(" the input is done without displaying of the pressed keys.\n"); + PRINTF("password <account_name> <new_password>\n"_fmt); + PRINTF(" Change the password of an account.\n"_fmt); + PRINTF(" When new password is omitted,\n"_fmt); + PRINTF(" the input is done without displaying of the pressed keys.\n"_fmt); } - else if (command == "reloadgm") + else if (command == "reloadgm"_s) { - PRINTF("reloadGM\n"); - PRINTF(" Reload GM configuration file\n"); + PRINTF("reloadGM\n"_fmt); + PRINTF(" Reload GM configuration file\n"_fmt); } - else if (command == "search") + else if (command == "search"_s) { - PRINTF("search <expression>\n"); - PRINTF(" Seek accounts.\n"); - PRINTF(" Displays the accounts whose names correspond.\n"); + PRINTF("search <expression>\n"_fmt); + PRINTF(" Seek accounts.\n"_fmt); + PRINTF(" Displays the accounts whose names correspond.\n"_fmt); } - else if (command == "sex") + else if (command == "sex"_s) { - PRINTF("sex <account_name> <sex>\n"); - PRINTF(" Modify the sex of an account.\n"); - PRINTF(" <example> sex testname Male\n"); + PRINTF("sex <account_name> <sex>\n"_fmt); + PRINTF(" Modify the sex of an account.\n"_fmt); + PRINTF(" <example> sex testname Male\n"_fmt); } - else if (command == "state") + else if (command == "state"_s) { - PRINTF("state <account_name> <new_state> <error_message_#7>\n"); - PRINTF(" Change the state of an account.\n"); - PRINTF(" 'new_state': state is the state of the packet 0x006a + 1.\n"); - PRINTF(" The possibilities are:\n"); - PRINTF(" 0 = Account ok\n"); - PRINTF(" 1 = Unregistered ID\n"); - PRINTF(" 2 = Incorrect Password\n"); - PRINTF(" 3 = This ID is expired\n"); - PRINTF(" 4 = Rejected from Server\n"); - PRINTF(" 5 = You have been blocked by the GM Team\n"); - PRINTF(" 6 = Your Game's EXE file is not the latest version\n"); - PRINTF(" 7 = You are Prohibited to log in until...\n"); - PRINTF(" 8 = Server is jammed due to over populated\n"); - PRINTF(" 9 = No MSG\n"); - PRINTF(" 100 = This ID has been totally erased\n"); - PRINTF(" all other values are 'No MSG', then use state 9 please.\n"); - PRINTF(" 'error_message_#7': message of the code error 6\n"); - PRINTF(" = Your are Prohibited to log in until... (packet 0x006a)\n"); + PRINTF("state <account_name> <new_state> <error_message_#7>\n"_fmt); + PRINTF(" Change the state of an account.\n"_fmt); + PRINTF(" 'new_state': state is the state of the packet 0x006a + 1.\n"_fmt); + PRINTF(" The possibilities are:\n"_fmt); + PRINTF(" 0 = Account ok\n"_fmt); + PRINTF(" 1 = Unregistered ID\n"_fmt); + PRINTF(" 2 = Incorrect Password\n"_fmt); + PRINTF(" 3 = This ID is expired\n"_fmt); + PRINTF(" 4 = Rejected from Server\n"_fmt); + PRINTF(" 5 = You have been blocked by the GM Team\n"_fmt); + PRINTF(" 6 = Your Game's EXE file is not the latest version\n"_fmt); + PRINTF(" 7 = You are Prohibited to log in until...\n"_fmt); + PRINTF(" 8 = Server is jammed due to over populated\n"_fmt); + PRINTF(" 9 = No MSG\n"_fmt); + PRINTF(" 100 = This ID has been totally erased\n"_fmt); + PRINTF(" all other values are 'No MSG', then use state 9 please.\n"_fmt); + PRINTF(" 'error_message_#7': message of the code error 6\n"_fmt); + PRINTF(" = Your are Prohibited to log in until... (packet 0x006a)\n"_fmt); } - else if (command == "timeadd") + else if (command == "timeadd"_s) { - PRINTF("timeadd <account_name> <modifier>\n"); - PRINTF(" Adds or substracts time from the validity limit of an account.\n"); - PRINTF(" Modifier is done as follows:\n"); - PRINTF(" Adjustment value (-1, 1, +1, etc...)\n"); - PRINTF(" Modified element:\n"); - PRINTF(" a or y: year\n"); - PRINTF(" m: month\n"); - PRINTF(" j or d: day\n"); - PRINTF(" h: hour\n"); - PRINTF(" mn: minute\n"); - PRINTF(" s: second\n"); - PRINTF(" <example> timeadd testname +1m-2mn1s-6y\n"); - PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"); - PRINTF(" and 6 years at the same time.\n"); - PRINTF("NOTE: You can not modify a unlimited validity limit.\n"); - PRINTF(" If you want modify it, you want probably create a limited validity limit.\n"); - PRINTF(" So, at first, you must set the validity limit to a date/time.\n"); + PRINTF("timeadd <account_name> <modifier>\n"_fmt); + PRINTF(" Adds or substracts time from the validity limit of an account.\n"_fmt); + PRINTF(" Modifier is done as follows:\n"_fmt); + PRINTF(" Adjustment value (-1, 1, +1, etc...)\n"_fmt); + PRINTF(" Modified element:\n"_fmt); + PRINTF(" a or y: year\n"_fmt); + PRINTF(" m: month\n"_fmt); + PRINTF(" j or d: day\n"_fmt); + PRINTF(" h: hour\n"_fmt); + PRINTF(" mn: minute\n"_fmt); + PRINTF(" s: second\n"_fmt); + PRINTF(" <example> timeadd testname +1m-2mn1s-6y\n"_fmt); + PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"_fmt); + PRINTF(" and 6 years at the same time.\n"_fmt); + PRINTF("NOTE: You can not modify a unlimited validity limit.\n"_fmt); + PRINTF(" If you want modify it, you want probably create a limited validity limit.\n"_fmt); + PRINTF(" So, at first, you must set the validity limit to a date/time.\n"_fmt); } - else if (command == "timeadd") + else if (command == "timeadd"_s) { - PRINTF("timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n"); - PRINTF(" Changes the validity limit of an account.\n"); - PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"); - PRINTF("timeset <account_name> 0\n"); - PRINTF(" Gives an unlimited validity limit (0 = unlimited).\n"); + PRINTF("timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n"_fmt); + PRINTF(" Changes the validity limit of an account.\n"_fmt); + PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"_fmt); + PRINTF("timeset <account_name> 0\n"_fmt); + PRINTF(" Gives an unlimited validity limit (0 = unlimited).\n"_fmt); } - else if (command == "unban") + else if (command == "unban"_s) { - PRINTF("unban/unbanish <account name>\n"); - PRINTF(" Remove the banishment of an account.\n"); - PRINTF(" This command works like banset <account_name> 0.\n"); + PRINTF("unban/unbanish <account name>\n"_fmt); + PRINTF(" Remove the banishment of an account.\n"_fmt); + PRINTF(" This command works like banset <account_name> 0.\n"_fmt); } - else if (command == "unblock") + else if (command == "unblock"_s) { - PRINTF("unblock <account name>\n"); - PRINTF(" Set state 0 (Account ok) to an account.\n"); - PRINTF(" This command works like state <account_name> 0.\n"); + PRINTF("unblock <account name>\n"_fmt); + PRINTF(" Set state 0 (Account ok) to an account.\n"_fmt); + PRINTF(" This command works like state <account_name> 0.\n"_fmt); } - else if (command == "version") + else if (command == "version"_s) { - PRINTF("version\n"); - PRINTF(" Display the version of the login-server.\n"); + PRINTF("version\n"_fmt); + PRINTF(" Display the version of the login-server.\n"_fmt); } - else if (command == "who") + else if (command == "who"_s) { - PRINTF("who <account name>\n"); - PRINTF(" Displays complete information of an account.\n"); + PRINTF("who <account name>\n"_fmt); + PRINTF(" Displays complete information of an account.\n"_fmt); } - else if (command == "quit" - || command == "exit" - || command == "end") - { - PRINTF("quit/end/exit\n"); - PRINTF(" End of the program of administration.\n"); + else if (command == "quit"_s + || command == "exit"_s + || command == "end"_s) + { + PRINTF("quit/end/exit\n"_fmt); + PRINTF(" End of the program of administration.\n"_fmt); } else { if (command) - PRINTF("Unknown command [%s] for help. Displaying of all commands.\n", - AString(command)); - PRINTF(" help/? -- Display this help\n"); - PRINTF(" help/? [command] -- Display the help of the command\n"); - PRINTF(" add <account_name> <sex> <password> -- Create an account with default email\n"); - PRINTF(" ban yyyy/mm/dd hh:mm:ss <account name> -- Change final date of a ban\n"); - PRINTF(" banadd <account_name> <modifier> -- Add or substract time from the final\n"); - PRINTF(" example: ba apple +1m-2mn1s-2y date of a banishment of an account\n"); - PRINTF(" banset <account_name> yyyy/mm/dd [hh:mm:ss] -- Change final date of a ban\n"); - PRINTF(" banset <account_name> 0 -- Un-banish an account\n"); - PRINTF(" block <account name> -- Set state 5 (blocked by the GM Team) to an account\n"); - PRINTF(" check <account_name> <password> -- Check the validity of a password\n"); - PRINTF(" create <account_name> <sex> <email> <passwrd> -- Create an account with email\n"); - PRINTF(" delete <account name> -- Remove an account\n"); - PRINTF(" email <account_name> <email> -- Modify an email of an account\n"); - PRINTF(" getcount -- Give the number of players online\n"); - PRINTF(" gm <account_name> [GM_level] -- Modify the GM level of an account\n"); - PRINTF(" id <account name> -- Give the id of an account\n"); - PRINTF(" info <account_id> -- Display all information of an account\n"); - PRINTF(" itemfrob <source-id> <dest-id> -- Map all items from one item ID to another\n"); - PRINTF(" kami <message> -- Sends a broadcast message (in yellow)\n"); - PRINTF(" kamib <message> -- Sends a broadcast message (in blue)\n"); - PRINTF(" list [First_id [Last_id]] -- Display a list of accounts\n"); - PRINTF(" listban [First_id [Last_id] ] -- Display a list of accounts\n"); - PRINTF(" with state or banished\n"); - PRINTF(" listgm [First_id [Last_id]] -- Display a list of GM accounts\n"); - PRINTF(" listok [First_id [Last_id] ] -- Display a list of accounts\n"); - PRINTF(" without state and not banished\n"); - PRINTF(" memo <account_name> <memo> -- Modify the memo of an account\n"); - PRINTF(" name <account_id> -- Give the name of an account\n"); - PRINTF(" password <account_name> <new_password> -- Change the password of an account\n"); - PRINTF(" quit/end/exit -- End of the program of administation\n"); - PRINTF(" reloadGM -- Reload GM configuration file\n"); - PRINTF(" search <expression> -- Seek accounts\n"); - PRINTF(" sex <nomcompte> <sexe> -- Modify the sex of an account\n"); - PRINTF(" state <account_name> <new_state> <error_message_#7> -- Change the state\n"); - PRINTF(" timeadd <account_name> <modifier> -- Add or substract time from the\n"); - PRINTF(" example: ta apple +1m-2mn1s-2y validity limit of an account\n"); - PRINTF(" timeset <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the validify limit\n"); - PRINTF(" timeset <account_name> 0 -- Give a unlimited validity limit\n"); - PRINTF(" unban <account name> -- Remove the banishment of an account\n"); - PRINTF(" unblock <account name> -- Set state 0 (Account ok) to an account\n"); - PRINTF(" version -- Gives the version of the login-server\n"); - PRINTF(" who <account name> -- Display all information of an account\n"); - PRINTF(" who <account name> -- Display all information of an account\n"); - PRINTF(" Note: To use spaces in an account name, type \"<account name>\" (or ').\n"); + PRINTF("Unknown command [%s] for help. Displaying of all commands.\n"_fmt, + AString(command)); + PRINTF(" help/? -- Display this help\n"_fmt); + PRINTF(" help/? [command] -- Display the help of the command\n"_fmt); + PRINTF(" add <account_name> <sex> <password> -- Create an account with default email\n"_fmt); + PRINTF(" ban yyyy/mm/dd hh:mm:ss <account name> -- Change final date of a ban\n"_fmt); + PRINTF(" banadd <account_name> <modifier> -- Add or substract time from the final\n"_fmt); + PRINTF(" example: ba apple +1m-2mn1s-2y date of a banishment of an account\n"_fmt); + PRINTF(" banset <account_name> yyyy/mm/dd [hh:mm:ss] -- Change final date of a ban\n"_fmt); + PRINTF(" banset <account_name> 0 -- Un-banish an account\n"_fmt); + PRINTF(" block <account name> -- Set state 5 (blocked by the GM Team) to an account\n"_fmt); + PRINTF(" check <account_name> <password> -- Check the validity of a password\n"_fmt); + PRINTF(" create <account_name> <sex> <email> <passwrd> -- Create an account with email\n"_fmt); + PRINTF(" delete <account name> -- Remove an account\n"_fmt); + PRINTF(" email <account_name> <email> -- Modify an email of an account\n"_fmt); + PRINTF(" getcount -- Give the number of players online\n"_fmt); + PRINTF(" gm <account_name> [GM_level] -- Modify the GM level of an account\n"_fmt); + PRINTF(" id <account name> -- Give the id of an account\n"_fmt); + PRINTF(" info <account_id> -- Display all information of an account\n"_fmt); + PRINTF(" itemfrob <source-id> <dest-id> -- Map all items from one item ID to another\n"_fmt); + PRINTF(" kami <message> -- Sends a broadcast message (in yellow)\n"_fmt); + PRINTF(" kamib <message> -- Sends a broadcast message (in blue)\n"_fmt); + PRINTF(" list [First_id [Last_id]] -- Display a list of accounts\n"_fmt); + PRINTF(" listban [First_id [Last_id] ] -- Display a list of accounts\n"_fmt); + PRINTF(" with state or banished\n"_fmt); + PRINTF(" listgm [First_id [Last_id]] -- Display a list of GM accounts\n"_fmt); + PRINTF(" listok [First_id [Last_id] ] -- Display a list of accounts\n"_fmt); + PRINTF(" without state and not banished\n"_fmt); + PRINTF(" memo <account_name> <memo> -- Modify the memo of an account\n"_fmt); + PRINTF(" name <account_id> -- Give the name of an account\n"_fmt); + PRINTF(" password <account_name> <new_password> -- Change the password of an account\n"_fmt); + PRINTF(" quit/end/exit -- End of the program of administation\n"_fmt); + PRINTF(" reloadGM -- Reload GM configuration file\n"_fmt); + PRINTF(" search <expression> -- Seek accounts\n"_fmt); + PRINTF(" sex <nomcompte> <sexe> -- Modify the sex of an account\n"_fmt); + PRINTF(" state <account_name> <new_state> <error_message_#7> -- Change the state\n"_fmt); + PRINTF(" timeadd <account_name> <modifier> -- Add or substract time from the\n"_fmt); + PRINTF(" example: ta apple +1m-2mn1s-2y validity limit of an account\n"_fmt); + PRINTF(" timeset <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the validify limit\n"_fmt); + PRINTF(" timeset <account_name> 0 -- Give a unlimited validity limit\n"_fmt); + PRINTF(" unban <account name> -- Remove the banishment of an account\n"_fmt); + PRINTF(" unblock <account name> -- Set state 0 (Account ok) to an account\n"_fmt); + PRINTF(" version -- Gives the version of the login-server\n"_fmt); + PRINTF(" who <account name> -- Display all information of an account\n"_fmt); + PRINTF(" who <account name> -- Display all information of an account\n"_fmt); + PRINTF(" Note: To use spaces in an account name, type \"<account name>\" (or ').\n"_fmt); } } @@ -680,9 +690,9 @@ void addaccount(ZString param, int emailflag) // add command if (!qsplit(param, &name, &sex_, &password)) { - PRINTF("Please input an account name, a sex and a password.\n"); - PRINTF("<example> add testname Male testpass\n"); - LADMIN_LOG("Incomplete parameters to create an account ('add' command).\n"); + PRINTF("Please input an account name, a sex and a password.\n"_fmt); + PRINTF("<example> add testname Male testpass\n"_fmt); + LADMIN_LOG("Incomplete parameters to create an account ('add' command).\n"_fmt); return; } email_ = DEFAULT_EMAIL; @@ -692,9 +702,9 @@ void addaccount(ZString param, int emailflag) // 1: create command if (!qsplit(param, &name, &sex_, &email_, &password)) { - PRINTF("Please input an account name, a sex and a password.\n"); - PRINTF("<example> create testname Male my@mail.com testpass\n"); - LADMIN_LOG("Incomplete parameters to create an account ('create' command).\n"); + PRINTF("Please input an account name, a sex and a password.\n"_fmt); + PRINTF("<example> create testname Male my@mail.com testpass\n"_fmt); + LADMIN_LOG("Incomplete parameters to create an account ('create' command).\n"_fmt); return; } } @@ -702,18 +712,18 @@ void addaccount(ZString param, int emailflag) if (!name.is_print()) return; - if (!XString("MF").contains(sex)) + if (!"MF"_s.contains(sex)) { - PRINTF("Illegal gender [%c]. Please input M or F.\n", sex); - LADMIN_LOG("Illegal gender [%c]. Please input M or F.\n", sex); + PRINTF("Illegal gender [%c]. Please input M or F.\n"_fmt, sex); + LADMIN_LOG("Illegal gender [%c]. Please input M or F.\n"_fmt, sex); return; } if (!e_mail_check(email_)) { - PRINTF("Invalid email [%s]. Please input a valid e-mail.\n", + PRINTF("Invalid email [%s]. Please input a valid e-mail.\n"_fmt, AString(email_)); - LADMIN_LOG("Invalid email [%s]. Please input a valid e-mail.\n", + LADMIN_LOG("Invalid email [%s]. Please input a valid e-mail.\n"_fmt, AString(email_)); return; } @@ -722,14 +732,14 @@ void addaccount(ZString param, int emailflag) if (!password.is_print()) return; - LADMIN_LOG("Request to login-server to create an account.\n"); + LADMIN_LOG("Request to login-server to create an account.\n"_fmt); - WFIFOW(login_session, 0) = 0x7930; - WFIFO_STRING(login_session, 2, name, 24); - WFIFO_STRING(login_session, 26, password, 24); - WFIFOB(login_session, 50) = sex; - WFIFO_STRING(login_session, 51, email, 40); - WFIFOSET(login_session, 91); + Packet_Fixed<0x7930> fixed_30; + fixed_30.account_name = name; + fixed_30.password = password; + fixed_30.sex = sex_from_char(sex); + fixed_30.email = email; + send_fpacket<0x7930, 91>(login_session, fixed_30); bytes_to_read = 1; } @@ -744,11 +754,11 @@ void banaddaccount(ZString param) if (!qsplit(param, &name, &modif)) { - PRINTF("Please input an account name and a modifier.\n"); - PRINTF(" <example>: banadd testname +1m-2mn1s-6y\n"); - PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"); - PRINTF(" and 6 years at the same time.\n"); - LADMIN_LOG("Incomplete parameters to modify the ban date/time of an account ('banadd' command).\n"); + PRINTF("Please input an account name and a modifier.\n"_fmt); + PRINTF(" <example>: banadd testname +1m-2mn1s-6y\n"_fmt); + PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"_fmt); + PRINTF(" and 6 years at the same time.\n"_fmt); + LADMIN_LOG("Incomplete parameters to modify the ban date/time of an account ('banadd' command).\n"_fmt); return; } if (!name.is_print()) @@ -756,28 +766,28 @@ void banaddaccount(ZString param) if (!modif) { - PRINTF("Please give an adjustment with this command:\n"); - PRINTF(" Adjustment value (-1, 1, +1, etc...)\n"); - PRINTF(" Modified element:\n"); - PRINTF(" a or y: year\n"); - PRINTF(" m: month\n"); - PRINTF(" j or d: day\n"); - PRINTF(" h: hour\n"); - PRINTF(" mn: minute\n"); - PRINTF(" s: second\n"); - PRINTF(" <example> banadd testname +1m-2mn1s-6y\n"); - PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"); - PRINTF(" and 6 years at the same time.\n"); - LADMIN_LOG("No adjustment isn't an adjustment ('banadd' command).\n"); + PRINTF("Please give an adjustment with this command:\n"_fmt); + PRINTF(" Adjustment value (-1, 1, +1, etc...)\n"_fmt); + PRINTF(" Modified element:\n"_fmt); + PRINTF(" a or y: year\n"_fmt); + PRINTF(" m: month\n"_fmt); + PRINTF(" j or d: day\n"_fmt); + PRINTF(" h: hour\n"_fmt); + PRINTF(" mn: minute\n"_fmt); + PRINTF(" s: second\n"_fmt); + PRINTF(" <example> banadd testname +1m-2mn1s-6y\n"_fmt); + PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"_fmt); + PRINTF(" and 6 years at the same time.\n"_fmt); + LADMIN_LOG("No adjustment isn't an adjustment ('banadd' command).\n"_fmt); return; } - LADMIN_LOG("Request to login-server to modify a ban date/time.\n"); + LADMIN_LOG("Request to login-server to modify a ban date/time.\n"_fmt); - WFIFOW(login_session, 0) = 0x794c; - WFIFO_STRING(login_session, 2, name, 24); - WFIFO_STRUCT(login_session, 26, modif); - WFIFOSET(login_session, 38); + Packet_Fixed<0x794c> fixed_4c; + fixed_4c.account_name = name; + fixed_4c.ban_add = modif; + send_fpacket<0x794c, 38>(login_session, fixed_4c); bytes_to_read = 1; } @@ -798,19 +808,19 @@ void bansetaccountsub(AccountName name, XString date, XString time_) if (!name.is_print()) return; - if (date != "0" + if (date != "0"_s && ((!extract(date, record<'/'>(&year, &month, &day)) && !extract(date, record<'-'>(&year, &month, &day)) && !extract(date, record<'.'>(&year, &month, &day))) || !extract(time_, record<':'>(&hour, &minute, &second)))) { - PRINTF("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n"); - PRINTF("You can imput 0 instead of if you use 'banset' command.\n"); - LADMIN_LOG("Invalid format for the date/time ('banset' or 'ban' command).\n"); + PRINTF("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n"_fmt); + PRINTF("You can imput 0 instead of if you use 'banset' command.\n"_fmt); + LADMIN_LOG("Invalid format for the date/time ('banset' or 'ban' command).\n"_fmt); return; } - if (date == "0") + if (date == "0"_s) { ban_until_time = TimeT(); } @@ -826,41 +836,41 @@ void bansetaccountsub(AccountName name, XString date, XString time_) } if (month < 1 || month > 12) { - PRINTF("Please give a correct value for the month (from 1 to 12).\n"); - LADMIN_LOG("Invalid month for the date ('banset' or 'ban' command).\n"); + PRINTF("Please give a correct value for the month (from 1 to 12).\n"_fmt); + LADMIN_LOG("Invalid month for the date ('banset' or 'ban' command).\n"_fmt); return; } month = month - 1; if (day < 1 || day > 31) { - PRINTF("Please give a correct value for the day (from 1 to 31).\n"); - LADMIN_LOG("Invalid day for the date ('banset' or 'ban' command).\n"); + PRINTF("Please give a correct value for the day (from 1 to 31).\n"_fmt); + LADMIN_LOG("Invalid day for the date ('banset' or 'ban' command).\n"_fmt); return; } if (((month == 3 || month == 5 || month == 8 || month == 10) && day > 30) || (month == 1 && day > 29)) { - PRINTF("Please give a correct value for a day of this month (%d).\n", - month); - LADMIN_LOG("Invalid day for this month ('banset' or 'ban' command).\n"); + PRINTF("Please give a correct value for a day of this month (%d).\n"_fmt, + month); + LADMIN_LOG("Invalid day for this month ('banset' or 'ban' command).\n"_fmt); return; } if (hour < 0 || hour > 23) { - PRINTF("Please give a correct value for the hour (from 0 to 23).\n"); - LADMIN_LOG("Invalid hour for the time ('banset' or 'ban' command).\n"); + PRINTF("Please give a correct value for the hour (from 0 to 23).\n"_fmt); + LADMIN_LOG("Invalid hour for the time ('banset' or 'ban' command).\n"_fmt); return; } if (minute < 0 || minute > 59) { - PRINTF("Please give a correct value for the minutes (from 0 to 59).\n"); - LADMIN_LOG("Invalid minute for the time ('banset' or 'ban' command).\n"); + PRINTF("Please give a correct value for the minutes (from 0 to 59).\n"_fmt); + LADMIN_LOG("Invalid minute for the time ('banset' or 'ban' command).\n"_fmt); return; } if (second < 0 || second > 59) { - PRINTF("Please give a correct value for the seconds (from 0 to 59).\n"); - LADMIN_LOG("Invalid second for the time ('banset' or 'ban' command).\n"); + PRINTF("Please give a correct value for the seconds (from 0 to 59).\n"_fmt); + LADMIN_LOG("Invalid second for the time ('banset' or 'ban' command).\n"_fmt); return; } tmtime.tm_year = year; @@ -873,20 +883,20 @@ void bansetaccountsub(AccountName name, XString date, XString time_) ban_until_time = tmtime; if (ban_until_time.error()) { - PRINTF("Invalid date.\n"); - PRINTF("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n"); - PRINTF("You can imput 0 instead of if you use 'banset' command.\n"); - LADMIN_LOG("Invalid date. ('banset' or 'ban' command).\n"); + PRINTF("Invalid date.\n"_fmt); + PRINTF("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n"_fmt); + PRINTF("You can imput 0 instead of if you use 'banset' command.\n"_fmt); + LADMIN_LOG("Invalid date. ('banset' or 'ban' command).\n"_fmt); return; } } - LADMIN_LOG("Request to login-server to set a ban.\n"); + LADMIN_LOG("Request to login-server to set a ban.\n"_fmt); - WFIFOW(login_session, 0) = 0x794a; - WFIFO_STRING(login_session, 2, name, 24); - WFIFOL(login_session, 26) = static_cast<time_t>(ban_until_time); - WFIFOSET(login_session, 30); + Packet_Fixed<0x794a> fixed_4a; + fixed_4a.account_name = name; + fixed_4a.ban_until = ban_until_time; + send_fpacket<0x794a, 30>(login_session, fixed_4a); bytes_to_read = 1; } @@ -902,18 +912,18 @@ void banaccount(ZString param) if (!qsplit(param, &date, &time_, &name)) { - PRINTF("Please input an account name, a date and a hour.\n"); - PRINTF("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n"); - PRINTF(" banset <account_name> 0 (0 = un-banished)\n"); - PRINTF(" ban/banish yyyy/mm/dd hh:mm:ss <account name>\n"); - PRINTF(" unban/unbanish <account name>\n"); - PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"); - LADMIN_LOG("Incomplete parameters to set a ban ('banset' or 'ban' command).\n"); + PRINTF("Please input an account name, a date and a hour.\n"_fmt); + PRINTF("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n"_fmt); + PRINTF(" banset <account_name> 0 (0 = un-banished)\n"_fmt); + PRINTF(" ban/banish yyyy/mm/dd hh:mm:ss <account name>\n"_fmt); + PRINTF(" unban/unbanish <account name>\n"_fmt); + PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"_fmt); + LADMIN_LOG("Incomplete parameters to set a ban ('banset' or 'ban' command).\n"_fmt); return; } if (!time_) - time_ = "23:59:59"; + time_ = "23:59:59"_s; bansetaccountsub(name, date, time_); } @@ -931,18 +941,18 @@ void bansetaccount(ZString param) if (!qsplit(param, &name, &date, &time_) && !qsplit(param, &name, &date)) { - PRINTF("Please input an account name, a date and a hour.\n"); - PRINTF("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n"); - PRINTF(" banset <account_name> 0 (0 = un-banished)\n"); - PRINTF(" ban/banish yyyy/mm/dd hh:mm:ss <account name>\n"); - PRINTF(" unban/unbanish <account name>\n"); - PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"); - LADMIN_LOG("Incomplete parameters to set a ban ('banset' or 'ban' command).\n"); + PRINTF("Please input an account name, a date and a hour.\n"_fmt); + PRINTF("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n"_fmt); + PRINTF(" banset <account_name> 0 (0 = un-banished)\n"_fmt); + PRINTF(" ban/banish yyyy/mm/dd hh:mm:ss <account name>\n"_fmt); + PRINTF(" unban/unbanish <account name>\n"_fmt); + PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"_fmt); + LADMIN_LOG("Incomplete parameters to set a ban ('banset' or 'ban' command).\n"_fmt); return; } if (!time_) - time_ = "23:59:59"; + time_ = "23:59:59"_s; bansetaccountsub(name, date, time_); } @@ -957,17 +967,17 @@ void unbanaccount(ZString param) if (!qsplit(param, &name)) { - PRINTF("Please input an account name.\n"); - PRINTF("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n"); - PRINTF(" banset <account_name> 0 (0 = un-banished)\n"); - PRINTF(" ban/banish yyyy/mm/dd hh:mm:ss <account name>\n"); - PRINTF(" unban/unbanish <account name>\n"); - PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"); - LADMIN_LOG("Incomplete parameters to set a ban ('unban' command).\n"); + PRINTF("Please input an account name.\n"_fmt); + PRINTF("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n"_fmt); + PRINTF(" banset <account_name> 0 (0 = un-banished)\n"_fmt); + PRINTF(" ban/banish yyyy/mm/dd hh:mm:ss <account name>\n"_fmt); + PRINTF(" unban/unbanish <account name>\n"_fmt); + PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"_fmt); + LADMIN_LOG("Incomplete parameters to set a ban ('unban' command).\n"_fmt); return; } - bansetaccountsub(name, "0", ""); + bansetaccountsub(name, "0"_s, ""_s); } //--------------------------------------------------------- @@ -982,9 +992,9 @@ void checkaccount(ZString param) if (!qsplit(param, &name, &password)) { - PRINTF("Please input an account name.\n"); - PRINTF("<example> check testname password\n"); - LADMIN_LOG("Incomplete parameters to check the password of an account ('check' command).\n"); + PRINTF("Please input an account name.\n"_fmt); + PRINTF("<example> check testname password\n"_fmt); + LADMIN_LOG("Incomplete parameters to check the password of an account ('check' command).\n"_fmt); return; } @@ -994,12 +1004,12 @@ void checkaccount(ZString param) if (!password.is_print()) return; - LADMIN_LOG("Request to login-server to check a password.\n"); + LADMIN_LOG("Request to login-server to check a password.\n"_fmt); - WFIFOW(login_session, 0) = 0x793a; - WFIFO_STRING(login_session, 2, name, 24); - WFIFO_STRING(login_session, 26, password, 24); - WFIFOSET(login_session, 50); + Packet_Fixed<0x793a> fixed_3a; + fixed_3a.account_name = name; + fixed_3a.password = password; + send_fpacket<0x793a, 50>(login_session, fixed_3a); bytes_to_read = 1; } @@ -1013,9 +1023,9 @@ void delaccount(ZString param) if (!qsplit(param, &name)) { - PRINTF("Please input an account name.\n"); - PRINTF("<example> delete testnametodelete\n"); - LADMIN_LOG("No name given to delete an account ('delete' command).\n"); + PRINTF("Please input an account name.\n"_fmt); + PRINTF("<example> delete testnametodelete\n"_fmt); + LADMIN_LOG("No name given to delete an account ('delete' command).\n"_fmt); return; } @@ -1025,7 +1035,7 @@ void delaccount(ZString param) char confirm; do { - PRINTF(SGR_BOLD SGR_CYAN " ** Are you really sure to DELETE account [%s]? (y/n) > " SGR_RESET, name); + PRINTF(SGR_BOLD SGR_CYAN " ** Are you really sure to DELETE account [%s]? (y/n) > " SGR_RESET ""_fmt, name); fflush(stdout); int seek = getchar(); confirm = seek; @@ -1035,20 +1045,20 @@ void delaccount(ZString param) while (seek != '\n' && seek != EOF) seek = getchar(); } - while (!XString("yn").contains(confirm)); + while (!"yn"_s.contains(confirm)); if (confirm == 'n') { - PRINTF("Deletion canceled.\n"); - LADMIN_LOG("Deletion canceled by user ('delete' command).\n"); + PRINTF("Deletion canceled.\n"_fmt); + LADMIN_LOG("Deletion canceled by user ('delete' command).\n"_fmt); return; } - LADMIN_LOG("Request to login-server to delete an acount.\n"); + LADMIN_LOG("Request to login-server to delete an acount.\n"_fmt); - WFIFOW(login_session, 0) = 0x7932; - WFIFO_STRING(login_session, 2, name, 24); - WFIFOSET(login_session, 26); + Packet_Fixed<0x7932> fixed_32; + fixed_32.account_name = name; + send_fpacket<0x7932, 26>(login_session, fixed_32); bytes_to_read = 1; } @@ -1062,9 +1072,9 @@ void changeemail(ZString param) XString email_; if (!qsplit(param, &name, &email_)) { - PRINTF("Please input an account name and an email.\n"); - PRINTF("<example> email testname newemail\n"); - LADMIN_LOG("Incomplete parameters to change the email of an account ('email' command).\n"); + PRINTF("Please input an account name and an email.\n"_fmt); + PRINTF("<example> email testname newemail\n"_fmt); + LADMIN_LOG("Incomplete parameters to change the email of an account ('email' command).\n"_fmt); return; } @@ -1073,20 +1083,20 @@ void changeemail(ZString param) if (!e_mail_check(email_)) { - PRINTF("Invalid email [%s]. Please input a valid e-mail.\n", + PRINTF("Invalid email [%s]. Please input a valid e-mail.\n"_fmt, AString(email_)); - LADMIN_LOG("Invalid email [%s]. Please input a valid e-mail.\n", + LADMIN_LOG("Invalid email [%s]. Please input a valid e-mail.\n"_fmt, AString(email_)); return; } AccountEmail email = stringish<AccountEmail>(email_); - LADMIN_LOG("Request to login-server to change an email.\n"); + LADMIN_LOG("Request to login-server to change an email.\n"_fmt); - WFIFOW(login_session, 0) = 0x7940; - WFIFO_STRING(login_session, 2, name, 24); - WFIFO_STRING(login_session, 26, email, 40); - WFIFOSET(login_session, 66); + Packet_Fixed<0x7940> fixed_40; + fixed_40.account_name = name; + fixed_40.email = email; + send_fpacket<0x7940, 66>(login_session, fixed_40); bytes_to_read = 1; } @@ -1096,10 +1106,10 @@ void changeemail(ZString param) static void getlogincount(void) { - LADMIN_LOG("Request to login-server to obtain the # of online players.\n"); + LADMIN_LOG("Request to login-server to obtain the # of online players.\n"_fmt); - WFIFOW(login_session, 0) = 0x7938; - WFIFOSET(login_session, 2); + Packet_Fixed<0x7938> fixed_38; + send_fpacket<0x7938, 2>(login_session, fixed_38); bytes_to_read = 1; } @@ -1110,34 +1120,25 @@ static void changegmlevel(ZString param) { AccountName name; - int GM_level = 0; + GmLevel GM_level; if (!qsplit(param, &name, &GM_level)) { - PRINTF("Please input an account name and a GM level.\n"); - PRINTF("<example> gm testname 80\n"); - LADMIN_LOG("Incomplete parameters to change the GM level of an account ('gm' command).\n"); + PRINTF("Please input an account name and a GM level.\n"_fmt); + PRINTF("<example> gm testname 80\n"_fmt); + LADMIN_LOG("Incomplete parameters to change the GM level of an account ('gm' command).\n"_fmt); return; } if (!name.is_print()) return; - if (GM_level < 0 || GM_level > 99) - { - PRINTF("Illegal GM level [%d]. Please input a value from 0 to 99.\n", - GM_level); - LADMIN_LOG("Illegal GM level [%d]. The value can be from 0 to 99.\n", - GM_level); - return; - } - - LADMIN_LOG("Request to login-server to change a GM level.\n"); + LADMIN_LOG("Request to login-server to change a GM level.\n"_fmt); - WFIFOW(login_session, 0) = 0x793e; - WFIFO_STRING(login_session, 2, name, 24); - WFIFOB(login_session, 26) = GM_level; - WFIFOSET(login_session, 27); + Packet_Fixed<0x793e> fixed_3e; + fixed_3e.account_name = name; + fixed_3e.gm_level = GM_level; + send_fpacket<0x793e, 27>(login_session, fixed_3e); bytes_to_read = 1; } @@ -1151,9 +1152,9 @@ void idaccount(ZString param) if (!qsplit(param, &name)) { - PRINTF("Please input an account name.\n"); - PRINTF("<example> id testname\n"); - LADMIN_LOG("No name given to search an account id ('id' command).\n"); + PRINTF("Please input an account name.\n"_fmt); + PRINTF("<example> id testname\n"_fmt); + LADMIN_LOG("No name given to search an account id ('id' command).\n"_fmt); return; } @@ -1162,11 +1163,11 @@ void idaccount(ZString param) return; } - LADMIN_LOG("Request to login-server to know an account id.\n"); + LADMIN_LOG("Request to login-server to know an account id.\n"_fmt); - WFIFOW(login_session, 0) = 0x7944; - WFIFO_STRING(login_session, 2, name, 24); - WFIFOSET(login_session, 26); + Packet_Fixed<0x7944> fixed_44; + fixed_44.account_name = name; + send_fpacket<0x7944, 26>(login_session, fixed_44); bytes_to_read = 1; } @@ -1174,20 +1175,13 @@ void idaccount(ZString param) // Sub-function: Asking to displaying information about an account (by its id) //---------------------------------------------------------------------------- static -void infoaccount(int account_id) +void infoaccount(AccountId account_id) { - if (account_id < 0) - { - PRINTF("Please input a positive value for the id.\n"); - LADMIN_LOG("Negative value was given to found the account.\n"); - return; - } + LADMIN_LOG("Request to login-server to obtain information about an account (by its id).\n"_fmt); - LADMIN_LOG("Request to login-server to obtain information about an account (by its id).\n"); - - WFIFOW(login_session, 0) = 0x7954; - WFIFOL(login_session, 2) = account_id; - WFIFOSET(login_session, 6); + Packet_Fixed<0x7954> fixed_54; + fixed_54.account_id = account_id; + send_fpacket<0x7954, 6>(login_session, fixed_54); bytes_to_read = 1; } @@ -1199,20 +1193,17 @@ void sendbroadcast(ZString message) { if (!message) { - PRINTF("Please input a message.\n"); + PRINTF("Please input a message.\n"_fmt); { - PRINTF("<example> kami a message\n"); + PRINTF("<example> kami a message\n"_fmt); } - LADMIN_LOG("The message is void ('kami' command).\n"); + LADMIN_LOG("The message is void ('kami' command).\n"_fmt); return; } - WFIFOW(login_session, 0) = 0x794e; - WFIFOW(login_session, 2) = 0; - size_t len = message.size() + 1; - WFIFOL(login_session, 4) = len; - WFIFO_STRING(login_session, 8, message, len); - WFIFOSET(login_session, 8 + len); + Packet_Head<0x794e> head_4e; + head_4e.unused = 0; + send_vpacket<0x794e, 8, 1>(login_session, head_4e, message); bytes_to_read = 1; } @@ -1227,8 +1218,8 @@ void listaccount(ZString param, int type) list_type = type; // set default values - list_first = 0; - list_last = 0; + list_first = AccountId(); + list_last = AccountId(); if (list_type == 1) { // if listgm @@ -1250,24 +1241,22 @@ void listaccount(ZString param, int type) { // if list (list_type == 0) extract(param, record<' '>(&list_first, &list_last)); - if (list_first < 0) - list_first = 0; - if (list_last < list_first || list_last < 0) - list_last = 0; + if (list_last < list_first) + list_last = AccountId(); } - LADMIN_LOG("Request to login-server to obtain the list of accounts from %d to %d.\n", - list_first, list_last); + LADMIN_LOG("Request to login-server to obtain the list of accounts from %d to %d.\n"_fmt, + list_first, list_last); - WFIFOW(login_session, 0) = 0x7920; - WFIFOL(login_session, 2) = list_first; - WFIFOL(login_session, 6) = list_last; - WFIFOSET(login_session, 10); + Packet_Fixed<0x7920> fixed_20; + fixed_20.start_account_id = list_first; + fixed_20.end_account_id = list_last; + send_fpacket<0x7920, 10>(login_session, fixed_20); bytes_to_read = 1; // 0123456789 01 01234567890123456789012301234 012345 0123456789012345678901234567 - Iprintf("account_id GM user_name sex count state\n"); - Iprintf("-------------------------------------------------------------------------------\n"); + Iprintf("account_id GM user_name sex count state\n"_fmt); + Iprintf("-------------------------------------------------------------------------------\n"_fmt); list_count = 0; } @@ -1277,18 +1266,18 @@ void listaccount(ZString param, int type) static int itemfrob(ZString param) { - int source_id, dest_id; + ItemNameId source_id, dest_id; if (!extract(param, record<' '>(&source_id, &dest_id))) { - PRINTF("You must provide the source and destination item IDs.\n"); + PRINTF("You must provide the source and destination item IDs.\n"_fmt); return 1; } - WFIFOW(login_session, 0) = 0x7924; - WFIFOL(login_session, 2) = source_id; - WFIFOL(login_session, 6) = dest_id; - WFIFOSET(login_session, 10); + Packet_Fixed<0x7924> fixed_24; + fixed_24.source_item_id = source_id; + fixed_24.dest_item_id = dest_id; + send_fpacket<0x7924, 10>(login_session, fixed_24); bytes_to_read = 1; // all logging is done to the three main servers return 0; @@ -1305,9 +1294,9 @@ void changememo(ZString param) if (!qsplit(param, &name, &memo) && !qsplit(param, &name)) { - PRINTF("Please input an account name and a memo.\n"); - PRINTF("<example> memo testname new memo\n"); - LADMIN_LOG("Incomplete parameters to change the memo of an account ('email' command).\n"); + PRINTF("Please input an account name and a memo.\n"_fmt); + PRINTF("<example> memo testname new memo\n"_fmt); + LADMIN_LOG("Incomplete parameters to change the memo of an account ('email' command).\n"_fmt); return; } @@ -1315,23 +1304,20 @@ void changememo(ZString param) return; size_t len = memo.size(); - size_t len1 = len + 1; if (len > 254) { - PRINTF("Memo is too long (%zu characters).\n", len); - PRINTF("Please input a memo of 254 bytes at the maximum.\n"); - LADMIN_LOG("Email is too long (%zu characters). Please input a memo of 254 bytes at the maximum.\n", - len); + PRINTF("Memo is too long (%zu characters).\n"_fmt, len); + PRINTF("Please input a memo of 254 bytes at the maximum.\n"_fmt); + LADMIN_LOG("Email is too long (%zu characters). Please input a memo of 254 bytes at the maximum.\n"_fmt, + len); return; } - LADMIN_LOG("Request to login-server to change a memo.\n"); + LADMIN_LOG("Request to login-server to change a memo.\n"_fmt); - WFIFOW(login_session, 0) = 0x7942; - WFIFO_STRING(login_session, 2, name, 24); - WFIFOW(login_session, 26) = len1; - WFIFO_STRING(login_session, 28, memo, len); - WFIFOSET(login_session, 28 + len1); + Packet_Head<0x7942> head_42; + head_42.account_name = name; + send_vpacket<0x7942, 28, 1>(login_session, head_42, memo); bytes_to_read = 1; } @@ -1339,20 +1325,13 @@ void changememo(ZString param) // Sub-function: Asking to obtain an account name //----------------------------------------------- static -void nameaccount(int id) +void nameaccount(AccountId id) { - if (id < 0) - { - PRINTF("Please input a positive value for the id.\n"); - LADMIN_LOG("Negativ id given to search an account name ('name' command).\n"); - return; - } - - LADMIN_LOG("Request to login-server to know an account name.\n"); + LADMIN_LOG("Request to login-server to know an account name.\n"_fmt); - WFIFOW(login_session, 0) = 0x7946; - WFIFOL(login_session, 2) = id; - WFIFOSET(login_session, 6); + Packet_Fixed<0x7946> fixed_46; + fixed_46.account_id = id; + send_fpacket<0x7946, 6>(login_session, fixed_46); bytes_to_read = 1; } @@ -1368,9 +1347,9 @@ void changepasswd(ZString param) if (!qsplit(param, &name, &password)) { - PRINTF("Please input an account name.\n"); - PRINTF("<example> password testname newpassword\n"); - LADMIN_LOG("Incomplete parameters to change the password of an account ('password' command).\n"); + PRINTF("Please input an account name.\n"_fmt); + PRINTF("<example> password testname newpassword\n"_fmt); + LADMIN_LOG("Incomplete parameters to change the password of an account ('password' command).\n"_fmt); return; } @@ -1382,12 +1361,12 @@ void changepasswd(ZString param) if (!password.is_print()) return; - LADMIN_LOG("Request to login-server to change a password.\n"); + LADMIN_LOG("Request to login-server to change a password.\n"_fmt); - WFIFOW(login_session, 0) = 0x7934; - WFIFO_STRING(login_session, 2, name, 24); - WFIFO_STRING(login_session, 26, password, 24); - WFIFOSET(login_session, 50); + Packet_Fixed<0x7934> fixed_34; + fixed_34.account_name = name; + fixed_34.password = password; + send_fpacket<0x7934, 50>(login_session, fixed_34); bytes_to_read = 1; } @@ -1398,13 +1377,13 @@ void changepasswd(ZString param) static void reloadGM(ZString params) { - WFIFOW(login_session, 0) = 0x7955; - WFIFOSET(login_session, 2); + Packet_Fixed<0x7955> fixed_55; + send_fpacket<0x7955, 2>(login_session, fixed_55); bytes_to_read = 0; - LADMIN_LOG("Request to reload the GM configuration file sended.\n"); - PRINTF("Request to reload the GM configuration file sended.\n"); - PRINTF("Check the actual GM accounts (after reloading):\n"); + LADMIN_LOG("Request to reload the GM configuration file sended.\n"_fmt); + PRINTF("Request to reload the GM configuration file sended.\n"_fmt); + PRINTF("Check the actual GM accounts (after reloading):\n"_fmt); listaccount(params, 1); // 1: to list only GM } @@ -1419,32 +1398,32 @@ void changesex(ZString param) if (!qsplit(param, &name, &sex_)) { - PRINTF("Please input an account name and a sex.\n"); - PRINTF("<example> sex testname Male\n"); - LADMIN_LOG("Incomplete parameters to change the sex of an account ('sex' command).\n"); + PRINTF("Please input an account name and a sex.\n"_fmt); + PRINTF("<example> sex testname Male\n"_fmt); + LADMIN_LOG("Incomplete parameters to change the sex of an account ('sex' command).\n"_fmt); return; } char sex = sex_.front(); if (!name.is_print()) { - PRINTF("bad name\n"); + PRINTF("bad name\n"_fmt); return; } - if (!XString("MF").contains(sex)) + if (!"MF"_s.contains(sex)) { - PRINTF("Illegal gender [%c]. Please input M or F.\n", sex); - LADMIN_LOG("Illegal gender [%c]. Please input M or F.\n", sex); + PRINTF("Illegal gender [%c]. Please input M or F.\n"_fmt, sex); + LADMIN_LOG("Illegal gender [%c]. Please input M or F.\n"_fmt, sex); return; } - LADMIN_LOG("Request to login-server to change a sex.\n"); + LADMIN_LOG("Request to login-server to change a sex.\n"_fmt); - WFIFOW(login_session, 0) = 0x793c; - WFIFO_STRING(login_session, 2, name, 24); - WFIFOB(login_session, 26) = sex; - WFIFOSET(login_session, 27); + Packet_Fixed<0x793c> fixed_3c; + fixed_3c.account_name = name; + fixed_3c.sex = sex_from_char(sex); + send_fpacket<0x793c, 27>(login_session, fixed_3c); bytes_to_read = 1; } @@ -1457,18 +1436,18 @@ void changestatesub(AccountName name, int state, XString error_message) { if ((state < 0 || state > 9) && state != 100) { // Valid values: 0: ok, or value of the 0x006a packet + 1 - PRINTF("Please input one of these states:\n"); - PRINTF(" 0 = Account ok 6 = Your Game's EXE file is not the latest version\n"); - PRINTF(" 1 = Unregistered ID 7 = You are Prohibited to log in until + message\n"); - PRINTF(" 2 = Incorrect Password 8 = Server is jammed due to over populated\n"); - PRINTF(" 3 = This ID is expired 9 = No MSG\n"); - PRINTF(" 4 = Rejected from Server 100 = This ID has been totally erased\n"); - PRINTF(" 5 = You have been blocked by the GM Team\n"); - PRINTF("<examples> state testname 5\n"); - PRINTF(" state testname 7 end of your ban\n"); - PRINTF(" block <account name>\n"); - PRINTF(" unblock <account name>\n"); - LADMIN_LOG("Invalid value for the state of an account ('state', 'block' or 'unblock' command).\n"); + PRINTF("Please input one of these states:\n"_fmt); + PRINTF(" 0 = Account ok 6 = Your Game's EXE file is not the latest version\n"_fmt); + PRINTF(" 1 = Unregistered ID 7 = You are Prohibited to log in until + message\n"_fmt); + PRINTF(" 2 = Incorrect Password 8 = Server is jammed due to over populated\n"_fmt); + PRINTF(" 3 = This ID is expired 9 = No MSG\n"_fmt); + PRINTF(" 4 = Rejected from Server 100 = This ID has been totally erased\n"_fmt); + PRINTF(" 5 = You have been blocked by the GM Team\n"_fmt); + PRINTF("<examples> state testname 5\n"_fmt); + PRINTF(" state testname 7 end of your ban\n"_fmt); + PRINTF(" block <account name>\n"_fmt); + PRINTF(" unblock <account name>\n"_fmt); + LADMIN_LOG("Invalid value for the state of an account ('state', 'block' or 'unblock' command).\n"_fmt); return; } @@ -1477,31 +1456,31 @@ void changestatesub(AccountName name, int state, XString error_message) if (state != 7) { - error_message = "-"; + error_message = "-"_s; } else { if (error_message.size() < 1) { - PRINTF("Error message is too short. Please input a message of 1-19 bytes.\n"); - LADMIN_LOG("Error message is too short. Please input a message of 1-19 bytes.\n"); + PRINTF("Error message is too short. Please input a message of 1-19 bytes.\n"_fmt); + LADMIN_LOG("Error message is too short. Please input a message of 1-19 bytes.\n"_fmt); return; } if (error_message.size() > 19) { - PRINTF("Error message is too long. Please input a message of 1-19 bytes.\n"); - LADMIN_LOG("Error message is too long. Please input a message of 1-19 bytes.\n"); + PRINTF("Error message is too long. Please input a message of 1-19 bytes.\n"_fmt); + LADMIN_LOG("Error message is too long. Please input a message of 1-19 bytes.\n"_fmt); return; } } - LADMIN_LOG("Request to login-server to change a state.\n"); + LADMIN_LOG("Request to login-server to change a state.\n"_fmt); - WFIFOW(login_session, 0) = 0x7936; - WFIFO_STRING(login_session, 2, name, 24); - WFIFOL(login_session, 26) = state; - WFIFO_STRING(login_session, 30, error_message, 20); - WFIFOSET(login_session, 50); + Packet_Fixed<0x7936> fixed_36; + fixed_36.account_name = name; + fixed_36.status = state; + fixed_36.error_message = stringish<timestamp_seconds_buffer>(error_message); + send_fpacket<0x7936, 50>(login_session, fixed_36); bytes_to_read = 1; } @@ -1517,12 +1496,12 @@ void changestate(ZString param) if (!qsplit(param, &name, &state, &error_message) && !qsplit(param, &name, &state)) { - PRINTF("Please input an account name and a state.\n"); - PRINTF("<examples> state testname 5\n"); - PRINTF(" state testname 7 end of your ban\n"); - PRINTF(" block <account name>\n"); - PRINTF(" unblock <account name>\n"); - LADMIN_LOG("Incomplete parameters to change the state of an account ('state' command).\n"); + PRINTF("Please input an account name and a state.\n"_fmt); + PRINTF("<examples> state testname 5\n"_fmt); + PRINTF(" state testname 7 end of your ban\n"_fmt); + PRINTF(" block <account name>\n"_fmt); + PRINTF(" unblock <account name>\n"_fmt); + LADMIN_LOG("Incomplete parameters to change the state of an account ('state' command).\n"_fmt); return; } @@ -1539,16 +1518,16 @@ void unblockaccount(ZString param) if (!qsplit(param, &name)) { - PRINTF("Please input an account name.\n"); - PRINTF("<examples> state testname 5\n"); - PRINTF(" state testname 7 end of your ban\n"); - PRINTF(" block <account name>\n"); - PRINTF(" unblock <account name>\n"); - LADMIN_LOG("Incomplete parameters to change the state of an account ('unblock' command).\n"); + PRINTF("Please input an account name.\n"_fmt); + PRINTF("<examples> state testname 5\n"_fmt); + PRINTF(" state testname 7 end of your ban\n"_fmt); + PRINTF(" block <account name>\n"_fmt); + PRINTF(" unblock <account name>\n"_fmt); + LADMIN_LOG("Incomplete parameters to change the state of an account ('unblock' command).\n"_fmt); return; } - changestatesub(name, 0, "-"); // state 0, no error message + changestatesub(name, 0, "-"_s); // state 0, no error message } //------------------------------------------- @@ -1561,16 +1540,16 @@ void blockaccount(ZString param) if (!qsplit(param, &name)) { - PRINTF("Please input an account name.\n"); - PRINTF("<examples> state testname 5\n"); - PRINTF(" state testname 7 end of your ban\n"); - PRINTF(" block <account name>\n"); - PRINTF(" unblock <account name>\n"); - LADMIN_LOG("Incomplete parameters to change the state of an account ('block' command).\n"); + PRINTF("Please input an account name.\n"_fmt); + PRINTF("<examples> state testname 5\n"_fmt); + PRINTF(" state testname 7 end of your ban\n"_fmt); + PRINTF(" block <account name>\n"_fmt); + PRINTF(" unblock <account name>\n"_fmt); + LADMIN_LOG("Incomplete parameters to change the state of an account ('block' command).\n"_fmt); return; } - changestatesub(name, 5, "-"); // state 5, no error message + changestatesub(name, 5, "-"_s); // state 5, no error message } //--------------------------------------------------------------------- @@ -1584,11 +1563,11 @@ void timeaddaccount(ZString param) if (!qsplit(param, &name, &modif)) { - PRINTF("Please input an account name and a modifier.\n"); - PRINTF(" <example>: timeadd testname +1m-2mn1s-6y\n"); - PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"); - PRINTF(" and 6 years at the same time.\n"); - LADMIN_LOG("Incomplete parameters to modify a limit time ('timeadd' command).\n"); + PRINTF("Please input an account name and a modifier.\n"_fmt); + PRINTF(" <example>: timeadd testname +1m-2mn1s-6y\n"_fmt); + PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"_fmt); + PRINTF(" and 6 years at the same time.\n"_fmt); + LADMIN_LOG("Incomplete parameters to modify a limit time ('timeadd' command).\n"_fmt); return; } if (name.is_print()) @@ -1598,28 +1577,28 @@ void timeaddaccount(ZString param) if (!modif) { - PRINTF("Please give an adjustment with this command:\n"); - PRINTF(" Adjustment value (-1, 1, +1, etc...)\n"); - PRINTF(" Modified element:\n"); - PRINTF(" a or y: year\n"); - PRINTF(" m: month\n"); - PRINTF(" j or d: day\n"); - PRINTF(" h: hour\n"); - PRINTF(" mn: minute\n"); - PRINTF(" s: second\n"); - PRINTF(" <example> timeadd testname +1m-2mn1s-6y\n"); - PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"); - PRINTF(" and 6 years at the same time.\n"); - LADMIN_LOG("No adjustment isn't an adjustment ('timeadd' command).\n"); + PRINTF("Please give an adjustment with this command:\n"_fmt); + PRINTF(" Adjustment value (-1, 1, +1, etc...)\n"_fmt); + PRINTF(" Modified element:\n"_fmt); + PRINTF(" a or y: year\n"_fmt); + PRINTF(" m: month\n"_fmt); + PRINTF(" j or d: day\n"_fmt); + PRINTF(" h: hour\n"_fmt); + PRINTF(" mn: minute\n"_fmt); + PRINTF(" s: second\n"_fmt); + PRINTF(" <example> timeadd testname +1m-2mn1s-6y\n"_fmt); + PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"_fmt); + PRINTF(" and 6 years at the same time.\n"_fmt); + LADMIN_LOG("No adjustment isn't an adjustment ('timeadd' command).\n"_fmt); return; } - LADMIN_LOG("Request to login-server to modify a time limit.\n"); + LADMIN_LOG("Request to login-server to modify a time limit.\n"_fmt); - WFIFOW(login_session, 0) = 0x7950; - WFIFO_STRING(login_session, 2, name, 24); - WFIFO_STRUCT(login_session, 26, modif); - WFIFOSET(login_session, 38); + Packet_Fixed<0x7950> fixed_50; + fixed_50.account_name = name; + fixed_50.valid_add = modif; + send_fpacket<0x7950, 38>(login_session, fixed_50); bytes_to_read = 1; } @@ -1643,31 +1622,31 @@ void timesetaccount(ZString param) if (!qsplit(param, &name, &date, &time_) && !qsplit(param, &name, &date)) { - PRINTF("Please input an account name, a date and a hour.\n"); - PRINTF("<example>: timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n"); - PRINTF(" timeset <account_name> 0 (0 = unlimited)\n"); - PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"); - LADMIN_LOG("Incomplete parameters to set a limit time ('timeset' command).\n"); + PRINTF("Please input an account name, a date and a hour.\n"_fmt); + PRINTF("<example>: timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n"_fmt); + PRINTF(" timeset <account_name> 0 (0 = unlimited)\n"_fmt); + PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"_fmt); + LADMIN_LOG("Incomplete parameters to set a limit time ('timeset' command).\n"_fmt); return; } if (!name.is_print()) return; if (!time_) - time_ = "23:59:59"; + time_ = "23:59:59"_s; - if (date != "0" + if (date != "0"_s && ((!extract(date, record<'/'>(&year, &month, &day)) && !extract(date, record<'-'>(&year, &month, &day)) && !extract(date, record<'.'>(&year, &month, &day))) || !extract(time_, record<':'>(&hour, &minute, &second)))) { - PRINTF("Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n"); - LADMIN_LOG("Invalid format for the date/time ('timeset' command).\n"); + PRINTF("Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n"_fmt); + LADMIN_LOG("Invalid format for the date/time ('timeset' command).\n"_fmt); return; } - if (date == "0") + if (date == "0"_s) { connect_until_time = TimeT(); } @@ -1683,41 +1662,41 @@ void timesetaccount(ZString param) } if (month < 1 || month > 12) { - PRINTF("Please give a correct value for the month (from 1 to 12).\n"); - LADMIN_LOG("Invalid month for the date ('timeset' command).\n"); + PRINTF("Please give a correct value for the month (from 1 to 12).\n"_fmt); + LADMIN_LOG("Invalid month for the date ('timeset' command).\n"_fmt); return; } month = month - 1; if (day < 1 || day > 31) { - PRINTF("Please give a correct value for the day (from 1 to 31).\n"); - LADMIN_LOG("Invalid day for the date ('timeset' command).\n"); + PRINTF("Please give a correct value for the day (from 1 to 31).\n"_fmt); + LADMIN_LOG("Invalid day for the date ('timeset' command).\n"_fmt); return; } if (((month == 3 || month == 5 || month == 8 || month == 10) && day > 30) ||(month == 1 && day > 29)) { - PRINTF("Please give a correct value for a day of this month (%d).\n", - month); - LADMIN_LOG("Invalid day for this month ('timeset' command).\n"); + PRINTF("Please give a correct value for a day of this month (%d).\n"_fmt, + month); + LADMIN_LOG("Invalid day for this month ('timeset' command).\n"_fmt); return; } if (hour < 0 || hour > 23) { - PRINTF("Please give a correct value for the hour (from 0 to 23).\n"); - LADMIN_LOG("Invalid hour for the time ('timeset' command).\n"); + PRINTF("Please give a correct value for the hour (from 0 to 23).\n"_fmt); + LADMIN_LOG("Invalid hour for the time ('timeset' command).\n"_fmt); return; } if (minute < 0 || minute > 59) { - PRINTF("Please give a correct value for the minutes (from 0 to 59).\n"); - LADMIN_LOG("Invalid minute for the time ('timeset' command).\n"); + PRINTF("Please give a correct value for the minutes (from 0 to 59).\n"_fmt); + LADMIN_LOG("Invalid minute for the time ('timeset' command).\n"_fmt); return; } if (second < 0 || second > 59) { - PRINTF("Please give a correct value for the seconds (from 0 to 59).\n"); - LADMIN_LOG("Invalid second for the time ('timeset' command).\n"); + PRINTF("Please give a correct value for the seconds (from 0 to 59).\n"_fmt); + LADMIN_LOG("Invalid second for the time ('timeset' command).\n"_fmt); return; } tmtime.tm_year = year; @@ -1730,19 +1709,19 @@ void timesetaccount(ZString param) connect_until_time = tmtime; if (connect_until_time.error()) { - PRINTF("Invalid date.\n"); - PRINTF("Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n"); - LADMIN_LOG("Invalid date. ('timeset' command).\n"); + PRINTF("Invalid date.\n"_fmt); + PRINTF("Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n"_fmt); + LADMIN_LOG("Invalid date. ('timeset' command).\n"_fmt); return; } } - LADMIN_LOG("Request to login-server to set a time limit.\n"); + LADMIN_LOG("Request to login-server to set a time limit.\n"_fmt); - WFIFOW(login_session, 0) = 0x7948; - WFIFO_STRING(login_session, 2, name, 24); - WFIFOL(login_session, 26) = static_cast<time_t>(connect_until_time); - WFIFOSET(login_session, 30); + Packet_Fixed<0x7948> fixed_48; + fixed_48.account_name = name; + fixed_48.valid_until = connect_until_time; + send_fpacket<0x7948, 30>(login_session, fixed_48); bytes_to_read = 1; } @@ -1756,9 +1735,9 @@ void whoaccount(ZString param) if (!qsplit(param, &name)) { - PRINTF("Please input an account name.\n"); - PRINTF("<example> who testname\n"); - LADMIN_LOG("No name was given to found the account.\n"); + PRINTF("Please input an account name.\n"_fmt); + PRINTF("<example> who testname\n"_fmt); + LADMIN_LOG("No name was given to found the account.\n"_fmt); return; } if (!name.is_print()) @@ -1766,11 +1745,11 @@ void whoaccount(ZString param) return; } - LADMIN_LOG("Request to login-server to obtain information about an account (by its name).\n"); + LADMIN_LOG("Request to login-server to obtain information about an account (by its name).\n"_fmt); - WFIFOW(login_session, 0) = 0x7952; - WFIFO_STRING(login_session, 2, name, 24); - WFIFOSET(login_session, 26); + Packet_Fixed<0x7952> fixed_52; + fixed_52.account_name = name; + send_fpacket<0x7952, 26>(login_session, fixed_52); bytes_to_read = 1; } @@ -1780,10 +1759,10 @@ void whoaccount(ZString param) static void checkloginversion(void) { - LADMIN_LOG("Request to login-server to obtain its version.\n"); + LADMIN_LOG("Request to login-server to obtain its version.\n"_fmt); - WFIFOW(login_session, 0) = 0x7530; - WFIFOSET(login_session, 2); + Packet_Fixed<0x7530> fixed_30; + send_fpacket<0x7530, 2>(login_session, fixed_30); bytes_to_read = 1; } @@ -1798,10 +1777,10 @@ void prompt(void) // while we don't wait new packets while (bytes_to_read == 0) { - Iprintf("\n"); - Iprintf(SGR_GREEN "To list the commands, type 'enter'." SGR_RESET "\n"); - Iprintf(SGR_CYAN "Ladmin-> " SGR_RESET); - Iprintf(SGR_BOLD); + Iprintf("\n"_fmt); + Iprintf(SGR_GREEN "To list the commands, type 'enter'." SGR_RESET "\n"_fmt); + Iprintf(SGR_CYAN "Ladmin-> " SGR_RESET ""_fmt); + Iprintf(SGR_BOLD ""_fmt); fflush(stdout); // get command and parameter @@ -1810,7 +1789,7 @@ void prompt(void) AString buf; cin->getline(buf); - Iprintf(SGR_RESET); + Iprintf(SGR_RESET ""_fmt); fflush(stdout); if (!cin->is_open()) @@ -1818,8 +1797,8 @@ void prompt(void) if (!buf.is_print()) { - printf("Cowardly refusing to execute a command that includes control or non-ascii characters\n"); - LADMIN_LOG("Cowardly refusing to execute a command that includes control or non-ascii characters\n"); + PRINTF("Cowardly refusing to execute a command that includes control or non-ascii characters\n"_fmt); + LADMIN_LOG("Cowardly refusing to execute a command that includes control or non-ascii characters\n"_fmt); continue; } @@ -1832,116 +1811,116 @@ void prompt(void) parameters = buf.xislice_t(space); if (!command || command.startswith('?')) - command = "help"; + command = "help"_s; if (!parameters) { - LADMIN_LOG("Command: '%s' (without parameters)\n", + LADMIN_LOG("Command: '%s' (without parameters)\n"_fmt, command); } else { // We don't want passwords in the log - Camel - if (command == "create" || command == "add" || command == "password") { + if (command == "create"_s || command == "add"_s || command == "password"_s) { AString name, email_, password; VString<1> sex_; if (qsplit(parameters, &name, &sex_, &email_, &password)) - LADMIN_LOG("Command: '%s', parameters: '%s %s %s ***'\n", + LADMIN_LOG("Command: '%s', parameters: '%s %s %s ***'\n"_fmt, command, name, sex_, email_); else if (qsplit(parameters, &name, &sex_, &password)) - LADMIN_LOG("Command: '%s', parameters: '%s %s ***'\n", + LADMIN_LOG("Command: '%s', parameters: '%s %s ***'\n"_fmt, command, name, sex_); else if (qsplit(parameters, &name, &password)) - LADMIN_LOG("Command: '%s', parameters: '%s ***'\n", + LADMIN_LOG("Command: '%s', parameters: '%s ***'\n"_fmt, command, name); else - LADMIN_LOG("Command: '%s' (invalid parameters)\n", command); + LADMIN_LOG("Command: '%s' (invalid parameters)\n"_fmt, command); } else { - LADMIN_LOG("Command: '%s', parameters: '%s'\n", + LADMIN_LOG("Command: '%s', parameters: '%s'\n"_fmt, command, parameters); } } // Analyse of the command - if (command == "help") + if (command == "help"_s) display_help(parameters); - else if (command == "add") + else if (command == "add"_s) addaccount(parameters, 0); // 0: no email - else if (command == "ban") + else if (command == "ban"_s) banaccount(parameters); - else if (command == "banadd") + else if (command == "banadd"_s) banaddaccount(parameters); - else if (command == "banset") + else if (command == "banset"_s) bansetaccount(parameters); - else if (command == "block") + else if (command == "block"_s) blockaccount(parameters); - else if (command == "check") + else if (command == "check"_s) checkaccount(parameters); - else if (command == "create") + else if (command == "create"_s) addaccount(parameters, 1); // 1: with email - else if (command == "delete") + else if (command == "delete"_s) delaccount(parameters); - else if (command == "email") + else if (command == "email"_s) changeemail(parameters); - else if (command == "getcount") + else if (command == "getcount"_s) getlogincount(); - else if (command == "gm") + else if (command == "gm"_s) changegmlevel(parameters); - else if (command == "id") + else if (command == "id"_s) idaccount(parameters); - else if (command == "info") - infoaccount(atoi(parameters.c_str())); - else if (command == "kami") + else if (command == "info"_s) + infoaccount(wrap<AccountId>(static_cast<uint32_t>(atoi(parameters.c_str())))); + else if (command == "kami"_s) sendbroadcast(parameters); // flag for normal - else if (command == "itemfrob") + else if (command == "itemfrob"_s) itemfrob(parameters); // 0: to list all - else if (command == "list") + else if (command == "list"_s) listaccount(parameters, 0); // 0: to list all - else if (command == "listban") + else if (command == "listban"_s) listaccount(parameters, 3); // 3: to list only accounts with state or bannished - else if (command == "listgm") + else if (command == "listgm"_s) listaccount(parameters, 1); // 1: to list only GM - else if (command == "listok") + else if (command == "listok"_s) listaccount(parameters, 4); // 4: to list only accounts without state and not bannished - else if (command == "memo") + else if (command == "memo"_s) changememo(parameters); - else if (command == "name") - nameaccount(atoi(parameters.c_str())); - else if (command == "password") + else if (command == "name"_s) + nameaccount(wrap<AccountId>(static_cast<uint32_t>(atoi(parameters.c_str())))); + else if (command == "password"_s) changepasswd(parameters); - else if (command == "reloadgm") + else if (command == "reloadgm"_s) reloadGM(parameters); - else if (command == "search") + else if (command == "search"_s) listaccount(parameters, 2); // 2: to list with pattern - else if (command == "sex") + else if (command == "sex"_s) changesex(parameters); - else if (command == "state") + else if (command == "state"_s) changestate(parameters); - else if (command == "timeadd") + else if (command == "timeadd"_s) timeaddaccount(parameters); - else if (command == "timeset") + else if (command == "timeset"_s) timesetaccount(parameters); - else if (command == "unban") + else if (command == "unban"_s) unbanaccount(parameters); - else if (command == "unblock") + else if (command == "unblock"_s) unblockaccount(parameters); - else if (command == "version") + else if (command == "version"_s) checkloginversion(); - else if (command == "who") + else if (command == "who"_s) whoaccount(parameters); - else if (command == "quit" - || command == "exit" - || command == "end") + else if (command == "quit"_s + || command == "exit"_s + || command == "end"_s) { - PRINTF("Bye.\n"); + PRINTF("Bye.\n"_fmt); exit(0); } else { - PRINTF("Unknown command [%s].\n", buf); - LADMIN_LOG("Unknown command [%s].\n", buf); + PRINTF("Unknown command [%s].\n"_fmt, buf); + LADMIN_LOG("Unknown command [%s].\n"_fmt, buf); } } } @@ -1952,828 +1931,905 @@ void prompt(void) static void parse_fromlogin(Session *s) { -// PRINTF("parse_fromlogin : %d %d %d\n", fd, RFIFOREST(fd), RFIFOW(fd,0)); - - while (RFIFOREST(s) >= 2) + RecvResult rv = RecvResult::Complete; + uint16_t packet_id; + while (rv == RecvResult::Complete && packet_peek_id(s, &packet_id)) { - switch (RFIFOW(s, 0)) + switch (packet_id) { case 0x7919: // answer of a connection request - if (RFIFOREST(s) < 3) - return; - if (RFIFOB(s, 2) != 0) + { + Packet_Fixed<0x7919> fixed; + rv = recv_fpacket<0x7919, 3>(s, fixed); + if (rv != RecvResult::Complete) + break; + + if (fixed.error != 0) { - PRINTF("Error at login:\n"); - PRINTF(" - incorrect password,\n"); - PRINTF(" - administration system not activated, or\n"); - PRINTF(" - unauthorised IP.\n"); - LADMIN_LOG("Error at login: incorrect password, administration system not activated, or unauthorised IP.\n"); + PRINTF("Error at login:\n"_fmt); + PRINTF(" - incorrect password,\n"_fmt); + PRINTF(" - administration system not activated, or\n"_fmt); + PRINTF(" - unauthorised IP.\n"_fmt); + LADMIN_LOG("Error at login: incorrect password, administration system not activated, or unauthorised IP.\n"_fmt); s->set_eof(); //bytes_to_read = 1; // not stop at prompt } else { - Iprintf("Established connection.\n"); - LADMIN_LOG("Established connection.\n"); - Iprintf("Reading of the version of the login-server...\n"); - LADMIN_LOG("Reading of the version of the login-server...\n"); + Iprintf("Established connection.\n"_fmt); + LADMIN_LOG("Established connection.\n"_fmt); + Iprintf("Reading of the version of the login-server...\n"_fmt); + LADMIN_LOG("Reading of the version of the login-server...\n"_fmt); //bytes_to_read = 1; // unchanged checkloginversion(); } - RFIFOSKIP(s, 3); break; + } case 0x7531: // Displaying of the version of the login-server - if (RFIFOREST(s) < 10) - return; { - Iprintf(" Login-Server [%s:%d]\n", + Packet_Fixed<0x7531> fixed; + rv = recv_fpacket<0x7531, 10>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Iprintf(" Login-Server [%s:%d]\n"_fmt, login_ip, login_port); - Version version; - RFIFO_STRUCT(login_session, 2, version); - Iprintf(" tmwA version %hhu.%hhu.%hhu (dev? %hhu) (flags %hhx) (which %hhx) (vend %hu)\n", + Version version = fixed.version; + Iprintf(" tmwA version %hhu.%hhu.%hhu (dev? %hhu) (flags %hhx) (which %hhx) (vend %hu)\n"_fmt, version.major, version.minor, version.patch, version.devel, version.flags, version.which, version.vend); - } bytes_to_read = 0; - RFIFOSKIP(s, 10); break; + } case 0x7925: // Itemfrob-OK - RFIFOSKIP(s, 2); + { + Packet_Fixed<0x7925> fixed; + rv = recv_fpacket<0x7925, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + bytes_to_read = 0; break; + } case 0x7921: // Displaying of the list of accounts - if (RFIFOREST(s) < 4 || RFIFOREST(s) < RFIFOW(s, 2)) - return; - if (RFIFOW(s, 2) < 5) + { + std::vector<Packet_Repeat<0x7921>> repeat; + rv = recv_packet_repeatonly<0x7921, 4, 38>(s, repeat); + if (rv != RecvResult::Complete) + break; + + // the admin client resends the request with a shrunken + // range until an empty reply is given + if (repeat.empty()) { - LADMIN_LOG(" Receiving of a void accounts list.\n"); + LADMIN_LOG(" Receiving of a void accounts list.\n"_fmt); if (list_count == 0) { - Iprintf("No account found.\n"); + Iprintf("No account found.\n"_fmt); } else if (list_count == 1) { - Iprintf("1 account found.\n"); + Iprintf("1 account found.\n"_fmt); } else - Iprintf("%d accounts found.\n", list_count); + Iprintf("%d accounts found.\n"_fmt, list_count); bytes_to_read = 0; } else { - int i; - LADMIN_LOG(" Receiving of a accounts list.\n"); - for (i = 4; i < RFIFOW(s, 2); i += 38) + LADMIN_LOG(" Receiving of a accounts list.\n"_fmt); + for (const Packet_Repeat<0x7921>& info : repeat) { - AccountName userid = stringish<AccountName>(RFIFO_STRING<24>(s, i + 5)); + AccountName userid = info.account_name; VString<23> lower_userid = userid.to_lower(); - list_first = RFIFOL(s, i) + 1; + // this is ad-hoc block streaming + // (with a global variable) + list_first = next(info.account_id); // here are checks... if (list_type == 0 - || (list_type == 1 && RFIFOB(s, i + 4) > 0) + || (list_type == 1 && info.gm_level) || (list_type == 2 && lower_userid.contains_seq(parameters)) - || (list_type == 3 && RFIFOL(s, i + 34) != 0) - || (list_type == 4 && RFIFOL(s, i + 34) == 0)) + || (list_type == 3 && info.status != 0) + || (list_type == 4 && info.status == 0)) { - PRINTF("%10d ", RFIFOL(s, i)); - if (RFIFOB(s, i + 4) == 0) - PRINTF(" "); + PRINTF("%10d "_fmt, info.account_id); + if (!info.gm_level) + PRINTF(" "_fmt); else - PRINTF("%2d ", RFIFOB(s, i + 4)); - PRINTF("%-24s", userid); - if (RFIFOB(s, i + 29) == 0) - PRINTF("%-5s ", "Femal"); - else if (RFIFOB(s, i + 29) == 1) - PRINTF("%-5s ", "Male"); + PRINTF("%2d "_fmt, info.gm_level); + PRINTF("%-24s"_fmt, userid); + if (info.sex == SEX::FEMALE) + PRINTF("%-5s "_fmt, "Femal"_s); + else if (info.sex == SEX::MALE) + PRINTF("%-5s "_fmt, "Male"_s); else - PRINTF("%-5s ", "Servr"); - PRINTF("%6d ", RFIFOL(s, i + 30)); - switch (RFIFOL(s, i + 34)) + PRINTF("%-5s "_fmt, "Servr"_s); + PRINTF("%6d "_fmt, info.login_count); + switch (info.status) { case 0: - PRINTF("%-27s\n", "Account OK"); + PRINTF("%-27s\n"_fmt, "Account OK"_s); break; case 1: - PRINTF("%-27s\n", "Unregistered ID"); + PRINTF("%-27s\n"_fmt, "Unregistered ID"_s); break; case 2: - PRINTF("%-27s\n", "Incorrect Password"); + PRINTF("%-27s\n"_fmt, "Incorrect Password"_s); break; case 3: - PRINTF("%-27s\n", "This ID is expired"); + PRINTF("%-27s\n"_fmt, "This ID is expired"_s); break; case 4: - PRINTF("%-27s\n", - "Rejected from Server"); + PRINTF("%-27s\n"_fmt, + "Rejected from Server"_s); break; case 5: - PRINTF("%-27s\n", "Blocked by the GM Team"); // You have been blocked by the GM Team + PRINTF("%-27s\n"_fmt, "Blocked by the GM Team"_s); // You have been blocked by the GM Team break; case 6: - PRINTF("%-27s\n", "Your EXE file is too old"); // Your Game's EXE file is not the latest version + PRINTF("%-27s\n"_fmt, "Your EXE file is too old"_s); // Your Game's EXE file is not the latest version break; case 7: - PRINTF("%-27s\n", "Banishement or"); - PRINTF(" Prohibited to login until...\n"); // You are Prohibited to log in until %s + PRINTF("%-27s\n"_fmt, "Banishement or"_s); + PRINTF(" Prohibited to login until...\n"_fmt); // You are Prohibited to log in until %s break; case 8: - PRINTF("%-27s\n", - "Server is over populated"); + PRINTF("%-27s\n"_fmt, + "Server is over populated"_s); break; case 9: - PRINTF("%-27s\n", "No MSG"); + PRINTF("%-27s\n"_fmt, "No MSG"_s); break; default: // 100 - PRINTF("%-27s\n", "This ID is totally erased"); // This ID has been totally erased + PRINTF("%-27s\n"_fmt, "This ID is totally erased"_s); // This ID has been totally erased break; } list_count++; } } // asking of the following acounts - LADMIN_LOG("Request to login-server to obtain the list of accounts from %d to %d (complement).\n", - list_first, list_last); - WFIFOW(login_session, 0) = 0x7920; - WFIFOL(login_session, 2) = list_first; - WFIFOL(login_session, 6) = list_last; - WFIFOSET(login_session, 10); + LADMIN_LOG("Request to login-server to obtain the list of accounts from %d to %d (complement).\n"_fmt, + list_first, list_last); + Packet_Fixed<0x7920> fixed_20; + fixed_20.start_account_id = list_first; + fixed_20.end_account_id = list_last; + send_fpacket<0x7920, 10>(login_session, fixed_20); bytes_to_read = 1; } - RFIFOSKIP(s, RFIFOW(s, 2)); break; + } case 0x7931: // Answer of login-server about an account creation - if (RFIFOREST(s) < 30) - return; { - int accid = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (accid == -1) + Packet_Fixed<0x7931> fixed; + rv = recv_fpacket<0x7931, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId accid = fixed.account_id; + AccountName name = fixed.account_name; + if (!accid) { - PRINTF("Account [%s] creation failed. Same account already exists.\n", + PRINTF("Account [%s] creation failed. Same account already exists.\n"_fmt, name); - LADMIN_LOG("Account [%s] creation failed. Same account already exists.\n", + LADMIN_LOG("Account [%s] creation failed. Same account already exists.\n"_fmt, name); } else { - PRINTF("Account [%s] is successfully created [id: %d].\n", + PRINTF("Account [%s] is successfully created [id: %d].\n"_fmt, name, accid); - LADMIN_LOG("Account [%s] is successfully created [id: %d].\n", + LADMIN_LOG("Account [%s] is successfully created [id: %d].\n"_fmt, name, accid); } bytes_to_read = 0; - } - RFIFOSKIP(s, 30); break; + } case 0x7933: // Answer of login-server about an account deletion - if (RFIFOREST(s) < 30) - return; { - int accid = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (accid == -1) + Packet_Fixed<0x7933> fixed; + rv = recv_fpacket<0x7933, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId accid = fixed.account_id; + AccountName name = fixed.account_name; + if (!accid) { - PRINTF("Account [%s] deletion failed. Account doesn't exist.\n", + PRINTF("Account [%s] deletion failed. Account doesn't exist.\n"_fmt, name); - LADMIN_LOG("Account [%s] deletion failed. Account doesn't exist.\n", + LADMIN_LOG("Account [%s] deletion failed. Account doesn't exist.\n"_fmt, name); } else { - PRINTF("Account [%s][id: %d] is successfully DELETED.\n", + PRINTF("Account [%s][id: %d] is successfully DELETED.\n"_fmt, name, accid); - LADMIN_LOG("Account [%s][id: %d] is successfully DELETED.\n", + LADMIN_LOG("Account [%s][id: %d] is successfully DELETED.\n"_fmt, name, accid); } bytes_to_read = 0; - } - RFIFOSKIP(s, 30); break; + } case 0x7935: // answer of the change of an account password - if (RFIFOREST(s) < 30) - return; { - int accid = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (accid == -1) + Packet_Fixed<0x7935> fixed; + rv = recv_fpacket<0x7935, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId accid = fixed.account_id; + AccountName name = fixed.account_name; + if (!accid) { - PRINTF("Account [%s] password changing failed.\n", + PRINTF("Account [%s] password changing failed.\n"_fmt, name); - PRINTF("Account [%s] doesn't exist.\n", + PRINTF("Account [%s] doesn't exist.\n"_fmt, name); - LADMIN_LOG("Account password changing failed. The compte [%s] doesn't exist.\n", + LADMIN_LOG("Account password changing failed. The compte [%s] doesn't exist.\n"_fmt, name); } else { - PRINTF("Account [%s][id: %d] password successfully changed.\n", + PRINTF("Account [%s][id: %d] password successfully changed.\n"_fmt, name, accid); - LADMIN_LOG("Account [%s][id: %d] password successfully changed.\n", + LADMIN_LOG("Account [%s][id: %d] password successfully changed.\n"_fmt, name, accid); } bytes_to_read = 0; - } - RFIFOSKIP(s, 30); break; + } case 0x7937: // answer of the change of an account state - if (RFIFOREST(s) < 34) - return; { - int accid = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - int state = RFIFOL(s, 30); - if (accid == -1) + Packet_Fixed<0x7937> fixed; + rv = recv_fpacket<0x7937, 34>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId accid = fixed.account_id; + AccountName name = fixed.account_name; + int state = fixed.status; + if (!accid) { - PRINTF("Account [%s] state changing failed. Account doesn't exist.\n", + PRINTF("Account [%s] state changing failed. Account doesn't exist.\n"_fmt, name); - LADMIN_LOG("Account [%s] state changing failed. Account doesn't exist.\n", + LADMIN_LOG("Account [%s] state changing failed. Account doesn't exist.\n"_fmt, name); } else { MString tmpstr; tmpstr += STRPRINTF( - "Account [%s] state successfully changed in [", + "Account [%s] state successfully changed in ["_fmt, name); switch (state) { case 0: - tmpstr += "0: Account OK"; + tmpstr += "0: Account OK"_s; break; case 1: - tmpstr += "1: Unregistered ID"; + tmpstr += "1: Unregistered ID"_s; break; case 2: - tmpstr += "2: Incorrect Password"; + tmpstr += "2: Incorrect Password"_s; break; case 3: - tmpstr += "3: This ID is expired"; + tmpstr += "3: This ID is expired"_s; break; case 4: - tmpstr += "4: Rejected from Server"; + tmpstr += "4: Rejected from Server"_s; break; case 5: - tmpstr += "5: You have been blocked by the GM Team"; + tmpstr += "5: You have been blocked by the GM Team"_s; break; case 6: - tmpstr += "6: [Your Game's EXE file is not the latest version"; + tmpstr += "6: [Your Game's EXE file is not the latest version"_s; break; case 7: - tmpstr += "7: You are Prohibited to log in until..."; + tmpstr += "7: You are Prohibited to log in until..."_s; break; case 8: - tmpstr += "8: Server is jammed due to over populated"; + tmpstr += "8: Server is jammed due to over populated"_s; break; case 9: - tmpstr += "9: No MSG"; + tmpstr += "9: No MSG"_s; break; default: // 100 - tmpstr += "100: This ID is totally erased"; + tmpstr += "100: This ID is totally erased"_s; break; } tmpstr += ']'; AString tmpstr_ = AString(tmpstr); - PRINTF("%s\n", tmpstr_); - LADMIN_LOG("%s\n", tmpstr_); + PRINTF("%s\n"_fmt, tmpstr_); + LADMIN_LOG("%s\n"_fmt, tmpstr_); } bytes_to_read = 0; - } - RFIFOSKIP(s, 34); break; + } case 0x7939: // answer of the number of online players - if (RFIFOREST(s) < 4 || RFIFOREST(s) < RFIFOW(s, 2)) - return; + { + std::vector<Packet_Repeat<0x7939>> repeat; + rv = recv_packet_repeatonly<0x7939, 4, 32>(s, repeat); + if (rv != RecvResult::Complete) + break; + { // Get length of the received packet - LADMIN_LOG(" Receiving of the number of online players.\n"); + LADMIN_LOG(" Receiving of the number of online players.\n"_fmt); // Read information of the servers - if (RFIFOW(s, 2) < 5) + if (repeat.empty()) { - PRINTF(" No server is connected to the login-server.\n"); + PRINTF(" No server is connected to the login-server.\n"_fmt); } else { - PRINTF(" Number of online players (server: number).\n"); + PRINTF(" Number of online players (server: number).\n"_fmt); // Displaying of result - for (int i = 4; i < RFIFOW(s, 2); i += 32) + for (const Packet_Repeat<0x7939>& info : repeat) { - ServerName name = stringish<ServerName>(RFIFO_STRING<20>(s, i + 6)); - PRINTF(" %-20s : %5d\n", name, - RFIFOW(s, i + 26)); + // info.ip + // info.port + ServerName name = info.name; + PRINTF(" %-20s : %5d\n"_fmt, name, + info.users); + // info.maintenance + // info.is_new } } } bytes_to_read = 0; - RFIFOSKIP(s, RFIFOW(s, 2)); break; + } case 0x793b: // answer of the check of a password - if (RFIFOREST(s) < 30) - return; { - int account_id = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (account_id == -1) + Packet_Fixed<0x793b> fixed; + rv = recv_fpacket<0x793b, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + AccountName name = fixed.account_name; + if (!account_id) { - PRINTF("The account [%s] doesn't exist or the password is incorrect.\n", + PRINTF("The account [%s] doesn't exist or the password is incorrect.\n"_fmt, name); - LADMIN_LOG("The account [%s] doesn't exist or the password is incorrect.\n", + LADMIN_LOG("The account [%s] doesn't exist or the password is incorrect.\n"_fmt, name); } else { - PRINTF("The proposed password is correct for the account [%s][id: %d].\n", + PRINTF("The proposed password is correct for the account [%s][id: %d].\n"_fmt, name, account_id); - LADMIN_LOG("The proposed password is correct for the account [%s][id: %d].\n", + LADMIN_LOG("The proposed password is correct for the account [%s][id: %d].\n"_fmt, name, account_id); } bytes_to_read = 0; - } - RFIFOSKIP(s, 30); break; + } case 0x793d: // answer of the change of an account sex - if (RFIFOREST(s) < 30) - return; { - int account_id = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (account_id == -1) + Packet_Fixed<0x793d> fixed; + rv = recv_fpacket<0x793d, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + AccountName name = fixed.account_name; + if (!account_id) { - PRINTF("Account [%s] sex changing failed.\n", + PRINTF("Account [%s] sex changing failed.\n"_fmt, name); - PRINTF("Account [%s] doesn't exist or the sex is already the good sex.\n", + PRINTF("Account [%s] doesn't exist or the sex is already the good sex.\n"_fmt, name); - LADMIN_LOG("Account sex changing failed. The compte [%s] doesn't exist or the sex is already the good sex.\n", + LADMIN_LOG("Account sex changing failed. The compte [%s] doesn't exist or the sex is already the good sex.\n"_fmt, name); } else { - PRINTF("Account [%s][id: %d] sex successfully changed.\n", + PRINTF("Account [%s][id: %d] sex successfully changed.\n"_fmt, name, account_id); - LADMIN_LOG("Account [%s][id: %d] sex successfully changed.\n", + LADMIN_LOG("Account [%s][id: %d] sex successfully changed.\n"_fmt, name, account_id); } bytes_to_read = 0; - } - RFIFOSKIP(s, 30); break; + } case 0x793f: // answer of the change of an account GM level - if (RFIFOREST(s) < 30) - return; { - int account_id = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (account_id == -1) + Packet_Fixed<0x793f> fixed; + rv = recv_fpacket<0x793f, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + AccountName name = fixed.account_name; + if (!account_id) { - PRINTF("Account [%s] GM level changing failed.\n", + PRINTF("Account [%s] GM level changing failed.\n"_fmt, name); - PRINTF("Account [%s] doesn't exist, the GM level is already the good GM level\n", + PRINTF("Account [%s] doesn't exist, the GM level is already the good GM level\n"_fmt, name); - PRINTF("or it's impossible to modify the GM accounts file.\n"); - LADMIN_LOG("Account GM level changing failed. The compte [%s] doesn't exist, the GM level is already the good sex or it's impossible to modify the GM accounts file.\n", + PRINTF("or it's impossible to modify the GM accounts file.\n"_fmt); + LADMIN_LOG("Account GM level changing failed. The compte [%s] doesn't exist, the GM level is already the good sex or it's impossible to modify the GM accounts file.\n"_fmt, name); } else { - PRINTF("Account [%s][id: %d] GM level successfully changed.\n", + PRINTF("Account [%s][id: %d] GM level successfully changed.\n"_fmt, name, account_id); - LADMIN_LOG("Account [%s][id: %d] GM level successfully changed.\n", + LADMIN_LOG("Account [%s][id: %d] GM level successfully changed.\n"_fmt, name, account_id); } bytes_to_read = 0; - } - RFIFOSKIP(s, 30); break; + } case 0x7941: // answer of the change of an account email - if (RFIFOREST(s) < 30) - return; { - int account_id = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (account_id == -1) + Packet_Fixed<0x7941> fixed; + rv = recv_fpacket<0x7941, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + AccountName name = fixed.account_name; + if (!account_id) { - PRINTF("Account [%s] e-mail changing failed.\n", + PRINTF("Account [%s] e-mail changing failed.\n"_fmt, name); - PRINTF("Account [%s] doesn't exist.\n", + PRINTF("Account [%s] doesn't exist.\n"_fmt, name); - LADMIN_LOG("Account e-mail changing failed. The compte [%s] doesn't exist.\n", + LADMIN_LOG("Account e-mail changing failed. The compte [%s] doesn't exist.\n"_fmt, name); } else { - PRINTF("Account [%s][id: %d] e-mail successfully changed.\n", + PRINTF("Account [%s][id: %d] e-mail successfully changed.\n"_fmt, name, account_id); - LADMIN_LOG("Account [%s][id: %d] e-mail successfully changed.\n", + LADMIN_LOG("Account [%s][id: %d] e-mail successfully changed.\n"_fmt, name, account_id); } bytes_to_read = 0; - } - RFIFOSKIP(s, 30); break; + } case 0x7943: // answer of the change of an account memo - if (RFIFOREST(s) < 30) - return; { - int account_id = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (account_id == -1) + Packet_Fixed<0x7943> fixed; + rv = recv_fpacket<0x7943, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + AccountName name = fixed.account_name; + if (!account_id) { - PRINTF("Account [%s] memo changing failed. Account doesn't exist.\n", + PRINTF("Account [%s] memo changing failed. Account doesn't exist.\n"_fmt, name); - LADMIN_LOG("Account [%s] memo changing failed. Account doesn't exist.\n", + LADMIN_LOG("Account [%s] memo changing failed. Account doesn't exist.\n"_fmt, name); } else { - PRINTF("Account [%s][id: %d] memo successfully changed.\n", + PRINTF("Account [%s][id: %d] memo successfully changed.\n"_fmt, name, account_id); - LADMIN_LOG("Account [%s][id: %d] memo successfully changed.\n", + LADMIN_LOG("Account [%s][id: %d] memo successfully changed.\n"_fmt, name, account_id); } bytes_to_read = 0; - } - RFIFOSKIP(s, 30); break; + } case 0x7945: // answer of an account id search - if (RFIFOREST(s) < 30) - return; { - int account_id = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (account_id == -1) + Packet_Fixed<0x7945> fixed; + rv = recv_fpacket<0x7945, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + AccountName name = fixed.account_name; + if (!account_id) { - PRINTF("Unable to find the account [%s] id. Account doesn't exist.\n", + PRINTF("Unable to find the account [%s] id. Account doesn't exist.\n"_fmt, name); - LADMIN_LOG("Unable to find the account [%s] id. Account doesn't exist.\n", + LADMIN_LOG("Unable to find the account [%s] id. Account doesn't exist.\n"_fmt, name); } else { - PRINTF("The account [%s] have the id: %d.\n", + PRINTF("The account [%s] have the id: %d.\n"_fmt, name, account_id); - LADMIN_LOG("The account [%s] have the id: %d.\n", + LADMIN_LOG("The account [%s] have the id: %d.\n"_fmt, name, account_id); } bytes_to_read = 0; - } - RFIFOSKIP(s, 30); break; + } case 0x7947: // answer of an account name search - if (RFIFOREST(s) < 30) - return; { - int account_id = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); + Packet_Fixed<0x7947> fixed; + rv = recv_fpacket<0x7947, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + AccountName name = fixed.account_name; if (!name) { - PRINTF("Unable to find the account [%d] name. Account doesn't exist.\n", + PRINTF("Unable to find the account [%d] name. Account doesn't exist.\n"_fmt, account_id); - LADMIN_LOG("Unable to find the account [%d] name. Account doesn't exist.\n", + LADMIN_LOG("Unable to find the account [%d] name. Account doesn't exist.\n"_fmt, account_id); } else { - PRINTF("The account [id: %d] have the name: %s.\n", + PRINTF("The account [id: %d] have the name: %s.\n"_fmt, account_id, name); - LADMIN_LOG("The account [id: %d] have the name: %s.\n", + LADMIN_LOG("The account [id: %d] have the name: %s.\n"_fmt, account_id, name); } bytes_to_read = 0; - } - RFIFOSKIP(s, 30); break; + } case 0x7949: // answer of an account validity limit set - if (RFIFOREST(s) < 34) - return; { - int account_id = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (RFIFOL(s, 2) == -1) + Packet_Fixed<0x7949> fixed; + rv = recv_fpacket<0x7949, 34>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + AccountName name = fixed.account_name; + if (!account_id) { - PRINTF("Account [%s] validity limit changing failed. Account doesn't exist.\n", + PRINTF("Account [%s] validity limit changing failed. Account doesn't exist.\n"_fmt, name); - LADMIN_LOG("Account [%s] validity limit changing failed. Account doesn't exist.\n", + LADMIN_LOG("Account [%s] validity limit changing failed. Account doesn't exist.\n"_fmt, name); } else { - TimeT timestamp = static_cast<time_t>(RFIFOL(s, 30)); + TimeT timestamp = fixed.valid_until; if (!timestamp) { - PRINTF("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n", + PRINTF("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n"_fmt, name, account_id); - LADMIN_LOG("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n", + LADMIN_LOG("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n"_fmt, name, account_id); } else { timestamp_seconds_buffer tmpstr; stamp_time(tmpstr, ×tamp); - PRINTF("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n", + PRINTF("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt, name, account_id, tmpstr); - LADMIN_LOG("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n", + LADMIN_LOG("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt, name, account_id, tmpstr); } } bytes_to_read = 0; - } - RFIFOSKIP(s, 34); break; + } case 0x794b: // answer of an account ban set - if (RFIFOREST(s) < 34) - return; { - int account_id = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (account_id == -1) + Packet_Fixed<0x794b> fixed; + rv = recv_fpacket<0x794b, 34>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + AccountName name = fixed.account_name; + if (!account_id) { - PRINTF("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", + PRINTF("Account [%s] final date of banishment changing failed. Account doesn't exist.\n"_fmt, name); - LADMIN_LOG("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", + LADMIN_LOG("Account [%s] final date of banishment changing failed. Account doesn't exist.\n"_fmt, name); } else { - TimeT timestamp = static_cast<time_t>(RFIFOL(s, 30)); + TimeT timestamp = fixed.ban_until; if (!timestamp) { - PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", + PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n"_fmt, name, account_id); - LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", + LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n"_fmt, name, account_id); } else { timestamp_seconds_buffer tmpstr; stamp_time(tmpstr, ×tamp); - PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", - name, RFIFOL(s, 2), tmpstr); - LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", - name, RFIFOL(s, 2), + PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt, + name, account_id, tmpstr); + LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt, + name, account_id, tmpstr); } } bytes_to_read = 0; - } - RFIFOSKIP(s, 34); break; + } case 0x794d: // answer of an account ban date/time changing - if (RFIFOREST(s) < 34) - return; { - int account_id = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (account_id == -1) + Packet_Fixed<0x794d> fixed; + rv = recv_fpacket<0x794d, 34>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + AccountName name = fixed.account_name; + if (!account_id) { - PRINTF("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", + PRINTF("Account [%s] final date of banishment changing failed. Account doesn't exist.\n"_fmt, name); - LADMIN_LOG("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", + LADMIN_LOG("Account [%s] final date of banishment changing failed. Account doesn't exist.\n"_fmt, name); } else { - TimeT timestamp = static_cast<time_t>(RFIFOL(s, 30)); + TimeT timestamp = fixed.ban_until; if (!timestamp) { - PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", + PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n"_fmt, name, account_id); - LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", + LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n"_fmt, name, account_id); } else { timestamp_seconds_buffer tmpstr; stamp_time(tmpstr, ×tamp); - PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", + PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt, name, account_id, tmpstr); - LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", + LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt, name, account_id, tmpstr); } } bytes_to_read = 0; - } - RFIFOSKIP(s, 34); break; + } case 0x794f: // answer of a broadcast - if (RFIFOREST(s) < 4) - return; - if (RFIFOW(s, 2) == static_cast<uint16_t>(-1)) + { + Packet_Fixed<0x794f> fixed; + rv = recv_fpacket<0x794f, 4>(s, fixed); + if (rv != RecvResult::Complete) + break; + + if (fixed.error == static_cast<uint16_t>(-1)) { - PRINTF("Message sending failed. No online char-server.\n"); - LADMIN_LOG("Message sending failed. No online char-server.\n"); + PRINTF("Message sending failed. No online char-server.\n"_fmt); + LADMIN_LOG("Message sending failed. No online char-server.\n"_fmt); } else { - PRINTF("Message successfully sended to login-server.\n"); - LADMIN_LOG("Message successfully sended to login-server.\n"); + PRINTF("Message successfully sended to login-server.\n"_fmt); + LADMIN_LOG("Message successfully sended to login-server.\n"_fmt); } bytes_to_read = 0; - RFIFOSKIP(s, 4); break; + } case 0x7951: // answer of an account validity limit changing - if (RFIFOREST(s) < 34) - return; { - int account_id = RFIFOL(s, 2); - AccountName name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - if (account_id == -1) + Packet_Fixed<0x7951> fixed; + rv = recv_fpacket<0x7951, 34>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + AccountName name = fixed.account_name; + if (!account_id) { - PRINTF("Account [%s] validity limit changing failed. Account doesn't exist.\n", + PRINTF("Account [%s] validity limit changing failed. Account doesn't exist.\n"_fmt, name); - LADMIN_LOG("Account [%s] validity limit changing failed. Account doesn't exist.\n", + LADMIN_LOG("Account [%s] validity limit changing failed. Account doesn't exist.\n"_fmt, name); } else { - TimeT timestamp = static_cast<time_t>(RFIFOL(s, 30)); + TimeT timestamp = fixed.valid_until; if (!timestamp) { - PRINTF("Validity limit of the account [%s][id: %d] unchanged.\n", + PRINTF("Validity limit of the account [%s][id: %d] unchanged.\n"_fmt, name, account_id); - PRINTF("The account have an unlimited validity limit or\n"); - PRINTF("the changing is impossible with the proposed adjustments.\n"); - LADMIN_LOG("Validity limit of the account [%s][id: %d] unchanged. The account have an unlimited validity limit or the changing is impossible with the proposed adjustments.\n", + PRINTF("The account have an unlimited validity limit or\n"_fmt); + PRINTF("the changing is impossible with the proposed adjustments.\n"_fmt); + LADMIN_LOG("Validity limit of the account [%s][id: %d] unchanged. The account have an unlimited validity limit or the changing is impossible with the proposed adjustments.\n"_fmt, name, account_id); } else { timestamp_seconds_buffer tmpstr; stamp_time(tmpstr, ×tamp); - PRINTF("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n", + PRINTF("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt, name, account_id, tmpstr); - LADMIN_LOG("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n", + LADMIN_LOG("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt, name, account_id, tmpstr); } } bytes_to_read = 0; - } - RFIFOSKIP(s, 34); break; + } case 0x7953: // answer of a request about informations of an account (by account name/id) - if (RFIFOREST(s) < 150 - || RFIFOREST(s) < (150 + RFIFOW(s, 148))) - return; + { + Packet_Head<0x7953> head; + AString repeat; + rv = recv_vpacket<0x7953, 150, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + break; + { - int account_id = RFIFOL(s, 2); - uint8_t gm = RFIFOB(s, 6); - AccountName userid = stringish<AccountName>(RFIFO_STRING<24>(s, 7)); - uint8_t sex = RFIFOB(s, 31); - int connections = RFIFOL(s, 32); - int state = RFIFOL(s, 36); - timestamp_seconds_buffer error_message = stringish<timestamp_seconds_buffer>(RFIFO_STRING<20>(s, 40)); - timestamp_milliseconds_buffer lastlogin = stringish<timestamp_milliseconds_buffer>(RFIFO_STRING<24>(s, 60)); - VString<15> last_ip_ = RFIFO_STRING<16>(s, 84); - AccountEmail email = stringish<AccountEmail>(RFIFO_STRING<40>(s, 100)); - TimeT connect_until_time = static_cast<time_t>(RFIFOL(s, 140)); - TimeT ban_until_time = static_cast<time_t>(RFIFOL(s, 144)); - AString memo = RFIFO_STRING(s, 150, RFIFOW(s, 148)); - if (account_id == -1) + AccountId account_id = head.account_id; + // TODO fix size (there's a lot of other stuff wrong with this packet too + GmLevel gm = head.gm_level; + AccountName userid = head.account_name; + SEX sex = head.sex; + int connections = head.login_count; + int state = head.state; + timestamp_seconds_buffer error_message = head.error_message; + timestamp_milliseconds_buffer lastlogin = head.last_login_string; + VString<15> last_ip_ = head.ip_string; + AccountEmail email = head.email; + TimeT connect_until_time = head.connect_until; + TimeT ban_until_time = head.ban_until; + AString& memo = repeat; + if (!account_id) { - PRINTF("Unabled to find the account [%s]. Account doesn't exist.\n", + PRINTF("Unabled to find the account [%s]. Account doesn't exist.\n"_fmt, userid); - LADMIN_LOG("Unabled to find the account [%s]. Account doesn't exist.\n", + LADMIN_LOG("Unabled to find the account [%s]. Account doesn't exist.\n"_fmt, userid); } else if (!userid) { - PRINTF("Unabled to find the account [id: %d]. Account doesn't exist.\n", + PRINTF("Unabled to find the account [id: %d]. Account doesn't exist.\n"_fmt, account_id); - LADMIN_LOG("Unabled to find the account [id: %d]. Account doesn't exist.\n", + LADMIN_LOG("Unabled to find the account [id: %d]. Account doesn't exist.\n"_fmt, account_id); } else { - LADMIN_LOG("Receiving information about an account.\n"); - PRINTF("The account is set with:\n"); + LADMIN_LOG("Receiving information about an account.\n"_fmt); + PRINTF("The account is set with:\n"_fmt); if (!gm) { - PRINTF(" Id: %d (non-GM)\n", account_id); + PRINTF(" Id: %d (non-GM)\n"_fmt, account_id); } else { - PRINTF(" Id: %d (GM level %d)\n", + PRINTF(" Id: %d (GM level %d)\n"_fmt, account_id, gm); } - PRINTF(" Name: '%s'\n", userid); - if (sex == 0) - PRINTF(" Sex: Female\n"); - else if (sex == 1) - PRINTF(" Sex: Male\n"); - else - PRINTF(" Sex: Server\n"); - PRINTF(" E-mail: %s\n", email); + PRINTF(" Name: '%s'\n"_fmt, userid); + if (sex == SEX::FEMALE) + PRINTF(" Sex: Female\n"_fmt); + else if (sex == SEX::MALE) + PRINTF(" Sex: Male\n"_fmt); + else // doesn't happen anymore + PRINTF(" Sex: Server\n"_fmt); + PRINTF(" E-mail: %s\n"_fmt, email); switch (state) { case 0: - PRINTF(" Statut: 0 [Account OK]\n"); + PRINTF(" Statut: 0 [Account OK]\n"_fmt); break; case 1: - PRINTF(" Statut: 1 [Unregistered ID]\n"); + PRINTF(" Statut: 1 [Unregistered ID]\n"_fmt); break; case 2: - PRINTF(" Statut: 2 [Incorrect Password]\n"); + PRINTF(" Statut: 2 [Incorrect Password]\n"_fmt); break; case 3: - PRINTF(" Statut: 3 [This ID is expired]\n"); + PRINTF(" Statut: 3 [This ID is expired]\n"_fmt); break; case 4: - PRINTF(" Statut: 4 [Rejected from Server]\n"); + PRINTF(" Statut: 4 [Rejected from Server]\n"_fmt); break; case 5: - PRINTF(" Statut: 5 [You have been blocked by the GM Team]\n"); + PRINTF(" Statut: 5 [You have been blocked by the GM Team]\n"_fmt); break; case 6: - PRINTF(" Statut: 6 [Your Game's EXE file is not the latest version]\n"); + PRINTF(" Statut: 6 [Your Game's EXE file is not the latest version]\n"_fmt); break; case 7: - PRINTF(" Statut: 7 [You are Prohibited to log in until %s]\n", - error_message); + PRINTF(" Statut: 7 [You are Prohibited to log in until %s]\n"_fmt, + error_message); break; case 8: - PRINTF(" Statut: 8 [Server is jammed due to over populated]\n"); + PRINTF(" Statut: 8 [Server is jammed due to over populated]\n"_fmt); break; case 9: - PRINTF(" Statut: 9 [No MSG]\n"); + PRINTF(" Statut: 9 [No MSG]\n"_fmt); break; default: // 100 - PRINTF(" Statut: %d [This ID is totally erased]\n", + PRINTF(" Statut: %d [This ID is totally erased]\n"_fmt, state); break; } if (!ban_until_time) { - PRINTF(" Banishment: not banished.\n"); + PRINTF(" Banishment: not banished.\n"_fmt); } else { timestamp_seconds_buffer tmpstr; stamp_time(tmpstr, &ban_until_time); - PRINTF(" Banishment: until %s.\n", tmpstr); + PRINTF(" Banishment: until %s.\n"_fmt, tmpstr); } if (connections > 1) - PRINTF(" Count: %d connections.\n", + PRINTF(" Count: %d connections.\n"_fmt, connections); else - PRINTF(" Count: %d connection.\n", + PRINTF(" Count: %d connection.\n"_fmt, connections); - PRINTF(" Last connection at: %s (ip: %s)\n", + PRINTF(" Last connection at: %s (ip: %s)\n"_fmt, lastlogin, last_ip_); if (!connect_until_time) { - PRINTF(" Validity limit: unlimited.\n"); + PRINTF(" Validity limit: unlimited.\n"_fmt); } else { timestamp_seconds_buffer tmpstr; stamp_time(tmpstr, &connect_until_time); - PRINTF(" Validity limit: until %s.\n", + PRINTF(" Validity limit: until %s.\n"_fmt, tmpstr); } - PRINTF(" Memo: '%s'\n", memo); + PRINTF(" Memo: '%s'\n"_fmt, memo); } } bytes_to_read = 0; - RFIFOSKIP(s, 150 + RFIFOW(s, 148)); break; + } default: - PRINTF("Remote administration has been disconnected (unknown packet).\n"); - LADMIN_LOG("'End of connection, unknown packet.\n"); + { + PRINTF("Remote administration has been disconnected (unknown packet).\n"_fmt); + LADMIN_LOG("'End of connection, unknown packet.\n"_fmt); s->set_eof(); return; + } } } + if (rv == RecvResult::Error) + { + s->set_eof(); + return; + } + + // The following was almost certainly wrong and only worked because + // localhost is a fast enough network to never split byte 1 vs byte 2 + // if we don't wait new packets, do the prompt - prompt(); + if (bytes_to_read == 0) + prompt(); } //------------------------------------ @@ -2782,23 +2838,23 @@ void parse_fromlogin(Session *s) static int Connect_login_server(void) { - Iprintf("Attempt to connect to login-server...\n"); - LADMIN_LOG("Attempt to connect to login-server...\n"); + Iprintf("Attempt to connect to login-server...\n"_fmt); + LADMIN_LOG("Attempt to connect to login-server...\n"_fmt); - login_session = make_connection(login_ip, login_port, SessionParsers{func_parse: parse_fromlogin, func_delete: delete_fromlogin}); + login_session = make_connection(login_ip, login_port, SessionParsers{.func_parse= parse_fromlogin, .func_delete= delete_fromlogin}); if (!login_session) return 0; { - WFIFOW(login_session, 0) = 0x7918; // Request for administation login - WFIFOW(login_session, 2) = 0; // no encrypted - WFIFO_STRING(login_session, 4, admin_pass, 24); - WFIFOSET(login_session, 28); + Packet_Fixed<0x7918> fixed_18; + fixed_18.encryption_zero = 0; + fixed_18.account_pass = admin_pass; + send_fpacket<0x7918, 28>(login_session, fixed_18); bytes_to_read = 1; - Iprintf("Sending of the password...\n"); - LADMIN_LOG("Sending of the password...\n"); + Iprintf("Sending of the password...\n"_fmt); + LADMIN_LOG("Sending of the password...\n"_fmt); } return 0; @@ -2808,12 +2864,12 @@ static bool admin_confs(XString w1, ZString w2) { { - if (w1 == "login_ip") + if (w1 == "login_ip"_s) { struct hostent *h = gethostbyname(w2.c_str()); - if (h != NULL) + if (h != nullptr) { - Iprintf("Login server IP address: %s -> %s\n", + Iprintf("Login server IP address: %s -> %s\n"_fmt, w2, login_ip); login_ip = IP4Address({ static_cast<uint8_t>(h->h_addr[0]), @@ -2823,21 +2879,21 @@ bool admin_confs(XString w1, ZString w2) }); } } - else if (w1 == "login_port") + else if (w1 == "login_port"_s) { login_port = atoi(w2.c_str()); } - else if (w1 == "admin_pass") + else if (w1 == "admin_pass"_s) { admin_pass = stringish<AccountPass>(w2); } - else if (w1 == "ladmin_log_filename") + else if (w1 == "ladmin_log_filename"_s) { ladmin_log_filename = w2; } else { - PRINTF("WARNING: unknown ladmin config key: %s\n", AString(w1)); + PRINTF("WARNING: unknown ladmin config key: %s\n"_fmt, AString(w1)); return false; } } @@ -2854,8 +2910,8 @@ void term_func(void) { delete_session(login_session); - Iprintf(SGR_RESET "----End of Ladmin (normal end with closing of all files).\n"); - LADMIN_LOG("----End of Ladmin (normal end with closing of all files).\n"); + Iprintf(SGR_RESET "----End of Ladmin (normal end with closing of all files).\n"_fmt); + LADMIN_LOG("----End of Ladmin (normal end with closing of all files).\n"_fmt); already_exit_function = 1; } @@ -2873,20 +2929,20 @@ int do_init(Slice<ZString> argv) ZString argvi = argv.pop_front(); if (argvi.startswith('-')) { - if (argvi == "--help") + if (argvi == "--help"_s) { - PRINTF("Usage: %s [--help] [--version] [files...]\n", + PRINTF("Usage: %s [--help] [--version] [files...]\n"_fmt, argv0); exit(0); } - else if (argvi == "--version") + else if (argvi == "--version"_s) { - PRINTF("%s\n", CURRENT_VERSION_STRING); + PRINTF("%s\n"_fmt, CURRENT_VERSION_STRING); exit(0); } else { - FPRINTF(stderr, "Unknown argument: %s\n", argvi); + FPRINTF(stderr, "Unknown argument: %s\n"_fmt, argvi); runflag = false; } } @@ -2898,26 +2954,27 @@ int do_init(Slice<ZString> argv) } if (!loaded_config_yet) - runflag &= load_config_file("conf/tmwa-admin.conf", admin_confs); + runflag &= load_config_file("conf/tmwa-admin.conf"_s, admin_confs); eathena_interactive_session = isatty(0); - LADMIN_LOG(""); - LADMIN_LOG("Configuration file readed.\n"); + LADMIN_LOG(""_fmt); + LADMIN_LOG("Configuration file readed.\n"_fmt); - Iprintf("EAthena login-server administration tool.\n"); + Iprintf("EAthena login-server administration tool.\n"_fmt); Version version = CURRENT_LOGIN_SERVER_VERSION; - Iprintf("for tmwA version %hhu.%hhu.%hhu (dev? %hhu) (flags %hhx) (which %hhx) (vend %hu)\n", + Iprintf("for tmwA version %hhu.%hhu.%hhu (dev? %hhu) (flags %hhx) (which %hhx) (vend %hu)\n"_fmt, version.major, version.minor, version.patch, version.devel, version.flags, version.which, version.vend); - LADMIN_LOG("Ladmin is ready.\n"); - Iprintf("Ladmin is " SGR_BOLD SGR_GREEN "ready" SGR_RESET ".\n\n"); + LADMIN_LOG("Ladmin is ready.\n"_fmt); + Iprintf("Ladmin is " SGR_BOLD SGR_GREEN "ready" SGR_RESET ".\n\n"_fmt); Connect_login_server(); return 0; } +} // namespace tmwa diff --git a/src/admin/ladmin.hpp b/src/admin/ladmin.hpp index 034f644..94783ac 100644 --- a/src/admin/ladmin.hpp +++ b/src/admin/ladmin.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_ADMIN_LADMIN_HPP -#define TMWA_ADMIN_LADMIN_HPP +#pragma once // ladmin.hpp - dummy header to make Make dependencies work. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,6 +18,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -#endif // TMWA_ADMIN_LADMIN_HPP + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/admin/main.cpp b/src/admin/main.cpp index c6f075e..678286e 100644 --- a/src/admin/main.cpp +++ b/src/admin/main.cpp @@ -1,4 +1,3 @@ -#include "ladmin.hpp" // admin/main.cpp - dummy file to make Make dependencies work // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -18,4 +17,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include "ladmin.hpp" + #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/char/char.cpp b/src/char/char.cpp index f8e12c0..b9cf17b 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -22,8 +22,6 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <arpa/inet.h> -#include <sys/socket.h> #include <sys/wait.h> #include <netdb.h> @@ -33,32 +31,45 @@ #include <cassert> #include <cstdlib> -#include <cstring> -#include <ctime> +#include <algorithm> +#include <array> #include <bitset> +#include <chrono> #include <set> -#include "../compat/alg.hpp" +#include "../ints/cmp.hpp" +#include "../ints/udl.hpp" #include "../strings/mstring.hpp" #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" -#include "../generic/db.hpp" +#include "../generic/array.hpp" #include "../io/cxxstdio.hpp" #include "../io/lock.hpp" #include "../io/read.hpp" #include "../io/tty.hpp" +#include "../io/write.hpp" + +#include "../net/packets.hpp" +#include "../net/socket.hpp" +#include "../net/timer.hpp" + +#include "../proto2/any-user.hpp" +#include "../proto2/login-admin.hpp" +#include "../proto2/login-char.hpp" +#include "../proto2/char-map.hpp" +#include "../proto2/char-user.hpp" #include "../mmo/config_parse.hpp" #include "../mmo/core.hpp" #include "../mmo/extract.hpp" #include "../mmo/human_time_diff.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" +#include "../mmo/mmo.hpp" +#include "../mmo/utils.hpp" #include "../mmo/version.hpp" #include "inter.hpp" @@ -67,6 +78,9 @@ #include "../poison.hpp" + +namespace tmwa +{ static Array<struct mmo_map_server, MAX_MAP_SERVERS> server; static @@ -76,11 +90,11 @@ Array<int, MAX_MAP_SERVERS> server_freezeflag; // Map-server anti-freeze syst static int anti_freeze_enable = 0; static -std::chrono::seconds anti_freeze_interval = std::chrono::seconds(6); +std::chrono::seconds anti_freeze_interval = 6_s; constexpr std::chrono::milliseconds DEFAULT_AUTOSAVE_INTERVAL = - std::chrono::minutes(5); + 5_min; static Session *login_session, *char_session; @@ -91,7 +105,7 @@ AccountPass passwd; static ServerName server_name; static -CharName wisp_server_name = stringish<CharName>("Server"); +CharName wisp_server_name = stringish<CharName>("Server"_s); static IP4Address login_ip; static @@ -103,9 +117,9 @@ int char_port = 6121; static AString char_txt; static -CharName unknown_char_name = stringish<CharName>("Unknown"); +CharName unknown_char_name = stringish<CharName>("Unknown"_s); static -AString char_log_filename = "log/char.log"; +AString char_log_filename = "log/char.log"_s; //Added for lan support static IP4Address lan_map_ip = IP4_LOCALHOST; @@ -115,10 +129,14 @@ static int char_name_option = 0; // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor] static std::bitset<256> char_name_letters; // list of letters/symbols authorised (or not) in a character name. by [Yor] +static constexpr +GmLevel default_gm_level = GmLevel::from(0_u32); + struct char_session_data : SessionData { - int account_id, login_id1, login_id2; + AccountId account_id; + int login_id1, login_id2; SEX sex; unsigned short packet_tmw_version; AccountEmail email; @@ -132,8 +150,8 @@ void SessionDeleter::operator()(SessionData *sd) struct AuthFifoEntry { - int account_id; - int char_id; + AccountId account_id; + CharId char_id; int login_id1, login_id2; IP4Address ip; int delflag; @@ -150,7 +168,7 @@ static int check_ip_flag = 1; // It's to check IP of a player between char-server and other servers (part of anti-hacking system) static -int char_id_count = 150000; +CharId char_id_count = wrap<CharId>(150000); static std::vector<CharPair> char_keys; static @@ -160,22 +178,22 @@ std::chrono::milliseconds autosave_time = DEFAULT_AUTOSAVE_INTERVAL; // Initial position (it's possible to set it in conf file) static -struct point start_point = { {"001-1.gat"}, 273, 354 }; +Point start_point = { {"001-1.gat"_s}, 273, 354 }; static std::vector<GM_Account> gm_accounts; // online players by [Yor] static -AString online_txt_filename = "online.txt"; +AString online_txt_filename = "online.txt"_s; static -AString online_html_filename = "online.html"; +AString online_html_filename = "online.html"_s; static int online_sorting_option = 0; // sorting option to display online players in online files static int online_refresh_html = 20; // refresh time (in sec) of the html file in the explorer static -int online_gm_display_min_level = 20; // minimum GM level to display 'GM' when we want to display it +GmLevel online_gm_display_min_level = GmLevel::from(20_u32); // minimum GM level to display 'GM' when we want to display it static std::vector<Session *> online_chars; // same size of char_keys, and id value of current server (or -1) @@ -185,6 +203,14 @@ TimeT update_online; // to update online files when we receiving infor static pid_t pid = 0; // For forked DB writes + +auto iter_map_sessions() -> decltype(filter_iterator<Session *>(std::declval<Array<Session *, MAX_MAP_SERVERS> *>())) +{ + return filter_iterator<Session *>(&server_session); +} + + + static void create_online_files(void); @@ -192,7 +218,7 @@ static void delete_tologin(Session *sess) { assert (sess == login_session); - PRINTF("Char-server can't connect to login-server (connection #%d).\n", + PRINTF("Char-server can't connect to login-server (connection #%d).\n"_fmt, sess); login_session = nullptr; } @@ -207,7 +233,7 @@ void delete_frommap(Session *sess) auto it = std::find(server_session.begin(), server_session.end(), sess); assert (it != server_session.end()); int id = it - server_session.begin(); - PRINTF("Map-server %d (session #%d) has disconnected.\n", id, + PRINTF("Map-server %d (session #%d) has disconnected.\n"_fmt, id, sess); server[id] = mmo_map_server{}; server_session[id] = nullptr; @@ -233,12 +259,12 @@ void char_log(XString line) // and returns its level (or 0 if it isn't a GM account or if not found) //---------------------------------------------------------------------- static -int isGM(int account_id) +GmLevel isGM(AccountId account_id) { for (GM_Account& gma : gm_accounts) if (gma.account_id == account_id) return gma.level; - return 0; + return default_gm_level; } //---------------------------------------------- @@ -264,7 +290,7 @@ const CharPair *search_character(CharName character_name) return nullptr; } -const CharPair *search_character_id(int char_id) +const CharPair *search_character_id(CharId char_id) { for (const CharPair& cd : char_keys) { @@ -317,7 +343,7 @@ AString mmo_char_tostr(struct CharPair *cp) "%d,%d,%d\t" "%d,%d,%d,%d,%d\t" "%s,%d,%d\t" - "%s,%d,%d,%d\t", + "%s,%d,%d,%d\t"_fmt, k->char_id, k->account_id, k->char_num, k->name, @@ -336,11 +362,12 @@ AString mmo_char_tostr(struct CharPair *cp) // memos were here (no longer supported) str_p += '\t'; - for (int i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) + { if (p->inventory[i].nameid) { - str_p += STRPRINTF("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ", - p->inventory[i].id, + str_p += STRPRINTF("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d "_fmt, + 0 /*id*/, p->inventory[i].nameid, p->inventory[i].amount, p->inventory[i].equip, @@ -353,33 +380,40 @@ AString mmo_char_tostr(struct CharPair *cp) 0 /*card[3]*/, 0 /*broken*/); } + } str_p += '\t'; // cart was here (no longer supported) str_p += '\t'; for (SkillID i : erange(SkillID(), MAX_SKILL)) + { if (p->skill[i].lv) { - str_p += STRPRINTF("%d,%d ", + str_p += STRPRINTF("%d,%d "_fmt, i, - p->skill[i].lv | (uint16_t(p->skill[i].flags) << 16)); + p->skill[i].lv | (static_cast<uint16_t>(p->skill[i].flags) << 16)); } + } str_p += '\t'; assert (p->global_reg_num < GLOBAL_REG_NUM); for (int i = 0; i < p->global_reg_num; i++) + { if (p->global_reg[i].str) - str_p += STRPRINTF("%s,%d ", + { + str_p += STRPRINTF("%s,%d "_fmt, p->global_reg[i].str, p->global_reg[i].value); + } + } str_p += '\t'; return AString(str_p); } static -bool extract(XString str, struct point *p) +bool extract(XString str, Point *p) { return extract(str, record<','>(&p->map_, &p->x, &p->y)); } @@ -414,10 +448,11 @@ bool extract(XString str, CharPair *cp) uint32_t unused_guild_id, unused_pet_id; XString unused_memos; - std::vector<struct item> inventory; + std::vector<Item> inventory; XString unused_cart; std::vector<struct skill_loader> skills; - std::vector<struct global_reg> vars; + std::vector<GlobalReg> vars; + XString hair_style; if (!extract(str, record<'\t'>( &k->char_id, @@ -430,7 +465,7 @@ bool extract(XString str, CharPair *cp) record<','>(&p->status_point, &p->skill_point), record<','>(&p->option, &p->karma, &p->manner), record<','>(&p->party_id, &unused_guild_id, &unused_pet_id), - record<','>(&p->hair, &p->hair_color, &p->clothes_color), + record<','>(&hair_style, &p->hair_color, &p->clothes_color), record<','>(&p->weapon, &p->shield, &p->head_top, &p->head_mid, &p->head_bottom), &p->last_point, // somebody was silly and stuck partner id as a field @@ -444,11 +479,19 @@ bool extract(XString str, CharPair *cp) vrec<' '>(&vars)))) return false; + // leftover corruption from Platinum + if (hair_style == "-1"_s) + { + p->hair = 0; + } + else if (!extract(hair_style, &p->hair)) + return false; + if (wisp_server_name == k->name) return false; // TODO replace *every* lookup with a map lookup - static std::set<int> seen_ids; + static std::set<CharId> seen_ids; static std::set<CharName> seen_names; // we don't have to worry about deleted characters, // this is only called during startup @@ -499,10 +542,10 @@ int mmo_char_init(void) io::ReadFile in(char_txt); if (!in.is_open()) { - PRINTF("Characters file not found: %s.\n", char_txt); - CHAR_LOG("Characters file not found: %s.\n", char_txt); - CHAR_LOG("Id for the next created character: %d.\n", - char_id_count); + PRINTF("Characters file not found: %s.\n"_fmt, char_txt); + CHAR_LOG("Characters file not found: %s.\n"_fmt, char_txt); + CHAR_LOG("Id for the next created character: %d.\n"_fmt, + char_id_count); return 0; } @@ -516,8 +559,8 @@ int mmo_char_init(void) continue; { - int i, j = 0; - if (SSCANF(line, "%d\t%%newid%%%n", &i, &j) == 1 && j > 0) + CharId i; + if (extract(line, record<'\t'>(&i, "%newid%"_s))) { if (char_id_count < i) char_id_count = i; @@ -528,21 +571,21 @@ int mmo_char_init(void) CharPair cd; if (!extract(line, &cd)) { - CHAR_LOG("Char skipped\n%s", line); + CHAR_LOG("Char skipped\n%s"_fmt, line); continue; } - if (cd.key.char_id >= char_id_count) - char_id_count = cd.key.char_id + 1; + if (char_id_count < next(cd.key.char_id)) + char_id_count = next(cd.key.char_id); char_keys.push_back(std::move(cd)); online_chars.push_back(nullptr); } - PRINTF("mmo_char_init: %zu characters read in %s.\n", + PRINTF("mmo_char_init: %zu characters read in %s.\n"_fmt, char_keys.size(), char_txt); - CHAR_LOG("mmo_char_init: %zu characters read in %s.\n", + CHAR_LOG("mmo_char_init: %zu characters read in %s.\n"_fmt, char_keys.size(), char_txt); - CHAR_LOG("Id for the next created character: %d.\n", + CHAR_LOG("Id for the next created character: %d.\n"_fmt, char_id_count); return 0; @@ -557,8 +600,8 @@ void mmo_char_sync(void) io::WriteLock fp(char_txt); if (!fp.is_open()) { - PRINTF("WARNING: Server can't not save characters.\n"); - CHAR_LOG("WARNING: Server can't not save characters.\n"); + PRINTF("WARNING: Server can't not save characters.\n"_fmt); + CHAR_LOG("WARNING: Server can't not save characters.\n"_fmt); return; } { @@ -568,7 +611,7 @@ void mmo_char_sync(void) AString line = mmo_char_tostr(&cd); fp.put_line(line); } - FPRINTF(fp, "%d\t%%newid%%\n", char_id_count); + FPRINTF(fp, "%d\t%%newid%%\n"_fmt, char_id_count); } } @@ -612,7 +655,7 @@ void mmo_char_sync_timer(TimerData *, tick_t) // Function to create a new character //----------------------------------- static -CharPair *make_new_char(Session *s, CharName name, const uint8_t (&stats)[6], uint8_t slot, uint16_t hair_color, uint16_t hair_style) +CharPair *make_new_char(Session *s, CharName name, const Stats6& stats, uint8_t slot, uint16_t hair_color, uint16_t hair_style) { // ugh char_session_data *sd = static_cast<char_session_data *>(s->session_data.get()); @@ -620,24 +663,24 @@ CharPair *make_new_char(Session *s, CharName name, const uint8_t (&stats)[6], ui // remove control characters from the name if (!name.to__actual().is_print()) { - CHAR_LOG("Make new char error (control char received in the name): (connection #%d, account: %d).\n", - s, sd->account_id); + CHAR_LOG("Make new char error (control char received in the name): (connection #%d, account: %d).\n"_fmt, + s, sd->account_id); return nullptr; } // Eliminate whitespace if (name.to__actual() != name.to__actual().strip()) { - CHAR_LOG("Make new char error (leading/trailing whitespace): (connection #%d, account: %d, name: '%s'.\n", - s, sd->account_id, name); + CHAR_LOG("Make new char error (leading/trailing whitespace): (connection #%d, account: %d, name: '%s'.\n"_fmt, + s, sd->account_id, name); return nullptr; } // check lenght of character name if (name.to__actual().size() < 4) { - CHAR_LOG("Make new char error (character name too small): (connection #%d, account: %d, name: '%s').\n", - s, sd->account_id, name); + CHAR_LOG("Make new char error (character name too small): (connection #%d, account: %d, name: '%s').\n"_fmt, + s, sd->account_id, name); return nullptr; } @@ -648,7 +691,7 @@ CharPair *make_new_char(Session *s, CharName name, const uint8_t (&stats)[6], ui for (uint8_t c : name.to__actual()) if (!char_name_letters[c]) { - CHAR_LOG("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n", + CHAR_LOG("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n"_fmt, s, sd->account_id, name, c); return nullptr; } @@ -659,36 +702,38 @@ CharPair *make_new_char(Session *s, CharName name, const uint8_t (&stats)[6], ui for (uint8_t c : name.to__actual()) if (char_name_letters[c]) { - CHAR_LOG("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n", + CHAR_LOG("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n"_fmt, s, sd->account_id, name, c); return nullptr; } } // else, all letters/symbols are authorised (except control char removed before) + // TODO this comment is obsolete // this is why it needs to be unsigned - if (stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5] != 5 * 6 || // stats + if (stats.str + stats.agi + stats.vit + stats.int_ + stats.dex + stats.luk != 5 * 6 || // stats slot >= 9 || hair_style >= 20 || hair_color >= 12) { - CHAR_LOG("Make new char error (invalid values): (connection #%d, account: %d) slot %d, name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d\n", - s, sd->account_id, slot, name, - stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], - stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], - hair_style, hair_color); + CHAR_LOG("Make new char error (invalid values): (connection #%d, account: %d) slot %d, name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d\n"_fmt, + s, sd->account_id, slot, name, + stats.str, stats.agi, stats.vit, stats.int_, stats.dex, stats.luk, + stats.str + stats.agi + stats.vit + stats.int_ + stats.dex + stats.luk, + hair_style, hair_color); return nullptr; } // check individual stat value for (int i = 0; i < 6; i++) { - if (stats[i] < 1 || stats[i] > 9) + uint8_t statsi = reinterpret_cast<const uint8_t *>(&stats)[i]; + if (statsi < 1 || statsi > 9) { - CHAR_LOG("Make new char error (invalid stat value: not between 1 to 9): (connection #%d, account: %d) slot %d, name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d\n", - s, sd->account_id, slot, name, - stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], - stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], - hair_style, hair_color); + CHAR_LOG("Make new char error (invalid stat value: not between 1 to 9): (connection #%d, account: %d) slot %d, name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d\n"_fmt, + s, sd->account_id, slot, name, + stats.str, stats.agi, stats.vit, stats.int_, stats.dex, stats.luk, + stats.str + stats.agi + stats.vit + stats.int_ + stats.dex + stats.luk, + hair_style, hair_color); return nullptr; } } @@ -697,63 +742,63 @@ CharPair *make_new_char(Session *s, CharName name, const uint8_t (&stats)[6], ui { if (cd.key.name == name) { - CHAR_LOG("Make new char error (name already exists): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n", - s, sd->account_id, slot, name, cd.key.name, - stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], - stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], - hair_style, hair_color); + CHAR_LOG("Make new char error (name already exists): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n"_fmt, + s, sd->account_id, slot, name, cd.key.name, + stats.str, stats.agi, stats.vit, stats.int_, stats.dex, stats.luk, + stats.str + stats.agi + stats.vit + stats.int_ + stats.dex + stats.luk, + hair_style, hair_color); return nullptr; } if (cd.key.account_id == sd->account_id && cd.key.char_num == slot) { - CHAR_LOG("Make new char error (slot already used): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n", - s, sd->account_id, slot, name, cd.key.name, - stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], - stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], - hair_style, hair_color); + CHAR_LOG("Make new char error (slot already used): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n"_fmt, + s, sd->account_id, slot, name, cd.key.name, + stats.str, stats.agi, stats.vit, stats.int_, stats.dex, stats.luk, + stats.str + stats.agi + stats.vit + stats.int_ + stats.dex + stats.luk, + hair_style, hair_color); return nullptr; } } if (wisp_server_name == name) { - CHAR_LOG("Make new char error (name used is wisp name for server): (connection #%d, account: %d) slot %d, name: %s (actual name whisper server: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n", - s, sd->account_id, slot, name, wisp_server_name, - stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], - stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], - hair_style, hair_color); + CHAR_LOG("Make new char error (name used is wisp name for server): (connection #%d, account: %d) slot %d, name: %s (actual name whisper server: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n"_fmt, + s, sd->account_id, slot, name, wisp_server_name, + stats.str, stats.agi, stats.vit, stats.int_, stats.dex, stats.luk, + stats.str + stats.agi + stats.vit + stats.int_ + stats.dex + stats.luk, + hair_style, hair_color); return nullptr; } IP4Address ip = s->client_ip; - CHAR_LOG("Creation of New Character: (connection #%d, account: %d) slot %d, character Name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d. [%s]\n", - s, sd->account_id, slot, name, - stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], - stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], - hair_style, hair_color, ip); + CHAR_LOG("Creation of New Character: (connection #%d, account: %d) slot %d, character Name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d. [%s]\n"_fmt, + s, sd->account_id, slot, name, + stats.str, stats.agi, stats.vit, stats.int_, stats.dex, stats.luk, + stats.str + stats.agi + stats.vit + stats.int_ + stats.dex + stats.luk, + hair_style, hair_color, ip); CharPair cp; CharKey& ck = cp.key; CharData& cd = *cp.data; - ck.char_id = char_id_count++; + ck.char_id = char_id_count; char_id_count = next(char_id_count); ck.account_id = sd->account_id; ck.char_num = slot; ck.name = name; - cd.species = 0; + cd.species = Species(); cd.base_level = 1; cd.job_level = 1; cd.base_exp = 0; cd.job_exp = 0; cd.zeny = 0; - cd.attrs[ATTR::STR] = stats[0]; - cd.attrs[ATTR::AGI] = stats[1]; - cd.attrs[ATTR::VIT] = stats[2]; - cd.attrs[ATTR::INT] = stats[3]; - cd.attrs[ATTR::DEX] = stats[4]; - cd.attrs[ATTR::LUK] = stats[5]; + cd.attrs[ATTR::STR] = stats.str; + cd.attrs[ATTR::AGI] = stats.agi; + cd.attrs[ATTR::VIT] = stats.vit; + cd.attrs[ATTR::INT] = stats.int_; + cd.attrs[ATTR::DEX] = stats.dex; + cd.attrs[ATTR::LUK] = stats.luk; cd.max_hp = 40 * (100 + cd.attrs[ATTR::VIT]) / 100; cd.max_sp = 11 * (100 + cd.attrs[ATTR::INT]) / 100; cd.hp = cd.max_hp; @@ -763,17 +808,17 @@ CharPair *make_new_char(Session *s, CharName name, const uint8_t (&stats)[6], ui cd.option = static_cast<Option>(0x0000); // Option is only declared cd.karma = 0; cd.manner = 0; - cd.party_id = 0; + cd.party_id = PartyId(); //cd.guild_id = 0; cd.hair = hair_style; cd.hair_color = hair_color; cd.clothes_color = 0; // removed initial armor/weapon - unused and problematic cd.weapon = ItemLook::NONE; - cd.shield = 0; - cd.head_top = 0; - cd.head_mid = 0; - cd.head_bottom = 0; + cd.shield = ItemNameId(); + cd.head_top = ItemNameId(); + cd.head_mid = ItemNameId(); + cd.head_bottom = ItemNameId(); cd.last_point = start_point; cd.save_point = start_point; char_keys.push_back(std::move(cp)); @@ -799,17 +844,17 @@ void create_online_files(void) timestamp_seconds_buffer timetemp; stamp_time(timetemp); // write heading - FPRINTF(fp2, "<HTML>\n"); - FPRINTF(fp2, " <META http-equiv=\"Refresh\" content=\"%d\">\n", online_refresh_html); // update on client explorer every x seconds - FPRINTF(fp2, " <HEAD>\n"); - FPRINTF(fp2, " <TITLE>Online Players on %s</TITLE>\n", - server_name); - FPRINTF(fp2, " </HEAD>\n"); - FPRINTF(fp2, " <BODY>\n"); - FPRINTF(fp2, " <H3>Online Players on %s (%s):</H3>\n", - server_name, timetemp); - FPRINTF(fp, "Online Players on %s (%s):\n", server_name, timetemp); - FPRINTF(fp, "\n"); + FPRINTF(fp2, "<HTML>\n"_fmt); + FPRINTF(fp2, " <META http-equiv=\"Refresh\" content=\"%d\">\n"_fmt, online_refresh_html); // update on client explorer every x seconds + FPRINTF(fp2, " <HEAD>\n"_fmt); + FPRINTF(fp2, " <TITLE>Online Players on %s</TITLE>\n"_fmt, + server_name); + FPRINTF(fp2, " </HEAD>\n"_fmt); + FPRINTF(fp2, " <BODY>\n"_fmt); + FPRINTF(fp2, " <H3>Online Players on %s (%s):</H3>\n"_fmt, + server_name, timetemp); + FPRINTF(fp, "Online Players on %s (%s):\n"_fmt, server_name, timetemp); + FPRINTF(fp, "\n"_fmt); int players = 0; // This used to be conditional on having any players, @@ -817,20 +862,20 @@ void create_online_files(void) //if (players > 0) { int j = 0; // count the number of characters for the txt version and to set the separate line - FPRINTF(fp2, " <table border=\"1\" cellspacing=\"1\">\n"); - FPRINTF(fp2, " <tr>\n"); + FPRINTF(fp2, " <table border=\"1\" cellspacing=\"1\">\n"_fmt); + FPRINTF(fp2, " <tr>\n"_fmt); { - FPRINTF(fp2, " <th>Name</th>\n"); + FPRINTF(fp2, " <th>Name</th>\n"_fmt); { - FPRINTF(fp, "Name "); // 30 + FPRINTF(fp, "Name "_fmt); // 30 j += 30; } } - FPRINTF(fp2, " </tr>\n"); - FPRINTF(fp, "\n"); + FPRINTF(fp2, " </tr>\n"_fmt); + FPRINTF(fp, "\n"_fmt); for (int k = 0; k < j; k++) - FPRINTF(fp, "-"); - FPRINTF(fp, "\n"); + FPRINTF(fp, "-"_fmt); + FPRINTF(fp, "\n"_fmt); // display each player. for (CharPair& cd : char_keys) @@ -838,55 +883,55 @@ void create_online_files(void) if (!server_for(&cd)) continue; players++; - FPRINTF(fp2, " <tr>\n"); + FPRINTF(fp2, " <tr>\n"_fmt); // displaying the character name { // without/with 'GM' display - int gml = isGM(cd.key.account_id); + GmLevel gml = isGM(cd.key.account_id); { - if (gml >= online_gm_display_min_level) - FPRINTF(fp, "%-24s (GM) ", cd.key.name); + if (gml.satisfies(online_gm_display_min_level)) + FPRINTF(fp, "%-24s (GM) "_fmt, cd.key.name); else - FPRINTF(fp, "%-24s ", cd.key.name); + FPRINTF(fp, "%-24s "_fmt, cd.key.name); } // name of the character in the html (no < >, because that create problem in html code) - FPRINTF(fp2, " <td>"); - if (gml >= online_gm_display_min_level) - FPRINTF(fp2, "<b>"); + FPRINTF(fp2, " <td>"_fmt); + if (gml.satisfies(online_gm_display_min_level)) + FPRINTF(fp2, "<b>"_fmt); for (char c : cd.key.name.to__actual()) { switch (c) { case '&': - FPRINTF(fp2, "&"); + FPRINTF(fp2, "&"_fmt); break; case '<': - FPRINTF(fp2, "<"); + FPRINTF(fp2, "<"_fmt); break; case '>': - FPRINTF(fp2, ">"); + FPRINTF(fp2, ">"_fmt); break; default: - FPRINTF(fp2, "%c", c); + FPRINTF(fp2, "%c"_fmt, c); break; }; } - if (gml >= online_gm_display_min_level) - FPRINTF(fp2, "</b> (GM)"); - FPRINTF(fp2, "</td>\n"); + if (gml.satisfies(online_gm_display_min_level)) + FPRINTF(fp2, "</b> (GM)"_fmt); + FPRINTF(fp2, "</td>\n"_fmt); } - FPRINTF(fp, "\n"); - FPRINTF(fp2, " </tr>\n"); + FPRINTF(fp, "\n"_fmt); + FPRINTF(fp2, " </tr>\n"_fmt); } - FPRINTF(fp2, " </table>\n"); - FPRINTF(fp, "\n"); + FPRINTF(fp2, " </table>\n"_fmt); + FPRINTF(fp, "\n"_fmt); } // Displaying number of online players if (players == 0) { - FPRINTF(fp2, " <p>No user is online.</p>\n"); - FPRINTF(fp, "No user is online.\n"); + FPRINTF(fp2, " <p>No user is online.</p>\n"_fmt); + FPRINTF(fp, "No user is online.\n"_fmt); } else if (players == 1) { @@ -894,11 +939,11 @@ void create_online_files(void) } else { - FPRINTF(fp2, " <p>%d users are online.</p>\n", players); - FPRINTF(fp, "%d users are online.\n", players); + FPRINTF(fp2, " <p>%d users are online.</p>\n"_fmt, players); + FPRINTF(fp, "%d users are online.\n"_fmt, players); } - FPRINTF(fp2, " </BODY>\n"); - FPRINTF(fp2, "</HTML>\n"); + FPRINTF(fp2, " </BODY>\n"_fmt); + FPRINTF(fp2, "</HTML>\n"_fmt); } } @@ -925,14 +970,18 @@ int count_users(void) // [Fate] Find inventory item based on equipment mask, return view. ID must match view ID (!). //---------------------------------------- static -int find_equip_view(const CharPair *cp, EPOS equipmask) +ItemNameId find_equip_view(const CharPair *cp, EPOS equipmask) { CharData *p = cp->data.get(); - for (int i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) + { if (p->inventory[i].nameid && p->inventory[i].amount && bool(p->inventory[i].equip & equipmask)) + { return p->inventory[i].nameid; - return 0; + } + } + return ItemNameId(); } //---------------------------------------- @@ -954,72 +1003,75 @@ int mmo_char_send006b(Session *s, struct char_session_data *sd) } } - const int offset = 24; - WFIFO_ZERO(s, 0, offset + found_num * 106); - WFIFOW(s, 0) = 0x6b; - WFIFOW(s, 2) = offset + found_num * 106; + Packet_Head<0x006b> head_6b; + std::vector<Packet_Repeat<0x006b>> repeat_6b; + + head_6b.unused = {}; for (int i = 0; i < found_num; i++) { const CharPair *cp = found_char[i]; - int j = offset + (i * 106); const CharKey *k = &cp->key; const CharData *p = cp->data.get(); - WFIFOL(s, j) = k->char_id; - WFIFOL(s, j + 4) = p->base_exp; - WFIFOL(s, j + 8) = p->zeny; - WFIFOL(s, j + 12) = p->job_exp; - WFIFOL(s, j + 16) = p->job_level; - - WFIFOW(s, j + 20) = find_equip_view(cp, EPOS::SHOES); - WFIFOW(s, j + 22) = find_equip_view(cp, EPOS::GLOVES); - WFIFOW(s, j + 24) = find_equip_view(cp, EPOS::CAPE); - WFIFOW(s, j + 26) = find_equip_view(cp, EPOS::MISC1); - WFIFOL(s, j + 28) = static_cast<uint16_t>(p->option); - - WFIFOL(s, j + 32) = p->karma; - WFIFOL(s, j + 36) = p->manner; - - WFIFOW(s, j + 40) = p->status_point; - WFIFOW(s, j + 42) = (p->hp > 0x7fff) ? 0x7fff : p->hp; - WFIFOW(s, j + 44) = (p->max_hp > 0x7fff) ? 0x7fff : p->max_hp; - WFIFOW(s, j + 46) = (p->sp > 0x7fff) ? 0x7fff : p->sp; - WFIFOW(s, j + 48) = (p->max_sp > 0x7fff) ? 0x7fff : p->max_sp; - WFIFOW(s, j + 50) = static_cast<uint16_t>(DEFAULT_WALK_SPEED.count()); // p->speed; - WFIFOW(s, j + 52) = p->species; - WFIFOW(s, j + 54) = p->hair; -// WFIFOW(s,j+56) = p->weapon; // dont send weapon since TMW does not support it - WFIFOW(s, j + 56) = 0; - WFIFOW(s, j + 58) = p->base_level; - WFIFOW(s, j + 60) = p->skill_point; - WFIFOW(s, j + 62) = p->head_bottom; - WFIFOW(s, j + 64) = p->shield; - WFIFOW(s, j + 66) = p->head_top; - WFIFOW(s, j + 68) = p->head_mid; - WFIFOW(s, j + 70) = p->hair_color; - WFIFOW(s, j + 72) = find_equip_view(cp, EPOS::MISC2); -// WFIFOW(s,j+72) = p->clothes_color; - - WFIFO_STRING(s, j + 74, k->name.to__actual(), 24); - - WFIFOB(s, j + 98) = min(p->attrs[ATTR::STR], 255); - WFIFOB(s, j + 99) = min(p->attrs[ATTR::AGI], 255); - WFIFOB(s, j + 100) = min(p->attrs[ATTR::VIT], 255); - WFIFOB(s, j + 101) = min(p->attrs[ATTR::INT], 255); - WFIFOB(s, j + 102) = min(p->attrs[ATTR::DEX], 255); - WFIFOB(s, j + 103) = min(p->attrs[ATTR::LUK], 255); - WFIFOB(s, j + 104) = k->char_num; + Packet_Repeat<0x006b> info; + CharSelect& sel = info.char_select; + + sel.char_id = k->char_id; + sel.base_exp = p->base_exp; + sel.zeny = p->zeny; + sel.job_exp = p->job_exp; + sel.job_level = p->job_level; + + sel.shoes = find_equip_view(cp, EPOS::SHOES); + sel.gloves = find_equip_view(cp, EPOS::GLOVES); + sel.cape = find_equip_view(cp, EPOS::CAPE); + sel.misc1 = find_equip_view(cp, EPOS::MISC1); + sel.option = p->option; + + sel.karma = p->karma; + sel.manner = p->manner; + + sel.status_point = p->status_point; + sel.hp = std::min(p->hp, 0x7fff); + sel.max_hp = std::min(p->max_hp, 0x7fff); + sel.sp = std::min(p->sp, 0x7fff); + sel.max_sp = std::min(p->max_sp, 0x7fff); + sel.speed = static_cast<uint16_t>(DEFAULT_WALK_SPEED.count()); // p->speed; + sel.species = p->species; + sel.hair_style = p->hair; + sel.weapon = 0; // p->weapon; // dont send weapon since TMW does not support it + sel.base_level = p->base_level; + sel.skill_point = p->skill_point; + sel.head_bottom = p->head_bottom; + sel.shield = p->shield; + sel.head_top = p->head_top; + sel.head_mid = p->head_mid; + sel.hair_color = p->hair_color; + sel.misc2 = find_equip_view(cp, EPOS::MISC2); // = p->clothes_color; + + sel.char_name = k->name; + + sel.stats.str = saturate<uint8_t>(p->attrs[ATTR::STR]); + sel.stats.agi = saturate<uint8_t>(p->attrs[ATTR::AGI]); + sel.stats.vit = saturate<uint8_t>(p->attrs[ATTR::VIT]); + sel.stats.int_ = saturate<uint8_t>(p->attrs[ATTR::INT]); + sel.stats.dex = saturate<uint8_t>(p->attrs[ATTR::DEX]); + sel.stats.luk = saturate<uint8_t>(p->attrs[ATTR::LUK]); + sel.char_num = k->char_num; + sel.unused = 0; + + repeat_6b.push_back(info); } - WFIFOSET(s, WFIFOW(s, 2)); + send_vpacket<0x006b, 24, 106>(s, head_6b, repeat_6b); return 0; } static -int set_account_reg2(int acc, Slice<global_reg> reg) +int set_account_reg2(AccountId acc, Slice<GlobalReg> reg) { size_t num = reg.size(); assert (num < ACCOUNT_REG2_NUM); @@ -1032,7 +1084,7 @@ int set_account_reg2(int acc, Slice<global_reg> reg) cd.data->account_reg2[i] = reg[i]; cd.data->account_reg2_num = num; for (int i = num; i < ACCOUNT_REG2_NUM; ++i) - cd.data->account_reg2[i] = global_reg{}; + cd.data->account_reg2[i] = GlobalReg{}; c++; } } @@ -1043,52 +1095,65 @@ int set_account_reg2(int acc, Slice<global_reg> reg) static int char_divorce(CharPair *cp) { - uint8_t buf[10]; - - if (cp == NULL) + if (cp == nullptr) return 0; CharKey *ck = &cp->key; CharData *cs = cp->data.get(); - if (cs->partner_id <= 0) + if (!cs->partner_id) { - WBUFW(buf, 0) = 0x2b12; - WBUFL(buf, 2) = ck->char_id; - WBUFL(buf, 6) = 0; // partner id 0 means failure - mapif_sendall(buf, 10); + Packet_Fixed<0x2b12> fixed_12; + fixed_12.char_id = ck->char_id; + // partner id 0 means failure + fixed_12.partner_id = cs->partner_id; + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x2b12, 10>(ss, fixed_12); + } return 0; } - WBUFW(buf, 0) = 0x2b12; - WBUFL(buf, 2) = ck->char_id; + Packet_Fixed<0x2b12> fixed_12; + fixed_12.char_id = ck->char_id; for (CharPair& cd : char_keys) { if (cd.key.char_id == cs->partner_id && cd.data->partner_id == ck->char_id) { - WBUFL(buf, 6) = cs->partner_id; - mapif_sendall(buf, 10); - cs->partner_id = 0; - cd.data->partner_id = 0; + fixed_12.partner_id = cs->partner_id; + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x2b12, 10>(ss, fixed_12); + } + + cs->partner_id = CharId(); + cd.data->partner_id = CharId(); return 0; } // The other char doesn't have us as their partner, so just clear our partner // Don't worry about this, as the map server should verify itself that the other doesn't have us as a partner, and so won't mess with their marriage else if (cd.key.char_id == cs->partner_id) { - WBUFL(buf, 6) = cs->partner_id; - mapif_sendall(buf, 10); - cs->partner_id = 0; + fixed_12.partner_id = cs->partner_id; + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x2b12, 10>(ss, fixed_12); + } + + cs->partner_id = CharId(); return 0; } } // Our partner wasn't found, so just clear our marriage - WBUFL(buf, 6) = cs->partner_id; - cs->partner_id = 0; - mapif_sendall(buf, 10); + fixed_12.partner_id = cs->partner_id; + cs->partner_id = CharId(); + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x2b12, 10>(ss, fixed_12); + } return 0; } @@ -1097,25 +1162,24 @@ int char_divorce(CharPair *cp) // Force disconnection of an online player (with account value) by [Yor] //---------------------------------------------------------------------- static -int disconnect_player(int accound_id) +void disconnect_player(AccountId accound_id) { // disconnect player if online on char-server for (io::FD i : iter_fds()) { - if (!get_session(i)) + Session *s = get_session(i); + if (!s) continue; - struct char_session_data *sd = static_cast<char_session_data *>(get_session(i)->session_data.get()); + struct char_session_data *sd = static_cast<char_session_data *>(s->session_data.get()); if (sd) { if (sd->account_id == accound_id) { - get_session(i)->set_eof(); - return 1; + s->set_eof(); + return; } } } - - return 0; } // キャラ削除に伴うデータ削除 @@ -1134,10 +1198,12 @@ int char_delete(CharPair *cp) // Force the character (and all on the same account) to leave all map servers { - unsigned char buf[6]; - WBUFW(buf, 0) = 0x2afe; - WBUFL(buf, 2) = ck->account_id; - mapif_sendall(buf, 6); + Packet_Fixed<0x2afe> fixed_fe; + fixed_fe.account_id = ck->account_id; + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x2afe, 6>(ss, fixed_fe); + } } return 0; @@ -1146,143 +1212,156 @@ int char_delete(CharPair *cp) static void parse_tologin(Session *ls) { - // only login-server can have an access to here. - // so, if it isn't the login-server, we disconnect the session (fd != login_fd). - if (ls != login_session) - { - ls->set_eof(); - return; - } + assert (ls == login_session); char_session_data *sd = static_cast<char_session_data *>(ls->session_data.get()); - while (RFIFOREST(ls) >= 2) + RecvResult rv = RecvResult::Complete; + uint16_t packet_id; + while (rv == RecvResult::Complete && packet_peek_id(ls, &packet_id)) { -// PRINTF("parse_tologin: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd)); - - switch (RFIFOW(ls, 0)) + switch (packet_id) { case 0x2711: - if (RFIFOREST(ls) < 3) - return; - if (RFIFOB(ls, 2)) + { + Packet_Fixed<0x2711> fixed; + rv = recv_fpacket<0x2711, 3>(ls, fixed); + if (rv != RecvResult::Complete) + break; + + if (fixed.code) { -// PRINTF("connect login server error : %d\n", RFIFOB(fd,2)); - PRINTF("Can not connect to login-server.\n"); - PRINTF("The server communication passwords (default s1/p1) is probably invalid.\n"); - PRINTF("Also, please make sure your accounts file (default: accounts.txt) has those values present.\n"); - PRINTF("If you changed the communication passwords, change them back at map_athena.conf and char_athena.conf\n"); + PRINTF("Can not connect to login-server.\n"_fmt); + PRINTF("The server communication passwords (default s1/p1) is probably invalid.\n"_fmt); + PRINTF("Also, please make sure your accounts file (default: accounts.txt) has those values present.\n"_fmt); + PRINTF("If you changed the communication passwords, change them back at map_athena.conf and char_athena.conf\n"_fmt); exit(1); } else { - PRINTF("Connected to login-server (connection #%d).\n", + PRINTF("Connected to login-server (connection #%d).\n"_fmt, ls); // if no map-server already connected, display a message... int i; for (i = 0; i < MAX_MAP_SERVERS; i++) + { if (server_session[i] && server[i].maps[0]) // if map-server online and at least 1 map break; + } if (i == MAX_MAP_SERVERS) - PRINTF("Awaiting maps from map-server.\n"); + PRINTF("Awaiting maps from map-server.\n"_fmt); } - RFIFOSKIP(ls, 3); break; + } case 0x2713: - if (RFIFOREST(ls) < 51) - return; -// PRINTF("parse_tologin 2713 : %d\n", RFIFOB(fd,6)); + { + Packet_Fixed<0x2713> fixed; + rv = recv_fpacket<0x2713, 51>(ls, fixed); + if (rv != RecvResult::Complete) + break; + for (io::FD i : iter_fds()) { + AccountId acc = fixed.account_id; Session *s2 = get_session(i); if (!s2) continue; sd = static_cast<char_session_data *>(s2->session_data.get()); - if (sd && sd->account_id == RFIFOL(ls, 2)) + if (sd && sd->account_id == acc) { - if (RFIFOB(ls, 6) != 0) + if (fixed.invalid != 0) { - WFIFOW(s2, 0) = 0x6c; - WFIFOB(s2, 2) = 0x42; - WFIFOSET(s2, 3); + Packet_Fixed<0x006c> fixed_6c; + fixed_6c.code = 0x42; + send_fpacket<0x006c, 3>(s2, fixed_6c); } else if (max_connect_user == 0 || count_users() < max_connect_user) { -// if (max_connect_user == 0) -// PRINTF("max_connect_user (unlimited) -> accepted.\n"); -// else -// PRINTF("count_users(): %d < max_connect_user (%d) -> accepted.\n", count_users(), max_connect_user); - sd->email = stringish<AccountEmail>(RFIFO_STRING<40>(ls, 7)); + sd->email = stringish<AccountEmail>(fixed.email); if (!e_mail_check(sd->email)) sd->email = DEFAULT_EMAIL; - sd->connect_until_time = static_cast<time_t>(RFIFOL(ls, 47)); + sd->connect_until_time = fixed.connect_until; // send characters to player mmo_char_send006b(s2, sd); } else { // refuse connection: too much online players -// PRINTF("count_users(): %d < max_connect_use (%d) -> fail...\n", count_users(), max_connect_user); - WFIFOW(s2, 0) = 0x6c; - WFIFOB(s2, 2) = 0; - WFIFOSET(s2, 3); + Packet_Fixed<0x006c> fixed_6c; + fixed_6c.code = 0; + send_fpacket<0x006c, 3>(s2, fixed_6c); } break; } } - RFIFOSKIP(ls, 51); break; + } // Receiving of an e-mail/time limit from the login-server (answer of a request because a player comes back from map-server to char-server) by [Yor] case 0x2717: - if (RFIFOREST(ls) < 50) - return; + { + Packet_Fixed<0x2717> fixed; + rv = recv_fpacket<0x2717, 50>(ls, fixed); + if (rv != RecvResult::Complete) + break; + for (io::FD i : iter_fds()) { + AccountId acc = fixed.account_id; Session *s2 = get_session(i); if (!s2) continue; sd = static_cast<char_session_data *>(s2->session_data.get()); if (sd) { - if (sd->account_id == RFIFOL(ls, 2)) + if (sd->account_id == acc) { - sd->email = stringish<AccountEmail>(RFIFO_STRING<40>(ls, 6)); + sd->email = fixed.email; if (!e_mail_check(sd->email)) sd->email = DEFAULT_EMAIL; - sd->connect_until_time = static_cast<time_t>(RFIFOL(ls, 46)); + sd->connect_until_time = fixed.connect_until; break; } } } - RFIFOSKIP(ls, 50); break; + } case 0x2721: // gm reply - if (RFIFOREST(ls) < 10) - return; + { + Packet_Fixed<0x2721> fixed; + rv = recv_fpacket<0x2721, 10>(ls, fixed); + if (rv != RecvResult::Complete) + break; + { - unsigned char buf[10]; - WBUFW(buf, 0) = 0x2b0b; - WBUFL(buf, 2) = RFIFOL(ls, 2); // account - WBUFL(buf, 6) = RFIFOL(ls, 6); // GM level - mapif_sendall(buf, 10); -// PRINTF("parse_tologin: To become GM answer: char -> map.\n"); + AccountId acc = fixed.account_id; + GmLevel gml = fixed.gm_level; + + Packet_Fixed<0x2b0b> fixed_2b; + fixed_2b.account_id = acc; + fixed_2b.gm_level = gml; + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x2b0b, 10>(ss, fixed_2b); + } } - RFIFOSKIP(ls, 10); break; + } case 0x2723: // changesex reply (modified by [Yor]) - if (RFIFOREST(ls) < 7) - return; + { + Packet_Fixed<0x2723> fixed; + rv = recv_fpacket<0x2723, 7>(ls, fixed); + if (rv != RecvResult::Complete) + break; + { - unsigned char buf[7]; - int acc = RFIFOL(ls, 2); - SEX sex = static_cast<SEX>(RFIFOB(ls, 6)); - RFIFOSKIP(ls, 7); - if (acc > 0) + AccountId acc = fixed.account_id; + SEX sex = fixed.sex; + if (acc) { for (CharPair& cp : char_keys) { @@ -1293,35 +1372,43 @@ void parse_tologin(Session *ls) cd.sex = sex; // auth_fifo[i].sex = sex; // to avoid any problem with equipment and invalid sex, equipment is unequiped. - for (int j = 0; j < MAX_INVENTORY; j++) + for (IOff0 j : IOff0::iter()) { if (cd.inventory[j].nameid && bool(cd.inventory[j].equip)) cd.inventory[j].equip = EPOS::ZERO; } cd.weapon = ItemLook::NONE; - cd.shield = 0; - cd.head_top = 0; - cd.head_mid = 0; - cd.head_bottom = 0; + cd.shield = ItemNameId(); + cd.head_top = ItemNameId(); + cd.head_mid = ItemNameId(); + cd.head_bottom = ItemNameId(); } } // disconnect player if online on char-server disconnect_player(acc); } - WBUFW(buf, 0) = 0x2b0d; - WBUFL(buf, 2) = acc; - WBUFB(buf, 6) = static_cast<uint8_t>(sex); - mapif_sendall(buf, 7); + Packet_Fixed<0x2b0d> fixed_0d; + fixed_0d.account_id = acc; + fixed_0d.sex = sex; + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x2b0d, 7>(ss, fixed_0d); + } } break; + } case 0x2726: // Request to send a broadcast message (no answer) - if (RFIFOREST(ls) < 8 - || RFIFOREST(ls) < (8 + RFIFOL(ls, 4))) - return; - if (RFIFOL(ls, 4) < 1) - CHAR_LOG("Receiving a message for broadcast, but message is void.\n"); + { + Packet_Head<0x2726> head; + AString repeat; + rv = recv_vpacket<0x2726, 8, 1>(ls, head, repeat); + if (rv != RecvResult::Complete) + break; + + if (!repeat) + CHAR_LOG("Receiving a message for broadcast, but message is void.\n"_fmt); else { int i; @@ -1330,82 +1417,100 @@ void parse_tologin(Session *ls) if (server_session[i]) break; if (i == MAX_MAP_SERVERS) - CHAR_LOG("'ladmin': Receiving a message for broadcast, but no map-server is online.\n"); + CHAR_LOG("'ladmin': Receiving a message for broadcast, but no map-server is online.\n"_fmt); else { - size_t len = RFIFOL(ls, 4); - AString message = RFIFO_STRING(ls, 8, len).to_print().lstrip(); + AString message = repeat.to_print().lstrip(); // if message is only composed of spaces if (!message) - CHAR_LOG("Receiving a message for broadcast, but message is only a lot of spaces.\n"); + CHAR_LOG("Receiving a message for broadcast, but message is only a lot of spaces.\n"_fmt); // else send message to all map-servers else { - CHAR_LOG("'ladmin': Receiving a message for broadcast (message (in yellow): %s)\n", + CHAR_LOG("'ladmin': Receiving a message for broadcast (message (in yellow): %s)\n"_fmt, message); // send broadcast to all map-servers - uint8_t buf[4 + len]; - WBUFW(buf, 0) = 0x3800; - WBUFW(buf, 2) = 4 + len; - WBUF_STRING(buf, 4, message, len); - mapif_sendall(buf, WBUFW(buf, 2)); + for (Session *ss : iter_map_sessions()) + { + send_packet_repeatonly<0x3800, 4, 1>(ss, message); + } } } } - RFIFOSKIP(ls, 8 + RFIFOL(ls, 4)); break; + } // account_reg2変更通知 case 0x2729: - if (RFIFOREST(ls) < 4 || RFIFOREST(ls) < RFIFOW(ls, 2)) - return; + { + Packet_Head<0x2729> head; + std::vector<Packet_Repeat<0x2729>> repeat; + rv = recv_vpacket<0x2729, 8, 36>(ls, head, repeat); + if (rv != RecvResult::Complete) + break; + { - Array<struct global_reg, ACCOUNT_REG2_NUM> reg; - int j, p, acc; - acc = RFIFOL(ls, 4); - for (p = 8, j = 0; - p < RFIFOW(ls, 2) && j < ACCOUNT_REG2_NUM; - p += 36, j++) + Array<GlobalReg, ACCOUNT_REG2_NUM> reg; + int j = 0; + AccountId acc = head.account_id; + for (const auto& info : repeat) + { + reg[j].str = info.name; + reg[j].value = info.value; + ++j; + if (j == ACCOUNT_REG2_NUM) + break; + } + set_account_reg2(acc, Slice<GlobalReg>(reg.begin(), j)); + + Packet_Head<0x2b11> head_11; + head_11.account_id = head.account_id; + std::vector<Packet_Repeat<0x2b11>> repeat_11(repeat.size()); + for (size_t k = 0; k < repeat.size(); ++k) + { + repeat_11[k].name = repeat[k].name; + repeat_11[k].value = repeat[k].value; + } + for (Session *ss : iter_map_sessions()) { - reg[j].str = stringish<VarName>(RFIFO_STRING<32>(ls, p)); - reg[j].value = RFIFOL(ls, p + 32); + send_vpacket<0x2b11, 8, 36>(ss, head_11, repeat_11); } - set_account_reg2(acc, Slice<struct global_reg>(reg.begin(), j)); - - size_t len = RFIFOW(ls, 2); - uint8_t buf[len]; - RFIFO_BUF_CLONE(ls, buf, len); - WBUFW(buf, 0) = 0x2b11; - mapif_sendall(buf, len); -// PRINTF("char: save_account_reg_reply\n"); } - RFIFOSKIP(ls, RFIFOW(ls, 2)); break; + } case 0x7924: { // [Fate] Itemfrob package: forwarded from login-server - if (RFIFOREST(ls) < 10) - return; - int source_id = RFIFOL(ls, 2); - int dest_id = RFIFOL(ls, 6); - unsigned char buf[10]; + Packet_Fixed<0x7924> fixed; + rv = recv_fpacket<0x7924, 10>(ls, fixed); + if (rv != RecvResult::Complete) + break; + + ItemNameId source_id = fixed.source_item_id; + ItemNameId dest_id = fixed.dest_item_id; + + Packet_Fixed<0x2afa> fixed_fa; + fixed_fa.source_item_id = source_id; + fixed_fa.dest_item_id = dest_id; - WBUFW(buf, 0) = 0x2afa; - WBUFL(buf, 2) = source_id; - WBUFL(buf, 6) = dest_id; + // forward package to map servers + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x2afa, 10>(ss, fixed_fa); + } - mapif_sendall(buf, 10); // forward package to map servers for (CharPair& cp : char_keys) { CharKey *k = &cp.key; CharData& cd = *cp.data.get(); CharData *c = &cd; - struct storage *s = account2storage(k->account_id); + Storage *s = account2storage(k->account_id); int changes = 0; - int j; #define FIX(v) if (v == source_id) {v = dest_id; ++changes; } - for (j = 0; j < MAX_INVENTORY; j++) + for (IOff0 j : IOff0::iter()) + { FIX(c->inventory[j].nameid); + } // used to FIX cart, but it's no longer supported // FIX(c->weapon); FIX(c->shield); @@ -1414,26 +1519,35 @@ void parse_tologin(Session *ls) FIX(c->head_bottom); if (s) - for (j = 0; j < s->storage_amount; j++) + { + for (SOff0 j : SOff0::iter()) + { FIX(s->storage_[j].nameid); + } + } #undef FIX if (changes) - CHAR_LOG("itemfrob(%d -> %d): `%s'(%d, account %d): changed %d times\n", - source_id, dest_id, k->name, k->char_id, - k->account_id, changes); + CHAR_LOG("itemfrob(%d -> %d): `%s'(%d, account %d): changed %d times\n"_fmt, + source_id, dest_id, k->name, k->char_id, + k->account_id, changes); } mmo_char_sync(); inter_storage_save(); - RFIFOSKIP(ls, 10); break; } // Account deletion notification (from login-server) case 0x2730: - if (RFIFOREST(ls) < 6) - return; + { + Packet_Fixed<0x2730> fixed; + rv = recv_fpacket<0x2730, 6>(ls, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId aid = fixed.account_id; + // Deletion of all characters of the account //#warning "This comment is a lie, but it's still true." // needs to use index because they may move during resize @@ -1441,7 +1555,7 @@ void parse_tologin(Session *ls) { CharPair& cp = char_keys[idx]; CharKey& ck = cp.key; - if (ck.account_id == RFIFOL(ls, 2)) + if (ck.account_id == aid) { char_delete(&cp); if (&cp != &char_keys.back()) @@ -1450,7 +1564,7 @@ void parse_tologin(Session *ls) // if moved character owns to deleted account, check again it's character // YES this is the newly swapped one // we could avoid this by working backwards - if (ck.account_id == RFIFOL(ls, 2)) + if (ck.account_id == aid) { idx--; // Correct moved character reference in the character's owner by [Yor] @@ -1460,69 +1574,91 @@ void parse_tologin(Session *ls) } } // Deletion of the storage - inter_storage_delete(RFIFOL(ls, 2)); + inter_storage_delete(aid); // send to all map-servers to disconnect the player { - unsigned char buf[6]; - WBUFW(buf, 0) = 0x2b13; - WBUFL(buf, 2) = RFIFOL(ls, 2); - mapif_sendall(buf, 6); + Packet_Fixed<0x2b13> fixed_13; + fixed_13.account_id = aid; + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x2b13, 6>(ss, fixed_13); + } } // disconnect player if online on char-server - disconnect_player(RFIFOL(ls, 2)); - RFIFOSKIP(ls, 6); + disconnect_player(aid); break; + } // State change of account/ban notification (from login-server) by [Yor] case 0x2731: - if (RFIFOREST(ls) < 11) - return; + { + Packet_Fixed<0x2731> fixed; + rv = recv_fpacket<0x2731, 11>(ls, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId aid = fixed.account_id; // send to all map-servers to disconnect the player { - unsigned char buf[11]; - WBUFW(buf, 0) = 0x2b14; - WBUFL(buf, 2) = RFIFOL(ls, 2); - WBUFB(buf, 6) = RFIFOB(ls, 6); // 0: change of statut, 1: ban - WBUFL(buf, 7) = RFIFOL(ls, 7); // status or final date of a banishment - mapif_sendall(buf, 11); + Packet_Fixed<0x2b14> fixed_14; + fixed_14.account_id = aid; + fixed_14.ban_not_status = fixed.ban_not_status; // 0: change of statut, 1: ban + fixed_14.status_or_ban_until = fixed.status_or_ban_until; // status or final date of a banishment + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x2b14, 11>(ss, fixed_14); + } } // disconnect player if online on char-server - disconnect_player(RFIFOL(ls, 2)); - RFIFOSKIP(ls, 11); + disconnect_player(aid); break; + } // Receiving GM acounts info from login-server (by [Yor]) case 0x2732: - if (RFIFOREST(ls) < 4 || RFIFOREST(ls) < RFIFOW(ls, 2)) - return; + { + std::vector<Packet_Repeat<0x2732>> repeat; + rv = recv_packet_repeatonly<0x2732, 4, 5>(ls, repeat); + if (rv != RecvResult::Complete) + break; + { - size_t len = RFIFOW(ls, 2); - uint8_t buf[len]; - gm_accounts.clear(); - gm_accounts.reserve((len - 4) / 5); - for (int i = 4; i < len; i += 5) + gm_accounts.resize(repeat.size()); + for (size_t k = 0; k < repeat.size(); ++k) { - gm_accounts.push_back({static_cast<int>(RFIFOL(ls, i)), RFIFOB(ls, i + 4)}); + gm_accounts[k].account_id = repeat[k].account_id; + gm_accounts[k].level = repeat[k].gm_level; } - PRINTF("From login-server: receiving of %zu GM accounts information.\n", - gm_accounts.size()); - CHAR_LOG("From login-server: receiving of %zu GM accounts information.\n", - gm_accounts.size()); + PRINTF("From login-server: receiving of %zu GM accounts information.\n"_fmt, + gm_accounts.size()); + CHAR_LOG("From login-server: receiving of %zu GM accounts information.\n"_fmt, + gm_accounts.size()); create_online_files(); // update online players files (perhaps some online players change of GM level) // send new gm acccounts level to map-servers - RFIFO_BUF_CLONE(ls, buf, len); - WBUFW(buf, 0) = 0x2b15; - mapif_sendall(buf, len); + std::vector<Packet_Repeat<0x2b15>> repeat_15(repeat.size()); + for (size_t k = 0; k < repeat.size(); ++k) + { + repeat_15[k].account_id = repeat[k].account_id; + repeat_15[k].gm_level = repeat[k].gm_level; + } + for (Session *ss : iter_map_sessions()) + { + send_packet_repeatonly<0x2b15, 4, 5>(ss, repeat_15); + } } - RFIFOSKIP(ls, RFIFOW(ls, 2)); break; + } case 0x2741: // change password reply - if (RFIFOREST(ls) < 7) - return; + { + Packet_Fixed<0x2741> fixed; + rv = recv_fpacket<0x2741, 7>(ls, fixed); + if (rv != RecvResult::Complete) + break; + { - int acc = RFIFOL(ls, 2); - int status = RFIFOB(ls, 6); + AccountId acc = fixed.account_id; + int status = fixed.status; for (io::FD i : iter_fds()) { @@ -1534,22 +1670,26 @@ void parse_tologin(Session *ls) { if (sd->account_id == acc) { - WFIFOW(s2, 0) = 0x62; - WFIFOB(s2, 2) = status; - WFIFOSET(s2, 3); + Packet_Fixed<0x0062> fixed_62; + fixed_62.status = status; + send_fpacket<0x0062, 3>(s2, fixed_62); break; } } } } - RFIFOSKIP(ls, 7); break; + } default: + { ls->set_eof(); return; + } } } + if (rv == RecvResult::Error) + ls->set_eof(); } //-------------------------------- @@ -1560,18 +1700,16 @@ void map_anti_freeze_system(TimerData *, tick_t) { int i; - //PRINTF("Entering in map_anti_freeze_system function to check freeze of servers.\n"); for (i = 0; i < MAX_MAP_SERVERS; i++) { if (server_session[i]) { // if map-server is online - //PRINTF("map_anti_freeze_system: server #%d, flag: %d.\n", i, server_freezeflag[i]); if (server_freezeflag[i]-- < 1) { // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed - PRINTF("Map-server anti-freeze system: char-server #%d is freezed -> disconnection.\n", - i); - CHAR_LOG("Map-server anti-freeze system: char-server #%d is freezed -> disconnection.\n", - i); + PRINTF("Map-server anti-freeze system: char-server #%d is freezed -> disconnection.\n"_fmt, + i); + CHAR_LOG("Map-server anti-freeze system: char-server #%d is freezed -> disconnection.\n"_fmt, + i); server_session[i]->set_eof(); } } @@ -1591,102 +1729,125 @@ void parse_frommap(Session *ms) return; } - while (RFIFOREST(ms) >= 2) + RecvResult rv = RecvResult::Complete; + uint16_t packet_id; + while (rv == RecvResult::Complete && packet_peek_id(ms, &packet_id)) { -// PRINTF("parse_frommap: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd)); - - switch (RFIFOW(ms, 0)) + switch (packet_id) { // request from map-server to reload GM accounts. Transmission to login-server (by Yor) case 0x2af7: + { + Packet_Fixed<0x2af7> fixed; + rv = recv_fpacket<0x2af7, 2>(ms, fixed); + if (rv != RecvResult::Complete) + break; + if (login_session) { // don't send request if no login-server - WFIFOW(login_session, 0) = 0x2709; - WFIFOSET(login_session, 2); + Packet_Fixed<0x2709> fixed_09; + send_fpacket<0x2709, 2>(login_session, fixed_09); } - RFIFOSKIP(ms, 2); break; + } // Receiving map names list from the map-server case 0x2afa: - if (RFIFOREST(ms) < 4 || RFIFOREST(ms) < RFIFOW(ms, 2)) - return; { + std::vector<Packet_Repeat<0x2afa>> repeat; + rv = recv_packet_repeatonly<0x2afa, 4, 16>(ms, repeat); + if (rv != RecvResult::Complete) + break; + for (MapName &foo : server[id].maps) foo = MapName(); - int j = 0; - for (int i = 4; i < RFIFOW(ms, 2); i += 16) + + for (size_t j = 0; j < repeat.size(); ++j) { - server[id].maps[j] = RFIFO_STRING<16>(ms, i); - j++; + server[id].maps[j] = repeat[j].map_name; } + const size_t j = repeat.size(); + { - PRINTF("Map-Server %d connected: %d maps, from IP %s port %d.\n", - id, j, server[id].ip, server[id].port); - PRINTF("Map-server %d loading complete.\n", id); - CHAR_LOG("Map-Server %d connected: %d maps, from IP %s port %d. Map-server %d loading complete.\n", - id, j, server[id].ip, - server[id].port, id); + PRINTF("Map-Server %d connected: %zu maps, from IP %s port %d.\n"_fmt, + id, j, server[id].ip, server[id].port); + PRINTF("Map-server %d loading complete.\n"_fmt, id); + CHAR_LOG("Map-Server %d connected: %zu maps, from IP %s port %d. Map-server %d loading complete.\n"_fmt, + id, j, server[id].ip, + server[id].port, id); } - WFIFOW(ms, 0) = 0x2afb; - WFIFOB(ms, 2) = 0; - WFIFO_STRING(ms, 3, wisp_server_name.to__actual(), 24); - WFIFOSET(ms, 27); + + Packet_Fixed<0x2afb> fixed_fb; + fixed_fb.unknown = 0; + fixed_fb.whisper_name = wisp_server_name; + send_fpacket<0x2afb, 27>(ms, fixed_fb); + { - unsigned char buf[16384]; if (j == 0) { - PRINTF("WARNING: Map-Server %d have NO map.\n", id); - CHAR_LOG("WARNING: Map-Server %d have NO map.\n", - id); + PRINTF("WARNING: Map-Server %d have NO map.\n"_fmt, id); + CHAR_LOG("WARNING: Map-Server %d have NO map.\n"_fmt, + id); // Transmitting maps information to the other map-servers } else { - WBUFW(buf, 0) = 0x2b04; - WBUFW(buf, 2) = j * 16 + 10; - WBUFIP(buf, 4) = server[id].ip; - WBUFW(buf, 8) = server[id].port; - // server[id].maps[i] = RFIFO_STRING(fd, 4 + i * 16) + Packet_Head<0x2b04> head_04; + head_04.ip = server[id].ip; + head_04.port = server[id].port; + std::vector<Packet_Repeat<0x2b04>> repeat_04(j); for (int i = 0; i < j; ++i) - WBUF_STRING(buf, 10, server[id].maps[i], 16); - mapif_sendallwos(ms, buf, WBUFW(buf, 2)); + { + repeat_04[i].map_name = server[id].maps[i]; + } + for (Session *ss : iter_map_sessions()) + { + if (ss == ms) + continue; + send_vpacket<0x2b04, 10, 16>(ss, head_04, repeat_04); + } } // Transmitting the maps of the other map-servers to the new map-server for (int x = 0; x < MAX_MAP_SERVERS; x++) { if (server_session[x] && x != id) { - WFIFOW(ms, 0) = 0x2b04; - WFIFOIP(ms, 4) = server[x].ip; - WFIFOW(ms, 8) = server[x].port; - j = 0; + Packet_Head<0x2b04> head_04; + head_04.ip = server[x].ip; + head_04.port = server[x].port; + std::vector<Packet_Repeat<0x2b04>> repeat_04; for (int i = 0; i < MAX_MAP_PER_SERVER; i++) + { if (server[x].maps[i]) - WFIFO_STRING(ms, 10 + (j++) * 16, server[x].maps[i], 16); - if (j > 0) + { + Packet_Repeat<0x2b04> info; + info.map_name = server[x].maps[i]; + repeat_04.push_back(info); + } + } + if (repeat.size()) { - WFIFOW(ms, 2) = j * 16 + 10; - WFIFOSET(ms, WFIFOW(ms, 2)); + send_vpacket<0x2b04, 10, 16>(ms, head_04, repeat_04); } } } } - } - RFIFOSKIP(ms, RFIFOW(ms, 2)); break; + } // 認証要求 case 0x2afc: - if (RFIFOREST(ms) < 22) - return; { - int account_id = RFIFOL(ms, 2); - int char_id = RFIFOL(ms, 6); - int login_id1 = RFIFOL(ms, 10); - int login_id2 = RFIFOL(ms, 14); - IP4Address ip = RFIFOIP(ms, 18); - //PRINTF("auth_fifo search: account: %d, char: %d, secure: %08x-%08x\n", RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14)); + Packet_Fixed<0x2afc> fixed; + rv = recv_fpacket<0x2afc, 22>(ms, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + CharId char_id = fixed.char_id; + int login_id1 = fixed.login_id1; + int login_id2 = fixed.login_id2; + IP4Address ip = fixed.ip; for (AuthFifoEntry& afi : auth_fifo) { if (afi.account_id == account_id && @@ -1706,46 +1867,49 @@ void parse_frommap(Session *ms) break; } } - assert (cp && "uh-oh - deleted while in queue?"); + assert (cp && "uh-oh - deleted while in queue?"_s); CharKey *ck = &cp->key; CharData *cd = cp->data.get(); afi.delflag = 1; - WFIFOW(ms, 0) = 0x2afd; - WFIFOW(ms, 2) = 18 + sizeof(*ck) + sizeof(*cd); - WFIFOL(ms, 4) = account_id; - WFIFOL(ms, 8) = afi.login_id2; - WFIFOL(ms, 12) = static_cast<time_t>(afi.connect_until_time); + Packet_Payload<0x2afd> payload_fd; // not file descriptor + payload_fd.account_id = account_id; + payload_fd.login_id2 = afi.login_id2; + payload_fd.connect_until = afi.connect_until_time; cd->sex = afi.sex; - WFIFOW(ms, 16) = afi.packet_tmw_version; + payload_fd.packet_tmw_version = afi.packet_tmw_version; FPRINTF(stderr, - "From queue index %zd: recalling packet version %d\n", - (&afi - &auth_fifo.front()), afi.packet_tmw_version); - WFIFO_STRUCT(ms, 18, *ck); - WFIFO_STRUCT(ms, 18 + sizeof(*ck), *cd); - WFIFOSET(ms, WFIFOW(ms, 2)); - //PRINTF("auth_fifo search success (auth #%d, account %d, character: %d).\n", i, RFIFOL(fd,2), RFIFOL(fd,6)); + "From queue index %zd: recalling packet version %d\n"_fmt, + (&afi - &auth_fifo.front()), afi.packet_tmw_version); + payload_fd.char_key = *ck; + payload_fd.char_data = *cd; + send_ppacket<0x2afd>(ms, payload_fd); goto x2afc_out; } } { - WFIFOW(ms, 0) = 0x2afe; - WFIFOL(ms, 2) = account_id; - WFIFOSET(ms, 6); - PRINTF("auth_fifo search error! account %d not authentified.\n", + Packet_Fixed<0x2afe> fixed_fe; + fixed_fe.account_id = account_id; + send_fpacket<0x2afe, 6>(ms, fixed_fe); + PRINTF("auth_fifo search error! account %d not authentified.\n"_fmt, account_id); } - } x2afc_out: - RFIFOSKIP(ms, 22); break; + } // MAPサーバー上のユーザー数受信 case 0x2aff: - if (RFIFOREST(ms) < 6 || RFIFOREST(ms) < RFIFOW(ms, 2)) - return; - server[id].users = RFIFOW(ms, 4); + { + Packet_Head<0x2aff> head; + std::vector<Packet_Repeat<0x2aff>> repeat; + rv = recv_vpacket<0x2aff, 6, 4>(ms, head, repeat); + if (rv != RecvResult::Complete) + break; + + server[id].users = head.users; + assert (head.users == repeat.size()); if (anti_freeze_enable) server_freezeflag[id] = 5; // Map anti-freeze system. Counter. 5 ok, 4...0 freezed // remove all previously online players of the server @@ -1758,7 +1922,7 @@ void parse_frommap(Session *ms) // add online players in the list by [Yor] for (int i = 0; i < server[id].users; i++) { - int char_id = RFIFOL(ms, 6 + i * 4); + CharId char_id = repeat[i].char_id; for (const CharPair& cd : char_keys) { if (cd.key.char_id == char_id) @@ -1776,306 +1940,374 @@ void parse_frommap(Session *ms) // only every 8 sec. (normally, 1 server send users every 5 sec.) Don't update every time, because that takes time, but only every 2 connection. // it set to 8 sec because is more than 5 (sec) and if we have more than 1 map-server, informations can be received in shifted. } - RFIFOSKIP(ms, RFIFOW(ms, 2)); break; + } // キャラデータ保存 case 0x2b01: - if (RFIFOREST(ms) < 4 || RFIFOREST(ms) < RFIFOW(ms, 2)) - return; + { + Packet_Payload<0x2b01> payload; + rv = recv_ppacket<0x2b01>(ms, payload); + if (rv != RecvResult::Complete) + break; + + AccountId aid = payload.account_id; + CharId cid = payload.char_id; for (CharPair& cd : char_keys) { - if (cd.key.account_id == RFIFOL(ms, 4) && - cd.key.char_id == RFIFOL(ms, 8)) + if (cd.key.account_id == aid && + cd.key.char_id == cid) { - RFIFO_STRUCT(ms, 12, cd.key); - RFIFO_STRUCT(ms, 12 + sizeof(cd.key), *cd.data); + cd.key = payload.char_key; + *cd.data = payload.char_data; break; } } - RFIFOSKIP(ms, RFIFOW(ms, 2)); break; + } // キャラセレ要求 case 0x2b02: - if (RFIFOREST(ms) < 18) - return; { - int account_id = RFIFOL(ms, 2); + Packet_Fixed<0x2b02> fixed; + rv = recv_fpacket<0x2b02, 18>(ms, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; if (auth_fifo_iter == auth_fifo.end()) auth_fifo_iter = auth_fifo.begin(); auth_fifo_iter->account_id = account_id; - auth_fifo_iter->char_id = 0; - auth_fifo_iter->login_id1 = RFIFOL(ms, 6); - auth_fifo_iter->login_id2 = RFIFOL(ms, 10); + auth_fifo_iter->char_id = CharId(); + auth_fifo_iter->login_id1 = fixed.login_id1; + auth_fifo_iter->login_id2 = fixed.login_id2; auth_fifo_iter->delflag = 2; auth_fifo_iter->connect_until_time = TimeT(); // unlimited/unknown time by default (not display in map-server) - auth_fifo_iter->ip = RFIFOIP(ms, 14); + auth_fifo_iter->ip = fixed.ip; auth_fifo_iter++; - WFIFOW(ms, 0) = 0x2b03; - WFIFOL(ms, 2) = account_id; - WFIFOB(ms, 6) = 0; - WFIFOSET(ms, 7); - } - RFIFOSKIP(ms, 18); + + Packet_Fixed<0x2b03> fixed_03; + fixed_03.account_id = account_id; + fixed_03.unknown = 0; + send_fpacket<0x2b03, 7>(ms, fixed_03); break; + } // マップサーバー間移動要求 case 0x2b05: - if (RFIFOREST(ms) < 49) - return; + { + Packet_Fixed<0x2b05> fixed; + rv = recv_fpacket<0x2b05, 49>(ms, fixed); + if (rv != RecvResult::Complete) + break; + if (auth_fifo_iter == auth_fifo.end()) auth_fifo_iter = auth_fifo.begin(); - RFIFO_WFIFO_CLONE(ms, ms, 44); - // overwrite - WFIFOW(ms, 0) = 0x2b06; - auth_fifo_iter->account_id = RFIFOL(ms, 2); - auth_fifo_iter->char_id = RFIFOL(ms, 14); - auth_fifo_iter->login_id1 = RFIFOL(ms, 6); - auth_fifo_iter->login_id2 = RFIFOL(ms, 10); + Packet_Fixed<0x2b06> fixed_06; + fixed_06.account_id = fixed.account_id; + //fixed_06.error = fixed.login_id1; + //fixed_06.unknown = fixed.login_id2; + fixed_06.char_id = fixed.char_id; + fixed_06.map_name = fixed.map_name; + fixed_06.x = fixed.x; + fixed_06.y = fixed.y; + fixed_06.map_ip = fixed.map_ip; + fixed_06.map_port = fixed.map_port; + + auth_fifo_iter->account_id = fixed.account_id; + auth_fifo_iter->login_id1 = fixed.login_id1; + auth_fifo_iter->login_id2 = fixed.login_id2; + auth_fifo_iter->char_id = fixed.char_id; auth_fifo_iter->delflag = 0; - auth_fifo_iter->sex = static_cast<SEX>(RFIFOB(ms, 44)); + auth_fifo_iter->sex = fixed.sex; auth_fifo_iter->connect_until_time = TimeT(); // unlimited/unknown time by default (not display in map-server) - auth_fifo_iter->ip = RFIFOIP(ms, 45); + auth_fifo_iter->ip = fixed.client_ip; // default, if not found in the loop - WFIFOW(ms, 6) = 1; + fixed_06.error = 1; for (const CharPair& cd : char_keys) - if (cd.key.account_id == RFIFOL(ms, 2) && - cd.key.char_id == RFIFOL(ms, 14)) + { + AccountId aid = fixed.account_id; + CharId cid = fixed.char_id; + if (cd.key.account_id == aid && + cd.key.char_id == cid) { auth_fifo_iter++; - WFIFOL(ms, 6) = 0; + fixed_06.error = 0; break; } - WFIFOSET(ms, 44); - RFIFOSKIP(ms, 49); + } + send_fpacket<0x2b06, 44>(ms, fixed_06); break; + } // it is a request to become GM case 0x2b0a: - if (RFIFOREST(ms) < 4 || RFIFOREST(ms) < RFIFOW(ms, 2)) - return; { - int account_id = RFIFOL(ms, 4); + Packet_Head<0x2b0a> head; + AString repeat; + rv = recv_vpacket<0x2b0a, 8, 1>(ms, head, repeat); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = head.account_id; if (login_session) { // don't send request if no login-server - size_t len = RFIFOW(ms, 2); - RFIFO_WFIFO_CLONE(ms, login_session, len); - WFIFOW(login_session, 0) = 0x2720; - WFIFOSET(login_session, len); + Packet_Head<0x2720> head_20; + head_20.account_id = account_id; + AString& repeat_20 = repeat; + send_vpacket<0x2720, 8, 1>(login_session, head_20, repeat_20); } else { - WFIFOW(ms, 0) = 0x2b0b; - WFIFOL(ms, 2) = account_id; - WFIFOL(ms, 6) = 0; - WFIFOSET(ms, 10); + Packet_Fixed<0x2b0b> fixed_0b; + fixed_0b.account_id = account_id; + fixed_0b.gm_level = GmLevel(); + send_fpacket<0x2b0b, 10>(ms, fixed_0b); } - } - RFIFOSKIP(ms, RFIFOW(ms, 2)); break; + } // Map server send information to change an email of an account -> login-server case 0x2b0c: - if (RFIFOREST(ms) < 86) - return; + { + Packet_Fixed<0x2b0c> fixed; + rv = recv_fpacket<0x2b0c, 86>(ms, fixed); + if (rv != RecvResult::Complete) + break; + if (login_session) { // don't send request if no login-server - RFIFO_WFIFO_CLONE(ms, login_session, 86); // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B - WFIFOW(login_session, 0) = 0x2722; - WFIFOSET(login_session, 86); + Packet_Fixed<0x2722> fixed_22; + fixed_22.account_id = fixed.account_id; + fixed_22.old_email = fixed.old_email; + fixed_22.new_email = fixed.new_email; + send_fpacket<0x2722, 86>(login_session, fixed_22); } - RFIFOSKIP(ms, 86); break; + } // Map server ask char-server about a character name to do some operations (all operations are transmitted to login-server) case 0x2b0e: - if (RFIFOREST(ms) < 44) - return; + { + Packet_Fixed<0x2b0e> fixed; + rv = recv_fpacket<0x2b0e, 44>(ms, fixed); + if (rv != RecvResult::Complete) + break; + { - int acc = RFIFOL(ms, 2); // account_id of who ask (-1 if nobody) - CharName character_name = stringish<CharName>(RFIFO_STRING<24>(ms, 6)); - int operation = RFIFOW(ms, 30); + AccountId acc = fixed.account_id; + CharName character_name = fixed.char_name; + int operation = fixed.operation; // prepare answer - WFIFOW(ms, 0) = 0x2b0f; // answer - WFIFOL(ms, 2) = acc; // who want do operation - WFIFOW(ms, 30) = operation; // type of operation: 1-block, 2-ban, 3-unblock, 4-unban, 5-changesex + Packet_Fixed<0x2b0f> fixed_0f; + fixed_0f.account_id = acc; + fixed_0f.operation = operation; // search character const CharPair *cd = search_character(character_name); + // TODO invert the below logic to shrink this code + // Current logic: + // 1. if no character, return error 1 + // 2. else if gm level too low, return error 2 + // 3. else if login server offline, return error 3 + // 4. else return error 0 and maybe do other stuff if (cd) { const CharKey *ck = &cd->key; - WFIFO_STRING(ms, 6, ck->name.to__actual(), 24); // put correct name if found - WFIFOW(ms, 32) = 0; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline - switch (RFIFOW(ms, 30)) + fixed_0f.char_name = ck->name; + fixed_0f.error = 0; + switch (operation) { case 1: // block - if (acc == -1 - || isGM(acc) >= isGM(ck->account_id)) + { + if (!acc + || isGM(acc).overwhelms(isGM(ck->account_id))) { if (login_session) { // don't send request if no login-server - WFIFOW(login_session, 0) = 0x2724; - WFIFOL(login_session, 2) = ck->account_id; // account value - WFIFOL(login_session, 6) = 5; // status of the account - WFIFOSET(login_session, 10); + Packet_Fixed<0x2724> fixed_24; + fixed_24.account_id = ck->account_id; + fixed_24.status = 5; + send_fpacket<0x2724, 10>(login_session, fixed_24); } else - WFIFOW(ms, 32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + fixed_0f.error = 3; } else - WFIFOW(ms, 32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + fixed_0f.error = 2; break; + } case 2: // ban - if (acc == -1 - || isGM(acc) >= isGM(ck->account_id)) + { + if (!acc + || isGM(acc).overwhelms(isGM(ck->account_id))) { if (login_session) { // don't send request if no login-server - WFIFOW(login_session, 0) = 0x2725; - WFIFOL(login_session, 2) = ck->account_id; // account value - HumanTimeDiff ban_change; - RFIFO_STRUCT(ms, 32, ban_change); - WFIFO_STRUCT(login_session, 6, ban_change); - WFIFOSET(login_session, 18); + Packet_Fixed<0x2725> fixed_25; + fixed_25.account_id = ck->account_id; + HumanTimeDiff ban_change = fixed.ban_add; + fixed_25.ban_add = ban_change; + send_fpacket<0x2725, 18>(login_session, fixed_25); } else - WFIFOW(ms, 32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + fixed_0f.error = 3; } else - WFIFOW(ms, 32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + fixed_0f.error = 2; break; + } case 3: // unblock - if (acc == -1 - || isGM(acc) >= isGM(ck->account_id)) + { + if (!acc + || isGM(acc).overwhelms(isGM(ck->account_id))) { if (login_session) { // don't send request if no login-server - WFIFOW(login_session, 0) = 0x2724; - WFIFOL(login_session, 2) = ck->account_id; // account value - WFIFOL(login_session, 6) = 0; // status of the account - WFIFOSET(login_session, 10); + Packet_Fixed<0x2724> fixed_24; + fixed_24.account_id = ck->account_id; + fixed_24.status = 0; + send_fpacket<0x2724, 10>(login_session, fixed_24); } else - WFIFOW(ms, 32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + fixed_0f.error = 3; } else - WFIFOW(ms, 32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + fixed_0f.error = 2; break; + } case 4: // unban - if (acc == -1 - || isGM(acc) >= isGM(ck->account_id)) + { + if (!acc + || isGM(acc).overwhelms(isGM(ck->account_id))) { if (login_session) { // don't send request if no login-server - WFIFOW(login_session, 0) = 0x272a; - WFIFOL(login_session, 2) = ck->account_id; // account value - WFIFOSET(login_session, 6); + Packet_Fixed<0x272a> fixed_2a; + fixed_2a.account_id = ck->account_id; + send_fpacket<0x272a, 6>(login_session, fixed_2a); } else - WFIFOW(ms, 32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + fixed_0f.error = 3; } else - WFIFOW(ms, 32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + fixed_0f.error = 2; break; + } case 5: // changesex - if (acc == -1 - || isGM(acc) >= isGM(ck->account_id)) + { + if (!acc + || isGM(acc).overwhelms(isGM(ck->account_id))) { if (login_session) { // don't send request if no login-server - WFIFOW(login_session, 0) = 0x2727; - WFIFOL(login_session, 2) = ck->account_id; // account value - WFIFOSET(login_session, 6); + Packet_Fixed<0x2727> fixed_27; + fixed_27.account_id = ck->account_id; + send_fpacket<0x2727, 6>(login_session, fixed_27); } else - WFIFOW(ms, 32) = 3; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + fixed_0f.error = 3; } else - WFIFOW(ms, 32) = 2; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + fixed_0f.error = 2; break; + } } } else { // character name not found - WFIFO_STRING(ms, 6, character_name.to__actual(), 24); - WFIFOW(ms, 32) = 1; // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline + fixed_0f.char_name = character_name; + fixed_0f.error = 1; } // send answer if a player ask, not if the server ask - if (acc != -1) + if (acc) { - WFIFOSET(ms, 34); + send_fpacket<0x2b0f, 34>(ms, fixed_0f); } - RFIFOSKIP(ms, 44); break; } - -// case 0x2b0f: not more used (available for futur usage) + } // account_reg保存要求 case 0x2b10: - if (RFIFOREST(ms) < 4 || RFIFOREST(ms) < RFIFOW(ms, 2)) - return; + { + Packet_Head<0x2b10> head; + std::vector<Packet_Repeat<0x2b10>> repeat; + rv = recv_vpacket<0x2b10, 8, 36>(ms, head, repeat); + if (rv != RecvResult::Complete) + break; + { - Array<struct global_reg, ACCOUNT_REG2_NUM> reg; - int p, j; - int acc = RFIFOL(ms, 4); - for (p = 8, j = 0; - p < RFIFOW(ms, 2) && j < ACCOUNT_REG2_NUM; - p += 36, j++) + Array<GlobalReg, ACCOUNT_REG2_NUM> reg; + AccountId acc = head.account_id; + auto jlim = std::min(repeat.size(), ACCOUNT_REG2_NUM); + for (size_t j = 0; j < jlim; ++j) { - reg[j].str = stringish<VarName>(RFIFO_STRING<32>(ms, p)); - reg[j].value = RFIFOL(ms, p + 32); + reg[j].str = repeat[j].name; + reg[j].value = repeat[j].value; } - set_account_reg2(acc, Slice<struct global_reg>(reg.begin(), j)); + set_account_reg2(acc, Slice<GlobalReg>(reg.begin(), jlim)); // loginサーバーへ送る if (login_session) { // don't send request if no login-server - RFIFO_WFIFO_CLONE(ms, login_session, RFIFOW(ms, 2)); - WFIFOW(login_session, 0) = 0x2728; - WFIFOSET(login_session, WFIFOW(login_session, 2)); + Packet_Head<0x2728> head_28; + std::vector<Packet_Repeat<0x2728>> repeat_28(repeat.size()); + for (size_t j = 0; j < repeat.size(); ++j) + { + repeat_28[j].name = repeat[j].name; + repeat_28[j].value = repeat[j].value; + } + send_vpacket<0x2728, 8, 36>(login_session, head_28, repeat_28); } - RFIFOSKIP(ms, RFIFOW(ms, 2)); break; } + } // Map server is requesting a divorce case 0x2b16: - if (RFIFOREST(ms) < 4) - return; + { + Packet_Fixed<0x2b16> fixed; + rv = recv_fpacket<0x2b16, 6>(ms, fixed); + if (rv != RecvResult::Complete) + break; + { + CharId cid = fixed.char_id; for (CharPair& cd : char_keys) - if (cd.key.char_id == RFIFOL(ms, 2)) + { + if (cd.key.char_id == cid) { char_divorce(&cd); break; } + } - RFIFOSKIP(ms, 6); break; } + } default: // inter server処理に渡す { - int r = inter_parse_frommap(ms); - if (r == 1) // 処理できた + RecvResult r = inter_parse_frommap(ms, packet_id); + if (r == RecvResult::Complete) break; - if (r == 2) // パケット長が足りない + if (r == RecvResult::Incomplete) return; - } // inter server処理でもない場合は切断 - PRINTF("char: unknown packet 0x%04x (%zu bytes to read in buffer)! (from map).\n", - RFIFOW(ms, 0), RFIFOREST(ms)); + PRINTF("char: unknown packet 0x%04x (%zu bytes to read in buffer)! (from map).\n"_fmt, + packet_id, packet_avail(ms)); ms->set_eof(); return; + } } } + if (rv == RecvResult::Error) + ms->set_eof(); } static @@ -2104,8 +2336,8 @@ int lan_ip_check(IP4Address addr) { bool lancheck = lan_subnet.covers(addr); - PRINTF("LAN test (result): %s.\n", - (lancheck) ? SGR_BOLD SGR_CYAN "LAN source" SGR_RESET : SGR_BOLD SGR_GREEN "WAN source" SGR_RESET); + PRINTF("LAN test (result): %s.\n"_fmt, + (lancheck) ? SGR_BOLD SGR_CYAN "LAN source" SGR_RESET ""_s : SGR_BOLD SGR_GREEN "WAN source" SGR_RESET ""_s); return lancheck; } @@ -2127,9 +2359,9 @@ void handle_x0066(Session *s, struct char_session_data *sd, uint8_t rfifob_2, IP CharKey *ck = &cp->key; CharData *cd = cp->data.get(); - CHAR_LOG("Character Selected, Account ID: %d, Character Slot: %d, Character Name: %s [%s]\n", - sd->account_id, rfifob_2, - ck->name, ip); + CHAR_LOG("Character Selected, Account ID: %d, Character Slot: %d, Character Name: %s [%s]\n"_fmt, + sd->account_id, rfifob_2, + ck->name, ip); // searching map server int i = search_mapserver(cd->last_point.map_); // if map is not found, we check major cities @@ -2144,33 +2376,35 @@ void handle_x0066(Session *s, struct char_session_data *sd, uint8_t rfifob_2, IP { // change save point to one of map found on the server (the first) i = j; cd->last_point.map_ = server[j].maps[0]; - PRINTF("Map-server #%d found with a map: '%s'.\n", - j, server[j].maps[0]); + PRINTF("Map-server #%d found with a map: '%s'.\n"_fmt, + j, server[j].maps[0]); // coordonates are unknown break; } // if no map-server is connected, we send: server closed if (j == MAX_MAP_SERVERS) { - WFIFOW(s, 0) = 0x81; - WFIFOB(s, 2) = 1; // 01 = Server closed - WFIFOSET(s, 3); + Packet_Fixed<0x0081> fixed_81; + fixed_81.error_code = 1; + send_fpacket<0x0081, 3>(s, fixed_81); return; } } - WFIFOW(s, 0) = 0x71; - WFIFOL(s, 2) = ck->char_id; - WFIFO_STRING(s, 6, cd->last_point.map_, 16); - PRINTF("Character selection '%s' (account: %d, slot: %d) [%s]\n", - ck->name, - sd->account_id, ck->char_num, ip); - PRINTF("--Send IP of map-server. "); + + Packet_Fixed<0x0071> fixed_71; + fixed_71.char_id = ck->char_id; + fixed_71.map_name = cd->last_point.map_; + PRINTF("Character selection '%s' (account: %d, slot: %d) [%s]\n"_fmt, + ck->name, + sd->account_id, ck->char_num, ip); + PRINTF("--Send IP of map-server. "_fmt); if (lan_ip_check(ip)) - WFIFOIP(s, 22) = lan_map_ip; + fixed_71.ip = lan_map_ip; else - WFIFOIP(s, 22) = server[i].ip; - WFIFOW(s, 26) = server[i].port; - WFIFOSET(s, 28); + fixed_71.ip = server[i].ip; + fixed_71.port = server[i].port; + send_fpacket<0x0071, 28>(s, fixed_71); + if (auth_fifo_iter == auth_fifo.end()) auth_fifo_iter = auth_fifo.begin(); auth_fifo_iter->account_id = sd->account_id; @@ -2192,73 +2426,75 @@ void parse_char(Session *s) { IP4Address ip = s->client_ip; + assert (s != login_session); + if (!login_session) { s->set_eof(); - - // I sure *hope* this doesn't happen ... - if (s == login_session) - login_session = nullptr; return; } char_session_data *sd = static_cast<char_session_data *>(s->session_data.get()); - while (RFIFOREST(s) >= 2) + RecvResult rv = RecvResult::Complete; + uint16_t packet_id; + while (rv == RecvResult::Complete && packet_peek_id(s, &packet_id)) { -// if (RFIFOW(fd,0) < 30000) -// PRINTF("parse_char: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd)); - - switch (RFIFOW(s, 0)) + switch (packet_id) { - case 0x20b: //20040622暗号化ragexe対応 - if (RFIFOREST(s) < 19) - return; - RFIFOSKIP(s, 19); - break; - case 0x61: // change password request - if (RFIFOREST(s) < 50) - return; + { + Packet_Fixed<0x0061> fixed; + rv = recv_fpacket<0x0061, 50>(s, fixed); + if (rv != RecvResult::Complete) + break; + { - WFIFOW(login_session, 0) = 0x2740; - WFIFOL(login_session, 2) = sd->account_id; - AccountPass old_pass = stringish<AccountPass>(RFIFO_STRING<24>(s, 2)); - WFIFO_STRING(login_session, 6, old_pass, 24); - AccountPass new_pass = stringish<AccountPass>(RFIFO_STRING<24>(s, 26)); - WFIFO_STRING(login_session, 30, new_pass, 24); - WFIFOSET(login_session, 54); + Packet_Fixed<0x2740> fixed_40; + fixed_40.account_id = sd->account_id; + AccountPass old_pass = fixed.old_pass; + fixed_40.old_pass = old_pass; + AccountPass new_pass = fixed.new_pass; + fixed_40.new_pass = new_pass; + send_fpacket<0x2740, 54>(login_session, fixed_40); } - RFIFOSKIP(s, 50); break; + } case 0x65: // 接続要求 - if (RFIFOREST(s) < 17) - return; + { + Packet_Fixed<0x0065> fixed; + rv = recv_fpacket<0x0065, 17>(s, fixed); + if (rv != RecvResult::Complete) + break; + { - int account_id = RFIFOL(s, 2); - int GM_value = isGM(account_id); + AccountId account_id = fixed.account_id; + GmLevel GM_value = isGM(account_id); if (GM_value) - PRINTF("Account Logged On; Account ID: %d (GM level %d).\n", + PRINTF("Account Logged On; Account ID: %d (GM level %d).\n"_fmt, account_id, GM_value); else - PRINTF("Account Logged On; Account ID: %d.\n", + PRINTF("Account Logged On; Account ID: %d.\n"_fmt, account_id); - if (sd == NULL) + if (sd == nullptr) { s->session_data = make_unique<char_session_data, SessionDeleter>(); sd = static_cast<char_session_data *>(s->session_data.get()); - sd->email = stringish<AccountEmail>("no mail"); // put here a mail without '@' to refuse deletion if we don't receive the e-mail + sd->email = stringish<AccountEmail>("no mail"_s); // put here a mail without '@' to refuse deletion if we don't receive the e-mail sd->connect_until_time = TimeT(); // unknow or illimited (not displaying on map-server) } sd->account_id = account_id; - sd->login_id1 = RFIFOL(s, 6); - sd->login_id2 = RFIFOL(s, 10); - sd->packet_tmw_version = RFIFOW(s, 14); - sd->sex = static_cast<SEX>(RFIFOB(s, 16)); - // send back account_id - WFIFOL(s, 0) = account_id; - WFIFOSET(s, 4); + sd->login_id1 = fixed.login_id1; + sd->login_id2 = fixed.login_id2; + sd->packet_tmw_version = fixed.packet_tmw_version; + sd->sex = fixed.sex; + + // formerly: send back account_id + Packet_Payload<0x8000> special; + special.magic_packet_length = 4; + send_ppacket<0x8000>(s, special); + // search authentification for (AuthFifoEntry& afi : auth_fifo) { @@ -2273,12 +2509,12 @@ void parse_char(Session *s) if (max_connect_user == 0 || count_users() < max_connect_user) { - if (login_session) - { // don't send request if no login-server + { + // there is always a login server // request to login-server to obtain e-mail/time limit - WFIFOW(login_session, 0) = 0x2716; - WFIFOL(login_session, 2) = sd->account_id; - WFIFOSET(login_session, 6); + Packet_Fixed<0x2716> fixed_16; + fixed_16.account_id = sd->account_id; + send_fpacket<0x2716, 6>(login_session, fixed_16); } // Record client version afi.packet_tmw_version = @@ -2289,126 +2525,153 @@ void parse_char(Session *s) else { // refuse connection (over populated) - WFIFOW(s, 0) = 0x6c; - WFIFOB(s, 2) = 0; - WFIFOSET(s, 3); + Packet_Fixed<0x006c> fixed_6c; + fixed_6c.code = 0; + send_fpacket<0x006c, 3>(s, fixed_6c); } goto x65_out; } } // authentification not found { - if (login_session) { - // don't send request if no login-server - WFIFOW(login_session, 0) = 0x2712; // ask login-server to authentify an account - WFIFOL(login_session, 2) = sd->account_id; - WFIFOL(login_session, 6) = sd->login_id1; - WFIFOL(login_session, 10) = sd->login_id2; // relate to the versions higher than 18 - WFIFOB(login_session, 14) = static_cast<uint8_t>(sd->sex); - WFIFOIP(login_session, 15) = s->client_ip; - WFIFOSET(login_session, 19); - } - else - { // if no login-server, we must refuse connection - WFIFOW(s, 0) = 0x6c; - WFIFOB(s, 2) = 0; - WFIFOSET(s, 3); + // there is always a login-server + Packet_Fixed<0x2712> fixed_12; + fixed_12.account_id = sd->account_id; + fixed_12.login_id1 = sd->login_id1; + fixed_12.login_id2 = sd->login_id2; // relate to the versions higher than 18 + fixed_12.sex = sd->sex; + fixed_12.ip = s->client_ip; + send_fpacket<0x2712, 19>(login_session, fixed_12); } } } x65_out: - RFIFOSKIP(s, 17); break; + } case 0x66: // キャラ選択 - if (!sd || RFIFOREST(s) < 3) + { + Packet_Fixed<0x0066> fixed; + rv = recv_fpacket<0x0066, 3>(s, fixed); + if (rv != RecvResult::Complete) + break; + + if (!sd) + { + s->set_eof(); return; - handle_x0066(s, sd, RFIFOB(s, 2), ip); - RFIFOSKIP(s, 3); + } + handle_x0066(s, sd, fixed.code, ip); break; + } case 0x67: // 作成 - if (!sd || RFIFOREST(s) < 37) - return; { - CharName name = stringish<CharName>(RFIFO_STRING<24>(s, 2)); - uint8_t stats[6]; - for (int i = 0; i < 6; ++i) - stats[i] = RFIFOB(s, 26 + i); - uint8_t slot = RFIFOB(s, 32); - uint16_t hair_color = RFIFOW(s, 33); - uint16_t hair_style = RFIFOW(s, 35); + Packet_Fixed<0x0067> fixed; + rv = recv_fpacket<0x0067, 37>(s, fixed); + if (rv != RecvResult::Complete) + break; + + if (!sd) + { + s->set_eof(); + return; + } + CharName name = fixed.char_name; + Stats6 stats = fixed.stats; + uint8_t slot = fixed.slot; + uint16_t hair_color = fixed.hair_color; + uint16_t hair_style = fixed.hair_style; const CharPair *cp = make_new_char(s, name, stats, slot, hair_color, hair_style); if (!cp) { - WFIFOW(s, 0) = 0x6e; - WFIFOB(s, 2) = 0x00; - WFIFOSET(s, 3); - RFIFOSKIP(s, 37); + Packet_Fixed<0x006e> fixed_6e; + fixed_6e.code = 0x00; + send_fpacket<0x006e, 3>(s, fixed_6e); break; } const CharKey *ck = &cp->key; const CharData *cd = cp->data.get(); - WFIFOW(s, 0) = 0x6d; - WFIFO_ZERO(s, 2, 106); - - WFIFOL(s, 2) = ck->char_id; - WFIFOL(s, 2 + 4) = cd->base_exp; - WFIFOL(s, 2 + 8) = cd->zeny; - WFIFOL(s, 2 + 12) = cd->job_exp; - WFIFOL(s, 2 + 16) = cd->job_level; - - WFIFOL(s, 2 + 28) = cd->karma; - WFIFOL(s, 2 + 32) = cd->manner; - - WFIFOW(s, 2 + 40) = 0x30; - WFIFOW(s, 2 + 42) = min(cd->hp, 0x7fff); - WFIFOW(s, 2 + 44) = min(cd->max_hp, 0x7fff); - WFIFOW(s, 2 + 46) = min(cd->sp, 0x7fff); - WFIFOW(s, 2 + 48) = min(cd->max_sp, 0x7fff); - WFIFOW(s, 2 + 50) = static_cast<uint16_t>(DEFAULT_WALK_SPEED.count()); // cd->speed; - WFIFOW(s, 2 + 52) = cd->species; - WFIFOW(s, 2 + 54) = cd->hair; - - WFIFOW(s, 2 + 58) = cd->base_level; - WFIFOW(s, 2 + 60) = cd->skill_point; - - WFIFOW(s, 2 + 64) = cd->shield; - WFIFOW(s, 2 + 66) = cd->head_top; - WFIFOW(s, 2 + 68) = cd->head_mid; - WFIFOW(s, 2 + 70) = cd->hair_color; - - WFIFO_STRING(s, 2 + 74, ck->name.to__actual(), 24); - - WFIFOB(s, 2 + 98) = min(cd->attrs[ATTR::STR], 255); - WFIFOB(s, 2 + 99) = min(cd->attrs[ATTR::AGI], 255); - WFIFOB(s, 2 + 100) = min(cd->attrs[ATTR::VIT], 255); - WFIFOB(s, 2 + 101) = min(cd->attrs[ATTR::INT], 255); - WFIFOB(s, 2 + 102) = min(cd->attrs[ATTR::DEX], 255); - WFIFOB(s, 2 + 103) = min(cd->attrs[ATTR::LUK], 255); - WFIFOB(s, 2 + 104) = ck->char_num; - - WFIFOSET(s, 108); - } - RFIFOSKIP(s, 37); + Packet_Fixed<0x006d> fixed_6d; + + fixed_6d.char_select.char_id = ck->char_id; + fixed_6d.char_select.base_exp = cd->base_exp; + fixed_6d.char_select.zeny = cd->zeny; + fixed_6d.char_select.job_exp = cd->job_exp; + fixed_6d.char_select.job_level = cd->job_level; + + fixed_6d.char_select.shoes = ItemNameId(); + fixed_6d.char_select.gloves = ItemNameId(); + fixed_6d.char_select.cape = ItemNameId(); + fixed_6d.char_select.misc1 = ItemNameId(); + fixed_6d.char_select.option = Option(); + fixed_6d.char_select.unused = 0; + + // this was buggy until the protocol became generated + // but the client ignores it anyway + fixed_6d.char_select.karma = cd->karma; + fixed_6d.char_select.manner = cd->manner; + + fixed_6d.char_select.status_point = 0x30; + fixed_6d.char_select.hp = saturate<int16_t>(cd->hp); + fixed_6d.char_select.max_hp = saturate<int16_t>(cd->max_hp); + fixed_6d.char_select.sp = saturate<int16_t>(cd->sp); + fixed_6d.char_select.max_sp = saturate<int16_t>(cd->max_sp); + fixed_6d.char_select.speed = static_cast<uint16_t>(DEFAULT_WALK_SPEED.count()); // cd->speed; + fixed_6d.char_select.species = cd->species; + fixed_6d.char_select.hair_style = cd->hair; + fixed_6d.char_select.weapon = 0; + + fixed_6d.char_select.base_level = cd->base_level; + fixed_6d.char_select.skill_point = cd->skill_point; + + fixed_6d.char_select.head_bottom = ItemNameId(); + fixed_6d.char_select.shield = cd->shield; + fixed_6d.char_select.head_top = cd->head_top; + fixed_6d.char_select.head_mid = cd->head_mid; + fixed_6d.char_select.hair_color = cd->hair_color; + fixed_6d.char_select.misc2 = ItemNameId(); + + fixed_6d.char_select.char_name = ck->name; + + fixed_6d.char_select.stats.str = saturate<uint8_t>(cd->attrs[ATTR::STR]); + fixed_6d.char_select.stats.agi = saturate<uint8_t>(cd->attrs[ATTR::AGI]); + fixed_6d.char_select.stats.vit = saturate<uint8_t>(cd->attrs[ATTR::VIT]); + fixed_6d.char_select.stats.int_ = saturate<uint8_t>(cd->attrs[ATTR::INT]); + fixed_6d.char_select.stats.dex = saturate<uint8_t>(cd->attrs[ATTR::DEX]); + fixed_6d.char_select.stats.luk = saturate<uint8_t>(cd->attrs[ATTR::LUK]); + fixed_6d.char_select.char_num = ck->char_num; + fixed_6d.char_select.unused2 = 0; + + send_fpacket<0x006d, 108>(s, fixed_6d); break; + } case 0x68: // delete char //Yor's Fix - if (!sd || RFIFOREST(s) < 46) - return; { - AccountEmail email = stringish<AccountEmail>(RFIFO_STRING<40>(s, 6)); + Packet_Fixed<0x0068> fixed; + rv = recv_fpacket<0x0068, 46>(s, fixed); + if (rv != RecvResult::Complete) + break; + + if (!sd) + { + s->set_eof(); + return; + } + AccountEmail email = fixed.email; if (!e_mail_check(email)) email = DEFAULT_EMAIL; { { + CharId cid = fixed.char_id; CharPair *cs = nullptr; for (CharPair& cd : char_keys) { - if (cd.key.char_id == RFIFOL(s, 2)) + if (cd.key.char_id == cid) { if (cd.key.account_id == sd->account_id) cs = &cd; @@ -2426,176 +2689,129 @@ void parse_char(Session *s) } char_keys.pop_back(); - WFIFOW(s, 0) = 0x6f; - WFIFOSET(s, 2); + Packet_Fixed<0x006f> fixed_6f; + send_fpacket<0x006f, 2>(s, fixed_6f); goto x68_out; } } { - WFIFOW(s, 0) = 0x70; - WFIFOB(s, 2) = 0; - WFIFOSET(s, 3); + Packet_Fixed<0x0070> fixed_70; + fixed_70.code = 0; + send_fpacket<0x0070, 3>(s, fixed_70); } } - } x68_out: - RFIFOSKIP(s, 46); break; + } case 0x2af8: // マップサーバーログイン - if (RFIFOREST(s) < 60) - return; { + Packet_Fixed<0x2af8> fixed; + rv = recv_fpacket<0x2af8, 60>(s, fixed); + if (rv != RecvResult::Complete) + break; + int i; - WFIFOW(s, 0) = 0x2af9; + Packet_Fixed<0x2af9> fixed_f9; for (i = 0; i < MAX_MAP_SERVERS; i++) { if (!server_session[i]) break; } - AccountName userid_ = stringish<AccountName>(RFIFO_STRING<24>(s, 2)); - AccountPass passwd_ = stringish<AccountPass>(RFIFO_STRING<24>(s, 26)); + AccountName userid_ = fixed.account_name; + AccountPass passwd_ = fixed.account_pass; if (i == MAX_MAP_SERVERS || userid_ != userid || passwd_ != passwd) { - WFIFOB(s, 2) = 3; - WFIFOSET(s, 3); - RFIFOSKIP(s, 60); + fixed_f9.code = 3; + send_fpacket<0x2af9, 3>(s, fixed_f9); } else { - int len; - WFIFOB(s, 2) = 0; - s->set_parsers(SessionParsers{func_parse: parse_frommap, func_delete: delete_frommap}); + fixed_f9.code = 0; + s->set_parsers(SessionParsers{.func_parse= parse_frommap, .func_delete= delete_frommap}); server_session[i] = s; if (anti_freeze_enable) server_freezeflag[i] = 5; // Map anti-freeze system. Counter. 5 ok, 4...0 freezed - // ignore RFIFOL(fd, 50) - server[i].ip = RFIFOIP(s, 54); - server[i].port = RFIFOW(s, 58); + // ignore fixed.unknown + server[i].ip = fixed.ip; + server[i].port = fixed.port; server[i].users = 0; for (MapName& mapi : server[i].maps) mapi = MapName(); - WFIFOSET(s, 3); - RFIFOSKIP(s, 60); + send_fpacket<0x2af9, 3>(s, fixed_f9); realloc_fifo(s, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); // send gm acccounts level to map-servers - len = 4; - WFIFOW(s, 0) = 0x2b15; + std::vector<Packet_Repeat<0x2b15>> repeat_15(gm_accounts.size()); + auto it = repeat_15.begin(); for (const GM_Account& gma : gm_accounts) { - WFIFOL(s, len) = gma.account_id; - WFIFOB(s, len + 4) = gma.level; - len += 5; + it->account_id = gma.account_id; + it->gm_level = gma.level; + ++it; } - WFIFOW(s, 2) = len; - WFIFOSET(s, len); + send_packet_repeatonly<0x2b15, 4, 5>(s, repeat_15); + // justification: we switched the session parsers + parse_frommap(s); return; } - } - break; - - case 0x187: // Alive信号? - if (RFIFOREST(s) < 6) - return; - RFIFOSKIP(s, 6); break; + } case 0x7530: // Athena情報所得 - WFIFOW(s, 0) = 0x7531; - WFIFO_STRUCT(s, 2, CURRENT_CHAR_SERVER_VERSION); - WFIFOSET(s, 10); - RFIFOSKIP(s, 2); - return; + { + Packet_Fixed<0x7530> fixed; + rv = recv_fpacket<0x7530, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x7531> fixed_31; + fixed_31.version = CURRENT_CHAR_SERVER_VERSION; + send_fpacket<0x7531, 10>(s, fixed_31); + break; + } case 0x7532: // 接続の切断(defaultと処理は一緒だが明示的にするため) + { + Packet_Fixed<0x7532> fixed; + rv = recv_fpacket<0x7532, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + s->set_eof(); return; + } default: s->set_eof(); return; } } -} - -// 全てのMAPサーバーにデータ送信(送信したmap鯖の数を返す) -int mapif_sendall(const uint8_t *buf, unsigned int len) -{ - int i, c; - - c = 0; - for (i = 0; i < MAX_MAP_SERVERS; i++) - { - Session *s = server_session[i]; - if (s) - { - WFIFO_BUF_CLONE(s, buf, len); - WFIFOSET(s, len); - c++; - } - } - return c; -} - -// 自分以外の全てのMAPサーバーにデータ送信(送信したmap鯖の数を返す) -int mapif_sendallwos(Session *ss, const uint8_t *buf, unsigned int len) -{ - int i, c; - - c = 0; - for (i = 0; i < MAX_MAP_SERVERS; i++) - { - Session *s = server_session[i]; - if (s && s != ss) - { - WFIFO_BUF_CLONE(s, buf, len); - WFIFOSET(s, len); - c++; - } - } - return c; -} - -// MAPサーバーにデータ送信(map鯖生存確認有り) -int mapif_send(Session *s, const uint8_t *buf, unsigned int len) -{ - int i; - - if (s) - { - for (i = 0; i < MAX_MAP_SERVERS; i++) - { - if (s == server_session[i]) - { - WFIFO_BUF_CLONE(s, buf, len); - WFIFOSET(s, len); - return 1; - } - } - } - return 0; + if (rv == RecvResult::Error) + s->set_eof(); } static void send_users_tologin(TimerData *, tick_t) { int users = count_users(); - uint8_t buf[16]; if (login_session) { // send number of user to login server - WFIFOW(login_session, 0) = 0x2714; - WFIFOL(login_session, 2) = users; - WFIFOSET(login_session, 6); + Packet_Fixed<0x2714> fixed_14; + fixed_14.users = users; + send_fpacket<0x2714, 6>(login_session, fixed_14); } // send number of players to all map-servers - WBUFW(buf, 0) = 0x2b00; - WBUFL(buf, 2) = users; - mapif_sendall(buf, 6); + Packet_Fixed<0x2b00> fixed_00; + fixed_00.users = users; + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x2b00, 6>(ss, fixed_00); + } } static @@ -2603,24 +2819,24 @@ void check_connect_login_server(TimerData *, tick_t) { if (!login_session) { - PRINTF("Attempt to connect to login-server...\n"); + PRINTF("Attempt to connect to login-server...\n"_fmt); login_session = make_connection(login_ip, login_port, - SessionParsers{func_parse: parse_tologin, func_delete: delete_tologin}); + SessionParsers{.func_parse= parse_tologin, .func_delete= delete_tologin}); if (!login_session) return; realloc_fifo(login_session, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - WFIFOW(login_session, 0) = 0x2710; - WFIFO_ZERO(login_session, 2, 24); - WFIFO_STRING(login_session, 2, userid, 24); - WFIFO_STRING(login_session, 26, passwd, 24); - WFIFOL(login_session, 50) = 0; - WFIFOIP(login_session, 54) = char_ip; - WFIFOL(login_session, 58) = char_port; - WFIFO_STRING(login_session, 60, server_name, 20); - WFIFOW(login_session, 80) = 0; - WFIFOW(login_session, 82) = 0; //char_maintenance; - WFIFOW(login_session, 84) = 0; //char_new; - WFIFOSET(login_session, 86); + + Packet_Fixed<0x2710> fixed_10; + fixed_10.account_name = userid; + fixed_10.account_pass = passwd; + fixed_10.unknown = 0; + fixed_10.ip = char_ip; + fixed_10.port = char_port; + fixed_10.server_name = server_name; + fixed_10.unknown2 = 0; + fixed_10.maintenance = 0; + fixed_10.is_new = 0; + send_fpacket<0x2710, 86>(login_session, fixed_10); } } @@ -2630,14 +2846,14 @@ void check_connect_login_server(TimerData *, tick_t) static bool char_lan_config(XString w1, ZString w2) { - struct hostent *h = NULL; + struct hostent *h = nullptr; { - if (w1 == "lan_map_ip") + if (w1 == "lan_map_ip"_s) { // Read map-server Lan IP Address h = gethostbyname(w2.c_str()); - if (h != NULL) + if (h != nullptr) { lan_map_ip = IP4Address({ static_cast<uint8_t>(h->h_addr[0]), @@ -2648,20 +2864,20 @@ bool char_lan_config(XString w1, ZString w2) } else { - PRINTF("Bad IP value: %s\n", w2); + PRINTF("Bad IP value: %s\n"_fmt, w2); return false; } - PRINTF("LAN IP of map-server: %s.\n", lan_map_ip); + PRINTF("LAN IP of map-server: %s.\n"_fmt, lan_map_ip); } - else if (w1 == "subnet" /*backward compatibility*/ - || w1 == "lan_subnet") + else if (w1 == "subnet"_s /*backward compatibility*/ + || w1 == "lan_subnet"_s) { if (!extract(w2, &lan_subnet)) { - PRINTF("Bad IP mask: %s\n", w2); + PRINTF("Bad IP mask: %s\n"_fmt, w2); return false; } - PRINTF("Sub-network of the map-server: %s.\n", + PRINTF("Sub-network of the map-server: %s.\n"_fmt, lan_subnet); } else @@ -2677,10 +2893,10 @@ bool lan_check() { // sub-network check of the map-server { - PRINTF("LAN test of LAN IP of the map-server: "); + PRINTF("LAN test of LAN IP of the map-server: "_fmt); if (!lan_ip_check(lan_map_ip)) { - PRINTF(SGR_BOLD SGR_RED "***ERROR: LAN IP of the map-server doesn't belong to the specified Sub-network." SGR_RESET "\n"); + PRINTF(SGR_BOLD SGR_RED "***ERROR: LAN IP of the map-server doesn't belong to the specified Sub-network." SGR_RESET "\n"_fmt); return false; } } @@ -2691,27 +2907,27 @@ bool lan_check() static bool char_config(XString w1, ZString w2) { - struct hostent *h = NULL; + struct hostent *h = nullptr; { - if (w1 == "userid") + if (w1 == "userid"_s) userid = stringish<AccountName>(w2); - else if (w1 == "passwd") + else if (w1 == "passwd"_s) passwd = stringish<AccountPass>(w2); - else if (w1 == "server_name") + else if (w1 == "server_name"_s) { server_name = stringish<ServerName>(w2); - PRINTF("%s server has been intialized\n", w2); + PRINTF("%s server has been intialized\n"_fmt, w2); } - else if (w1 == "wisp_server_name") + else if (w1 == "wisp_server_name"_s) { if (w2.size() >= 4) wisp_server_name = stringish<CharName>(w2); } - else if (w1 == "login_ip") + else if (w1 == "login_ip"_s) { h = gethostbyname(w2.c_str()); - if (h != NULL) + if (h != nullptr) { login_ip = IP4Address({ static_cast<uint8_t>(h->h_addr[0]), @@ -2719,23 +2935,23 @@ bool char_config(XString w1, ZString w2) static_cast<uint8_t>(h->h_addr[2]), static_cast<uint8_t>(h->h_addr[3]), }); - PRINTF("Login server IP address : %s -> %s\n", + PRINTF("Login server IP address : %s -> %s\n"_fmt, w2, login_ip); } else { - PRINTF("Bad IP value: %s\n", w2); + PRINTF("Bad IP value: %s\n"_fmt, w2); return false; } } - else if (w1 == "login_port") + else if (w1 == "login_port"_s) { login_port = atoi(w2.c_str()); } - else if (w1 == "char_ip") + else if (w1 == "char_ip"_s) { h = gethostbyname(w2.c_str()); - if (h != NULL) + if (h != nullptr) { char_ip = IP4Address({ static_cast<uint8_t>(h->h_addr[0]), @@ -2743,56 +2959,56 @@ bool char_config(XString w1, ZString w2) static_cast<uint8_t>(h->h_addr[2]), static_cast<uint8_t>(h->h_addr[3]), }); - PRINTF("Character server IP address : %s -> %s\n", + PRINTF("Character server IP address : %s -> %s\n"_fmt, w2, char_ip); } else { - PRINTF("Bad IP value: %s\n", w2); + PRINTF("Bad IP value: %s\n"_fmt, w2); return false; } } - else if (w1 == "char_port") + else if (w1 == "char_port"_s) { char_port = atoi(w2.c_str()); } - else if (w1 == "char_txt") + else if (w1 == "char_txt"_s) { char_txt = w2; } - else if (w1 == "max_connect_user") + else if (w1 == "max_connect_user"_s) { max_connect_user = atoi(w2.c_str()); if (max_connect_user < 0) max_connect_user = 0; // unlimited online players } - else if (w1 == "check_ip_flag") + else if (w1 == "check_ip_flag"_s) { check_ip_flag = config_switch(w2); } - else if (w1 == "autosave_time") + else if (w1 == "autosave_time"_s) { autosave_time = std::chrono::seconds(atoi(w2.c_str())); if (autosave_time <= std::chrono::seconds::zero()) autosave_time = DEFAULT_AUTOSAVE_INTERVAL; } - else if (w1 == "start_point") + else if (w1 == "start_point"_s) { extract(w2, &start_point); } - else if (w1 == "unknown_char_name") + else if (w1 == "unknown_char_name"_s) { unknown_char_name = stringish<CharName>(w2); } - else if (w1 == "char_log_filename") + else if (w1 == "char_log_filename"_s) { char_log_filename = w2; } - else if (w1 == "char_name_option") + else if (w1 == "char_name_option"_s) { char_name_option = atoi(w2.c_str()); } - else if (w1 == "char_name_letters") + else if (w1 == "char_name_letters"_s) { if (!w2) char_name_letters.reset(); @@ -2800,39 +3016,38 @@ bool char_config(XString w1, ZString w2) for (uint8_t c : w2) char_name_letters[c] = true; } - else if (w1 == "online_txt_filename") + else if (w1 == "online_txt_filename"_s) { online_txt_filename = w2; } - else if (w1 == "online_html_filename") + else if (w1 == "online_html_filename"_s) { online_html_filename = w2; } - else if (w1 == "online_sorting_option") + else if (w1 == "online_sorting_option"_s) { online_sorting_option = atoi(w2.c_str()); } - else if (w1 == "online_gm_display_min_level") - { // minimum GM level to display 'GM' when we want to display it - online_gm_display_min_level = atoi(w2.c_str()); - if (online_gm_display_min_level < 5) // send online file every 5 seconds to player is enough - online_gm_display_min_level = 5; + else if (w1 == "online_gm_display_min_level"_s) + { + // minimum GM level to display 'GM' when we want to display it + return extract(w2, &online_gm_display_min_level); } - else if (w1 == "online_refresh_html") + else if (w1 == "online_refresh_html"_s) { online_refresh_html = atoi(w2.c_str()); if (online_refresh_html < 1) online_refresh_html = 1; } - else if (w1 == "anti_freeze_enable") + else if (w1 == "anti_freeze_enable"_s) { anti_freeze_enable = config_switch(w2); } - else if (w1 == "anti_freeze_interval") + else if (w1 == "anti_freeze_interval"_s) { anti_freeze_interval = std::max( std::chrono::seconds(atoi(w2.c_str())), - std::chrono::seconds(5)); + 5_s); } else { @@ -2859,7 +3074,7 @@ void term_func(void) delete_session(login_session); delete_session(char_session); - CHAR_LOG("----End of char-server (normal end with closing of all files).\n"); + CHAR_LOG("----End of char-server (normal end with closing of all files).\n"_fmt); } static @@ -2884,20 +3099,20 @@ int do_init(Slice<ZString> argv) ZString argvi = argv.pop_front(); if (argvi.startswith('-')) { - if (argvi == "--help") + if (argvi == "--help"_s) { - PRINTF("Usage: %s [--help] [--version] [files...]\n", + PRINTF("Usage: %s [--help] [--version] [files...]\n"_fmt, argv0); exit(0); } - else if (argvi == "--version") + else if (argvi == "--version"_s) { - PRINTF("%s\n", CURRENT_VERSION_STRING); + PRINTF("%s\n"_fmt, CURRENT_VERSION_STRING); exit(0); } else { - FPRINTF(stderr, "Unknown argument: %s\n", argvi); + FPRINTF(stderr, "Unknown argument: %s\n"_fmt, argvi); runflag = false; } } @@ -2909,11 +3124,11 @@ int do_init(Slice<ZString> argv) } if (!loaded_config_yet) - runflag &= load_config_file("conf/tmwa-char.conf", char_confs); + runflag &= load_config_file("conf/tmwa-char.conf"_s, char_confs); // a newline in the log... - CHAR_LOG(""); - CHAR_LOG("The char-server starting...\n"); + CHAR_LOG(""_fmt); + CHAR_LOG("The char-server starting...\n"_fmt); runflag &= lan_check(); @@ -2925,13 +3140,13 @@ int do_init(Slice<ZString> argv) char_session = make_listen_port(char_port, SessionParsers{parse_char, delete_char}); - Timer(gettick() + std::chrono::seconds(1), + Timer(gettick() + 1_s, check_connect_login_server, - std::chrono::seconds(10) + 10_s ).detach(); - Timer(gettick() + std::chrono::seconds(1), + Timer(gettick() + 1_s, send_users_tologin, - std::chrono::seconds(5) + 5_s ).detach(); Timer(gettick() + autosave_time, mmo_char_sync_timer, @@ -2940,17 +3155,18 @@ int do_init(Slice<ZString> argv) if (anti_freeze_enable > 0) { - Timer(gettick() + std::chrono::seconds(1), + Timer(gettick() + 1_s, map_anti_freeze_system, anti_freeze_interval ).detach(); } - CHAR_LOG("The char-server is ready (Server is listening on the port %d).\n", - char_port); + CHAR_LOG("The char-server is ready (Server is listening on the port %d).\n"_fmt, + char_port); - PRINTF("The char-server is " SGR_BOLD SGR_GREEN "ready" SGR_RESET " (Server is listening on the port %d).\n\n", - char_port); + PRINTF("The char-server is " SGR_BOLD SGR_GREEN "ready" SGR_RESET " (Server is listening on the port %d).\n\n"_fmt, + char_port); return 0; } +} // namespace tmwa diff --git a/src/char/char.hpp b/src/char/char.hpp index 4c11073..a9c786f 100644 --- a/src/char/char.hpp +++ b/src/char/char.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_CHAR_CHAR_HPP -#define TMWA_CHAR_CHAR_HPP +#pragma once // char.hpp - Character server. // // Copyright © ????-2004 Athena Dev Teams @@ -21,15 +20,19 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "../mmo/ip.hpp" -# include "../mmo/mmo.hpp" +#include "../generic/array.hpp" -struct Session; +#include "../net/ip.hpp" +#include "../mmo/mmo.hpp" + + +namespace tmwa +{ constexpr int MAX_MAP_SERVERS = 30; struct mmo_map_server @@ -41,16 +44,13 @@ struct mmo_map_server }; const CharPair *search_character(CharName character_name); -const CharPair *search_character_id(int char_id); +const CharPair *search_character_id(CharId char_id); Session *server_for(const CharPair *mcs); -int mapif_sendall(const uint8_t *buf, unsigned int len); -int mapif_sendallwos(Session *s, const uint8_t *buf, unsigned int len); -int mapif_send(Session *s, const uint8_t *buf, unsigned int len); +auto iter_map_sessions() -> decltype(filter_iterator<Session *>(std::declval<Array<Session *, MAX_MAP_SERVERS> *>())); void char_log(XString line); -# define CHAR_LOG(fmt, ...) \ +#define CHAR_LOG(fmt, ...) \ char_log(STRPRINTF(fmt, ## __VA_ARGS__)) - -#endif // TMWA_CHAR_CHAR_HPP +} // namespace tmwa diff --git a/src/char/fwd.hpp b/src/char/fwd.hpp new file mode 100644 index 0000000..31cd1ba --- /dev/null +++ b/src/char/fwd.hpp @@ -0,0 +1,27 @@ +#pragma once +// char/fwd.hpp - list of type names for char server +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +// meh, add more when I feel like it +} // namespace tmwa diff --git a/src/char/int_party.cpp b/src/char/int_party.cpp index c9965dc..c9ab5a4 100644 --- a/src/char/int_party.cpp +++ b/src/char/int_party.cpp @@ -20,8 +20,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <cstdlib> -#include <cstring> +#include "../ints/udl.hpp" #include "../strings/mstring.hpp" #include "../strings/astring.hpp" @@ -32,50 +31,58 @@ #include "../io/cxxstdio.hpp" #include "../io/lock.hpp" #include "../io/read.hpp" +#include "../io/write.hpp" + +#include "../net/packets.hpp" + +#include "../proto2/char-map.hpp" #include "../mmo/extract.hpp" +#include "../mmo/ids.hpp" #include "../mmo/mmo.hpp" -#include "../mmo/socket.hpp" #include "char.hpp" #include "inter.hpp" #include "../poison.hpp" -AString party_txt = "save/party.txt"; + +namespace tmwa +{ +AString party_txt = "save/party.txt"_s; static -Map<int, struct party> party_db; +Map<PartyId, PartyMost> party_db; static -int party_newid = 100; +PartyId party_newid = wrap<PartyId>(100_u32); static -void mapif_party_broken(int party_id, int flag); +void mapif_party_broken(PartyId party_id, int flag); static -int party_check_empty(struct party *p); +int party_check_empty(PartyPair p); static -void mapif_parse_PartyLeave(Session *s, int party_id, int account_id); +void mapif_parse_PartyLeave(Session *s, PartyId party_id, AccountId account_id); // パーティデータの文字列への変換 static -AString inter_party_tostr(struct party *p) +AString inter_party_tostr(PartyPair p) { MString str; str += STRPRINTF( "%d\t" "%s\t" - "%d,%d\t", - p->party_id, + "%d,%d\t"_fmt, + p.party_id, p->name, p->exp, p->item); for (int i = 0; i < MAX_PARTY; i++) { - struct party_member *m = &p->member[i]; + PartyMember *m = &p->member[i]; if (!m->account_id) continue; str += STRPRINTF( "%d,%d\t" - "%s\t", + "%s\t"_fmt, m->account_id, m->leader, m->name); } @@ -84,9 +91,9 @@ AString inter_party_tostr(struct party *p) } static -bool extract(XString str, party *p) +bool extract(XString str, PartyPair *pp) { - *p = party(); + PartyPair& p = *pp; // not compatible with the normal extract()ors since it has // a variable-size element that uses the same separator @@ -95,7 +102,7 @@ bool extract(XString str, party *p) return false; auto begin = bits.begin(); auto end = bits.end(); - if (begin == end || !extract(*begin, &p->party_id)) + if (begin == end || !extract(*begin, &p.party_id)) return false; ++begin; if (begin == end || !extract(*begin, &p->name)) @@ -107,7 +114,7 @@ bool extract(XString str, party *p) for (int i = 0; begin != end && i < MAX_PARTY; ++i) { - struct party_member *m = &p->member[i]; + PartyMember *m = &p->member[i]; if (begin == end || !extract(*begin, record<','>(&m->account_id, &m->leader))) return false; @@ -123,7 +130,7 @@ bool extract(XString str, party *p) } static -void party_check_deleted_init(struct party *p) +void party_check_deleted_init(PartyPair p) { for (int i = 0; i < MAX_PARTY; i++) { @@ -132,13 +139,13 @@ void party_check_deleted_init(struct party *p) const CharPair *c = search_character(p->member[i].name); if (!c || c->key.account_id != p->member[i].account_id) { - CHAR_LOG("WARNING: deleting obsolete party member %d %s of %d %s\n", + CHAR_LOG("WARNING: deleting obsolete party member %d %s of %d %s\n"_fmt, p->member[i].account_id, p->member[i].name, - p->party_id, p->name); - PRINTF("WARNING: deleting obsolete party member %d %s of %d %s\n", + p.party_id, p->name); + PRINTF("WARNING: deleting obsolete party member %d %s of %d %s\n"_fmt, p->member[i].account_id, p->member[i].name, - p->party_id, p->name); - p->member[i] = party_member{}; + p.party_id, p->name); + p->member[i] = PartyMember{}; } } } @@ -150,31 +157,33 @@ void inter_party_init(void) if (!in.is_open()) return; - // TODO: convert to use char_id, and change to extract() + // TODO: convert to use char_id AString line; int c = 0; while (in.getline(line)) { - int i, j = 0; - if (SSCANF(line, "%d\t%%newid%%\n%n", &i, &j) == 1 && j > 0 - && party_newid <= i) + PartyId i; + if (extract(line, record<'\t'>(&i, "%newid%"_s)) + && party_newid < i) { party_newid = i; continue; } - struct party p {}; - if (extract(line, &p) && p.party_id > 0) + PartyMost pm; + PartyPair pp; + pp.party_most = ± + if (extract(line, &pp) && pp.party_id) { - if (p.party_id >= party_newid) - party_newid = p.party_id + 1; - party_check_deleted_init(&p); - party_db.insert(p.party_id, p); - party_check_empty(&p); + if (party_newid < next(pp.party_id)) + party_newid = next(pp.party_id); + party_check_deleted_init(pp); + party_db.insert(pp.party_id, pm); + party_check_empty(pp); } else { - PRINTF("int_party: broken data [%s] line %d\n", party_txt, + PRINTF("int_party: broken data [%s] line %d\n"_fmt, party_txt, c + 1); } c++; @@ -183,7 +192,7 @@ void inter_party_init(void) // パーティーデータのセーブ用 static -void inter_party_save_sub(struct party *data, io::WriteFile& fp) +void inter_party_save_sub(PartyPair data, io::WriteFile& fp) { AString line = inter_party_tostr(data); fp.put_line(line); @@ -195,19 +204,24 @@ int inter_party_save(void) io::WriteLock fp(party_txt); if (!fp.is_open()) { - PRINTF("int_party: cant write [%s] !!! data is lost !!!\n", + PRINTF("int_party: cant write [%s] !!! data is lost !!!\n"_fmt, party_txt); return 1; } for (auto& pair : party_db) - inter_party_save_sub(&pair.second, fp); + { + PartyPair tmp; + tmp.party_id = pair.first; + tmp.party_most = &pair.second; + inter_party_save_sub(tmp, fp); + } return 0; } // パーティ名検索用 static -void search_partyname_sub(struct party *p, PartyName str, struct party **dst) +void search_partyname_sub(PartyPair p, PartyName str, PartyPair *dst) { if (p->name == str) *dst = p; @@ -215,18 +229,23 @@ void search_partyname_sub(struct party *p, PartyName str, struct party **dst) // パーティ名検索 static -struct party *search_partyname(PartyName str) +PartyPair search_partyname(PartyName str) { - struct party *p = NULL; + PartyPair p; for (auto& pair : party_db) - search_partyname_sub(&pair.second, str, &p); + { + PartyPair tmp; + tmp.party_id = pair.first; + tmp.party_most = &pair.second; + search_partyname_sub(tmp, str, &p); + } return p; } // EXP公平分配できるかチェック static -int party_check_exp_share(struct party *p) +int party_check_exp_share(PartyPair p) { int i; int maxlv = 0, minlv = 0x7fffffff; @@ -247,34 +266,32 @@ int party_check_exp_share(struct party *p) } // パーティが空かどうかチェック -int party_check_empty(struct party *p) +int party_check_empty(PartyPair p) { int i; -// PRINTF("party check empty %08X\n", (int)p); for (i = 0; i < MAX_PARTY; i++) { -// PRINTF("%d acc=%d\n", i, p->member[i].account_id); - if (p->member[i].account_id > 0) + if (p->member[i].account_id) { return 0; } } // 誰もいないので解散 - mapif_party_broken(p->party_id, 0); - party_db.erase(p->party_id); + mapif_party_broken(p.party_id, 0); + party_db.erase(p.party_id); return 1; } // キャラの競合がないかチェック用 static -void party_check_conflict_sub(struct party *p, - int party_id, int account_id, CharName nick) +void party_check_conflict_sub(PartyPair p, + PartyId party_id, AccountId account_id, CharName nick) { int i; - if (p->party_id == party_id) // 本来の所属なので問題なし + if (p.party_id == party_id) // 本来の所属なので問題なし return; for (i = 0; i < MAX_PARTY; i++) @@ -283,20 +300,25 @@ void party_check_conflict_sub(struct party *p, && p->member[i].name == nick) { // 別のパーティに偽の所属データがあるので脱退 - PRINTF("int_party: party conflict! %d %d %d\n", account_id, - party_id, p->party_id); - mapif_parse_PartyLeave(nullptr, p->party_id, account_id); + PRINTF("int_party: party conflict! %d %d %d\n"_fmt, account_id, + party_id, p.party_id); + mapif_parse_PartyLeave(nullptr, p.party_id, account_id); } } } // キャラの競合がないかチェック static -void party_check_conflict(int party_id, int account_id, CharName nick) +void party_check_conflict(PartyId party_id, AccountId account_id, CharName nick) { for (auto& pair : party_db) - party_check_conflict_sub(&pair.second, + { + PartyPair tmp; + tmp.party_id = pair.first; + tmp.party_most = &pair.second; + party_check_conflict_sub(tmp, party_id, account_id, nick); + } } //------------------------------------------------------------------- @@ -304,140 +326,156 @@ void party_check_conflict(int party_id, int account_id, CharName nick) // パーティ作成可否 static -void mapif_party_created(Session *s, int account_id, struct party *p) +void mapif_party_created(Session *s, AccountId account_id, PartyPair p) { - WFIFOW(s, 0) = 0x3820; - WFIFOL(s, 2) = account_id; - if (p != NULL) + Packet_Fixed<0x3820> fixed_20; + fixed_20.account_id = account_id; + if (p) { - WFIFOB(s, 6) = 0; - WFIFOL(s, 7) = p->party_id; - WFIFO_STRING(s, 11, p->name, 24); - PRINTF("int_party: created! %d %s\n", p->party_id, p->name); + fixed_20.error = 0; + fixed_20.party_id = p.party_id; + fixed_20.party_name = p->name; + PRINTF("int_party: created! %d %s\n"_fmt, p.party_id, p->name); } else { - WFIFOB(s, 6) = 1; - WFIFOL(s, 7) = 0; - WFIFO_STRING(s, 11, "error", 24); + fixed_20.error = 1; + fixed_20.party_id = PartyId(); + fixed_20.party_name = stringish<PartyName>("error"_s); } - WFIFOSET(s, 35); + send_fpacket<0x3820, 35>(s, fixed_20); } // パーティ情報見つからず static -void mapif_party_noinfo(Session *s, int party_id) +void mapif_party_noinfo(Session *s, PartyId party_id) { - WFIFOW(s, 0) = 0x3821; - WFIFOW(s, 2) = 8; - WFIFOL(s, 4) = party_id; - WFIFOSET(s, 8); - PRINTF("int_party: info not found %d\n", party_id); + Packet_Head<0x3821> head_21; + Packet_Option<0x3821> option_21; + head_21.party_id = party_id; + send_opacket<0x3821, 8, sizeof(NetPacket_Option<0x3821>)>(s, head_21, false, option_21); + PRINTF("int_party: info not found %d\n"_fmt, party_id); } // パーティ情報まとめ送り static -void mapif_party_info(Session *s, struct party *p) +void mapif_party_info(Session *s, PartyPair p) { - unsigned char buf[4 + sizeof(struct party)]; - - WBUFW(buf, 0) = 0x3821; - WBUF_STRUCT(buf, 4, *p); - WBUFW(buf, 2) = 4 + sizeof(struct party); + Packet_Head<0x3821> head_21; + head_21.party_id = p.party_id; + Packet_Option<0x3821> option_21; + option_21.party_most = *p.party_most; if (!s) - mapif_sendall(buf, WBUFW(buf, 2)); + { + for (Session *ss : iter_map_sessions()) + { + send_opacket<0x3821, 8, sizeof(NetPacket_Option<0x3821>)>(ss, head_21, true, option_21); + } + } else - mapif_send(s, buf, WBUFW(buf, 2)); -// PRINTF("int_party: info %d %s\n", p->party_id, p->name); + { + send_opacket<0x3821, 8, sizeof(NetPacket_Option<0x3821>)>(s, head_21, true, option_21); + } } // パーティメンバ追加可否 static -void mapif_party_memberadded(Session *s, int party_id, int account_id, int flag) +void mapif_party_memberadded(Session *s, PartyId party_id, AccountId account_id, int flag) { - WFIFOW(s, 0) = 0x3822; - WFIFOL(s, 2) = party_id; - WFIFOL(s, 6) = account_id; - WFIFOB(s, 10) = flag; - WFIFOSET(s, 11); + Packet_Fixed<0x3822> fixed_22; + fixed_22.party_id = party_id; + fixed_22.account_id = account_id; + fixed_22.flag = flag; + send_fpacket<0x3822, 11>(s, fixed_22); } // パーティ設定変更通知 static -void mapif_party_optionchanged(Session *s, struct party *p, int account_id, +void mapif_party_optionchanged(Session *s, PartyPair p, AccountId account_id, int flag) { - unsigned char buf[15]; - - WBUFW(buf, 0) = 0x3823; - WBUFL(buf, 2) = p->party_id; - WBUFL(buf, 6) = account_id; - WBUFW(buf, 10) = p->exp; - WBUFW(buf, 12) = p->item; - WBUFB(buf, 14) = flag; + Packet_Fixed<0x3823> fixed_23; + fixed_23.party_id = p.party_id; + fixed_23.account_id = account_id; + fixed_23.exp = p->exp; + fixed_23.item = p->item; + fixed_23.flag = flag; if (flag == 0) - mapif_sendall(buf, 15); + { + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x3823, 15>(ss, fixed_23); + } + } else - mapif_send(s, buf, 15); - PRINTF("int_party: option changed %d %d %d %d %d\n", p->party_id, + { + send_fpacket<0x3823, 15>(s, fixed_23); + } + PRINTF("int_party: option changed %d %d %d %d %d\n"_fmt, p.party_id, account_id, p->exp, p->item, flag); } // パーティ脱退通知 static -void mapif_party_leaved(int party_id, int account_id, CharName name) +void mapif_party_leaved(PartyId party_id, AccountId account_id, CharName name) { - unsigned char buf[34]; + Packet_Fixed<0x3824> fixed_24; + fixed_24.party_id = party_id; + fixed_24.account_id = account_id; + fixed_24.char_name = name; + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x3824, 34>(ss, fixed_24); + } - WBUFW(buf, 0) = 0x3824; - WBUFL(buf, 2) = party_id; - WBUFL(buf, 6) = account_id; - WBUF_STRING(buf, 10, name.to__actual(), 24); - mapif_sendall(buf, 34); - PRINTF("int_party: party leaved %d %d %s\n", party_id, account_id, name); + PRINTF("int_party: party leaved %d %d %s\n"_fmt, party_id, account_id, name); } // パーティマップ更新通知 static -void mapif_party_membermoved(struct party *p, int idx) +void mapif_party_membermoved(PartyPair p, int idx) { assert (idx < MAX_PARTY); - unsigned char buf[29]; - - WBUFW(buf, 0) = 0x3825; - WBUFL(buf, 2) = p->party_id; - WBUFL(buf, 6) = p->member[idx].account_id; - WBUF_STRING(buf, 10, p->member[idx].map, 16); - WBUFB(buf, 26) = p->member[idx].online; - WBUFW(buf, 27) = p->member[idx].lv; - mapif_sendall(buf, 29); + + Packet_Fixed<0x3825> fixed_25; + fixed_25.party_id = p.party_id; + fixed_25.account_id = p->member[idx].account_id; + fixed_25.map_name = p->member[idx].map; + fixed_25.online = p->member[idx].online; + fixed_25.level = p->member[idx].lv; + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x3825, 29>(ss, fixed_25); + } } // パーティ解散通知 -void mapif_party_broken(int party_id, int flag) -{ - unsigned char buf[7]; - WBUFW(buf, 0) = 0x3826; - WBUFL(buf, 2) = party_id; - WBUFB(buf, 6) = flag; - mapif_sendall(buf, 7); - PRINTF("int_party: broken %d\n", party_id); - CHAR_LOG("int_party: broken %d\n", party_id); +void mapif_party_broken(PartyId party_id, int flag) +{ + Packet_Fixed<0x3826> fixed_26; + fixed_26.party_id = party_id; + fixed_26.flag = flag; + for (Session *ss : iter_map_sessions()) + { + send_fpacket<0x3826, 7>(ss, fixed_26); + } + + PRINTF("int_party: broken %d\n"_fmt, party_id); + CHAR_LOG("int_party: broken %d\n"_fmt, party_id); } // パーティ内発言 static -void mapif_party_message(int party_id, int account_id, XString mes) +void mapif_party_message(PartyId party_id, AccountId account_id, XString mes) { - size_t len = mes.size() + 1; - unsigned char buf[len + 12]; - - WBUFW(buf, 0) = 0x3827; - WBUFW(buf, 2) = len + 12; - WBUFL(buf, 4) = party_id; - WBUFL(buf, 8) = account_id; - WBUF_STRING(buf, 12, mes, len); - mapif_sendall(buf, len + 12); + Packet_Head<0x3827> head_27; + XString repeat_27 = mes; + head_27.party_id = party_id; + head_27.account_id = account_id; + for (Session *ss : iter_map_sessions()) + { + send_vpacket<0x3827, 12, 1>(ss, head_27, repeat_27); + } } //------------------------------------------------------------------- @@ -445,26 +483,29 @@ void mapif_party_message(int party_id, int account_id, XString mes) // パーティ static -void mapif_parse_CreateParty(Session *s, int account_id, PartyName name, CharName nick, +void mapif_parse_CreateParty(Session *s, AccountId account_id, PartyName name, CharName nick, MapName map, int lv) { { if (!name.is_print()) { - PRINTF("int_party: illegal party name [%s]\n", name); - mapif_party_created(s, account_id, NULL); + PRINTF("int_party: illegal party name [%s]\n"_fmt, name); + mapif_party_created(s, account_id, PartyPair()); return; } } - if (search_partyname(name) != NULL) + if (search_partyname(name)) { - PRINTF("int_party: same name party exists [%s]\n", name); - mapif_party_created(s, account_id, NULL); + PRINTF("int_party: same name party exists [%s]\n"_fmt, name); + mapif_party_created(s, account_id, PartyPair()); return; } - struct party p {}; - p.party_id = party_newid++; + PartyMost p {}; + PartyPair pp; + pp.party_most = &p; + party_newid = next(party_newid); + pp.party_id = party_newid; p.name = name; p.exp = 0; p.item = 0; @@ -475,18 +516,19 @@ void mapif_parse_CreateParty(Session *s, int account_id, PartyName name, CharNam p.member[0].online = 1; p.member[0].lv = lv; - party_db.insert(p.party_id, p); + party_db.insert(pp.party_id, p); - mapif_party_created(s, account_id, &p); - mapif_party_info(s, &p); + mapif_party_created(s, account_id, pp); + mapif_party_info(s, pp); } // パーティ情報要求 static -void mapif_parse_PartyInfo(Session *s, int party_id) +void mapif_parse_PartyInfo(Session *s, PartyId party_id) { - struct party *p = party_db.search(party_id); - if (p != NULL) + PartyPair p; + p.party_most = party_db.search(party_id); + if (p) mapif_party_info(s, p); else mapif_party_noinfo(s, party_id); @@ -494,11 +536,12 @@ void mapif_parse_PartyInfo(Session *s, int party_id) // パーティ追加要求 static -void mapif_parse_PartyAddMember(Session *s, int party_id, int account_id, +void mapif_parse_PartyAddMember(Session *s, PartyId party_id, AccountId account_id, CharName nick, MapName map, int lv) { - struct party *p = party_db.search(party_id); - if (p == NULL) + PartyPair p; + p.party_most = party_db.search(party_id); + if (!p) { mapif_party_memberadded(s, party_id, account_id, 1); return; @@ -506,7 +549,7 @@ void mapif_parse_PartyAddMember(Session *s, int party_id, int account_id, for (int i = 0; i < MAX_PARTY; i++) { - if (p->member[i].account_id == 0) + if (!p->member[i].account_id) { int flag = 0; @@ -525,7 +568,7 @@ void mapif_parse_PartyAddMember(Session *s, int party_id, int account_id, flag = 0x01; } if (flag) - mapif_party_optionchanged(s, p, 0, 0); + mapif_party_optionchanged(s, p, AccountId(), 0); return; } } @@ -534,11 +577,12 @@ void mapif_parse_PartyAddMember(Session *s, int party_id, int account_id, // パーティー設定変更要求 static -void mapif_parse_PartyChangeOption(Session *s, int party_id, int account_id, +void mapif_parse_PartyChangeOption(Session *s, PartyId party_id, AccountId account_id, int exp, int item) { - struct party *p = party_db.search(party_id); - if (p == NULL) + PartyPair p; + p.party_most = party_db.search(party_id); + if (!p) return; p->exp = exp; @@ -555,9 +599,10 @@ void mapif_parse_PartyChangeOption(Session *s, int party_id, int account_id, } // パーティ脱退要求 -void mapif_parse_PartyLeave(Session *, int party_id, int account_id) +void mapif_parse_PartyLeave(Session *, PartyId party_id, AccountId account_id) { - struct party *p = party_db.search(party_id); + PartyPair p; + p.party_most = party_db.search(party_id); if (!p) return; for (int i = 0; i < MAX_PARTY; i++) @@ -566,7 +611,7 @@ void mapif_parse_PartyLeave(Session *, int party_id, int account_id) continue; mapif_party_leaved(party_id, account_id, p->member[i].name); - p->member[i] = party_member{}; + p->member[i] = PartyMember{}; if (party_check_empty(p) == 0) mapif_party_info(nullptr, p); // まだ人がいるのでデータ送信 return; @@ -575,11 +620,12 @@ void mapif_parse_PartyLeave(Session *, int party_id, int account_id) // パーティマップ更新要求 static -void mapif_parse_PartyChangeMap(Session *s, int party_id, int account_id, +void mapif_parse_PartyChangeMap(Session *s, PartyId party_id, AccountId account_id, MapName map, int online, int lv) { - struct party *p = party_db.search(party_id); - if (p == NULL) + PartyPair p; + p.party_most = party_db.search(party_id); + if (!p) return; for (int i = 0; i < MAX_PARTY; i++) @@ -599,33 +645,21 @@ void mapif_parse_PartyChangeMap(Session *s, int party_id, int account_id, flag = 1; } if (flag) - mapif_party_optionchanged(s, p, 0, 0); + mapif_party_optionchanged(s, p, AccountId(), 0); return; } } -// パーティ解散要求 -static -void mapif_parse_BreakParty(Session *, int party_id) -{ - struct party *p = party_db.search(party_id); - if (p == NULL) - return; - - party_db.erase(party_id); - mapif_party_broken(party_id, 0 /*unknown*/); -} - // パーティメッセージ送信 static -void mapif_parse_PartyMessage(Session *, int party_id, int account_id, XString mes) +void mapif_parse_PartyMessage(Session *, PartyId party_id, AccountId account_id, XString mes) { mapif_party_message(party_id, account_id, mes); } // パーティチェック要求 static -void mapif_parse_PartyCheck(Session *, int party_id, int account_id, CharName nick) +void mapif_parse_PartyCheck(Session *, PartyId party_id, AccountId account_id, CharName nick) { party_check_conflict(party_id, account_id, nick); } @@ -635,121 +669,157 @@ void mapif_parse_PartyCheck(Session *, int party_id, int account_id, CharName ni // ・パケット長データはinter.cにセットしておくこと // ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない // ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない -int inter_party_parse_frommap(Session *ms) +RecvResult inter_party_parse_frommap(Session *ms, uint16_t packet_id) { - switch (RFIFOW(ms, 0)) + RecvResult rv = RecvResult::Error; + switch (packet_id) { case 0x3020: { - int account = RFIFOL(ms, 2); - PartyName name = stringish<PartyName>(RFIFO_STRING<24>(ms, 6)); - CharName nick = stringish<CharName>(RFIFO_STRING<24>(ms, 30)); - MapName map = RFIFO_STRING<16>(ms, 54); - uint16_t lv = RFIFOW(ms, 70); + Packet_Fixed<0x3020> fixed; + rv = recv_fpacket<0x3020, 72>(ms, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account = fixed.account_id; + PartyName name = fixed.party_name; + CharName nick = fixed.char_name; + MapName map = fixed.map_name; + uint16_t lv = fixed.level; mapif_parse_CreateParty(ms, account, name, nick, map, lv); - } break; + } case 0x3021: { - int party_id = RFIFOL(ms, 2); + Packet_Fixed<0x3021> fixed; + rv = recv_fpacket<0x3021, 6>(ms, fixed); + if (rv != RecvResult::Complete) + break; + + PartyId party_id = fixed.party_id; mapif_parse_PartyInfo(ms, party_id); - } break; + } case 0x3022: { - int party_id = RFIFOL(ms, 2); - int account_id = RFIFOL(ms, 6); - CharName nick = stringish<CharName>(RFIFO_STRING<24>(ms, 10)); - MapName map = RFIFO_STRING<16>(ms, 34); - uint16_t lv = RFIFOW(ms, 50); + Packet_Fixed<0x3022> fixed; + rv = recv_fpacket<0x3022, 52>(ms, fixed); + if (rv != RecvResult::Complete) + break; + + PartyId party_id = fixed.party_id; + AccountId account_id = fixed.account_id; + CharName nick = fixed.char_name; + MapName map = fixed.map_name; + uint16_t lv = fixed.level; mapif_parse_PartyAddMember(ms, party_id, account_id, nick, map, lv); - } break; + } case 0x3023: { - int party_id = RFIFOL(ms, 2); - int account_id = RFIFOL(ms, 6); - uint16_t exp = RFIFOW(ms, 10); - uint16_t item = RFIFOW(ms, 12); + Packet_Fixed<0x3023> fixed; + rv = recv_fpacket<0x3023, 14>(ms, fixed); + if (rv != RecvResult::Complete) + break; + + PartyId party_id = fixed.party_id; + AccountId account_id = fixed.account_id; + uint16_t exp = fixed.exp; + uint16_t item = fixed.item; mapif_parse_PartyChangeOption(ms, party_id, account_id, exp, item); - } break; + } case 0x3024: { - int party_id = RFIFOL(ms, 2); - int account_id = RFIFOL(ms, 6); + Packet_Fixed<0x3024> fixed; + rv = recv_fpacket<0x3024, 10>(ms, fixed); + if (rv != RecvResult::Complete) + break; + + PartyId party_id = fixed.party_id; + AccountId account_id = fixed.account_id; mapif_parse_PartyLeave(ms, party_id, account_id); - } break; + } case 0x3025: { - int party_id = RFIFOL(ms, 2); - int account_id = RFIFOL(ms, 6); - MapName map = RFIFO_STRING<16>(ms, 10); - uint8_t online = RFIFOB(ms, 26); - uint16_t lv = RFIFOW(ms, 27); + Packet_Fixed<0x3025> fixed; + rv = recv_fpacket<0x3025, 29>(ms, fixed); + if (rv != RecvResult::Complete) + break; + + PartyId party_id = fixed.party_id; + AccountId account_id = fixed.account_id; + MapName map = fixed.map_name; + uint8_t online = fixed.online; + uint16_t lv = fixed.level; mapif_parse_PartyChangeMap(ms, party_id, account_id, map, online, lv); - } break; - case 0x3026: - { - int party_id = RFIFOL(ms, 2); - mapif_parse_BreakParty(ms, party_id); } - break; case 0x3027: { - size_t len = RFIFOW(ms, 2) - 12; - int party_id = RFIFOL(ms, 4); - int account_id = RFIFOL(ms, 8); - AString mes = RFIFO_STRING(ms, 12, len); + Packet_Head<0x3027> head; + AString repeat; + rv = recv_vpacket<0x3027, 12, 1>(ms, head, repeat); + if (rv != RecvResult::Complete) + break; + + PartyId party_id = head.party_id; + AccountId account_id = head.account_id; + AString& mes = repeat; mapif_parse_PartyMessage(ms, party_id, account_id, mes); - } break; + } case 0x3028: { - int party_id = RFIFOL(ms, 2); - int account_id = RFIFOL(ms, 6); - CharName nick = stringish<CharName>(RFIFO_STRING<24>(ms, 10)); + Packet_Fixed<0x3028> fixed; + rv = recv_fpacket<0x3028, 34>(ms, fixed); + if (rv != RecvResult::Complete) + break; + + PartyId party_id = fixed.party_id; + AccountId account_id = fixed.account_id; + CharName nick = fixed.char_name; mapif_parse_PartyCheck(ms, party_id, account_id, nick); - } break; + } default: - return 0; + return RecvResult::Error; } - return 1; + return rv; } // サーバーから脱退要求(キャラ削除用) -void inter_party_leave(int party_id, int account_id) +void inter_party_leave(PartyId party_id, AccountId account_id) { mapif_parse_PartyLeave(nullptr, party_id, account_id); } +} // namespace tmwa diff --git a/src/char/int_party.hpp b/src/char/int_party.hpp index 1608c37..f33fc0d 100644 --- a/src/char/int_party.hpp +++ b/src/char/int_party.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_CHAR_INT_PARTY_HPP -#define TMWA_CHAR_INT_PARTY_HPP +#pragma once // int_party.hpp - Internal party handling. // // Copyright © ????-2004 Athena Dev Teams @@ -21,19 +20,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -struct Session; +#include "../net/fwd.hpp" +#include "../mmo/fwd.hpp" + + +namespace tmwa +{ void inter_party_init(void); int inter_party_save(void); -int inter_party_parse_frommap(Session *ms); +RecvResult inter_party_parse_frommap(Session *ms, uint16_t); -void inter_party_leave(int party_id, int account_id); +void inter_party_leave(PartyId party_id, AccountId account_id); extern AString party_txt; - -#endif // TMWA_CHAR_INT_PARTY_HPP +} // namespace tmwa diff --git a/src/char/int_storage.cpp b/src/char/int_storage.cpp index c7c1343..01665ec 100644 --- a/src/char/int_storage.cpp +++ b/src/char/int_storage.cpp @@ -20,50 +20,54 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <cstdlib> -#include <cstring> - -#include <functional> - #include "../strings/mstring.hpp" #include "../strings/astring.hpp" #include "../strings/xstring.hpp" +#include "../strings/literal.hpp" #include "../generic/db.hpp" #include "../io/cxxstdio.hpp" #include "../io/lock.hpp" #include "../io/read.hpp" +#include "../io/write.hpp" + +#include "../net/packets.hpp" + +#include "../proto2/char-map.hpp" #include "../mmo/extract.hpp" #include "../mmo/mmo.hpp" -#include "../mmo/socket.hpp" #include "../poison.hpp" + +namespace tmwa +{ // ファイル名のデフォルト // inter_config_read()で再設定される -AString storage_txt = "save/storage.txt"; +AString storage_txt = "save/storage.txt"_s; static -Map<int, struct storage> storage_db; +Map<AccountId, Storage> storage_db; // 倉庫データを文字列に変換 static -AString storage_tostr(struct storage *p) +AString storage_tostr(Storage *p) { MString str; str += STRPRINTF( - "%d,%d\t", + "%d,%d\t"_fmt, p->account_id, p->storage_amount); int f = 0; - for (int i = 0; i < MAX_STORAGE; i++) + for (SOff0 i : SOff0::iter()) + { if (p->storage_[i].nameid && p->storage_[i].amount) { str += STRPRINTF( - "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ", - p->storage_[i].id, + "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d "_fmt, + 0 /*id*/, p->storage_[i].nameid, p->storage_[i].amount, p->storage_[i].equip, @@ -77,6 +81,7 @@ AString storage_tostr(struct storage *p) // shouldn't that include 'broken' also? Oh, well ... f++; } + } str += '\t'; @@ -87,9 +92,9 @@ AString storage_tostr(struct storage *p) // 文字列を倉庫データに変換 static -bool extract(XString str, struct storage *p) +bool extract(XString str, Storage *p) { - std::vector<struct item> storage_items; + std::vector<Item> storage_items; if (!extract(str, record<'\t'>( record<','>( @@ -98,7 +103,7 @@ bool extract(XString str, struct storage *p) vrec<' '>(&storage_items)))) return false; - if (p->account_id <= 0) + if (!p->account_id) return false; if (storage_items.size() > MAX_STORAGE) @@ -106,15 +111,15 @@ bool extract(XString str, struct storage *p) std::copy(storage_items.begin(), storage_items.end(), p->storage_.begin()); if (p->storage_amount != storage_items.size()) - PRINTF("WARNING: storage desync for %d\n", p->account_id); + PRINTF("WARNING: storage desync for %d\n"_fmt, p->account_id); return true; } // アカウントから倉庫データインデックスを得る(新規倉庫追加可能) -struct storage *account2storage(int account_id) +Storage *account2storage(AccountId account_id) { - struct storage *s = storage_db.search(account_id); - if (s == NULL) + Storage *s = storage_db.search(account_id); + if (s == nullptr) { s = storage_db.init(account_id); s->account_id = account_id; @@ -131,21 +136,21 @@ void inter_storage_init(void) io::ReadFile in(storage_txt); if (!in.is_open()) { - PRINTF("cant't read : %s\n", storage_txt); + PRINTF("cant't read : %s\n"_fmt, storage_txt); return; } AString line; while (in.getline(line)) { - struct storage s {}; + Storage s {}; if (extract(line, &s)) { storage_db.insert(s.account_id, s); } else { - PRINTF("int_storage: broken data [%s] line %d\n", + PRINTF("int_storage: broken data [%s] line %d\n"_fmt, storage_txt, c); } c++; @@ -153,7 +158,7 @@ void inter_storage_init(void) } static -void inter_storage_save_sub(struct storage *data, io::WriteFile& fp) +void inter_storage_save_sub(Storage *data, io::WriteFile& fp) { AString line = storage_tostr(data); if (line) @@ -168,7 +173,7 @@ int inter_storage_save(void) if (!fp.is_open()) { - PRINTF("int_storage: cant write [%s] !!! data is lost !!!\n", + PRINTF("int_storage: cant write [%s] !!! data is lost !!!\n"_fmt, storage_txt); return 1; } @@ -178,7 +183,7 @@ int inter_storage_save(void) } // 倉庫データ削除 -void inter_storage_delete(int account_id) +void inter_storage_delete(AccountId account_id) { storage_db.erase(account_id); } @@ -188,54 +193,62 @@ void inter_storage_delete(int account_id) // 倉庫データの送信 static -void mapif_load_storage(Session *ss, int account_id) +void mapif_load_storage(Session *ss, AccountId account_id) { - struct storage *st = account2storage(account_id); - WFIFOW(ss, 0) = 0x3810; - WFIFOW(ss, 2) = sizeof(struct storage) + 8; - WFIFOL(ss, 4) = account_id; - WFIFO_STRUCT(ss, 8, *st); - WFIFOSET(ss, WFIFOW(ss, 2)); + Storage *st = account2storage(account_id); + Packet_Payload<0x3810> payload_10; + payload_10.account_id = account_id; + payload_10.storage = *st; + send_ppacket<0x3810>(ss, payload_10); } // 倉庫データ保存完了送信 static -void mapif_save_storage_ack(Session *ss, int account_id) +void mapif_save_storage_ack(Session *ss, AccountId account_id) { - WFIFOW(ss, 0) = 0x3811; - WFIFOL(ss, 2) = account_id; - WFIFOB(ss, 6) = 0; - WFIFOSET(ss, 7); + Packet_Fixed<0x3811> fixed_11; + fixed_11.account_id = account_id; + fixed_11.unknown = 0; + send_fpacket<0x3811, 7>(ss, fixed_11); } //--------------------------------------------------------- // map serverからの通信 // 倉庫データ要求受信 -static -void mapif_parse_LoadStorage(Session *ss) +static __attribute__((warn_unused_result)) +RecvResult mapif_parse_LoadStorage(Session *ss) { - mapif_load_storage(ss, RFIFOL(ss, 2)); + Packet_Fixed<0x3010> fixed; + RecvResult rv = recv_fpacket<0x3010, 6>(ss, fixed); + if (rv != RecvResult::Complete) + return rv; + + AccountId account_id = fixed.account_id; + mapif_load_storage(ss, account_id); + + return rv; } // 倉庫データ受信&保存 -static -void mapif_parse_SaveStorage(Session *ss) +static __attribute__((warn_unused_result)) +RecvResult mapif_parse_SaveStorage(Session *ss) { - struct storage *st; - int account_id = RFIFOL(ss, 4); - int len = RFIFOW(ss, 2); - if (sizeof(struct storage) != len - 8) - { - PRINTF("inter storage: data size error %zu %d\n", - sizeof(struct storage), len - 8); - } - else + Packet_Payload<0x3011> payload; + RecvResult rv = recv_ppacket<0x3011>(ss, payload); + if (rv != RecvResult::Complete) + return rv; + + Storage *st; + AccountId account_id = payload.account_id; + { st = account2storage(account_id); - RFIFO_STRUCT(ss, 8, *st); + *st = payload.storage; mapif_save_storage_ack(ss, account_id); } + + return rv; } // map server からの通信 @@ -243,18 +256,20 @@ void mapif_parse_SaveStorage(Session *ss) // ・パケット長データはinter.cにセットしておくこと // ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない // ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない -int inter_storage_parse_frommap(Session *ms) +RecvResult inter_storage_parse_frommap(Session *ms, uint16_t packet_id) { - switch (RFIFOW(ms, 0)) + RecvResult rv; + switch (packet_id) { case 0x3010: - mapif_parse_LoadStorage(ms); + rv = mapif_parse_LoadStorage(ms); break; case 0x3011: - mapif_parse_SaveStorage(ms); + rv = mapif_parse_SaveStorage(ms); break; default: - return 0; + return RecvResult::Error; } - return 1; + return rv; } +} // namespace tmwa diff --git a/src/char/int_storage.hpp b/src/char/int_storage.hpp index 7f6deb5..b8ec9db 100644 --- a/src/char/int_storage.hpp +++ b/src/char/int_storage.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_CHAR_INT_STORAGE_HPP -#define TMWA_CHAR_INT_STORAGE_HPP +#pragma once // int_storage.hpp - Internal storage handling. // // Copyright © ????-2004 Athena Dev Teams @@ -21,19 +20,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -struct Session; +#include "../net/fwd.hpp" +#include "../mmo/fwd.hpp" + + +namespace tmwa +{ void inter_storage_init(void); int inter_storage_save(void); -void inter_storage_delete(int account_id); -struct storage *account2storage(int account_id); +void inter_storage_delete(AccountId account_id); +Storage *account2storage(AccountId account_id); -int inter_storage_parse_frommap(Session *ms); +RecvResult inter_storage_parse_frommap(Session *ms, uint16_t); extern AString storage_txt; - -#endif // TMWA_CHAR_INT_STORAGE_HPP +} // namespace tmwa diff --git a/src/char/inter.cpp b/src/char/inter.cpp index 204a0e2..1cf41ff 100644 --- a/src/char/inter.cpp +++ b/src/char/inter.cpp @@ -21,8 +21,6 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include <cassert> -#include <cstdlib> -#include <cstring> #include <vector> @@ -30,18 +28,22 @@ #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" +#include "../strings/literal.hpp" +#include "../generic/array.hpp" #include "../generic/db.hpp" #include "../io/cxxstdio.hpp" #include "../io/lock.hpp" #include "../io/read.hpp" +#include "../io/write.hpp" + +#include "../net/packets.hpp" + +#include "../proto2/char-map.hpp" -#include "../mmo/config_parse.hpp" #include "../mmo/extract.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" -#include "../mmo/utils.hpp" +#include "../mmo/mmo.hpp" #include "char.hpp" #include "int_party.hpp" @@ -49,34 +51,23 @@ #include "../poison.hpp" + +namespace tmwa +{ static -AString accreg_txt = "save/accreg.txt"; +AString accreg_txt = "save/accreg.txt"_s; struct accreg { - int account_id, reg_num; - Array<struct global_reg, ACCOUNT_REG_NUM> reg; + AccountId account_id; + int reg_num; + Array<GlobalReg, ACCOUNT_REG_NUM> reg; }; static -Map<int, struct accreg> accreg_db; +Map<AccountId, struct accreg> accreg_db; int party_share_level = 10; -// 受信パケット長リスト -static -int inter_recv_packet_length[] = -{ - -1, -1, 7, -1, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, -1, 0, 0, 0, 0, 0, 0, 10, -1, 0, 0, 0, 0, 0, 0, - 72, 6, 52, 14, 10, 29, 6, -1, 34, 0, 0, 0, 0, 0, 0, 0, - -1, 6, -1, 0, 55, 19, 6, -1, 14, -1, -1, -1, 14, 19, 186, -1, - 5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 14, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - //-------------------------------------------------------- // アカウント変数を文字列へ変換 @@ -85,9 +76,9 @@ AString inter_accreg_tostr(struct accreg *reg) { assert(reg->reg_num < ACCOUNT_REG_NUM); MString str; - str += STRPRINTF("%d\t", reg->account_id); + str += STRPRINTF("%d\t"_fmt, reg->account_id); for (int j = 0; j < reg->reg_num; j++) - str += STRPRINTF("%s,%d ", reg->reg[j].str, reg->reg[j].value); + str += STRPRINTF("%s,%d "_fmt, reg->reg[j].str, reg->reg[j].value); return AString(str); } @@ -95,13 +86,13 @@ AString inter_accreg_tostr(struct accreg *reg) static bool extract(XString str, struct accreg *reg) { - std::vector<struct global_reg> vars; + std::vector<GlobalReg> vars; if (!extract(str, record<'\t'>( ®->account_id, vrec<' '>(&vars)))) return false; - if (reg->account_id <= 0) + if (!reg->account_id) return false; if (vars.size() > ACCOUNT_REG_NUM) @@ -130,7 +121,7 @@ void inter_accreg_init(void) } else { - PRINTF("inter: accreg: broken data [%s] line %d\n", accreg_txt, + PRINTF("inter: accreg: broken data [%s] line %d\n"_fmt, accreg_txt, c); } c++; @@ -155,7 +146,7 @@ int inter_accreg_save(void) io::WriteLock fp(accreg_txt); if (!fp.is_open()) { - PRINTF("int_accreg: cant write [%s] !!! data is lost !!!\n", + PRINTF("int_accreg: cant write [%s] !!! data is lost !!!\n"_fmt, accreg_txt); return 1; } @@ -168,19 +159,19 @@ int inter_accreg_save(void) bool inter_config(XString w1, ZString w2) { { - if (w1 == "storage_txt") + if (w1 == "storage_txt"_s) { storage_txt = w2; } - else if (w1 == "party_txt") + else if (w1 == "party_txt"_s) { party_txt = w2; } - else if (w1 == "accreg_txt") + else if (w1 == "accreg_txt"_s) { accreg_txt = w2; } - else if (w1 == "party_share_level") + else if (w1 == "party_share_level"_s) { party_share_level = atoi(w2.c_str()); if (party_share_level < 0) @@ -218,14 +209,10 @@ void inter_init2() static void mapif_GMmessage(XString mes) { - size_t str_len = mes.size() + 1; - size_t msg_len = str_len + 4; - uint8_t buf[msg_len]; - - WBUFW(buf, 0) = 0x3800; - WBUFW(buf, 2) = msg_len; - WBUF_STRING(buf, 4, mes, str_len); - mapif_sendall(buf, msg_len); + for (Session *ss : iter_map_sessions()) + { + send_packet_repeatonly<0x3800, 4, 1>(ss, mes); + } } // Wisp/page transmission to correct map-server @@ -235,103 +222,105 @@ void mapif_wis_message(Session *tms, CharName src, CharName dst, XString msg) const CharPair *mcs = search_character(src); assert (mcs); - size_t str_size = msg.size() + 1; - uint8_t buf[56 + str_size]; - - WBUFW(buf, 0) = 0x3801; - WBUFW(buf, 2) = 56 + str_size; - WBUFL(buf, 4) = mcs->key.char_id; // formerly, whisper ID - WBUF_STRING(buf, 8, src.to__actual(), 24); - WBUF_STRING(buf, 32, dst.to__actual(), 24); - WBUF_STRING(buf, 56, msg, str_size); - mapif_send(tms, buf, WBUFW(buf, 2)); + Packet_Head<0x3801> head_01; + head_01.whisper_id = mcs->key.char_id; + head_01.src_char_name = src; + head_01.dst_char_name = dst; + send_vpacket<0x3801, 56, 1>(tms, head_01, msg); } // Wisp/page transmission result to map-server static void mapif_wis_end(Session *sms, CharName sender, int flag) { - uint8_t buf[27]; - - WBUFW(buf, 0) = 0x3802; - WBUF_STRING(buf, 2, sender.to__actual(), 24); - WBUFB(buf, 26) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - mapif_send(sms, buf, 27); + Packet_Fixed<0x3802> fixed_02; + fixed_02.sender_char_name = sender; + fixed_02.flag = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + send_fpacket<0x3802, 27>(sms, fixed_02); } // アカウント変数送信 static -void mapif_account_reg(Session *s) +void mapif_account_reg(Session *s, AccountId account_id, const std::vector<Packet_Repeat<0x3004>>& repeat) { - size_t len = RFIFOW(s, 2); - uint8_t buf[len]; - RFIFO_BUF_CLONE(s, buf, len); - WBUFW(buf, 0) = 0x3804; - mapif_sendallwos(s, buf, WBUFW(buf, 2)); + Packet_Head<0x3804> head_04; + head_04.account_id = account_id; + std::vector<Packet_Repeat<0x3804>> repeat_04(repeat.size()); + for (size_t i = 0; i < repeat.size(); ++i) + { + repeat_04[i].name = repeat[i].name; + repeat_04[i].value = repeat[i].value; + } + + for (Session *ss : iter_map_sessions()) + { + if (ss == s) + continue; + send_vpacket<0x3804, 8, 36>(ss, head_04, repeat_04); + } } // アカウント変数要求返信 static -void mapif_account_reg_reply(Session *s, int account_id) +void mapif_account_reg_reply(Session *s, AccountId account_id) { struct accreg *reg = accreg_db.search(account_id); - WFIFOW(s, 0) = 0x3804; - WFIFOL(s, 4) = account_id; - if (reg == NULL) - { - WFIFOW(s, 2) = 8; - } - else + Packet_Head<0x3804> head_04; + head_04.account_id = account_id; + std::vector<Packet_Repeat<0x3804>> repeat_04; + if (reg) { + repeat_04.resize(reg->reg_num); assert (reg->reg_num < ACCOUNT_REG_NUM); - int j, p; - for (j = 0, p = 8; j < reg->reg_num; j++, p += 36) + for (size_t j = 0; j < reg->reg_num; ++j) { - WFIFO_STRING(s, p, reg->reg[j].str, 32); - WFIFOL(s, p + 32) = reg->reg[j].value; + repeat_04[j].name = reg->reg[j].str; + repeat_04[j].value = reg->reg[j].value; } - WFIFOW(s, 2) = p; } - WFIFOSET(s, WFIFOW(s, 2)); + send_vpacket<0x3804, 8, 36>(s, head_04, repeat_04); } //-------------------------------------------------------- // received packets from map-server // GMメッセージ送信 -static -void mapif_parse_GMmessage(Session *s) +static __attribute__((warn_unused_result)) +RecvResult mapif_parse_GMmessage(Session *s) { - size_t msg_len = RFIFOW(s, 2); - size_t str_len = msg_len - 4; - AString buf = RFIFO_STRING(s, 4, str_len); + AString repeat; + RecvResult rv = recv_packet_repeatonly<0x3000, 4, 1>(s, repeat); + if (rv != RecvResult::Complete) + return rv; + AString& buf = repeat; mapif_GMmessage(buf); + + return rv; } // Wisp/page request to send -static -void mapif_parse_WisRequest(Session *sms) +static __attribute__((warn_unused_result)) +RecvResult mapif_parse_WisRequest(Session *sms) { - if (RFIFOW(sms, 2) - 52 <= 0) - { // normaly, impossible, but who knows... - PRINTF("inter: Wis message doesn't exist.\n"); - return; - } + Packet_Head<0x3001> head; + AString repeat; + RecvResult rv = recv_vpacket<0x3001, 52, 1>(sms, head, repeat); + if (rv != RecvResult::Complete) + return rv; - CharName from = stringish<CharName>(RFIFO_STRING<24>(sms, 4)); - CharName to = stringish<CharName>(RFIFO_STRING<24>(sms, 28)); + CharName from = head.from_char_name; + CharName to = head.to_char_name; // search if character exists before to ask all map-servers const CharPair *mcs = search_character(to); if (!mcs) { - uint8_t buf[27]; - WBUFW(buf, 0) = 0x3802; - WBUF_STRING(buf, 2, from.to__actual(), 24); - WBUFB(buf, 26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - mapif_send(sms, buf, 27); + Packet_Fixed<0x3802> fixed_02; + fixed_02.sender_char_name = from; + fixed_02.flag = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + send_fpacket<0x3802, 27>(sms, fixed_02); // Character exists. So, ask all map-servers } else @@ -341,17 +330,15 @@ void mapif_parse_WisRequest(Session *sms) // if source is destination, don't ask other servers. if (from == to) { - uint8_t buf[27]; - WBUFW(buf, 0) = 0x3802; - WBUF_STRING(buf, 2, from.to__actual(), 24); - WBUFB(buf, 26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - mapif_send(sms, buf, 27); + Packet_Fixed<0x3802> fixed_02; + fixed_02.sender_char_name = from; + fixed_02.flag = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + send_fpacket<0x3802, 27>(sms, fixed_02); } else { - size_t len = RFIFOW(sms, 2) - 52; Session *tms = server_for(mcs); // for to - AString msg = RFIFO_STRING(sms, 52, len); + AString& msg = repeat; if (tms) { mapif_wis_message(tms, from, to, msg); @@ -362,68 +349,99 @@ void mapif_parse_WisRequest(Session *sms) } } } + + return rv; } // Wisp/page transmission result -static -int mapif_parse_WisReply(Session *tms) +static __attribute__((warn_unused_result)) +RecvResult mapif_parse_WisReply(Session *tms) { - int id = RFIFOL(tms, 2), flag = RFIFOB(tms, 6); + Packet_Fixed<0x3002> fixed; + RecvResult rv = recv_fpacket<0x3002, 7>(tms, fixed); + if (rv != RecvResult::Complete) + return rv; + + CharId id = fixed.char_id; + uint8_t flag = fixed.flag; const CharPair *smcs = search_character_id(id); CharName from = smcs->key.name; Session *sms = server_for(smcs); + { mapif_wis_end(sms, from, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target } - return 0; + return rv; } // Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers) -static -void mapif_parse_WisToGM(Session *s) +static __attribute__((warn_unused_result)) +RecvResult mapif_parse_WisToGM(Session *s) { - size_t len = RFIFOW(s, 2); - uint8_t buf[len]; - // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B + Packet_Head<0x3003> head; + AString repeat; + RecvResult rv = recv_vpacket<0x3003, 30, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + return rv; + + Packet_Head<0x3803> head_03; + head_03.char_name = head.char_name; + head_03.min_gm_level = head.min_gm_level; + for (Session *ss : iter_map_sessions()) + { + send_vpacket<0x3803, 30, 1>(ss, head_03, repeat); + } - RFIFO_BUF_CLONE(s, buf, len); - WBUFW(buf, 0) = 0x3803; - mapif_sendall(buf, len); + return rv; } // アカウント変数保存要求 -static -void mapif_parse_AccReg(Session *s) +static __attribute__((warn_unused_result)) +RecvResult mapif_parse_AccReg(Session *s) { - int j, p; - struct accreg *reg = accreg_db.search(RFIFOL(s, 4)); + Packet_Head<0x3004> head; + std::vector<Packet_Repeat<0x3004>> repeat; + RecvResult rv = recv_vpacket<0x3004, 8, 36>(s, head, repeat); + if (rv != RecvResult::Complete) + return rv; + + struct accreg *reg = accreg_db.search(head.account_id); - if (reg == NULL) + if (reg == nullptr) { - int account_id = RFIFOL(s, 4); + AccountId account_id = head.account_id; reg = accreg_db.init(account_id); reg->account_id = account_id; } - for (j = 0, p = 8; j < ACCOUNT_REG_NUM && p < RFIFOW(s, 2); - j++, p += 36) + size_t jlim = std::min(repeat.size(), ACCOUNT_REG_NUM); + for (size_t j = 0; j < jlim; ++j) { - reg->reg[j].str = stringish<VarName>(RFIFO_STRING<32>(s, p)); - reg->reg[j].value = RFIFOL(s, p + 32); + reg->reg[j].str = repeat[j].name; + reg->reg[j].value = repeat[j].value; } - reg->reg_num = j; + reg->reg_num = jlim; // 他のMAPサーバーに送信 - mapif_account_reg(s); + mapif_account_reg(s, head.account_id, repeat); + + return rv; } // アカウント変数送信要求 -static -void mapif_parse_AccRegRequest(Session *s) +static __attribute__((warn_unused_result)) +RecvResult mapif_parse_AccRegRequest(Session *s) { - mapif_account_reg_reply(s, RFIFOL(s, 2)); + Packet_Fixed<0x3005> fixed; + RecvResult rv = recv_fpacket<0x3005, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + mapif_account_reg_reply(s, fixed.account_id); + + return rv; } //-------------------------------------------------------- @@ -431,70 +449,42 @@ void mapif_parse_AccRegRequest(Session *s) // map server からの通信(1パケットのみ解析すること) // エラーなら0(false)、処理できたなら1、 // パケット長が足りなければ2をかえさなければならない -int inter_parse_frommap(Session *ms) +RecvResult inter_parse_frommap(Session *ms, uint16_t packet_id) { - int cmd = RFIFOW(ms, 0); - int len = 0; - - // inter鯖管轄かを調べる - if (cmd < 0x3000 - || cmd >= - 0x3000 + - (sizeof(inter_recv_packet_length) / - sizeof(inter_recv_packet_length[0]))) - return 0; - - // パケット長を調べる - if ((len = - inter_check_length(ms, - inter_recv_packet_length[cmd - 0x3000])) == 0) - return 2; + int cmd = packet_id; + + RecvResult rv; switch (cmd) { case 0x3000: - mapif_parse_GMmessage(ms); + rv = mapif_parse_GMmessage(ms); break; case 0x3001: - mapif_parse_WisRequest(ms); + rv = mapif_parse_WisRequest(ms); break; case 0x3002: - mapif_parse_WisReply(ms); + rv = mapif_parse_WisReply(ms); break; case 0x3003: - mapif_parse_WisToGM(ms); + rv = mapif_parse_WisToGM(ms); break; case 0x3004: - mapif_parse_AccReg(ms); + rv = mapif_parse_AccReg(ms); break; case 0x3005: - mapif_parse_AccRegRequest(ms); + rv = mapif_parse_AccRegRequest(ms); break; default: - if (inter_party_parse_frommap(ms)) - break; - if (inter_storage_parse_frommap(ms)) - break; - return 0; + rv = inter_party_parse_frommap(ms, packet_id); + if (rv != RecvResult::Error) + return rv; + rv = inter_storage_parse_frommap(ms, packet_id); + if (rv != RecvResult::Error) + return rv; + return RecvResult::Error; } - RFIFOSKIP(ms, len); - - return 1; -} - -// RFIFOのパケット長確認 -// 必要パケット長があればパケット長、まだ足りなければ0 -int inter_check_length(Session *s, int length) -{ - if (length == -1) - { // 可変パケット長 - if (RFIFOREST(s) < 4) // パケット長が未着 - return 0; - length = RFIFOW(s, 2); - } - - if (RFIFOREST(s) < length) // パケットが未着 - return 0; - return length; + return rv; } +} // namespace tmwa diff --git a/src/char/inter.hpp b/src/char/inter.hpp index 7d1a38b..19900f9 100644 --- a/src/char/inter.hpp +++ b/src/char/inter.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_CHAR_INTER_HPP -#define TMWA_CHAR_INTER_HPP +#pragma once // inter.hpp - Internal server. // // Copyright © ????-2004 Athena Dev Teams @@ -21,19 +20,19 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -struct Session; +#include "../net/fwd.hpp" + +namespace tmwa +{ bool inter_config(XString key, ZString value); void inter_init2(); void inter_save(void); -int inter_parse_frommap(Session *ms); - -int inter_check_length(Session *ms, int length); +RecvResult inter_parse_frommap(Session *ms, uint16_t packet_id); extern int party_share_level; - -#endif // TMWA_CHAR_INTER_HPP +} // namespace tmwa diff --git a/src/char/main.cpp b/src/char/main.cpp index 6814574..6636196 100644 --- a/src/char/main.cpp +++ b/src/char/main.cpp @@ -1,4 +1,3 @@ -#include "char.hpp" // char/main.cpp - dummy file to make Make dependencies work // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -18,4 +17,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include "char.hpp" + #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/compat/attr.hpp b/src/compat/attr.hpp index ea7ba86..238a5d5 100644 --- a/src/compat/attr.hpp +++ b/src/compat/attr.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_COMPAT_ATTR_HPP -#define TMWA_COMPAT_ATTR_HPP +#pragma once // attr.hpp - Attributes. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,13 +18,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# ifdef __clang__ -# define FALLTHROUGH [[clang::fallthrough]] -# else -# define FALLTHROUGH /* fallthrough */ -# endif - -#endif // TMWA_COMPAT_ATTR_HPP +namespace tmwa +{ +#ifdef __clang__ +# define FALLTHROUGH [[clang::fallthrough]] +#else +# define FALLTHROUGH /* fallthrough */ +#endif +} // namespace tmwa diff --git a/src/compat/cast.cpp b/src/compat/cast.cpp index 43c0b53..482529d 100644 --- a/src/compat/cast.cpp +++ b/src/compat/cast.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/compat/cast.hpp b/src/compat/cast.hpp index 8db486f..35dbc62 100644 --- a/src/compat/cast.hpp +++ b/src/compat/cast.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_COMPAT_CAST_HPP -#define TMWA_COMPAT_CAST_HPP +#pragma once // cast.hpp - Change the type of a variable. // // Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,12 +18,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <utility> -# include <type_traits> +#include <utility> +#include <type_traits> +namespace tmwa +{ template<class T> const T& const_(T& t) { @@ -68,5 +69,4 @@ typename std::remove_pointer<T>::type *sign_cast(U *u) static_assert(sizeof(T_) == sizeof(U), "sign cast must be same size"); return reinterpret_cast<T_ *>(u); } - -#endif // TMWA_COMPAT_CAST_HPP +} // namespace tmwa diff --git a/src/compat/fun.hpp b/src/compat/fun.hpp index 005f2c5..8073fe7 100644 --- a/src/compat/fun.hpp +++ b/src/compat/fun.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_COMPAT_FUN_HPP -#define TMWA_COMPAT_FUN_HPP +#pragma once // fun.hpp - Functional placeholders. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,13 +18,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <functional> - -# include "../sanity.hpp" +#include <functional> +namespace tmwa +{ namespace ph = std::placeholders; - -#endif // TMWA_COMPAT_FUN_HPP +} // namespace tmwa diff --git a/src/compat/fwd.hpp b/src/compat/fwd.hpp new file mode 100644 index 0000000..45f3c24 --- /dev/null +++ b/src/compat/fwd.hpp @@ -0,0 +1,27 @@ +#pragma once +// compat/fwd.hpp - list of type names for compat libs +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +// meh, add more when I feel like it +} // namespace tmwa diff --git a/src/compat/iter.cpp b/src/compat/iter.cpp index f0ab0af..b6d6b63 100644 --- a/src/compat/iter.cpp +++ b/src/compat/iter.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/compat/iter.hpp b/src/compat/iter.hpp index 7793d90..ff146a0 100644 --- a/src/compat/iter.hpp +++ b/src/compat/iter.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_COMPAT_ITER_HPP -#define TMWA_COMPAT_ITER_HPP +#pragma once // iter.hpp - tools for dealing with iterators // // Copyright © 2012-2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,11 +18,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <iterator> +#include <iterator> +namespace tmwa +{ /// Simple class to use a pair of iterators with foreach template<class It> class IteratorPair @@ -94,4 +95,59 @@ IteratorPair<ValueIterator<T>> value_range(T b, T e) return {b, e}; } -#endif // TMWA_COMPAT_ITER_HPP + +template<class T, class F, class C> +class FilterIterator +{ + F filter; + C *container; + + using InnerIterator = decltype(std::begin(*container)); + InnerIterator impl; +public: + void post_adv() + { + while (impl != std::end(*container)) + { + if (filter(*impl)) + break; + ++impl; + } + } + + FilterIterator(C *c, F f) + : filter(f), container(c), impl(std::begin(*c)) + { + post_adv(); + } + + void operator ++() + { + ++impl; + post_adv(); + } + + T operator *() + { + return *impl; + } + + friend + bool operator != (FilterIterator l, FilterIterator) + { + return l.impl != std::end(*l.container); + } +}; + +template<class T> +bool is_truthy(T v) +{ + return v; +} + +template<class T, class F=decltype(is_truthy<T>)*, class C> +IteratorPair<FilterIterator<T, F, C>> filter_iterator(C *c, F f=is_truthy<T>) +{ + return {FilterIterator<T, F, C>(c, f), FilterIterator<T, F, C>(c, f)}; +} +} // namespace tmwa diff --git a/src/compat/iter_test.cpp b/src/compat/iter_test.cpp index a07cb0f..6732c47 100644 --- a/src/compat/iter_test.cpp +++ b/src/compat/iter_test.cpp @@ -20,10 +20,15 @@ #include <gtest/gtest.h> -#include "../strings/xstring.hpp" +#include <algorithm> + +#include "../ints/udl.hpp" #include "../poison.hpp" + +namespace tmwa +{ TEST(iterpair, strings) { IteratorPair<ValueIterator<char>> pair = value_range('0', ':'); @@ -33,7 +38,7 @@ TEST(iterpair, strings) TEST(iterpair, signed8) { - IteratorPair<ValueIterator<int8_t>> pair = value_range(int8_t(-128), int8_t(127)); + IteratorPair<ValueIterator<int8_t>> pair = value_range(-128_n8, +127_p8); int8_t arr[255] = { -128, -127, -126, -125, -124, -123, -122, -121, -120, @@ -68,7 +73,7 @@ TEST(iterpair, signed8) TEST(iterpair, unsigned8) { - IteratorPair<ValueIterator<uint8_t>> pair = value_range(uint8_t(0), uint8_t(255)); + IteratorPair<ValueIterator<uint8_t>> pair = value_range(0_u8, 255_u8); uint8_t arr[255] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, @@ -100,3 +105,57 @@ TEST(iterpair, unsigned8) }; EXPECT_TRUE(std::equal(pair.begin(), pair.end(), arr)); } + +static +bool is_odd_ref(int& i) +{ + return i % 2; +} + +TEST(iterpair, filter1) +{ + int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + + int expected_arr[] = {1, 3, 5, 7}; + int *expected_it = expected_arr; + int *expected_end = expected_arr + 4; + + for (int& i : filter_iterator<int&>(&arr, is_odd_ref)) + { + EXPECT_EQ(i, *expected_it); + ++expected_it; + } + EXPECT_EQ(expected_it, expected_end); +} + +TEST(iterpair, filter2) +{ + std::vector<int> vals = {0, 1, 0, 2, 0, 3, 0}; + + int sum = 0, count = 0; + for (int i : filter_iterator<int>(&vals)) + { + sum += i; + count++; + } + EXPECT_EQ(sum, 6); + EXPECT_EQ(count, 3); +} + +TEST(iterpair, filter3) +{ + int one = 1; + int two = 2; + int three = 3; + std::vector<int *> vals = {nullptr, &one, nullptr, &two, nullptr, &three, nullptr}; + + int sum = 0, count = 0; + for (int *i : filter_iterator<int *>(&vals)) + { + sum += *i; + count++; + } + EXPECT_EQ(sum, 6); + EXPECT_EQ(count, 3); +} +} // namespace tmwa diff --git a/src/compat/memory.cpp b/src/compat/memory.cpp index 5db23b2..f9f2c22 100644 --- a/src/compat/memory.cpp +++ b/src/compat/memory.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/compat/memory.hpp b/src/compat/memory.hpp index 2c0f742..566cc8b 100644 --- a/src/compat/memory.hpp +++ b/src/compat/memory.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_COMPAT_MEMORY_HPP -#define TMWA_COMPAT_MEMORY_HPP +#pragma once // memory.hpp - I forget ... // // Copyright © 2013-2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,11 +18,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <memory> +#include <memory> +#include <type_traits> +namespace tmwa +{ template<class T> struct is_array_of_unknown_bound : std::is_same<T, typename std::remove_extent<T>::type[]> @@ -41,5 +43,4 @@ typename std::enable_if<is_array_of_unknown_bound<T>::value, std::unique_ptr<T, typedef typename std::remove_extent<T>::type E; return std::unique_ptr<E[], D>(new E[sz]()); } - -#endif // TMWA_COMPAT_MEMORY_HPP +} // namespace tmwa diff --git a/src/compat/nullpo.cpp b/src/compat/nullpo.cpp index a31cc34..bb80b27 100644 --- a/src/compat/nullpo.cpp +++ b/src/compat/nullpo.cpp @@ -24,6 +24,9 @@ #include "../poison.hpp" + +namespace tmwa +{ /// Actual output function static void nullpo_info(const char *file, int line, const char *func) @@ -46,3 +49,4 @@ bool nullpo_chk(const char *file, int line, const char *func, nullpo_info(file, line, func); return 1; } +} // namespace tmwa diff --git a/src/compat/nullpo.hpp b/src/compat/nullpo.hpp index 75f8110..5be674a 100644 --- a/src/compat/nullpo.hpp +++ b/src/compat/nullpo.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_COMPAT_NULLPO_HPP -#define TMWA_COMPAT_NULLPO_HPP +#pragma once // nullpo.hpp - Non-fatal pointer assertions. // // Copyright © ????-2004 Athena Dev Teams @@ -26,23 +25,28 @@ //# define BUG_FREE /// All functions print to standard error (was: standard output) -/// nullpo_ret(cond) - return 0 if given pointer is NULL +/// nullpo_retn(cond) - return nullptr if given pointer is nullptr +/// nullpo_retz(cond) - return 0 if given pointer is nullptr /// nullpo_retv(cond) - just return (function returns void) /// nullpo_retr(rv, cond) - return given value instead -# ifndef BUG_FREE -# define nullpo_retr(ret, t) \ +#ifndef BUG_FREE +# define nullpo_retr(ret, t) \ if (nullpo_chk(__FILE__, __LINE__, __PRETTY_FUNCTION__, t)) \ return ret; -# else // BUG_FREE -# define nullpo_retr(ret, t) /*t*/ -# endif // BUG_FREE +#else // BUG_FREE +# define nullpo_retr(ret, t) /*t*/ +#endif // BUG_FREE -# define nullpo_ret(t) nullpo_retr(0, t) -# define nullpo_retv(t) nullpo_retr(, t) +#define nullpo_retn(t) nullpo_retr(nullptr, t) +#define nullpo_retz(t) nullpo_retr(0, t) +#define nullpo_retv(t) nullpo_retr(, t) -# include "../sanity.hpp" +#include "fwd.hpp" + +namespace tmwa +{ /// Used by macros in this header bool nullpo_chk(const char *file, int line, const char *func, const void *target); @@ -57,5 +61,4 @@ bool nullpo_chk(const char *file, int line, const char *func, T *target) { return nullpo_chk(file, line, func, static_cast<const void *>(target)); } - -#endif // TMWA_COMPAT_NULLPO_HPP +} // namespace tmwa diff --git a/src/compat/rawmem.cpp b/src/compat/rawmem.cpp index 74fdc0b..d322437 100644 --- a/src/compat/rawmem.cpp +++ b/src/compat/rawmem.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/compat/rawmem.hpp b/src/compat/rawmem.hpp index bbe917c..c271a56 100644 --- a/src/compat/rawmem.hpp +++ b/src/compat/rawmem.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_COMPAT_RAWMEM_HPP -#define TMWA_COMPAT_RAWMEM_HPP +#pragma once // rawmem.hpp - Ignore poisoning and really frob this memory unsafely. // // Copyright © 2013-2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,12 +18,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include <cstddef> -# include <cstdint> -# include <cstring> +#include <cstddef> +#include <cstdint> +#include <cstring> -# include "../sanity.hpp" +#include "fwd.hpp" + +namespace tmwa +{ inline void really_memcpy(uint8_t *dest, const uint8_t *src, size_t n) { @@ -47,5 +49,4 @@ void really_memset0(uint8_t *dest, size_t n) { memset(dest, '\0', n); } - -#endif // TMWA_COMPAT_RAWMEM_HPP +} // namespace tmwa diff --git a/src/compat/time_t.cpp b/src/compat/time_t.cpp new file mode 100644 index 0000000..ee0bbde --- /dev/null +++ b/src/compat/time_t.cpp @@ -0,0 +1,26 @@ +#include "time_t.hpp" +// time_t.cpp - time_t with a reliable representation +// +// Copyright © 2013-2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/compat/time_t.hpp b/src/compat/time_t.hpp new file mode 100644 index 0000000..9e7cf25 --- /dev/null +++ b/src/compat/time_t.hpp @@ -0,0 +1,29 @@ +#pragma once +// time_t.hpp - time_t with a reliable representation +// +// Copyright © 2013-2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +// TODO fix this ordering violation by promoting TimeT here +#include "../mmo/utils.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/conf/install.hpp b/src/conf/install.hpp new file mode 100644 index 0000000..42fd125 --- /dev/null +++ b/src/conf/install.hpp @@ -0,0 +1,30 @@ +#pragma once +// conf/install.hpp - Import configuration variables related to install. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// just mention "fwd.hpp" to make formatter happy + +#include "conf-raw/str-PACKAGESYSCONFDIR.h" +#include "conf-raw/str-PACKAGELOCALSTATEDIR.h" +#include "conf-raw/str-PACKAGEDATADIR.h" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/conf/version.hpp b/src/conf/version.hpp index ea394e6..df8a8b6 100644 --- a/src/conf/version.hpp +++ b/src/conf/version.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_CONF_VERSION_HPP -#define TMWA_CONF_VERSION_HPP +#pragma once // conf/version.hpp - Import configuration variables related to version. // // Copyright © 2013-2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,20 +18,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +// just mention "fwd.hpp" to make formatter happy -# include "conf-raw/str-VERSION_FULL.h" -# include "conf-raw/str-VERSION_HASH.h" +#include "conf-raw/str-VERSION_FULL.h" +#include "conf-raw/str-VERSION_HASH.h" -# include "conf-raw/int-VERSION_MAJOR.h" -# include "conf-raw/int-VERSION_MINOR.h" -# include "conf-raw/int-VERSION_PATCH.h" -# include "conf-raw/int-VERSION_DEVEL.h" +#include "conf-raw/int-VERSION_MAJOR.h" +#include "conf-raw/int-VERSION_MINOR.h" +#include "conf-raw/int-VERSION_PATCH.h" +#include "conf-raw/int-VERSION_DEVEL.h" -# include "conf-raw/str-VENDOR_NAME.h" -# include "conf-raw/int-VENDOR_POINT.h" -# include "conf-raw/str-VENDOR_SOURCE.h" +#include "conf-raw/str-VENDOR_NAME.h" +#include "conf-raw/int-VENDOR_POINT.h" +#include "conf-raw/str-VENDOR_SOURCE.h" -# include "conf-raw/str-VERSION_STRING.h" +#include "conf-raw/str-VERSION_STRING.h" -#endif // TMWA_CONF_VERSION_HPP + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/diagnostics.hpp b/src/diagnostics.hpp new file mode 100644 index 0000000..31596dc --- /dev/null +++ b/src/diagnostics.hpp @@ -0,0 +1,1251 @@ +#pragma once +// diagnostics.hpp - List of useful warnings and macros to control them. +// +// Copyright © 2013-2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// just mention "fwd.hpp" to make formatter happy + + +namespace tmwa +{ +// Notes about reading this file: +// * Currently only implemented for C++, but could work in C +// * the HAS_DIAG_ is subject to an additional check for clang +// * because token dispatching, it can't be #define HAS_XXX (GCC >= yyy) +// * gcc 4.6 is required for function scope pragmas +// * when upgrading compiler, diff 'gcc --help=warnings' +// * clang-specific warning support is incomplete + +// List of warnings that require arguments, +// and thus cannot reliably be activated: +// gcc 4.6: +// -Wlarger-than=<1024> +// -Wnormalized=<id|nfc|nfd> +// -Wsuggest-attribute=<noreturn,const,pure,format> +// gcc 4.7: +// -Wstack-usage=<8192> +// ???: +// -Wstrict-aliasing=<1> +// -Wstrict-overflow=<1> + +#ifdef __GNUC__ +# ifdef __clang__ +# define GCC (0) +# define CLANG (1) // clang's versions are vendor-specific - stupid apple +# else +# define GCC (__GNUC__ * 100 + __GNUC_MINOR__) +# define CLANG (0) +# endif +#endif + +#if GCC >= 406 || CLANG +# define PRAGMA(x) _Pragma(#x) static_assert(1, "I like my semicolons") +#else +# define PRAGMA(x) static_assert(1, "pragmas not available, can't do: " #x) +#endif + +#define DIAG_E(tag) DO_DIAG_IF(HAS_DIAG_##tag)(error, DIAG_##tag) +#define DIAG_W(tag) DO_DIAG_IF(HAS_DIAG_##tag)(warning, DIAG_##tag) +#define DIAG_I(tag) DO_DIAG_IF(HAS_DIAG_##tag)(ignored, DIAG_##tag) +#define DIAG_X(tag) DO_DIAG_IF(HAS_DIAG_##tag)(ignored, DIAG_##tag) + +#define DO_DIAG_IF(c) JOIN_PLEASE(PRAGMA_IF_,c) +#define JOIN_PLEASE(a, b) a##b +#define PRAGMA_IF_0(lvl, str) static_assert(1, "warning " #str " not enabled for this compiler version, sorry") +#if CLANG +# define PRAGMA_IF_1(lvl, str) DO_DIAG_IF2(__has_warning(str))(lvl, str) +# define DO_DIAG_IF2(s) JOIN_PLEASE(PRAGMA_IF2_, s) +# define PRAGMA_IF2_0(lvl, str) static_assert(1, "warning " #str " not available in this compiler version, sorry") +# define PRAGMA_IF2_1(lvl, str) PRAGMA(GCC diagnostic lvl str) +#else +# define PRAGMA_IF_1(lvl, str) PRAGMA(GCC diagnostic lvl str) +#endif + +#define DIAG_PUSH() PRAGMA(GCC diagnostic push) +#define DIAG_POP() PRAGMA(GCC diagnostic pop) + + +/// Warn about things that will change when compiling +/// with an ABI-compliant compiler +// see note about -fabi-version=6 in the makefile +#define DIAG_abi "-Wabi" +#if 1 +# define HAS_DIAG_abi 1 +#else +# define HAS_DIAG_abi 0 +#endif + +/// Warn if a subobject has an abi_tag attribute that +/// the complete object type does not have +#define DIAG_abi_tag "-Wabi-tag" +#if GCC >= 408 +# define HAS_DIAG_abi_tag 1 +#else +# define HAS_DIAG_abi_tag 0 +#endif + +/// Warn about suspicious uses of memory addresses +#define DIAG_address "-Waddress" +#if 1 +# define HAS_DIAG_address 1 +#else +# define HAS_DIAG_address 0 +#endif + +/// Warn about returning structures, unions or arrays +#define DIAG_aggregate_return "-Waggregate-return" +#if 1 +# define HAS_DIAG_aggregate_return 1 +#else +# define HAS_DIAG_aggregate_return 0 +#endif + +/// Warn if an array is accessed out of bounds +#define DIAG_array_bounds "-Warray-bounds" +#if 1 +# define HAS_DIAG_array_bounds 1 +#else +# define HAS_DIAG_array_bounds 0 +#endif + +/// Warn about inappropriate attribute usage +#define DIAG_attributes "-Wattributes" +#if 1 +# define HAS_DIAG_attributes 1 +#else +# define HAS_DIAG_attributes 0 +#endif + +/// Warn when a built-in preprocessor macro is +// undefined or redefined +#define DIAG_builtin_macro_redefined "-Wbuiltin-macro-redefined" +#if 1 +# define HAS_DIAG_builtin_macro_redefined 1 +#else +# define HAS_DIAG_builtin_macro_redefined 0 +#endif + +/// Warn about C++ constructs whose meaning differs +/// between ISO C++ 1998 and ISO C++ 2011 +#if CLANG || GCC >= 407 +# define DIAG_cxx0x_compat "-Wc++11-compat" +# define DIAG_cxx11_compat "-Wc++11-compat" +#else +# define DIAG_cxx0x_compat "-Wc++0x-compat" +# define DIAG_cxx11_compat "-Wc++0x-compat" +#endif +#if 1 +# define HAS_DIAG_cxx0x_compat 1 +# define HAS_DIAG_cxx11_compat 1 +#else +# define HAS_DIAG_cxx0x_compat 0 +# define HAS_DIAG_cxx11_compat 0 +#endif + +// I care about whether my code compiles with the standard as implemented +// by certain compilers, not whether it matches with an *exact* standard. +#define DIAG_cxx1y_extensions "-Wc++1y-extensions" +#if CLANG +# define HAS_DIAG_cxx1y_extensions 1 +#else +# define HAS_DIAG_cxx1y_extensions 0 +#endif + +/// Warn about pointer casts which increase alignment +#define DIAG_cast_align "-Wcast-align" +#if 1 +# define HAS_DIAG_cast_align 1 +#else +# define HAS_DIAG_cast_align 0 +#endif + +/// Warn about casts which discard qualifiers +#define DIAG_cast_qual "-Wcast-qual" +#if 1 +# define HAS_DIAG_cast_qual 1 +#else +# define HAS_DIAG_cast_qual 0 +#endif + +/// Warn about subscripts whose type is "char" +#define DIAG_char_subscripts "-Wchar-subscripts" +#if 1 +# define HAS_DIAG_char_subscripts 1 +#else +# define HAS_DIAG_char_subscripts 0 +#endif + +/// Warn about variables that might be changed by +/// "longjmp" or "vfork" +#define DIAG_clobbered "-Wclobbered" +#if GCC +# define HAS_DIAG_clobbered 1 +#else +# define HAS_DIAG_clobbered 0 +#endif + +/// Warn about possibly nested block comments, and +/// C++ comments spanning more than one physical line +#define DIAG_comment "-Wcomment" +#if 1 +# define HAS_DIAG_comment 1 +#else +# define HAS_DIAG_comment 0 +#endif + +/// Warn for conditionally-supported constructs +#define DIAG_conditionally_supported "-Wconditionally-supported" +#if GCC >= 409 +# define HAS_DIAG_conditionally_supported 1 +#else +# define HAS_DIAG_conditionally_supported 0 +#endif + +// A fixable difference between c++11 and c++14 +#define DIAG_constexpr_not_const "-Wconstexpr-not-const" +#if CLANG +# define HAS_DIAG_constexpr_not_const 1 +#else +# define HAS_DIAG_constexpr_not_const 0 +#endif + +/// Warn for implicit type conversions that may +/// change a value +#define DIAG_conversion "-Wconversion" +#if 1 +# define HAS_DIAG_conversion 1 +#else +# define HAS_DIAG_conversion 0 +#endif + +/// Warn for converting NULL from/to a non-pointer +/// type +#define DIAG_conversion_null "-Wconversion-null" +#if 1 +# define HAS_DIAG_conversion_null 1 +#else +# define HAS_DIAG_conversion_null 0 +#endif + +/// Warn in case profiles in -fprofile-use do not +/// match +#define DIAG_coverage_mismatch "-Wcoverage-mismatch" +#if GCC +# define HAS_DIAG_coverage_mismatch 1 +#else +# define HAS_DIAG_coverage_mismatch 0 +#endif + +/// +#define DIAG_covered_switch_default "-Wcovered-switch-default" +#if CLANG +# define HAS_DIAG_covered_switch_default 1 +#else +# define HAS_DIAG_covered_switch_default 0 +#endif + +/// Warn when a #warning directive is encountered +#define DIAG_cpp "-Wcpp" +#if GCC +# define HAS_DIAG_cpp 1 +#else +# define HAS_DIAG_cpp 0 +#endif + +/// Warn when all constructors and destructors are +/// private +#define DIAG_ctor_dtor_privacy "-Wctor-dtor-privacy" +#if 1 +# define HAS_DIAG_ctor_dtor_privacy 1 +#else +# define HAS_DIAG_ctor_dtor_privacy 0 +#endif + +/// Warn about __TIME__, __DATE__ and __TIMESTAMP__ +/// usage +#define DIAG_date_time "-Wdate-time" +#if GCC >= 409 +# define HAS_DIAG_date_time 1 +#else +# define HAS_DIAG_date_time 0 +#endif + +/// Warn when deleting a pointer to incomplete type +#define DIAG_delete_incomplete "-Wdelete-incomplete" +#if GCC >= 409 +# define HAS_DIAG_delete_incomplete 1 +#else +# define HAS_DIAG_delete_incomplete 0 +#endif + +/// Warn about deleting polymorphic objects with non- +/// virtual destructors +#define DIAG_delete_non_virtual_dtor "-Wdelete-non-virtual-dtor" +#if GCC >= 407 +# define HAS_DIAG_delete_non_virtual_dtor 1 +#else +# define HAS_DIAG_delete_non_virtual_dtor 0 +#endif + +/// Warn if a deprecated compiler feature, class, +/// method, or field is used +#define DIAG_deprecated "-Wdeprecated" +#if 1 +# define HAS_DIAG_deprecated 1 +#else +# define HAS_DIAG_deprecated 0 +#endif + +/// Warn about uses of __attribute__((deprecated)") +/// declarations +#define DIAG_deprecated_declarations "-Wdeprecated-declarations" +#if 1 +# define HAS_DIAG_deprecated_declarations 1 +#else +# define HAS_DIAG_deprecated_declarations 0 +#endif + +/// Warn when an optimization pass is disabled +#define DIAG_disabled_optimization "-Wdisabled-optimization" +#if 1 +# define HAS_DIAG_disabled_optimization 1 +#else +# define HAS_DIAG_disabled_optimization 0 +#endif + +/// Warn about compile-time integer division by zero +#define DIAG_div_by_zero "-Wdiv-by-zero" +#if 1 +# define HAS_DIAG_div_by_zero 1 +#else +# define HAS_DIAG_div_by_zero 0 +#endif + +/// +#define DIAG_documentation "-Wdocumentation" +#if CLANG +# define HAS_DIAG_documentation 1 +#else +# define HAS_DIAG_documentation 0 +#endif + +/// Warn about implicit conversions from "float" to +/// "double" +#define DIAG_double_promotion "-Wdouble-promotion" +#if GCC +# define HAS_DIAG_double_promotion 1 +#else +# define HAS_DIAG_double_promotion 0 +#endif + +/// Warn about violations of Effective C++ style rules +#define DIAG_effcxx "-Weffc++" +#if 1 +# define HAS_DIAG_effcxx 1 +#else +# define HAS_DIAG_effcxx 0 +#endif + +/// Warn about an empty body in an if or else +/// statement +#define DIAG_empty_body "-Wempty-body" +#if 1 +# define HAS_DIAG_empty_body 1 +#else +# define HAS_DIAG_empty_body 0 +#endif + +/// Warn about stray tokens after #elif and #endif +#define DIAG_endif_labels "-Wendif-labels" +#if 1 +# define HAS_DIAG_endif_labels 1 +#else +# define HAS_DIAG_endif_labels 0 +#endif + +/// Warn about comparison of different enum types +#define DIAG_enum_compare "-Wenum-compare" +#if 1 +# define HAS_DIAG_enum_compare 1 +#else +# define HAS_DIAG_enum_compare 0 +#endif + +/// +#define DIAG_extra_semi "-Wextra-semi" +#if CLANG +# define HAS_DIAG_extra_semi 1 +#else +# define HAS_DIAG_extra_semi 0 +#endif + +/// Warn if testing floating point numbers for +/// equality +#define DIAG_float_equal "-Wfloat-equal" +#if 1 +# define HAS_DIAG_float_equal 1 +#else +# define HAS_DIAG_float_equal 0 +#endif + +/// Warn about printf/scanf/strftime/strfmon format +/// string anomalies +// see below +#define DIAG_format "-Wformat" +#if GCC +# define HAS_DIAG_format 1 +#else +# define HAS_DIAG_format 0 +#endif +// but gcc 4.8 warns on %ms, since we enabled -Wpedantic. +//WG48("-Wformat") + +/// Warn about format strings that contain NUL bytes +#define DIAG_format_contains_nul "-Wformat-contains-nul" +#if GCC +# define HAS_DIAG_format_contains_nul 1 +#else +# define HAS_DIAG_format_contains_nul 0 +#endif + +/// Warn if passing too many arguments to a function +/// for its format string +#define DIAG_format_extra_args "-Wformat-extra-args" +#if 1 +# define HAS_DIAG_format_extra_args 1 +#else +# define HAS_DIAG_format_extra_args 0 +#endif + +/// Warn about format strings that are not literals +// Available in clang, but not smart enough to handle constexpr. +#define DIAG_format_nonliteral "-Wformat-nonliteral" +#if GCC || (CLANG && 1) +# define HAS_DIAG_format_nonliteral 1 +#else +# define HAS_DIAG_format_nonliteral 0 +#endif + +/// Warn about possible security problems with format +/// functions +// Same. +#define DIAG_format_security "-Wformat-security" +#if GCC || (CLANG && 1) +# define HAS_DIAG_format_security 1 +#else +# define HAS_DIAG_format_security 0 +#endif + +/// Warn about strftime formats yielding 2-digit years +#define DIAG_format_y2k "-Wformat-y2k" +#if 1 +# define HAS_DIAG_format_y2k 1 +#else +# define HAS_DIAG_format_y2k 0 +#endif + +/// Warn about zero-length formats +#define DIAG_format_zero_length "-Wformat-zero-length" +#if 1 +# define HAS_DIAG_format_zero_length 1 +#else +# define HAS_DIAG_format_zero_length 0 +#endif + +/// Warn when attempting to free a non-heap object +#define DIAG_free_nonheap_object "-Wfree-nonheap-object" +#if GCC >= 407 +# define HAS_DIAG_free_nonheap_object 1 +#else +# define HAS_DIAG_free_nonheap_object 0 +#endif + +// -Wgnu is a clang alias for -Wpedantic + +// Foo{x: y} +#define DIAG_gnu_designator "-Wgnu-designator" +#if CLANG +# define HAS_DIAG_gnu_designator 1 +#else +# define HAS_DIAG_gnu_designator 0 +#endif + + +/// Warn whenever type qualifiers are ignored. +#define DIAG_ignored_qualifiers "-Wignored-qualifiers" +#if 1 +# define HAS_DIAG_ignored_qualifiers 1 +#else +# define HAS_DIAG_ignored_qualifiers 0 +#endif + +/// +#define DIAG_implicit_fallthrough "-Wimplicit-fallthrough" +#if CLANG +# define HAS_DIAG_implicit_fallthrough 1 +#else +# define HAS_DIAG_implicit_fallthrough 0 +#endif + +/// Warn about C++11 inheriting constructors when the +/// base has a variadic constructor +#define DIAG_inherited_variadic_ctor "-Winherited-variadic-ctor" +#if GCC >= 408 +# define HAS_DIAG_inherited_variadic_ctor 1 +#else +# define HAS_DIAG_inherited_variadic_ctor 0 +#endif + +/// Warn about variables which are initialized to +/// themselves +#define DIAG_init_self "-Winit-self" +#if 1 +# define HAS_DIAG_init_self 1 +#else +# define HAS_DIAG_init_self 0 +#endif + +/// Warn when an inlined function cannot be inlined +#define DIAG_inline "-Winline" +#if 1 +# define HAS_DIAG_inline 1 +#else +# define HAS_DIAG_inline 0 +#endif + +/// Warn when there is a cast to a pointer from an +/// integer of a different size +#define DIAG_int_to_pointer_cast "-Wint-to-pointer-cast" +#if 1 +# define HAS_DIAG_int_to_pointer_cast 1 +#else +# define HAS_DIAG_int_to_pointer_cast 0 +#endif + +/// Warn when an atomic memory model parameter is +/// known to be outside the valid range. +#define DIAG_invalid_memory_model "-Winvalid-memory-model" +#if GCC >= 407 +# define HAS_DIAG_invalid_memory_model 1 +#else +# define HAS_DIAG_invalid_memory_model 0 +#endif + +/// Warn about invalid uses of the "offsetof" macro +#define DIAG_invalid_offsetof "-Winvalid-offsetof" +#if 1 +# define HAS_DIAG_invalid_offsetof 1 +#else +# define HAS_DIAG_invalid_offsetof 0 +#endif + +/// Warn about PCH files that are found but not used +#define DIAG_invalid_pch "-Winvalid-pch" +#if 1 +# define HAS_DIAG_invalid_pch 1 +#else +# define HAS_DIAG_invalid_pch 0 +#endif + +/// Warn when a string or character literal is +/// followed by a ud-suffix which does not begin with +/// an underscore. +#define DIAG_literal_suffix "-Wliteral-suffix" +#if GCC >= 408 +# define HAS_DIAG_literal_suffix 1 +#else +# define HAS_DIAG_literal_suffix 0 +#endif + +/// Warn when a logical operator is suspiciously +/// always evaluating to true or false +#define DIAG_logical_op "-Wlogical-op" +#if GCC +# define HAS_DIAG_logical_op 1 +#else +# define HAS_DIAG_logical_op 0 +#endif + +/// Do not warn about using "long long" when -pedantic +#define DIAG_long_long "-Wlong-long" +#if 1 +# define HAS_DIAG_long_long 1 +#else +# define HAS_DIAG_long_long 0 +#endif + +/// Warn about suspicious declarations of "main" +#define DIAG_main "-Wmain" +#if 1 +# define HAS_DIAG_main 1 +#else +# define HAS_DIAG_main 0 +#endif + +/// Warn about maybe uninitialized automatic variables +#define DIAG_maybe_uninitialized "-Wmaybe-uninitialized" +#if GCC >= 407 +# define HAS_DIAG_maybe_uninitialized 1 +#else +# define HAS_DIAG_maybe_uninitialized 0 +#endif + +// bitch about 'struct Foo' vs 'class Foo' +#define DIAG_mismatched_tags "-Wmismatched-tags" +#if CLANG +# define HAS_DIAG_mismatched_tags 1 +#else +# define HAS_DIAG_mismatched_tags 0 +#endif + +/// Warn about possibly missing braces around +/// initializers +// beware of things like std::array! +#define DIAG_missing_braces "-Wmissing-braces" +#if 1 +# define HAS_DIAG_missing_braces 1 +#else +# define HAS_DIAG_missing_braces 0 +#endif + +/// Warn about global functions without previous +/// declarations +// This doesn't work for clang, it wants -Wmissing-prototypes instead. +#define DIAG_missing_declarations "-Wmissing-declarations" +#if 1 +# define HAS_DIAG_missing_declarations 1 +#else +# define HAS_DIAG_missing_declarations 0 +#endif + +/// Warn about missing fields in struct initializers +// Actually supported by GCC, but gives warnings when I don't want, e.g.: +// Foo foo = {}; +#define DIAG_missing_field_initializers "-Wmissing-field-initializers" +#if CLANG || (GCC && 1) +# define HAS_DIAG_missing_field_initializers 1 +#else +# define HAS_DIAG_missing_field_initializers 0 +#endif + +/// Warn about functions which might be candidates +/// for format attributes +#define DIAG_missing_format_attribute "-Wmissing-format-attribute" +#if 1 +# define HAS_DIAG_missing_format_attribute 1 +#else +# define HAS_DIAG_missing_format_attribute 0 +#endif + +/// Warn about user-specified include directories +/// that do not exist +#define DIAG_missing_include_dirs "-Wmissing-include-dirs" +#if 1 +# define HAS_DIAG_missing_include_dirs 1 +#else +# define HAS_DIAG_missing_include_dirs 0 +#endif + +/// Warn about functions which might be candidates +/// for __attribute__((noreturn)") +#define DIAG_missing_noreturn "-Wmissing-noreturn" +#if 1 +# define HAS_DIAG_missing_noreturn 1 +#else +# define HAS_DIAG_missing_noreturn 0 +#endif + +// clang uses this instead of -Wmissing-declarations +#define DIAG_missing_prototypes "-Wmissing-prototypes" +#if CLANG +# define HAS_DIAG_missing_prototypes 1 +#else +# define HAS_DIAG_missing_prototypes 0 +#endif + +/// +// like -Wmissing-declarations but for variables instead of functions +#define DIAG_missing_variable_declarations "-Wmissing-variable-declarations" +#if CLANG +# define HAS_DIAG_missing_variable_declarations 1 +#else +# define HAS_DIAG_missing_variable_declarations 0 +#endif + +/// Warn about constructs not instrumented by +/// -fmudflap +#define DIAG_mudflap "-Wmudflap" +#if GCC +# define HAS_DIAG_mudflap 1 +#else +# define HAS_DIAG_mudflap 0 +#endif + +/// Warn about use of multi-character character +/// constants +#define DIAG_multichar "-Wmultichar" +#if 1 +# define HAS_DIAG_multichar 1 +#else +# define HAS_DIAG_multichar 0 +#endif + +/// Warn about narrowing conversions within { } that +/// are ill-formed in C++11 +#define DIAG_narrowing "-Wnarrowing" +#if GCC >= 407 +# define HAS_DIAG_narrowing 1 +#else +# define HAS_DIAG_narrowing 0 +#endif + +/// Warn when a noexcept expression evaluates to +/// false even though the expression can't actually +/// throw +#define DIAG_noexcept "-Wnoexcept" +#if GCC +# define HAS_DIAG_noexcept 1 +#else +# define HAS_DIAG_noexcept 0 +#endif + +/// Warn when non-templatized friend functions are +/// declared within a template +#define DIAG_non_template_friend "-Wnon-template-friend" +#if GCC +# define HAS_DIAG_non_template_friend 1 +#else +# define HAS_DIAG_non_template_friend 0 +#endif + +/// Warn about non-virtual destructors +#define DIAG_non_virtual_dtor "-Wnon-virtual-dtor" +#if 1 +# define HAS_DIAG_non_virtual_dtor 1 +#else +# define HAS_DIAG_non_virtual_dtor 0 +#endif + +/// Warn about NULL being passed to argument slots +/// marked as requiring non-NULL +#define DIAG_nonnull "-Wnonnull" +#if 1 +# define HAS_DIAG_nonnull 1 +#else +# define HAS_DIAG_nonnull 0 +#endif + +/// +#define DIAG_null_conversion "-Wnull-conversion" +#if CLANG +# define HAS_DIAG_null_conversion 1 +#else +# define HAS_DIAG_null_conversion 0 +#endif + +/// Warn if a C-style cast is used in a program +#define DIAG_old_style_cast "-Wold-style-cast" +#if 1 +# define HAS_DIAG_old_style_cast 1 +#else +# define HAS_DIAG_old_style_cast 0 +#endif + +/// Warn about overflow in arithmetic expressions +#define DIAG_overflow "-Woverflow" +#if 1 +# define HAS_DIAG_overflow 1 +#else +# define HAS_DIAG_overflow 0 +#endif + +/// Warn if a simd directive is overridden by the +/// vectorizer cost model +#define DIAG_openmp_simd "-Wopenmp-simd" +#if GCC >= 409 +# define HAS_DIAG_openmp_simd 1 +#else +# define HAS_DIAG_openmp_simd 0 +#endif + +/// Warn if a string is longer than the maximum +/// portable length specified by the standard +//X("-Woverlength-strings") + +/// Warn about overloaded virtual function names +#define DIAG_overloaded_virtual "-Woverloaded-virtual" +#if 1 +# define HAS_DIAG_overloaded_virtual 1 +#else +# define HAS_DIAG_overloaded_virtual 0 +#endif + +/// Warn when the packed attribute has no effect on +/// struct layout +#define DIAG_packed "-Wpacked" +#if 1 +# define HAS_DIAG_packed 1 +#else +# define HAS_DIAG_packed 0 +#endif + +/// Warn about packed bit-fields whose offset changed +/// in GCC 4.4 +#define DIAG_packed_bitfield_compat "-Wpacked-bitfield-compat" +#if GCC +# define HAS_DIAG_packed_bitfield_compat 1 +#else +# define HAS_DIAG_packed_bitfield_compat 0 +#endif + +/// Warn when padding is required to align structure +/// members +#define DIAG_padded "-Wpadded" +#if 1 +# define HAS_DIAG_padded 1 +#else +# define HAS_DIAG_padded 0 +#endif + +/// Warn about possibly missing parentheses +#define DIAG_parentheses "-Wparentheses" +#if 1 +# define HAS_DIAG_parentheses 1 +#else +# define HAS_DIAG_parentheses 0 +#endif + +/// Issue warnings needed for strict compliance to +/// the standard +// a bit too noisy +//EG48("-Wpedantic") +// lots of minor extensions are used +#define DIAG_pedantic "-Wpedantic" +#if GCC >= 408 || CLANG +# define HAS_DIAG_pedantic 1 +#else +# define HAS_DIAG_pedantic 0 +#endif + +/// Warn when converting the type of pointers to +/// member functions +#define DIAG_pmf_conversions "-Wpmf-conversions" +#if GCC +# define HAS_DIAG_pmf_conversions 1 +#else +# define HAS_DIAG_pmf_conversions 0 +#endif + +/// Warn about function pointer arithmetic +#define DIAG_pointer_arith "-Wpointer-arith" +#if 1 +# define HAS_DIAG_pointer_arith 1 +#else +# define HAS_DIAG_pointer_arith 0 +#endif + +/// Warn about misuses of pragmas +#define DIAG_pragmas "-Wpragmas" +#if GCC +# define HAS_DIAG_pragmas 1 +#else +# define HAS_DIAG_pragmas 0 +#endif + +/// Warn about multiple declarations of the same +/// object +#define DIAG_redundant_decls "-Wredundant-decls" +#if 1 +# define HAS_DIAG_redundant_decls 1 +#else +# define HAS_DIAG_redundant_decls 0 +#endif + +/// Warn when the compiler reorders code +#define DIAG_reorder "-Wreorder" +#if 1 +# define HAS_DIAG_reorder 1 +#else +# define HAS_DIAG_reorder 0 +#endif + +/// Warn about returning a pointer/reference to a +/// local or temporary variable. +#define DIAG_return_local_addr "-Wreturn-local-addr" +#if GCC >= 408 +# define HAS_DIAG_return_local_addr 1 +#else +# define HAS_DIAG_return_local_addr 0 +#endif + +/// Warn whenever a function's return type defaults +/// to "int" (C), or about inconsistent return types +/// (C++") +#define DIAG_return_type "-Wreturn-type" +#if 1 +# define HAS_DIAG_return_type 1 +#else +# define HAS_DIAG_return_type 0 +#endif + +/// Warn about possible violations of sequence point +/// rules +#define DIAG_sequence_point "-Wsequence-point" +#if 1 +# define HAS_DIAG_sequence_point 1 +#else +# define HAS_DIAG_sequence_point 0 +#endif + +/// Warn when one local variable shadows another +#define DIAG_shadow "-Wshadow" +#if 1 +# define HAS_DIAG_shadow 1 +#else +# define HAS_DIAG_shadow 0 +#endif + +/// Warn about signed-unsigned comparisons +#define DIAG_sign_compare "-Wsign-compare" +#if 1 +# define HAS_DIAG_sign_compare 1 +#else +# define HAS_DIAG_sign_compare 0 +#endif + +/// Warn when overload promotes from unsigned to +/// signed +#define DIAG_sign_promo "-Wsign-promo" +#if 1 +# define HAS_DIAG_sign_promo 1 +#else +# define HAS_DIAG_sign_promo 0 +#endif + +/// This switch lacks documentation +#define DIAG_sizeof_pointer_memaccess "-Wsizeof-pointer-memaccess" +#if GCC >= 408 +# define HAS_DIAG_sizeof_pointer_memaccess 1 +#else +# define HAS_DIAG_sizeof_pointer_memaccess 0 +#endif + +/// Warn when not issuing stack smashing protection +/// for some reason +#define DIAG_stack_protector "-Wstack-protector" +#if 1 +# define HAS_DIAG_stack_protector 1 +#else +# define HAS_DIAG_stack_protector 0 +#endif + +/// Warn about code which might break strict aliasing +/// rules +#define DIAG_strict_aliasing "-Wstrict-aliasing" +#if 1 +# define HAS_DIAG_strict_aliasing 1 +#else +# define HAS_DIAG_strict_aliasing 0 +#endif + +/// Warn about uncasted NULL used as sentinel +#define DIAG_strict_null_sentinel "-Wstrict-null-sentinel" +#if GCC +# define HAS_DIAG_strict_null_sentinel 1 +#else +# define HAS_DIAG_strict_null_sentinel 0 +#endif + +/// Warn about optimizations that assume that signed +/// overflow is undefined +#define DIAG_strict_overflow "-Wstrict-overflow" +#if 1 +# define HAS_DIAG_strict_overflow 1 +#else +# define HAS_DIAG_strict_overflow 0 +#endif + +/// Warn about enumerated switches, with no default, +/// missing a case +#define DIAG_switch "-Wswitch" +#if 1 +# define HAS_DIAG_switch 1 +#else +# define HAS_DIAG_switch 0 +#endif + +/// Warn about enumerated switches missing a +/// "default:" statement +#define DIAG_switch_default "-Wswitch-default" +#if 1 +# define HAS_DIAG_switch_default 1 +#else +# define HAS_DIAG_switch_default 0 +#endif + +/// Warn about all enumerated switches missing a +/// specific case +#define DIAG_switch_enum "-Wswitch-enum" +#if 1 +# define HAS_DIAG_switch_enum 1 +#else +# define HAS_DIAG_switch_enum 0 +#endif + +/// Warn when __sync_fetch_and_nand and +/// __sync_nand_and_fetch built-in functions are used +#define DIAG_sync_nand "-Wsync-nand" +#if GCC +# define HAS_DIAG_sync_nand 1 +#else +# define HAS_DIAG_sync_nand 0 +#endif + +/// Warn whenever a trampoline is generated +#define DIAG_trampolines "-Wtrampolines" +#if GCC +# define HAS_DIAG_trampolines 1 +#else +# define HAS_DIAG_trampolines 0 +#endif + +/// Warn if trigraphs are encountered that might +/// affect the meaning of the program +#define DIAG_trigraphs "-Wtrigraphs" +#if 1 +# define HAS_DIAG_trigraphs 1 +#else +# define HAS_DIAG_trigraphs 0 +#endif + +/// Warn if a comparison is always true or always +/// false due to the limited range of the data type +#define DIAG_type_limits "-Wtype-limits" +#if 1 +# define HAS_DIAG_type_limits 1 +#else +# define HAS_DIAG_type_limits 0 +#endif + +/// Warn if an undefined macro is used in an #if +/// directive +#define DIAG_undef "-Wundef" +#if 1 +# define HAS_DIAG_undef 1 +#else +# define HAS_DIAG_undef 0 +#endif + +/// Warn about uninitialized automatic variables +#define DIAG_uninitialized "-Wuninitialized" +#if 1 +# define HAS_DIAG_uninitialized 1 +#else +# define HAS_DIAG_uninitialized 0 +#endif + +/// Warn about unrecognized pragmas +#define DIAG_unknown_pragmas "-Wunknown-pragmas" +#if 1 +# define HAS_DIAG_unknown_pragmas 1 +#else +# define HAS_DIAG_unknown_pragmas 0 +#endif + +/// +// Not an error because of some remaining enum+default +#define DIAG_unreachable_code "-Wunreachable-code" +#if CLANG +# define HAS_DIAG_unreachable_code 1 +#else +# define HAS_DIAG_unreachable_code 0 +#endif + +/// Warn if the loop cannot be optimized due to +/// nontrivial assumptions. +#define DIAG_unsafe_loop_optimizations "-Wunsafe-loop-optimizations" +#if GCC +# define HAS_DIAG_unsafe_loop_optimizations 1 +#else +# define HAS_DIAG_unsafe_loop_optimizations 0 +#endif + +/// Warn when a function parameter is only set, +/// otherwise unused +#define DIAG_unused_but_set_parameter "-Wunused-but-set-parameter" +#if GCC +# define HAS_DIAG_unused_but_set_parameter 1 +#else +# define HAS_DIAG_unused_but_set_parameter 0 +#endif + +/// Warn when a variable is only set, otherwise unused +#define DIAG_unused_but_set_variable "-Wunused-but-set-variable" +#if GCC +# define HAS_DIAG_unused_but_set_variable 1 +#else +# define HAS_DIAG_unused_but_set_variable 0 +#endif + +/// Warn when a function is unused +#define DIAG_unused_function "-Wunused-function" +#if 1 +# define HAS_DIAG_unused_function 1 +#else +# define HAS_DIAG_unused_function 0 +#endif + +/// Warn when a label is unused +#define DIAG_unused_label "-Wunused-label" +#if 1 +# define HAS_DIAG_unused_label 1 +#else +# define HAS_DIAG_unused_label 0 +#endif + +/// Warn when typedefs locally defined in a function +/// are not used +#define DIAG_unused_local_typedefs "-Wunused-local-typedefs" +#if GCC >= 407 +# define HAS_DIAG_unused_local_typedefs 1 +#else +# define HAS_DIAG_unused_local_typedefs 0 +#endif + +/// Warn about macros defined in the main file that +/// are not used +#define DIAG_unused_macros "-Wunused-macros" +#if 1 +# define HAS_DIAG_unused_macros 1 +#else +# define HAS_DIAG_unused_macros 0 +#endif + +/// Warn when a function parameter is unused +#define DIAG_unused_parameter "-Wunused-parameter" +#if 1 +# define HAS_DIAG_unused_parameter 1 +#else +# define HAS_DIAG_unused_parameter 0 +#endif + +/// Warn if a caller of a function, marked with +/// attribute warn_unused_result, does not use its +/// return value +#define DIAG_unused_result "-Wunused-result" +#if 1 +# define HAS_DIAG_unused_result 1 +#else +# define HAS_DIAG_unused_result 0 +#endif + +/// Warn when an expression value is unused +#define DIAG_unused_value "-Wunused-value" +#if 1 +# define HAS_DIAG_unused_value 1 +#else +# define HAS_DIAG_unused_value 0 +#endif + +/// Warn when a variable is unused +#define DIAG_unused_variable "-Wunused-variable" +#if 1 +# define HAS_DIAG_unused_variable 1 +#else +# define HAS_DIAG_unused_variable 0 +#endif + +/// Warn about useless casts +#define DIAG_useless_cast "-Wuseless-cast" +#if GCC >= 408 +# define HAS_DIAG_useless_cast 1 +#else +# define HAS_DIAG_useless_cast 0 +#endif + +/// Warn about questionable usage of the macros used +/// to retrieve variable arguments +#define DIAG_varargs "-Wvarargs" +#if GCC >= 408 +# define HAS_DIAG_varargs 1 +#else +# define HAS_DIAG_varargs 0 +#endif + +/// Warn about using variadic macros +#define DIAG_variadic_macros "-Wvariadic-macros" +#if 1 +# define HAS_DIAG_variadic_macros 1 +#else +# define HAS_DIAG_variadic_macros 0 +#endif + +/// Warn when a vector operation is compiled +/// outside the SIMD +#define DIAG_vector_operation_performance "-Wvector-operation-performance" +#if GCC >= 407 +# define HAS_DIAG_vector_operation_performance 1 +#else +# define HAS_DIAG_vector_operation_performance 0 +#endif + +/// Warn if a virtual base has a non-trivial move +/// assignment operator +#define DIAG_virtual_move_assign "-Wvirtual-move-assign" +#if GCC >= 408 +# define HAS_DIAG_virtual_move_assign 1 +#else +# define HAS_DIAG_virtual_move_assign 0 +#endif + +/// Warn if a variable length array is used +#define DIAG_vla "-Wvla" +#if 1 +# define HAS_DIAG_vla 1 +#else +# define HAS_DIAG_vla 0 +#endif + +/// Warn when a register variable is declared volatile +#define DIAG_volatile_register_var "-Wvolatile-register-var" +#if 1 +# define HAS_DIAG_volatile_register_var 1 +#else +# define HAS_DIAG_volatile_register_var 0 +#endif + +/// In C++, nonzero means warn about deprecated +/// conversion from string literals to 'char *'. In +/// C, similar warning, except that the conversion is +/// of course not deprecated by the ISO C standard. +#define DIAG_write_strings "-Wwrite-strings" +#if 1 +# define HAS_DIAG_write_strings 1 +#else +# define HAS_DIAG_write_strings 0 +#endif + +/// Warn when a literal '0' is used as null +/// pointer +#define DIAG_zero_as_null_pointer_constant "-Wzero-as-null-pointer-constant" +#if GCC >= 407 +# define HAS_DIAG_zero_as_null_pointer_constant 1 +#else +# define HAS_DIAG_zero_as_null_pointer_constant 0 +#endif +} // namespace tmwa diff --git a/src/spell-convert/main.cpp b/src/generic/array.cpp index 0c0d04e..3063569 100644 --- a/src/spell-convert/main.cpp +++ b/src/generic/array.cpp @@ -1,4 +1,5 @@ -// spell-convert/main.cpp - Hacky magic conversion driver. +#include "array.hpp" +// array.cpp - A simple bounds-checked array. // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> // @@ -17,12 +18,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include "lexer.hpp" -#include "parser.hpp" - #include "../poison.hpp" -int main() + +namespace tmwa { - spell_converterparse(); -} +} // namespace tmwa diff --git a/src/generic/array.hpp b/src/generic/array.hpp new file mode 100644 index 0000000..dccb91e --- /dev/null +++ b/src/generic/array.hpp @@ -0,0 +1,118 @@ +#pragma once +// array.hpp - A simple bounds-checked array. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include <cassert> +#include <cstddef> + +#include "oops.hpp" + + +namespace tmwa +{ +template<class I, I be, I en> +struct ExclusiveIndexing +{ + using index_type = I; + constexpr static size_t index_to_offset(index_type idx) + { return static_cast<size_t>(idx) - static_cast<size_t>(be); } + constexpr static index_type offset_to_index(size_t off) + { return static_cast<I>(off + static_cast<size_t>(be)); } + constexpr static size_t alloc_size = index_to_offset(en) - index_to_offset(be); +}; + +template<size_t n> +using SimpleIndexing = ExclusiveIndexing<size_t, 0, n>; + +template<class I, I lo, I hi> +struct InclusiveIndexing +{ + using index_type = I; + constexpr static size_t index_to_offset(index_type idx) + { return static_cast<size_t>(idx) - static_cast<size_t>(lo); } + constexpr static index_type offset_to_index(size_t off) + { return static_cast<I>(off + static_cast<size_t>(lo)); } + constexpr static size_t alloc_size = index_to_offset(hi) - index_to_offset(lo) + 1; +}; + +template<class E, E n=E::COUNT> +struct EnumIndexing : ExclusiveIndexing<E, static_cast<E>(0), n> +{ +}; + +template<class I, size_t limit> +struct InventoryIndexing +{ + using index_type = I; + constexpr static size_t index_to_offset(index_type idx) + { return idx.get0(); } + constexpr static index_type offset_to_index(size_t off) + { return I::from(off); } + constexpr static size_t alloc_size = limit; +}; + +template<class T, class I> +struct GenericArray +{ + T data[I::alloc_size]; +public: + T *begin() + { return data + 0; } + T *end() + { return data + I::alloc_size; } + const T *begin() const + { return data + 0; } + const T *end() const + { return data + I::alloc_size; } + size_t size() const + { return I::alloc_size; } + + T& operator [](typename I::index_type i_) + { + size_t i = I::index_to_offset(i_); + ALLEGE ("index in bounds", i < size()); + return data[i]; + } + const T& operator [](typename I::index_type i_) const + { + size_t i = I::index_to_offset(i_); + ALLEGE ("index in bounds", i < size()); + return data[i]; + } + + friend bool operator == (GenericArray& lhs, GenericArray& rhs) + { + for (size_t i = 0; i < I::alloc_size; ++i) + { + if (lhs.data[i] != rhs.data[i]) + return false; + } + return true; + } + friend bool operator != (GenericArray& lhs, GenericArray& rhs) + { + return !(lhs == rhs); + } +}; + +template<class T, size_t n> +using Array = GenericArray<T, SimpleIndexing<n>>; +} // namespace tmwa diff --git a/src/generic/array_test.cpp b/src/generic/array_test.cpp new file mode 100644 index 0000000..aff47ee --- /dev/null +++ b/src/generic/array_test.cpp @@ -0,0 +1,162 @@ +#include "array.hpp" +// array_test.cpp - Testsuite for a simple bounds-checked array. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <gtest/gtest.h> + +#include "../poison.hpp" + + +namespace tmwa +{ +TEST(Array, simple) +{ + GenericArray<int, SimpleIndexing<3>> a; + try + { + a[0]; + a[1]; + a[2]; + SUCCEED(); + } + catch (const AssertionError&) + { + FAIL(); + } + try + { + a[3]; + FAIL(); + } + catch (const AssertionError&) + { + SUCCEED(); + } +} + +TEST(Array, inclusive1) +{ + GenericArray<int, InclusiveIndexing<int, 1, 3>> a; + try + { + a[0]; + FAIL(); + } + catch (const AssertionError&) + { + SUCCEED(); + } + try + { + a[1]; + a[2]; + a[3]; + SUCCEED(); + } + catch (const AssertionError&) + { + FAIL(); + } + try + { + a[4]; + FAIL(); + } + catch (const AssertionError&) + { + SUCCEED(); + } +} + +TEST(Array, negative) +{ + GenericArray<int, InclusiveIndexing<int, -1, 1>> a; + try + { + a[-2]; + FAIL(); + } + catch (const AssertionError&) + { + SUCCEED(); + } + try + { + a[-1]; + a[0]; + a[1]; + SUCCEED(); + } + catch (const AssertionError&) + { + FAIL(); + } + try + { + a[2]; + FAIL(); + } + catch (const AssertionError&) + { + SUCCEED(); + } +} + +TEST(Array, enum) +{ + enum class Blah + { + FOO, + BAR, + BAZ, + COUNT, + }; + + GenericArray<int, EnumIndexing<Blah>> a; + try + { + a[static_cast<Blah>(-1)]; + FAIL(); + } + catch (const AssertionError&) + { + SUCCEED(); + } + try + { + a[Blah::FOO]; + a[Blah::BAR]; + a[Blah::BAZ]; + SUCCEED(); + } + catch (const AssertionError&) + { + FAIL(); + } + try + { + a[Blah::COUNT]; + FAIL(); + } + catch (const AssertionError&) + { + SUCCEED(); + } +} +} // namespace tmwa diff --git a/src/generic/db.cpp b/src/generic/db.cpp index b953ff0..458068c 100644 --- a/src/generic/db.cpp +++ b/src/generic/db.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/generic/db.hpp b/src/generic/db.hpp index 314c449..90c4f92 100644 --- a/src/generic/db.hpp +++ b/src/generic/db.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_GENERIC_DB_HPP -#define TMWA_GENERIC_DB_HPP +#pragma once // db.hpp - convenience wrappers over std::map<K, V> // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,11 +18,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <map> -# include <memory> +#include <map> +#include <memory> + +namespace tmwa +{ template<class K, class V> class Map { @@ -176,5 +178,4 @@ public: return impl.size(); } }; - -#endif // TMWA_GENERIC_DB_HPP +} // namespace tmwa diff --git a/src/mmo/dumb_ptr.cpp b/src/generic/dumb_ptr.cpp index 77e3080..e690f7d 100644 --- a/src/mmo/dumb_ptr.cpp +++ b/src/generic/dumb_ptr.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/mmo/dumb_ptr.hpp b/src/generic/dumb_ptr.hpp index 9632945..a9d6893 100644 --- a/src/mmo/dumb_ptr.hpp +++ b/src/generic/dumb_ptr.hpp @@ -1,6 +1,5 @@ -#ifndef TMWA_MMO_DUMB_PTR_HPP -#define TMWA_MMO_DUMB_PTR_HPP -// ptr.hpp - temporary new/delete wrappers +#pragma once +// dumb_ptr.hpp - temporary new/delete wrappers // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> // @@ -19,16 +18,20 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstring> +#include <cstring> -# include <algorithm> +#include <algorithm> +#include <utility> -# include "../strings/astring.hpp" -# include "../strings/zstring.hpp" -# include "../strings/xstring.hpp" +#include "../strings/astring.hpp" +#include "../strings/zstring.hpp" +#include "../strings/xstring.hpp" + +namespace tmwa +{ // unmanaged new/delete-able pointer // should be replaced by std::unique_ptr<T> template<class T> @@ -199,18 +202,14 @@ struct dumb_string std::copy(b, e, &rv.impl[0]); return rv; } - static dumb_string copy(const char *sz) - { - return dumb_string::copy(sz, sz + strlen(sz)); - } static dumb_string copys(XString s) { return dumb_string::copy(&*s.begin(), &*s.end()); } static -# ifndef __clang__ +#ifndef __clang__ __attribute__((warning("shouldn't use this - slice instead"))) -# endif +#endif dumb_string copyn(const char *sn, size_t n) { return dumb_string::copy(sn, sn + strnlen(sn, n)); @@ -227,7 +226,7 @@ struct dumb_string dumb_string dup() const { - return dumb_string::copy(&impl[0]); + return dumb_string::copy(&impl[0], &impl[0] + impl.size()); } void delete_() { @@ -270,5 +269,4 @@ const char *convert_for_printf(dumb_string ds) { return ds.c_str(); } - -#endif // TMWA_MMO_DUMB_PTR_HPP +} // namespace tmwa diff --git a/src/generic/enum.cpp b/src/generic/enum.cpp index 8c54aba..49402e9 100644 --- a/src/generic/enum.cpp +++ b/src/generic/enum.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/generic/enum.hpp b/src/generic/enum.hpp index 8b3509f..81c9b12 100644 --- a/src/generic/enum.hpp +++ b/src/generic/enum.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_GENERIC_ENUM_HPP -#define TMWA_GENERIC_ENUM_HPP +#pragma once // enum.hpp - Safe building blocks for enumerated types. // // Copyright © 2012-2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,70 +18,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cassert> +#include <cassert> +#include <cstddef> -# include <type_traits> +#include <algorithm> +#include <type_traits> -# include "../compat/iter.hpp" +#include "../compat/iter.hpp" -template<class T, class E, E max> -struct earray -{ - constexpr static - size_t size() - { - return static_cast<size_t>(max); - } - - // no ctor/dtor and one public member variable for easy initialization - T _data[size()]; - - T& operator[](E v) - { - auto i = static_cast<size_t>(v); - assert (i < size()); - return _data[i]; - } - - const T& operator[](E v) const - { - auto i = static_cast<size_t>(v); - assert (i < size()); - return _data[i]; - } - - T *begin() - { - return _data; - } +#include "array.hpp" - T *end() - { - return _data + size(); - } - const T *begin() const - { - return _data; - } - - const T *end() const - { - return _data + size(); - } - - friend bool operator == (const earray& l, const earray& r) - { - return std::equal(l.begin(), l.end(), r.begin()); - } - - friend bool operator != (const earray& l, const earray& r) - { - return !(l == r); - } -}; +namespace tmwa +{ +template<class T, class E, E max> +using earray = GenericArray<T, EnumIndexing<E, max>>; template<class T, class E, E max> class eptr @@ -100,7 +52,7 @@ public: {} eptr(earray<T, E, max>& arr) - : _data(arr._data) + : _data(arr.data) {} T& operator [](E v) const @@ -123,6 +75,7 @@ public: // std::underlying_type isn't supported until gcc 4.7 // this is a poor man's emulation +// TODO I'm depending on GCC 4.7 now, this can go away template<class E> struct underlying_type { @@ -148,7 +101,7 @@ struct remove_enum<E, true> // This really should just go in a namespace // that's how I use it anyway ... -# define ENUM_BITWISE_OPERATORS(E) \ +#define ENUM_BITWISE_OPERATORS(E) \ inline \ E operator & (E l, E r) \ { \ @@ -196,7 +149,7 @@ public: static E inced(E v) { - return E(U(v) + 1); + return static_cast<E>(static_cast<U>(v) + 1); } }; @@ -205,5 +158,4 @@ IteratorPair<ValueIterator<E, EnumMath<E>>> erange(E b, E e) { return {b, e}; } - -#endif // TMWA_GENERIC_ENUM_HPP +} // namespace tmwa diff --git a/src/generic/fwd.hpp b/src/generic/fwd.hpp new file mode 100644 index 0000000..81c4e26 --- /dev/null +++ b/src/generic/fwd.hpp @@ -0,0 +1,30 @@ +#pragma once +// generic/fwd.hpp - list of type names for generic lib +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +// meh, add more when I feel like it +template<class T> +class dumb_ptr; +class dumb_string; +} // namespace tmwa diff --git a/src/generic/intern-pool.cpp b/src/generic/intern-pool.cpp index f6df5a6..f45b098 100644 --- a/src/generic/intern-pool.cpp +++ b/src/generic/intern-pool.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/generic/intern-pool.hpp b/src/generic/intern-pool.hpp index 0ffddd2..030aa38 100644 --- a/src/generic/intern-pool.hpp +++ b/src/generic/intern-pool.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_GENERIC_INTERN_POOL_HPP -#define TMWA_GENERIC_INTERN_POOL_HPP +#pragma once // intern-pool.hpp - Cached integer/string lookups. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,17 +18,21 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cassert> +#include <cassert> +#include <cstddef> -# include <map> -# include <vector> +#include <map> +#include <vector> -# include "../strings/rstring.hpp" -# include "../strings/zstring.hpp" -# include "../strings/xstring.hpp" +#include "../strings/rstring.hpp" +#include "../strings/zstring.hpp" +#include "../strings/xstring.hpp" + +namespace tmwa +{ class InternPool { std::map<RString, size_t> known; @@ -58,5 +61,4 @@ public: return known.size(); } }; - -#endif // TMWA_GENERIC_INTERN_POOL_HPP +} // namespace tmwa diff --git a/src/generic/intern-pool_test.cpp b/src/generic/intern-pool_test.cpp index b72ab04..c91be91 100644 --- a/src/generic/intern-pool_test.cpp +++ b/src/generic/intern-pool_test.cpp @@ -1,5 +1,5 @@ #include "intern-pool.hpp" -// intern-pool.hpp - Testsuite for cached integer/string lookups. +// intern-pool_test.cpp - Testsuite for cached integer/string lookups. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> // @@ -20,21 +20,25 @@ #include <gtest/gtest.h> -#include "../strings/base.hpp" +#include "../strings/literal.hpp" #include "../poison.hpp" + +namespace tmwa +{ TEST(InternPool, whydoesthisalwaysneedasecondname) { InternPool p; EXPECT_EQ(0, p.size()); - EXPECT_EQ(0, p.intern("hello")); - EXPECT_EQ(0, p.intern("hello")); + EXPECT_EQ(0, p.intern("hello"_s)); + EXPECT_EQ(0, p.intern("hello"_s)); EXPECT_EQ(1, p.size()); - EXPECT_EQ(1, p.intern("world")); - EXPECT_EQ(0, p.intern("hello")); - EXPECT_EQ(1, p.intern("world")); + EXPECT_EQ(1, p.intern("world"_s)); + EXPECT_EQ(0, p.intern("hello"_s)); + EXPECT_EQ(1, p.intern("world"_s)); EXPECT_EQ(2, p.size()); - EXPECT_EQ("hello", p.outtern(0)); - EXPECT_EQ("world", p.outtern(1)); + EXPECT_EQ("hello"_s, p.outtern(0)); + EXPECT_EQ("world"_s, p.outtern(1)); } +} // namespace tmwa diff --git a/src/generic/matrix.cpp b/src/generic/matrix.cpp index e1e1f5e..b14ab7d 100644 --- a/src/generic/matrix.cpp +++ b/src/generic/matrix.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/generic/matrix.hpp b/src/generic/matrix.hpp index 40ff9a8..86ce6c2 100644 --- a/src/generic/matrix.hpp +++ b/src/generic/matrix.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_GENERIC_MATRIX_HPP -#define TMWA_GENERIC_MATRIX_HPP +#pragma once // matrix.hpp - A 2D array. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,12 +18,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cassert> +#include <cassert> -# include "../compat/memory.hpp" +#include "../compat/memory.hpp" + +namespace tmwa +{ template<class T> class Matrix { @@ -74,5 +76,4 @@ public: return _ys; } }; - -#endif // TMWA_GENERIC_MATRIX_HPP +} // namespace tmwa diff --git a/src/generic/md5.cpp b/src/generic/md5.cpp index b49d36f..771ad0f 100644 --- a/src/generic/md5.cpp +++ b/src/generic/md5.cpp @@ -18,17 +18,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <cstring> - #include "../compat/rawmem.hpp" #include "../strings/xstring.hpp" -#include "../strings/vstring.hpp" - -#include "random.hpp" #include "../poison.hpp" + +namespace tmwa +{ // auxilary data /* sin() constant table @@ -250,3 +248,4 @@ MD5_state MD5_from_string(XString msg) } return state; } +} // namespace tmwa diff --git a/src/generic/md5.hpp b/src/generic/md5.hpp index 8b1c6ad..50bc987 100644 --- a/src/generic/md5.hpp +++ b/src/generic/md5.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_GENERIC_MD5CALC_HPP -#define TMWA_GENERIC_MD5CALC_HPP +#pragma once // md5.hpp - Fundamental MD5 operations. // // Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,19 +18,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <netinet/in.h> +#include <cstdint> -# include <cstdint> -# include <cstddef> -# include <cstdio> +#include <array> -# include <array> +#include "../strings/fwd.hpp" +#include "../strings/vstring.hpp" -# include "../strings/fwd.hpp" -# include "../strings/vstring.hpp" +namespace tmwa +{ /// The digest state - becomes the output struct MD5_state { @@ -58,5 +56,4 @@ void MD5_to_str(MD5_state state, md5_string& out); // Convenience MD5_state MD5_from_string(XString msg); - -#endif // TMWA_GENERIC_MD5CALC_HPP +} // namespace tmwa diff --git a/src/generic/md5_test.cpp b/src/generic/md5_test.cpp index f6a2324..86cbd53 100644 --- a/src/generic/md5_test.cpp +++ b/src/generic/md5_test.cpp @@ -25,6 +25,9 @@ #include "../poison.hpp" + +namespace tmwa +{ // This should be made part of the main API, // but is not yet to keep the diff small. // Edit: hack to fix the new strict comparison. @@ -38,11 +41,12 @@ VString<32> MD5(XString in) TEST(md5calc, rfc1321) { - EXPECT_EQ("d41d8cd98f00b204e9800998ecf8427e", MD5("")); - EXPECT_EQ("0cc175b9c0f1b6a831c399e269772661", MD5("a")); - EXPECT_EQ("900150983cd24fb0d6963f7d28e17f72", MD5("abc")); - EXPECT_EQ("f96b697d7cb7938d525a2f31aaf161d0", MD5("message digest")); - EXPECT_EQ("c3fcd3d76192e4007dfb496cca67e13b", MD5("abcdefghijklmnopqrstuvwxyz")); - EXPECT_EQ("d174ab98d277d9f5a5611c2c9f419d9f", MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")); - EXPECT_EQ("57edf4a22be3c955ac49da2e2107b67a", MD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890")); + EXPECT_EQ("d41d8cd98f00b204e9800998ecf8427e"_s, MD5(""_s)); + EXPECT_EQ("0cc175b9c0f1b6a831c399e269772661"_s, MD5("a"_s)); + EXPECT_EQ("900150983cd24fb0d6963f7d28e17f72"_s, MD5("abc"_s)); + EXPECT_EQ("f96b697d7cb7938d525a2f31aaf161d0"_s, MD5("message digest"_s)); + EXPECT_EQ("c3fcd3d76192e4007dfb496cca67e13b"_s, MD5("abcdefghijklmnopqrstuvwxyz"_s)); + EXPECT_EQ("d174ab98d277d9f5a5611c2c9f419d9f"_s, MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"_s)); + EXPECT_EQ("57edf4a22be3c955ac49da2e2107b67a"_s, MD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890"_s)); } +} // namespace tmwa diff --git a/src/generic/oops.cpp b/src/generic/oops.cpp new file mode 100644 index 0000000..601ab37 --- /dev/null +++ b/src/generic/oops.cpp @@ -0,0 +1,48 @@ +#include "oops.hpp" +// oops.cpp - Stuff that shouldn't happen. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <cstdlib> +#include <cstring> +#include <cstdio> + +//#include "../poison.hpp" + + +namespace tmwa +{ +static +std::string do_asprintf(const char *desc, const char *expr, + const char *file, size_t line, const char *function) +{ + char *what = nullptr; + int len = asprintf(&what, "%s:%zu: error: in '%s', incorrectly alleged that '%s' (%s)", + file, line, function, desc, expr); + if (len == -1) + abort(); + std::string out = what; + free(what); + return out; +} + +AssertionError::AssertionError(const char *desc, const char *expr, + const char *file, size_t line, const char *function) +: std::runtime_error(do_asprintf(desc, expr, file, line, function)) +{} +} // namespace tmwa diff --git a/src/generic/oops.hpp b/src/generic/oops.hpp new file mode 100644 index 0000000..f5cf54a --- /dev/null +++ b/src/generic/oops.hpp @@ -0,0 +1,40 @@ +#pragma once +// oops.hpp - Stuff that shouldn't happen. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include <cstddef> + +#include <stdexcept> + + +namespace tmwa +{ +class AssertionError : public std::runtime_error +{ +public: + AssertionError(const char *desc, const char *expr, + const char *file, size_t line, const char *function); +}; + +#define ALLEGE(desc, expr) \ + if (expr) {} \ + else throw AssertionError(desc, #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__) +} // namespace tmwa diff --git a/src/generic/oops_test.cpp b/src/generic/oops_test.cpp new file mode 100644 index 0000000..11c87e7 --- /dev/null +++ b/src/generic/oops_test.cpp @@ -0,0 +1,54 @@ +#include "oops.hpp" +// oops_test.cpp - Testsuite for stuff that shouldn't happen. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <gtest/gtest.h> + +#include "../poison.hpp" + + +namespace tmwa +{ +TEST(oops, okay) +{ + try + { + ALLEGE ("the sky is gray", true); + SUCCEED(); + } + catch (const AssertionError& e) + { + FAIL(); + } +} + +TEST(oops, uhoh) +{ + try + { + ALLEGE ("the sky is falling", 1 == 0); + FAIL(); + } + catch (const AssertionError& e) + { + ASSERT_STREQ(strstr(e.what(), "src/generic/"), + "src/generic/oops_test.cpp:45: error: in 'virtual void tmwa::oops_uhoh_Test::TestBody()', incorrectly alleged that 'the sky is falling' (1 == 0)"); + } +} +} // namespace tmwa diff --git a/src/generic/operators.cpp b/src/generic/operators.cpp index 8d79e1b..614ae51 100644 --- a/src/generic/operators.cpp +++ b/src/generic/operators.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/generic/operators.hpp b/src/generic/operators.hpp index 2a71c46..bb05765 100644 --- a/src/generic/operators.hpp +++ b/src/generic/operators.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_GENERIC_OPERATORS_HPP -#define TMWA_GENERIC_OPERATORS_HPP +#pragma once // operators.hpp - ADL helper for value wrappers. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,8 +18,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" + +namespace tmwa +{ namespace _operators { class Comparable {}; @@ -63,5 +65,4 @@ namespace _operators } using _operators::Comparable; - -#endif // TMWA_GENERIC_OPERATORS_HPP +} // namespace tmwa diff --git a/src/generic/random.cpp b/src/generic/random.cpp index 8a06571..e37a3d1 100644 --- a/src/generic/random.cpp +++ b/src/generic/random.cpp @@ -20,7 +20,11 @@ #include "../poison.hpp" + +namespace tmwa +{ namespace random_ { std::mt19937 generate{std::random_device()()}; } // namespace random_ +} // namespace tmwa diff --git a/src/generic/random.hpp b/src/generic/random.hpp index 45b5371..5d67236 100644 --- a/src/generic/random.hpp +++ b/src/generic/random.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_GENERIC_RANDOM_HPP -#define TMWA_GENERIC_RANDOM_HPP +#pragma once // random.hpp - Random number generation. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,14 +18,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "random.t.hpp" +#include "random.t.hpp" -# include "../sanity.hpp" +#include <random> -# include <random> +namespace tmwa +{ // This is not namespace random since that collides with a C function, // but this can be revisited when everything goes into namespace tmwa. namespace random_ @@ -85,5 +85,4 @@ namespace random_ return random_::choice(il); } } // namespace random_ - -#endif // TMWA_GENERIC_RANDOM_HPP +} // namespace tmwa diff --git a/src/generic/random.t.hpp b/src/generic/random.t.hpp index d26bf56..b4c4764 100644 --- a/src/generic/random.t.hpp +++ b/src/generic/random.t.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_GENERIC_RANDOM_T_HPP -#define TMWA_GENERIC_RANDOM_T_HPP +#pragma once // random.t.hpp - Random number generation. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,8 +18,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" + +namespace tmwa +{ namespace random_ { struct Fraction @@ -39,5 +41,4 @@ namespace random_ } }; } // namespace random_ - -#endif // TMWA_GENERIC_RANDOM_T_HPP +} // namespace tmwa diff --git a/src/generic/random2.hpp b/src/generic/random2.hpp index 40fcbcf..23d165c 100644 --- a/src/generic/random2.hpp +++ b/src/generic/random2.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_GENERIC_RANDOM2_HPP -#define TMWA_GENERIC_RANDOM2_HPP +#pragma once // random2.hpp - Random number generation. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,14 +18,17 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "random.hpp" +#include "random.hpp" -# include <algorithm> +#include <algorithm> -# include "../compat/iter.hpp" +#include "../compat/iter.hpp" + +namespace tmwa +{ namespace random_ { namespace detail @@ -91,5 +93,4 @@ namespace random_ std::random_shuffle(c.begin(), c.end(), random_::to); } } // namespace random_ - -#endif // TMWA_GENERIC_RANDOM2_HPP +} // namespace tmwa diff --git a/src/ints/cmp.cpp b/src/ints/cmp.cpp new file mode 100644 index 0000000..94ff0e3 --- /dev/null +++ b/src/ints/cmp.cpp @@ -0,0 +1,26 @@ +#include "cmp.hpp" +// cmp.cpp - comparison related operations +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/ints/cmp.hpp b/src/ints/cmp.hpp new file mode 100644 index 0000000..08308e1 --- /dev/null +++ b/src/ints/cmp.hpp @@ -0,0 +1,71 @@ +#pragma once +// cmp.hpp - comparison related operations +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include <limits> + +#include "../diagnostics.hpp" + + +namespace tmwa +{ +namespace ints +{ + DIAG_PUSH(); + DIAG_I(type_limits); + template<class T, class U> + T saturate(const U& v) + { + typedef std::numeric_limits<T> Tlim; + typedef std::numeric_limits<U> Ulim; + + if (Tlim::is_signed == Ulim::is_signed) + { + if (v > Tlim::max()) + return Tlim::max(); + if (v < Tlim::min()) + return Tlim::min(); + return v; + } + else if (Ulim::is_signed) + { + // from signed to unsigned + + // Not like v < Tlim::min(), even though Tlim::min() == 0 + if (v < 0) + return 0; + if (v > Tlim::max()) + return Tlim::max(); + return v; + } + else // Tlim::is_signed + { + // from unsigned to signed + if (v > Tlim::max()) + return Tlim::max(); + return v; + } + } + DIAG_POP(); +} // namespace ints + +using ints::saturate; +} // namespace tmwa diff --git a/src/ints/cmp_test.cpp b/src/ints/cmp_test.cpp new file mode 100644 index 0000000..5c605c0 --- /dev/null +++ b/src/ints/cmp_test.cpp @@ -0,0 +1,1465 @@ +#include "cmp.hpp" +// cmp_test.cpp - Testsuite for comparison related operations +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <gtest/gtest.h> + +#include "../compat/cast.hpp" + +#include "../poison.hpp" + + +namespace tmwa +{ +// Google Test is *really* slow to compile this file +#undef EXPECT_EQ +#define EXPECT_EQ(a, b) assert(a == b) + +TEST(ints, sati8) +{ + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int8_t>( -0x80ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x7fULL), saturate<int8_t>(maybe_cast<int8_t>( -0x7fULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x7eULL), saturate<int8_t>(maybe_cast<int8_t>( -0x7eULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x01ULL), saturate<int8_t>(maybe_cast<int8_t>( -0x01ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x00ULL), saturate<int8_t>(maybe_cast<int8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x01ULL), saturate<int8_t>(maybe_cast<int8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7eULL), saturate<int8_t>(maybe_cast<int8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int8_t>( +0x7fULL))); + + EXPECT_EQ(maybe_cast<int8_t>(+0x00ULL), saturate<int8_t>(maybe_cast<uint8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x01ULL), saturate<int8_t>(maybe_cast<uint8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7eULL), saturate<int8_t>(maybe_cast<uint8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint8_t>( +0x7fULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint8_t>( +0x80ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint8_t>( +0xfeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint8_t>( +0xffULL))); + + + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int16_t>( -0x8000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int16_t>( -0x7fffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int16_t>( -0x0100ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int16_t>( -0x00ffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int16_t>( -0x00feULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int16_t>( -0x0081ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int16_t>( -0x0080ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x7fULL), saturate<int8_t>(maybe_cast<int16_t>( -0x007fULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x01ULL), saturate<int8_t>(maybe_cast<int16_t>( -0x0001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x00ULL), saturate<int8_t>(maybe_cast<int16_t>( +0x0000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x01ULL), saturate<int8_t>(maybe_cast<int16_t>( +0x0001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7eULL), saturate<int8_t>(maybe_cast<int16_t>( +0x007eULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int16_t>( +0x007fULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int16_t>( +0x0080ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int16_t>( +0x00feULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int16_t>( +0x00ffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int16_t>( +0x0100ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int16_t>( +0x7ffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int16_t>( +0x7fffULL))); + + EXPECT_EQ(maybe_cast<int8_t>(+0x00ULL), saturate<int8_t>(maybe_cast<uint16_t>(+0x0000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x01ULL), saturate<int8_t>(maybe_cast<uint16_t>(+0x0001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7eULL), saturate<int8_t>(maybe_cast<uint16_t>(+0x007eULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint16_t>(+0x007fULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint16_t>(+0x0080ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint16_t>(+0x00feULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint16_t>(+0x00ffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint16_t>(+0x0100ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint16_t>(+0x7ffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint16_t>(+0x7fffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint16_t>(+0x8000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint16_t>(+0xfffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint16_t>(+0xffffULL))); + + + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x80000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x7fffffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x00010000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x00008001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x00008000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x00007fffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x00000100ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x000000ffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x000000feULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x00000081ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x00000080ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( -0x0000007fULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x01ULL), saturate<int8_t>(maybe_cast<int32_t>( -0x00000001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x00ULL), saturate<int8_t>(maybe_cast<int32_t>( +0x00000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x01ULL), saturate<int8_t>(maybe_cast<int32_t>( +0x00000001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7eULL), saturate<int8_t>(maybe_cast<int32_t>( +0x0000007eULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x0000007fULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x00000080ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x000000feULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x000000ffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x00000100ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x00007ffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x00007fffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x00008000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x00010000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int32_t>( +0x7fffffffULL))); + + EXPECT_EQ(maybe_cast<int8_t>(+0x00ULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x00000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x01ULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x00000001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7eULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x0000007eULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x0000007fULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x00000080ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x000000feULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x000000ffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x00000100ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x00007ffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x00007fffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x00008000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x00010000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x7fffffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0x80000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0xfffffffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint32_t>(+0xffffffffULL))); + + + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x0000000080000001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x0000000000008001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x0000000000000081ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x80ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( -0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int8_t>(-0x01ULL), saturate<int8_t>(maybe_cast<int64_t>( -0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x00ULL), saturate<int8_t>(maybe_cast<int64_t>( +0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x01ULL), saturate<int8_t>(maybe_cast<int64_t>( +0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7eULL), saturate<int8_t>(maybe_cast<int64_t>( +0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<int64_t>( +0x7fffffffffffffffULL))); + + EXPECT_EQ(maybe_cast<int8_t>(+0x00ULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x01ULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7eULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0xfffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int8_t>(+0x7fULL), saturate<int8_t>(maybe_cast<uint64_t>(+0xffffffffffffffffULL))); +} + +TEST(ints, satu8) +{ + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int8_t>( -0x80ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int8_t>( -0x7fULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int8_t>( -0x7eULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int8_t>( -0x01ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x01ULL), saturate<uint8_t>(maybe_cast<int8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7eULL), saturate<uint8_t>(maybe_cast<int8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7fULL), saturate<uint8_t>(maybe_cast<int8_t>( +0x7fULL))); + + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<uint8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x01ULL), saturate<uint8_t>(maybe_cast<uint8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7eULL), saturate<uint8_t>(maybe_cast<uint8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7fULL), saturate<uint8_t>(maybe_cast<uint8_t>( +0x7fULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x80ULL), saturate<uint8_t>(maybe_cast<uint8_t>( +0x80ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xfeULL), saturate<uint8_t>(maybe_cast<uint8_t>( +0xfeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint8_t>( +0xffULL))); + + + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int16_t>( -0x8000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int16_t>( -0x7fffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int16_t>( -0x0100ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int16_t>( -0x00ffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int16_t>( -0x00feULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int16_t>( -0x0081ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int16_t>( -0x0080ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int16_t>( -0x007fULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int16_t>( -0x0001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int16_t>( +0x0000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x01ULL), saturate<uint8_t>(maybe_cast<int16_t>( +0x0001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7eULL), saturate<uint8_t>(maybe_cast<int16_t>( +0x007eULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7fULL), saturate<uint8_t>(maybe_cast<int16_t>( +0x007fULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x80ULL), saturate<uint8_t>(maybe_cast<int16_t>( +0x0080ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xfeULL), saturate<uint8_t>(maybe_cast<int16_t>( +0x00feULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int16_t>( +0x00ffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int16_t>( +0x0100ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int16_t>( +0x7ffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int16_t>( +0x7fffULL))); + + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0x0000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x01ULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0x0001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7eULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0x007eULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7fULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0x007fULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x80ULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0x0080ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xfeULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0x00feULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0x00ffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0x0100ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0x7ffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0x7fffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0x8000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0xfffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint16_t>(+0xffffULL))); + + + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x80000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x7fffffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x00008001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x000000feULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x00000081ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( -0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x00000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x01ULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7eULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x0000007eULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7fULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x80ULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xfeULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x000000feULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x00007ffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int32_t>( +0x7fffffffULL))); + + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x00000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x01ULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7eULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x0000007eULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7fULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x80ULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xfeULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x000000feULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x00007ffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x7fffffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0x80000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0xfffffffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint32_t>(+0xffffffffULL))); + + + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x0000000080000001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x0000000000008001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x0000000000000081ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( -0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x01ULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7eULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7fULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x80ULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xfeULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<int64_t>( +0x7fffffffffffffffULL))); + + EXPECT_EQ(maybe_cast<uint8_t>(+0x00ULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x01ULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7eULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x7fULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0x80ULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xfeULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0xfffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint8_t>(+0xffULL), saturate<uint8_t>(maybe_cast<uint64_t>(+0xffffffffffffffffULL))); +} + +TEST(ints, sati16) +{ + EXPECT_EQ(maybe_cast<int16_t>(-0x80ULL), saturate<int16_t>(maybe_cast<int8_t>( -0x80ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x7fULL), saturate<int16_t>(maybe_cast<int8_t>( -0x7fULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x7eULL), saturate<int16_t>(maybe_cast<int8_t>( -0x7eULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x01ULL), saturate<int16_t>(maybe_cast<int8_t>( -0x01ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00ULL), saturate<int16_t>(maybe_cast<int8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x01ULL), saturate<int16_t>(maybe_cast<int8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7eULL), saturate<int16_t>(maybe_cast<int8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fULL), saturate<int16_t>(maybe_cast<int8_t>( +0x7fULL))); + + EXPECT_EQ(maybe_cast<int16_t>(+0x00ULL), saturate<int16_t>(maybe_cast<uint8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x01ULL), saturate<int16_t>(maybe_cast<uint8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7eULL), saturate<int16_t>(maybe_cast<uint8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fULL), saturate<int16_t>(maybe_cast<uint8_t>( +0x7fULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x80ULL), saturate<int16_t>(maybe_cast<uint8_t>( +0x80ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0xfeULL), saturate<int16_t>(maybe_cast<uint8_t>( +0xfeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0xffULL), saturate<int16_t>(maybe_cast<uint8_t>( +0xffULL))); + + + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int16_t>( -0x8000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x7fffULL), saturate<int16_t>(maybe_cast<int16_t>( -0x7fffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0100ULL), saturate<int16_t>(maybe_cast<int16_t>( -0x0100ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x00ffULL), saturate<int16_t>(maybe_cast<int16_t>( -0x00ffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x00feULL), saturate<int16_t>(maybe_cast<int16_t>( -0x00feULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0081ULL), saturate<int16_t>(maybe_cast<int16_t>( -0x0081ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0080ULL), saturate<int16_t>(maybe_cast<int16_t>( -0x0080ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x007fULL), saturate<int16_t>(maybe_cast<int16_t>( -0x007fULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0001ULL), saturate<int16_t>(maybe_cast<int16_t>( -0x0001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0000ULL), saturate<int16_t>(maybe_cast<int16_t>( +0x0000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0001ULL), saturate<int16_t>(maybe_cast<int16_t>( +0x0001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007eULL), saturate<int16_t>(maybe_cast<int16_t>( +0x007eULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007fULL), saturate<int16_t>(maybe_cast<int16_t>( +0x007fULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0080ULL), saturate<int16_t>(maybe_cast<int16_t>( +0x0080ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00feULL), saturate<int16_t>(maybe_cast<int16_t>( +0x00feULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00ffULL), saturate<int16_t>(maybe_cast<int16_t>( +0x00ffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0100ULL), saturate<int16_t>(maybe_cast<int16_t>( +0x0100ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7ffeULL), saturate<int16_t>(maybe_cast<int16_t>( +0x7ffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int16_t>( +0x7fffULL))); + + EXPECT_EQ(maybe_cast<int16_t>(+0x0000ULL), saturate<int16_t>(maybe_cast<uint16_t>(+0x0000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0001ULL), saturate<int16_t>(maybe_cast<uint16_t>(+0x0001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007eULL), saturate<int16_t>(maybe_cast<uint16_t>(+0x007eULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007fULL), saturate<int16_t>(maybe_cast<uint16_t>(+0x007fULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0080ULL), saturate<int16_t>(maybe_cast<uint16_t>(+0x0080ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00feULL), saturate<int16_t>(maybe_cast<uint16_t>(+0x00feULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00ffULL), saturate<int16_t>(maybe_cast<uint16_t>(+0x00ffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0100ULL), saturate<int16_t>(maybe_cast<uint16_t>(+0x0100ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7ffeULL), saturate<int16_t>(maybe_cast<uint16_t>(+0x7ffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint16_t>(+0x7fffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint16_t>(+0x8000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint16_t>(+0xfffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint16_t>(+0xffffULL))); + + + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int32_t>( -0x80000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int32_t>( -0x7fffffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int32_t>( -0x00010000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int32_t>( -0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int32_t>( -0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int32_t>( -0x00008001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int32_t>( -0x00008000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x7fffULL), saturate<int16_t>(maybe_cast<int32_t>( -0x00007fffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0100ULL), saturate<int16_t>(maybe_cast<int32_t>( -0x00000100ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x00ffULL), saturate<int16_t>(maybe_cast<int32_t>( -0x000000ffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x00feULL), saturate<int16_t>(maybe_cast<int32_t>( -0x000000feULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0081ULL), saturate<int16_t>(maybe_cast<int32_t>( -0x00000081ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0080ULL), saturate<int16_t>(maybe_cast<int32_t>( -0x00000080ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x007fULL), saturate<int16_t>(maybe_cast<int32_t>( -0x0000007fULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0001ULL), saturate<int16_t>(maybe_cast<int32_t>( -0x00000001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0000ULL), saturate<int16_t>(maybe_cast<int32_t>( +0x00000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0001ULL), saturate<int16_t>(maybe_cast<int32_t>( +0x00000001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007eULL), saturate<int16_t>(maybe_cast<int32_t>( +0x0000007eULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007fULL), saturate<int16_t>(maybe_cast<int32_t>( +0x0000007fULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0080ULL), saturate<int16_t>(maybe_cast<int32_t>( +0x00000080ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00feULL), saturate<int16_t>(maybe_cast<int32_t>( +0x000000feULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00ffULL), saturate<int16_t>(maybe_cast<int32_t>( +0x000000ffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0100ULL), saturate<int16_t>(maybe_cast<int32_t>( +0x00000100ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7ffeULL), saturate<int16_t>(maybe_cast<int32_t>( +0x00007ffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int32_t>( +0x00007fffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int32_t>( +0x00008000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int32_t>( +0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int32_t>( +0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int32_t>( +0x00010000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int32_t>( +0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int32_t>( +0x7fffffffULL))); + + EXPECT_EQ(maybe_cast<int16_t>(+0x0000ULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x00000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0001ULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x00000001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007eULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x0000007eULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007fULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x0000007fULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0080ULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x00000080ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00feULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x000000feULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00ffULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x000000ffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0100ULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x00000100ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7ffeULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x00007ffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x00007fffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x00008000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x00010000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x7fffffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint32_t>(+0x80000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint32_t>(+0xfffffffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint32_t>(+0xffffffffULL))); + + + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x0000000080000001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x0000000000008001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x8000ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( -0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0100ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x00ffULL), saturate<int16_t>(maybe_cast<int64_t>( -0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x00feULL), saturate<int16_t>(maybe_cast<int64_t>( -0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0081ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x0000000000000081ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0080ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x007fULL), saturate<int16_t>(maybe_cast<int64_t>( -0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int16_t>(-0x0001ULL), saturate<int16_t>(maybe_cast<int64_t>( -0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0000ULL), saturate<int16_t>(maybe_cast<int64_t>( +0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0001ULL), saturate<int16_t>(maybe_cast<int64_t>( +0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007eULL), saturate<int16_t>(maybe_cast<int64_t>( +0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007fULL), saturate<int16_t>(maybe_cast<int64_t>( +0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0080ULL), saturate<int16_t>(maybe_cast<int64_t>( +0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00feULL), saturate<int16_t>(maybe_cast<int64_t>( +0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00ffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0100ULL), saturate<int16_t>(maybe_cast<int64_t>( +0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7ffeULL), saturate<int16_t>(maybe_cast<int64_t>( +0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<int64_t>( +0x7fffffffffffffffULL))); + + EXPECT_EQ(maybe_cast<int16_t>(+0x0000ULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0001ULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007eULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x007fULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0080ULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00feULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x00ffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x0100ULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7ffeULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0xfffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int16_t>(+0x7fffULL), saturate<int16_t>(maybe_cast<uint64_t>(+0xffffffffffffffffULL))); +} + +TEST(ints, satu16) +{ + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ULL), saturate<uint16_t>(maybe_cast<int8_t>( -0x80ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ULL), saturate<uint16_t>(maybe_cast<int8_t>( -0x7fULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ULL), saturate<uint16_t>(maybe_cast<int8_t>( -0x7eULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ULL), saturate<uint16_t>(maybe_cast<int8_t>( -0x01ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ULL), saturate<uint16_t>(maybe_cast<int8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x01ULL), saturate<uint16_t>(maybe_cast<int8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7eULL), saturate<uint16_t>(maybe_cast<int8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7fULL), saturate<uint16_t>(maybe_cast<int8_t>( +0x7fULL))); + + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ULL), saturate<uint16_t>(maybe_cast<uint8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x01ULL), saturate<uint16_t>(maybe_cast<uint8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7eULL), saturate<uint16_t>(maybe_cast<uint8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7fULL), saturate<uint16_t>(maybe_cast<uint8_t>( +0x7fULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x80ULL), saturate<uint16_t>(maybe_cast<uint8_t>( +0x80ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xfeULL), saturate<uint16_t>(maybe_cast<uint8_t>( +0xfeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffULL), saturate<uint16_t>(maybe_cast<uint8_t>( +0xffULL))); + + + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int16_t>( -0x8000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int16_t>( -0x7fffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int16_t>( -0x0100ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int16_t>( -0x00ffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int16_t>( -0x00feULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int16_t>( -0x0081ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int16_t>( -0x0080ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int16_t>( -0x007fULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int16_t>( -0x0001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int16_t>( +0x0000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0001ULL), saturate<uint16_t>(maybe_cast<int16_t>( +0x0001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007eULL), saturate<uint16_t>(maybe_cast<int16_t>( +0x007eULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007fULL), saturate<uint16_t>(maybe_cast<int16_t>( +0x007fULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0080ULL), saturate<uint16_t>(maybe_cast<int16_t>( +0x0080ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00feULL), saturate<uint16_t>(maybe_cast<int16_t>( +0x00feULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ffULL), saturate<uint16_t>(maybe_cast<int16_t>( +0x00ffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0100ULL), saturate<uint16_t>(maybe_cast<int16_t>( +0x0100ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7ffeULL), saturate<uint16_t>(maybe_cast<int16_t>( +0x7ffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7fffULL), saturate<uint16_t>(maybe_cast<int16_t>( +0x7fffULL))); + + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0x0000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0001ULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0x0001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007eULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0x007eULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007fULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0x007fULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0080ULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0x0080ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00feULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0x00feULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ffULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0x00ffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0100ULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0x0100ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7ffeULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0x7ffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7fffULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0x7fffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x8000ULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0x8000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xfffeULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0xfffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint16_t>(+0xffffULL))); + + + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x80000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x7fffffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x00008001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x000000feULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x00000081ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( -0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x00000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0001ULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007eULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x0000007eULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007fULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0080ULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00feULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x000000feULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ffULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0100ULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7ffeULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x00007ffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7fffULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x8000ULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xfffeULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int32_t>( +0x7fffffffULL))); + + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x00000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0001ULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007eULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x0000007eULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007fULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0080ULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00feULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x000000feULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ffULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0100ULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7ffeULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x00007ffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7fffULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x8000ULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xfffeULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x7fffffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0x80000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0xfffffffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint32_t>(+0xffffffffULL))); + + + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x0000000080000001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x0000000000008001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x0000000000000081ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( -0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0001ULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007eULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007fULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0080ULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00feULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0100ULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7ffeULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7fffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x8000ULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xfffeULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<int64_t>( +0x7fffffffffffffffULL))); + + EXPECT_EQ(maybe_cast<uint16_t>(+0x0000ULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0001ULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007eULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x007fULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0080ULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00feULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x00ffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x0100ULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7ffeULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x7fffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0x8000ULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xfffeULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0xfffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint16_t>(+0xffffULL), saturate<uint16_t>(maybe_cast<uint64_t>(+0xffffffffffffffffULL))); +} + +TEST(ints, sati32) +{ + EXPECT_EQ(maybe_cast<int32_t>(-0x80ULL), saturate<int32_t>(maybe_cast<int8_t>( -0x80ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x7fULL), saturate<int32_t>(maybe_cast<int8_t>( -0x7fULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x7eULL), saturate<int32_t>(maybe_cast<int8_t>( -0x7eULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x01ULL), saturate<int32_t>(maybe_cast<int8_t>( -0x01ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00ULL), saturate<int32_t>(maybe_cast<int8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x01ULL), saturate<int32_t>(maybe_cast<int8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7eULL), saturate<int32_t>(maybe_cast<int8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fULL), saturate<int32_t>(maybe_cast<int8_t>( +0x7fULL))); + + EXPECT_EQ(maybe_cast<int32_t>(+0x00ULL), saturate<int32_t>(maybe_cast<uint8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x01ULL), saturate<int32_t>(maybe_cast<uint8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7eULL), saturate<int32_t>(maybe_cast<uint8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fULL), saturate<int32_t>(maybe_cast<uint8_t>( +0x7fULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x80ULL), saturate<int32_t>(maybe_cast<uint8_t>( +0x80ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0xfeULL), saturate<int32_t>(maybe_cast<uint8_t>( +0xfeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0xffULL), saturate<int32_t>(maybe_cast<uint8_t>( +0xffULL))); + + + EXPECT_EQ(maybe_cast<int32_t>(-0x8000ULL), saturate<int32_t>(maybe_cast<int16_t>( -0x8000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x7fffULL), saturate<int32_t>(maybe_cast<int16_t>( -0x7fffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x0100ULL), saturate<int32_t>(maybe_cast<int16_t>( -0x0100ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00ffULL), saturate<int32_t>(maybe_cast<int16_t>( -0x00ffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00feULL), saturate<int32_t>(maybe_cast<int16_t>( -0x00feULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x0081ULL), saturate<int32_t>(maybe_cast<int16_t>( -0x0081ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x0080ULL), saturate<int32_t>(maybe_cast<int16_t>( -0x0080ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x007fULL), saturate<int32_t>(maybe_cast<int16_t>( -0x007fULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x0001ULL), saturate<int32_t>(maybe_cast<int16_t>( -0x0001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000ULL), saturate<int32_t>(maybe_cast<int16_t>( +0x0000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0001ULL), saturate<int32_t>(maybe_cast<int16_t>( +0x0001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x007eULL), saturate<int32_t>(maybe_cast<int16_t>( +0x007eULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x007fULL), saturate<int32_t>(maybe_cast<int16_t>( +0x007fULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0080ULL), saturate<int32_t>(maybe_cast<int16_t>( +0x0080ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00feULL), saturate<int32_t>(maybe_cast<int16_t>( +0x00feULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00ffULL), saturate<int32_t>(maybe_cast<int16_t>( +0x00ffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0100ULL), saturate<int32_t>(maybe_cast<int16_t>( +0x0100ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7ffeULL), saturate<int32_t>(maybe_cast<int16_t>( +0x7ffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffULL), saturate<int32_t>(maybe_cast<int16_t>( +0x7fffULL))); + + EXPECT_EQ(maybe_cast<int32_t>(+0x0000ULL), saturate<int32_t>(maybe_cast<uint16_t>(+0x0000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0001ULL), saturate<int32_t>(maybe_cast<uint16_t>(+0x0001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x007eULL), saturate<int32_t>(maybe_cast<uint16_t>(+0x007eULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x007fULL), saturate<int32_t>(maybe_cast<uint16_t>(+0x007fULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0080ULL), saturate<int32_t>(maybe_cast<uint16_t>(+0x0080ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00feULL), saturate<int32_t>(maybe_cast<uint16_t>(+0x00feULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00ffULL), saturate<int32_t>(maybe_cast<uint16_t>(+0x00ffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0100ULL), saturate<int32_t>(maybe_cast<uint16_t>(+0x0100ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7ffeULL), saturate<int32_t>(maybe_cast<uint16_t>(+0x7ffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffULL), saturate<int32_t>(maybe_cast<uint16_t>(+0x7fffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x8000ULL), saturate<int32_t>(maybe_cast<uint16_t>(+0x8000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0xfffeULL), saturate<int32_t>(maybe_cast<uint16_t>(+0xfffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0xffffULL), saturate<int32_t>(maybe_cast<uint16_t>(+0xffffULL))); + + + EXPECT_EQ(maybe_cast<int32_t>(-0x80000000ULL), saturate<int32_t>(maybe_cast<int32_t>( -0x80000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x7fffffffULL), saturate<int32_t>(maybe_cast<int32_t>( -0x7fffffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00010000ULL), saturate<int32_t>(maybe_cast<int32_t>( -0x00010000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x0000ffffULL), saturate<int32_t>(maybe_cast<int32_t>( -0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x0000fffeULL), saturate<int32_t>(maybe_cast<int32_t>( -0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00008001ULL), saturate<int32_t>(maybe_cast<int32_t>( -0x00008001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00008000ULL), saturate<int32_t>(maybe_cast<int32_t>( -0x00008000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00007fffULL), saturate<int32_t>(maybe_cast<int32_t>( -0x00007fffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00000100ULL), saturate<int32_t>(maybe_cast<int32_t>( -0x00000100ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x000000ffULL), saturate<int32_t>(maybe_cast<int32_t>( -0x000000ffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x000000feULL), saturate<int32_t>(maybe_cast<int32_t>( -0x000000feULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00000081ULL), saturate<int32_t>(maybe_cast<int32_t>( -0x00000081ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00000080ULL), saturate<int32_t>(maybe_cast<int32_t>( -0x00000080ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x0000007fULL), saturate<int32_t>(maybe_cast<int32_t>( -0x0000007fULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00000001ULL), saturate<int32_t>(maybe_cast<int32_t>( -0x00000001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000000ULL), saturate<int32_t>(maybe_cast<int32_t>( +0x00000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000001ULL), saturate<int32_t>(maybe_cast<int32_t>( +0x00000001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000007eULL), saturate<int32_t>(maybe_cast<int32_t>( +0x0000007eULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000007fULL), saturate<int32_t>(maybe_cast<int32_t>( +0x0000007fULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000080ULL), saturate<int32_t>(maybe_cast<int32_t>( +0x00000080ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x000000feULL), saturate<int32_t>(maybe_cast<int32_t>( +0x000000feULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x000000ffULL), saturate<int32_t>(maybe_cast<int32_t>( +0x000000ffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000100ULL), saturate<int32_t>(maybe_cast<int32_t>( +0x00000100ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00007ffeULL), saturate<int32_t>(maybe_cast<int32_t>( +0x00007ffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00007fffULL), saturate<int32_t>(maybe_cast<int32_t>( +0x00007fffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00008000ULL), saturate<int32_t>(maybe_cast<int32_t>( +0x00008000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000fffeULL), saturate<int32_t>(maybe_cast<int32_t>( +0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000ffffULL), saturate<int32_t>(maybe_cast<int32_t>( +0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00010000ULL), saturate<int32_t>(maybe_cast<int32_t>( +0x00010000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7ffffffeULL), saturate<int32_t>(maybe_cast<int32_t>( +0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<int32_t>( +0x7fffffffULL))); + + EXPECT_EQ(maybe_cast<int32_t>(+0x00000000ULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x00000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000001ULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x00000001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000007eULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x0000007eULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000007fULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x0000007fULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000080ULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x00000080ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x000000feULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x000000feULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x000000ffULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x000000ffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000100ULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x00000100ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00007ffeULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x00007ffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00007fffULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x00007fffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00008000ULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x00008000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000fffeULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000ffffULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00010000ULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x00010000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7ffffffeULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x7fffffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint32_t>(+0x80000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint32_t>(+0xfffffffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint32_t>(+0xffffffffULL))); + + + EXPECT_EQ(maybe_cast<int32_t>(-0x80000000ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x80000000ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x80000000ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x80000000ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x80000000ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x80000000ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x0000000080000001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x80000000ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x7fffffffULL), saturate<int32_t>(maybe_cast<int64_t>( -0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00010000ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x0000ffffULL), saturate<int32_t>(maybe_cast<int64_t>( -0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x0000fffeULL), saturate<int32_t>(maybe_cast<int64_t>( -0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00008001ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x0000000000008001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00008000ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00007fffULL), saturate<int32_t>(maybe_cast<int64_t>( -0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00000100ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x000000ffULL), saturate<int32_t>(maybe_cast<int64_t>( -0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x000000feULL), saturate<int32_t>(maybe_cast<int64_t>( -0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00000081ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x0000000000000081ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00000080ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x0000007fULL), saturate<int32_t>(maybe_cast<int64_t>( -0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int32_t>(-0x00000001ULL), saturate<int32_t>(maybe_cast<int64_t>( -0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000000ULL), saturate<int32_t>(maybe_cast<int64_t>( +0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000001ULL), saturate<int32_t>(maybe_cast<int64_t>( +0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000007eULL), saturate<int32_t>(maybe_cast<int64_t>( +0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000007fULL), saturate<int32_t>(maybe_cast<int64_t>( +0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000080ULL), saturate<int32_t>(maybe_cast<int64_t>( +0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x000000feULL), saturate<int32_t>(maybe_cast<int64_t>( +0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x000000ffULL), saturate<int32_t>(maybe_cast<int64_t>( +0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000100ULL), saturate<int32_t>(maybe_cast<int64_t>( +0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00007ffeULL), saturate<int32_t>(maybe_cast<int64_t>( +0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00007fffULL), saturate<int32_t>(maybe_cast<int64_t>( +0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00008000ULL), saturate<int32_t>(maybe_cast<int64_t>( +0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000fffeULL), saturate<int32_t>(maybe_cast<int64_t>( +0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000ffffULL), saturate<int32_t>(maybe_cast<int64_t>( +0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00010000ULL), saturate<int32_t>(maybe_cast<int64_t>( +0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7ffffffeULL), saturate<int32_t>(maybe_cast<int64_t>( +0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<int64_t>( +0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<int64_t>( +0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<int64_t>( +0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<int64_t>( +0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<int64_t>( +0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<int64_t>( +0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<int64_t>( +0x7fffffffffffffffULL))); + + EXPECT_EQ(maybe_cast<int32_t>(+0x00000000ULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000001ULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000007eULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000007fULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000080ULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x000000feULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x000000ffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00000100ULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00007ffeULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00007fffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00008000ULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000fffeULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x0000ffffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x00010000ULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7ffffffeULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0xfffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int32_t>(+0x7fffffffULL), saturate<int32_t>(maybe_cast<uint64_t>(+0xffffffffffffffffULL))); +} + +TEST(ints, satu32) +{ + EXPECT_EQ(maybe_cast<uint32_t>(+0x00ULL), saturate<uint32_t>(maybe_cast<int8_t>( -0x80ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00ULL), saturate<uint32_t>(maybe_cast<int8_t>( -0x7fULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00ULL), saturate<uint32_t>(maybe_cast<int8_t>( -0x7eULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00ULL), saturate<uint32_t>(maybe_cast<int8_t>( -0x01ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00ULL), saturate<uint32_t>(maybe_cast<int8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x01ULL), saturate<uint32_t>(maybe_cast<int8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7eULL), saturate<uint32_t>(maybe_cast<int8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7fULL), saturate<uint32_t>(maybe_cast<int8_t>( +0x7fULL))); + + EXPECT_EQ(maybe_cast<uint32_t>(+0x00ULL), saturate<uint32_t>(maybe_cast<uint8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x01ULL), saturate<uint32_t>(maybe_cast<uint8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7eULL), saturate<uint32_t>(maybe_cast<uint8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7fULL), saturate<uint32_t>(maybe_cast<uint8_t>( +0x7fULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x80ULL), saturate<uint32_t>(maybe_cast<uint8_t>( +0x80ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xfeULL), saturate<uint32_t>(maybe_cast<uint8_t>( +0xfeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffULL), saturate<uint32_t>(maybe_cast<uint8_t>( +0xffULL))); + + + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ULL), saturate<uint32_t>(maybe_cast<int16_t>( -0x8000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ULL), saturate<uint32_t>(maybe_cast<int16_t>( -0x7fffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ULL), saturate<uint32_t>(maybe_cast<int16_t>( -0x0100ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ULL), saturate<uint32_t>(maybe_cast<int16_t>( -0x00ffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ULL), saturate<uint32_t>(maybe_cast<int16_t>( -0x00feULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ULL), saturate<uint32_t>(maybe_cast<int16_t>( -0x0081ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ULL), saturate<uint32_t>(maybe_cast<int16_t>( -0x0080ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ULL), saturate<uint32_t>(maybe_cast<int16_t>( -0x007fULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ULL), saturate<uint32_t>(maybe_cast<int16_t>( -0x0001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ULL), saturate<uint32_t>(maybe_cast<int16_t>( +0x0000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0001ULL), saturate<uint32_t>(maybe_cast<int16_t>( +0x0001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x007eULL), saturate<uint32_t>(maybe_cast<int16_t>( +0x007eULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x007fULL), saturate<uint32_t>(maybe_cast<int16_t>( +0x007fULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0080ULL), saturate<uint32_t>(maybe_cast<int16_t>( +0x0080ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00feULL), saturate<uint32_t>(maybe_cast<int16_t>( +0x00feULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00ffULL), saturate<uint32_t>(maybe_cast<int16_t>( +0x00ffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0100ULL), saturate<uint32_t>(maybe_cast<int16_t>( +0x0100ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7ffeULL), saturate<uint32_t>(maybe_cast<int16_t>( +0x7ffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7fffULL), saturate<uint32_t>(maybe_cast<int16_t>( +0x7fffULL))); + + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0x0000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0001ULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0x0001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x007eULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0x007eULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x007fULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0x007fULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0080ULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0x0080ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00feULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0x00feULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00ffULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0x00ffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0100ULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0x0100ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7ffeULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0x7ffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7fffULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0x7fffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x8000ULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0x8000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xfffeULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0xfffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffULL), saturate<uint32_t>(maybe_cast<uint16_t>(+0xffffULL))); + + + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x80000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x7fffffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x00008001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x000000feULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x00000081ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( -0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x00000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000001ULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000007eULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x0000007eULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000007fULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000080ULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x000000feULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x000000feULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x000000ffULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000100ULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00007ffeULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x00007ffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00007fffULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00008000ULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000fffeULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ffffULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00010000ULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7ffffffeULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7fffffffULL), saturate<uint32_t>(maybe_cast<int32_t>( +0x7fffffffULL))); + + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x00000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000001ULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000007eULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x0000007eULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000007fULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000080ULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x000000feULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x000000feULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x000000ffULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000100ULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00007ffeULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x00007ffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00007fffULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00008000ULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000fffeULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ffffULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00010000ULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7ffffffeULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7fffffffULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x7fffffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x80000000ULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0x80000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xfffffffeULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0xfffffffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<uint32_t>(+0xffffffffULL))); + + + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x0000000080000001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x0000000000008001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x0000000000000081ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( -0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000001ULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000007eULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000007fULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000080ULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x000000feULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x000000ffULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000100ULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00007ffeULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00007fffULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00008000ULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000fffeULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ffffULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00010000ULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7ffffffeULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7fffffffULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x80000000ULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xfffffffeULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<int64_t>( +0x7fffffffffffffffULL))); + + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000000ULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000001ULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000007eULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000007fULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000080ULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x000000feULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x000000ffULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00000100ULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00007ffeULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00007fffULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00008000ULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000fffeULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x0000ffffULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x00010000ULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7ffffffeULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x7fffffffULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0x80000000ULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xfffffffeULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0xfffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint32_t>(+0xffffffffULL), saturate<uint32_t>(maybe_cast<uint64_t>(+0xffffffffffffffffULL))); +} + +TEST(ints, sati64) +{ + EXPECT_EQ(maybe_cast<int64_t>(-0x80ULL), saturate<int64_t>(maybe_cast<int8_t>( -0x80ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x7fULL), saturate<int64_t>(maybe_cast<int8_t>( -0x7fULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x7eULL), saturate<int64_t>(maybe_cast<int8_t>( -0x7eULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x01ULL), saturate<int64_t>(maybe_cast<int8_t>( -0x01ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00ULL), saturate<int64_t>(maybe_cast<int8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x01ULL), saturate<int64_t>(maybe_cast<int8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7eULL), saturate<int64_t>(maybe_cast<int8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7fULL), saturate<int64_t>(maybe_cast<int8_t>( +0x7fULL))); + + EXPECT_EQ(maybe_cast<int64_t>(+0x00ULL), saturate<int64_t>(maybe_cast<uint8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x01ULL), saturate<int64_t>(maybe_cast<uint8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7eULL), saturate<int64_t>(maybe_cast<uint8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7fULL), saturate<int64_t>(maybe_cast<uint8_t>( +0x7fULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x80ULL), saturate<int64_t>(maybe_cast<uint8_t>( +0x80ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0xfeULL), saturate<int64_t>(maybe_cast<uint8_t>( +0xfeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0xffULL), saturate<int64_t>(maybe_cast<uint8_t>( +0xffULL))); + + + EXPECT_EQ(maybe_cast<int64_t>(-0x8000ULL), saturate<int64_t>(maybe_cast<int16_t>( -0x8000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x7fffULL), saturate<int64_t>(maybe_cast<int16_t>( -0x7fffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0100ULL), saturate<int64_t>(maybe_cast<int16_t>( -0x0100ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00ffULL), saturate<int64_t>(maybe_cast<int16_t>( -0x00ffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00feULL), saturate<int64_t>(maybe_cast<int16_t>( -0x00feULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0081ULL), saturate<int64_t>(maybe_cast<int16_t>( -0x0081ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0080ULL), saturate<int64_t>(maybe_cast<int16_t>( -0x0080ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x007fULL), saturate<int64_t>(maybe_cast<int16_t>( -0x007fULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0001ULL), saturate<int64_t>(maybe_cast<int16_t>( -0x0001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000ULL), saturate<int64_t>(maybe_cast<int16_t>( +0x0000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0001ULL), saturate<int64_t>(maybe_cast<int16_t>( +0x0001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x007eULL), saturate<int64_t>(maybe_cast<int16_t>( +0x007eULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x007fULL), saturate<int64_t>(maybe_cast<int16_t>( +0x007fULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0080ULL), saturate<int64_t>(maybe_cast<int16_t>( +0x0080ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00feULL), saturate<int64_t>(maybe_cast<int16_t>( +0x00feULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00ffULL), saturate<int64_t>(maybe_cast<int16_t>( +0x00ffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0100ULL), saturate<int64_t>(maybe_cast<int16_t>( +0x0100ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7ffeULL), saturate<int64_t>(maybe_cast<int16_t>( +0x7ffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7fffULL), saturate<int64_t>(maybe_cast<int16_t>( +0x7fffULL))); + + EXPECT_EQ(maybe_cast<int64_t>(+0x0000ULL), saturate<int64_t>(maybe_cast<uint16_t>(+0x0000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0001ULL), saturate<int64_t>(maybe_cast<uint16_t>(+0x0001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x007eULL), saturate<int64_t>(maybe_cast<uint16_t>(+0x007eULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x007fULL), saturate<int64_t>(maybe_cast<uint16_t>(+0x007fULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0080ULL), saturate<int64_t>(maybe_cast<uint16_t>(+0x0080ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00feULL), saturate<int64_t>(maybe_cast<uint16_t>(+0x00feULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00ffULL), saturate<int64_t>(maybe_cast<uint16_t>(+0x00ffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0100ULL), saturate<int64_t>(maybe_cast<uint16_t>(+0x0100ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7ffeULL), saturate<int64_t>(maybe_cast<uint16_t>(+0x7ffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7fffULL), saturate<int64_t>(maybe_cast<uint16_t>(+0x7fffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x8000ULL), saturate<int64_t>(maybe_cast<uint16_t>(+0x8000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0xfffeULL), saturate<int64_t>(maybe_cast<uint16_t>(+0xfffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0xffffULL), saturate<int64_t>(maybe_cast<uint16_t>(+0xffffULL))); + + + EXPECT_EQ(maybe_cast<int64_t>(-0x80000000ULL), saturate<int64_t>(maybe_cast<int32_t>( -0x80000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x7fffffffULL), saturate<int64_t>(maybe_cast<int32_t>( -0x7fffffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00010000ULL), saturate<int64_t>(maybe_cast<int32_t>( -0x00010000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000ffffULL), saturate<int64_t>(maybe_cast<int32_t>( -0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000fffeULL), saturate<int64_t>(maybe_cast<int32_t>( -0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00008001ULL), saturate<int64_t>(maybe_cast<int32_t>( -0x00008001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00008000ULL), saturate<int64_t>(maybe_cast<int32_t>( -0x00008000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00007fffULL), saturate<int64_t>(maybe_cast<int32_t>( -0x00007fffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00000100ULL), saturate<int64_t>(maybe_cast<int32_t>( -0x00000100ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x000000ffULL), saturate<int64_t>(maybe_cast<int32_t>( -0x000000ffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x000000feULL), saturate<int64_t>(maybe_cast<int32_t>( -0x000000feULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00000081ULL), saturate<int64_t>(maybe_cast<int32_t>( -0x00000081ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00000080ULL), saturate<int64_t>(maybe_cast<int32_t>( -0x00000080ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000007fULL), saturate<int64_t>(maybe_cast<int32_t>( -0x0000007fULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00000001ULL), saturate<int64_t>(maybe_cast<int32_t>( -0x00000001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000000ULL), saturate<int64_t>(maybe_cast<int32_t>( +0x00000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000001ULL), saturate<int64_t>(maybe_cast<int32_t>( +0x00000001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000007eULL), saturate<int64_t>(maybe_cast<int32_t>( +0x0000007eULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000007fULL), saturate<int64_t>(maybe_cast<int32_t>( +0x0000007fULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000080ULL), saturate<int64_t>(maybe_cast<int32_t>( +0x00000080ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000feULL), saturate<int64_t>(maybe_cast<int32_t>( +0x000000feULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000ffULL), saturate<int64_t>(maybe_cast<int32_t>( +0x000000ffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000100ULL), saturate<int64_t>(maybe_cast<int32_t>( +0x00000100ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00007ffeULL), saturate<int64_t>(maybe_cast<int32_t>( +0x00007ffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00007fffULL), saturate<int64_t>(maybe_cast<int32_t>( +0x00007fffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00008000ULL), saturate<int64_t>(maybe_cast<int32_t>( +0x00008000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000fffeULL), saturate<int64_t>(maybe_cast<int32_t>( +0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000ffffULL), saturate<int64_t>(maybe_cast<int32_t>( +0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00010000ULL), saturate<int64_t>(maybe_cast<int32_t>( +0x00010000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7ffffffeULL), saturate<int64_t>(maybe_cast<int32_t>( +0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7fffffffULL), saturate<int64_t>(maybe_cast<int32_t>( +0x7fffffffULL))); + + EXPECT_EQ(maybe_cast<int64_t>(+0x00000000ULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x00000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000001ULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x00000001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000007eULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x0000007eULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000007fULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x0000007fULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000080ULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x00000080ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000feULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x000000feULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000ffULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x000000ffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000100ULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x00000100ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00007ffeULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x00007ffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00007fffULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x00007fffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00008000ULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x00008000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000fffeULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x0000fffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000ffffULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x0000ffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00010000ULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x00010000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7ffffffeULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7fffffffULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x7fffffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x80000000ULL), saturate<int64_t>(maybe_cast<uint32_t>(+0x80000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0xfffffffeULL), saturate<int64_t>(maybe_cast<uint32_t>(+0xfffffffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0xffffffffULL), saturate<int64_t>(maybe_cast<uint32_t>(+0xffffffffULL))); + + + EXPECT_EQ(maybe_cast<int64_t>(-0x8000000000000000ULL), saturate<int64_t>(maybe_cast<int64_t>( -0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x7fffffffffffffffULL), saturate<int64_t>(maybe_cast<int64_t>( -0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000000100000000ULL), saturate<int64_t>(maybe_cast<int64_t>( -0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00000000ffffffffULL), saturate<int64_t>(maybe_cast<int64_t>( -0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00000000fffffffeULL), saturate<int64_t>(maybe_cast<int64_t>( -0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000000080000001ULL), saturate<int64_t>(maybe_cast<int64_t>( -0x0000000080000001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000000080000000ULL), saturate<int64_t>(maybe_cast<int64_t>( -0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x000000007fffffffULL), saturate<int64_t>(maybe_cast<int64_t>( -0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000000000010000ULL), saturate<int64_t>(maybe_cast<int64_t>( -0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x000000000000ffffULL), saturate<int64_t>(maybe_cast<int64_t>( -0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x000000000000fffeULL), saturate<int64_t>(maybe_cast<int64_t>( -0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000000000008001ULL), saturate<int64_t>(maybe_cast<int64_t>( -0x0000000000008001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000000000008000ULL), saturate<int64_t>(maybe_cast<int64_t>( -0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000000000007fffULL), saturate<int64_t>(maybe_cast<int64_t>( -0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000000000000100ULL), saturate<int64_t>(maybe_cast<int64_t>( -0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00000000000000ffULL), saturate<int64_t>(maybe_cast<int64_t>( -0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x00000000000000feULL), saturate<int64_t>(maybe_cast<int64_t>( -0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000000000000081ULL), saturate<int64_t>(maybe_cast<int64_t>( -0x0000000000000081ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000000000000080ULL), saturate<int64_t>(maybe_cast<int64_t>( -0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x000000000000007fULL), saturate<int64_t>(maybe_cast<int64_t>( -0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int64_t>(-0x0000000000000001ULL), saturate<int64_t>(maybe_cast<int64_t>( -0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000000000ULL), saturate<int64_t>(maybe_cast<int64_t>( +0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000000001ULL), saturate<int64_t>(maybe_cast<int64_t>( +0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000000000007eULL), saturate<int64_t>(maybe_cast<int64_t>( +0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000000000007fULL), saturate<int64_t>(maybe_cast<int64_t>( +0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000000080ULL), saturate<int64_t>(maybe_cast<int64_t>( +0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000000000000feULL), saturate<int64_t>(maybe_cast<int64_t>( +0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000000000000ffULL), saturate<int64_t>(maybe_cast<int64_t>( +0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000000100ULL), saturate<int64_t>(maybe_cast<int64_t>( +0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000007ffeULL), saturate<int64_t>(maybe_cast<int64_t>( +0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000007fffULL), saturate<int64_t>(maybe_cast<int64_t>( +0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000008000ULL), saturate<int64_t>(maybe_cast<int64_t>( +0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000000000fffeULL), saturate<int64_t>(maybe_cast<int64_t>( +0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000000000ffffULL), saturate<int64_t>(maybe_cast<int64_t>( +0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000010000ULL), saturate<int64_t>(maybe_cast<int64_t>( +0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000007ffffffeULL), saturate<int64_t>(maybe_cast<int64_t>( +0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000007fffffffULL), saturate<int64_t>(maybe_cast<int64_t>( +0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000080000000ULL), saturate<int64_t>(maybe_cast<int64_t>( +0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000000fffffffeULL), saturate<int64_t>(maybe_cast<int64_t>( +0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000000ffffffffULL), saturate<int64_t>(maybe_cast<int64_t>( +0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000100000000ULL), saturate<int64_t>(maybe_cast<int64_t>( +0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7ffffffffffffffeULL), saturate<int64_t>(maybe_cast<int64_t>( +0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7fffffffffffffffULL), saturate<int64_t>(maybe_cast<int64_t>( +0x7fffffffffffffffULL))); + + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000000000ULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000000001ULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000000000007eULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000000000007fULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000000080ULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000000000000feULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000000000000ffULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000000100ULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000007ffeULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000007fffULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000008000ULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000000000fffeULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000000000ffffULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000000010000ULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000007ffffffeULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x000000007fffffffULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000080000000ULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000000fffffffeULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x00000000ffffffffULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x0000000100000000ULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7ffffffffffffffeULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7fffffffffffffffULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7fffffffffffffffULL), saturate<int64_t>(maybe_cast<uint64_t>(+0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7fffffffffffffffULL), saturate<int64_t>(maybe_cast<uint64_t>(+0xfffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<int64_t>(+0x7fffffffffffffffULL), saturate<int64_t>(maybe_cast<uint64_t>(+0xffffffffffffffffULL))); +} + +TEST(ints, satu64) +{ + EXPECT_EQ(maybe_cast<uint64_t>(+0x00ULL), saturate<uint64_t>(maybe_cast<int8_t>( -0x80ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00ULL), saturate<uint64_t>(maybe_cast<int8_t>( -0x7fULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00ULL), saturate<uint64_t>(maybe_cast<int8_t>( -0x7eULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00ULL), saturate<uint64_t>(maybe_cast<int8_t>( -0x01ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00ULL), saturate<uint64_t>(maybe_cast<int8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x01ULL), saturate<uint64_t>(maybe_cast<int8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7eULL), saturate<uint64_t>(maybe_cast<int8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7fULL), saturate<uint64_t>(maybe_cast<int8_t>( +0x7fULL))); + + EXPECT_EQ(maybe_cast<uint64_t>(+0x00ULL), saturate<uint64_t>(maybe_cast<uint8_t>( +0x00ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x01ULL), saturate<uint64_t>(maybe_cast<uint8_t>( +0x01ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7eULL), saturate<uint64_t>(maybe_cast<uint8_t>( +0x7eULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7fULL), saturate<uint64_t>(maybe_cast<uint8_t>( +0x7fULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x80ULL), saturate<uint64_t>(maybe_cast<uint8_t>( +0x80ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0xfeULL), saturate<uint64_t>(maybe_cast<uint8_t>( +0xfeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0xffULL), saturate<uint64_t>(maybe_cast<uint8_t>( +0xffULL))); + + + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ULL), saturate<uint64_t>(maybe_cast<int16_t>( -0x8000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ULL), saturate<uint64_t>(maybe_cast<int16_t>( -0x7fffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ULL), saturate<uint64_t>(maybe_cast<int16_t>( -0x0100ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ULL), saturate<uint64_t>(maybe_cast<int16_t>( -0x00ffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ULL), saturate<uint64_t>(maybe_cast<int16_t>( -0x00feULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ULL), saturate<uint64_t>(maybe_cast<int16_t>( -0x0081ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ULL), saturate<uint64_t>(maybe_cast<int16_t>( -0x0080ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ULL), saturate<uint64_t>(maybe_cast<int16_t>( -0x007fULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ULL), saturate<uint64_t>(maybe_cast<int16_t>( -0x0001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ULL), saturate<uint64_t>(maybe_cast<int16_t>( +0x0000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0001ULL), saturate<uint64_t>(maybe_cast<int16_t>( +0x0001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x007eULL), saturate<uint64_t>(maybe_cast<int16_t>( +0x007eULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x007fULL), saturate<uint64_t>(maybe_cast<int16_t>( +0x007fULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0080ULL), saturate<uint64_t>(maybe_cast<int16_t>( +0x0080ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00feULL), saturate<uint64_t>(maybe_cast<int16_t>( +0x00feULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00ffULL), saturate<uint64_t>(maybe_cast<int16_t>( +0x00ffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0100ULL), saturate<uint64_t>(maybe_cast<int16_t>( +0x0100ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7ffeULL), saturate<uint64_t>(maybe_cast<int16_t>( +0x7ffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7fffULL), saturate<uint64_t>(maybe_cast<int16_t>( +0x7fffULL))); + + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0x0000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0001ULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0x0001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x007eULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0x007eULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x007fULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0x007fULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0080ULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0x0080ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00feULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0x00feULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00ffULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0x00ffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0100ULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0x0100ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7ffeULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0x7ffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7fffULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0x7fffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x8000ULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0x8000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0xfffeULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0xfffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0xffffULL), saturate<uint64_t>(maybe_cast<uint16_t>(+0xffffULL))); + + + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x80000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x7fffffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x00008001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x000000feULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x00000081ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( -0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x00000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000001ULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000007eULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x0000007eULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000007fULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000080ULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000feULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x000000feULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000ffULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000100ULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00007ffeULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x00007ffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00007fffULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00008000ULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000fffeULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ffffULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00010000ULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7ffffffeULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7fffffffULL), saturate<uint64_t>(maybe_cast<int32_t>( +0x7fffffffULL))); + + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x00000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000001ULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x00000001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000007eULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x0000007eULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000007fULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x0000007fULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000080ULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x00000080ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000feULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x000000feULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000ffULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x000000ffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000100ULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x00000100ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00007ffeULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x00007ffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00007fffULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x00007fffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00008000ULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x00008000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000fffeULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x0000fffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000ffffULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x0000ffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00010000ULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x00010000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7ffffffeULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x7ffffffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7fffffffULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x7fffffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x80000000ULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0x80000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0xfffffffeULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0xfffffffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0xffffffffULL), saturate<uint64_t>(maybe_cast<uint32_t>(+0xffffffffULL))); + + + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x0000000080000001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x0000000000008001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x0000000000000081ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( -0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000001ULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000000000007eULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000000000007fULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000080ULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000000000feULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000000000ffULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000100ULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000007ffeULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000007fffULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000008000ULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000000000fffeULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000000000ffffULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000010000ULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000007ffffffeULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000007fffffffULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000080000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000fffffffeULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ffffffffULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000100000000ULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7ffffffffffffffeULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7fffffffffffffffULL), saturate<uint64_t>(maybe_cast<int64_t>( +0x7fffffffffffffffULL))); + + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000000ULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x0000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000001ULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x0000000000000001ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000000000007eULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x000000000000007eULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000000000007fULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x000000000000007fULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000080ULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x0000000000000080ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000000000feULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x00000000000000feULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000000000ffULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x00000000000000ffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000000100ULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x0000000000000100ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000007ffeULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x0000000000007ffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000007fffULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x0000000000007fffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000008000ULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x0000000000008000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000000000fffeULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x000000000000fffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000000000ffffULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x000000000000ffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000000010000ULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x0000000000010000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000007ffffffeULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x000000007ffffffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x000000007fffffffULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x000000007fffffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000080000000ULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x0000000080000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000fffffffeULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x00000000fffffffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x00000000ffffffffULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x00000000ffffffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x0000000100000000ULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x0000000100000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7ffffffffffffffeULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x7ffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x7fffffffffffffffULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x7fffffffffffffffULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0x8000000000000000ULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0x8000000000000000ULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0xfffffffffffffffeULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0xfffffffffffffffeULL))); + EXPECT_EQ(maybe_cast<uint64_t>(+0xffffffffffffffffULL), saturate<uint64_t>(maybe_cast<uint64_t>(+0xffffffffffffffffULL))); +} +} // namespace tmwa diff --git a/src/ints/fwd.hpp b/src/ints/fwd.hpp new file mode 100644 index 0000000..a08e546 --- /dev/null +++ b/src/ints/fwd.hpp @@ -0,0 +1,27 @@ +#pragma once +// ints/fwd.hpp - list of type names for ints library +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +// meh, add more when I feel like it +} // namespace tmwa diff --git a/src/ints/little.cpp b/src/ints/little.cpp new file mode 100644 index 0000000..0ae5bf7 --- /dev/null +++ b/src/ints/little.cpp @@ -0,0 +1,26 @@ +#include "little.hpp" +// little.cpp - integers of known endianness +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/ints/little.hpp b/src/ints/little.hpp new file mode 100644 index 0000000..b3046f7 --- /dev/null +++ b/src/ints/little.hpp @@ -0,0 +1,210 @@ +#pragma once +// little.hpp - integers of known endianness +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include <endian.h> + +#include <cstdint> + + +namespace tmwa +{ +// We implement our own actual swapping, because glibc emits assembly +// instead of letting the *compiler* do what it does best. +#if __BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN +# error "broken endians" +#endif + +namespace ints +{ + // gcc doesn't always provide a builtin for this, + // but it *does* optimize hand-written ones + constexpr + uint16_t bswap16(uint16_t v) + { + return v >> 8 | v << 8; + } + + // TODO hoist this to byte.hpp and also implement big.hpp + struct Byte + { + uint8_t value; + }; + + struct Little16 + { + uint8_t data[2]; + }; + + struct Little32 + { + uint8_t data[4]; + }; + + struct Little64 + { + uint8_t data[8]; + }; + + + inline __attribute__((warn_unused_result)) + bool native_to_network(Byte *net, uint8_t nat) + { + net->value = nat; + return true; + } + inline __attribute__((warn_unused_result)) + bool native_to_network(Little16 *net, uint16_t nat) + { + if (__BYTE_ORDER == __BIG_ENDIAN) + nat = bswap16(nat); + __builtin_memcpy(net, &nat, 2); + return true; + } + inline __attribute__((warn_unused_result)) + bool native_to_network(Little32 *net, uint32_t nat) + { + if (__BYTE_ORDER == __BIG_ENDIAN) + nat = __builtin_bswap32(nat); + __builtin_memcpy(net, &nat, 4); + return true; + } + inline __attribute__((warn_unused_result)) + bool native_to_network(Little64 *net, uint64_t nat) + { + if (__BYTE_ORDER == __BIG_ENDIAN) + nat = __builtin_bswap64(nat); + __builtin_memcpy(net, &nat, 8); + return true; + } + + inline __attribute__((warn_unused_result)) + bool network_to_native(uint8_t *nat, Byte net) + { + *nat = net.value; + return true; + } + inline __attribute__((warn_unused_result)) + bool network_to_native(uint16_t *nat, Little16 net) + { + uint16_t tmp; + __builtin_memcpy(&tmp, &net, 2); + if (__BYTE_ORDER == __BIG_ENDIAN) + tmp = bswap16(tmp); + *nat = tmp; + return true; + } + inline __attribute__((warn_unused_result)) + bool network_to_native(uint32_t *nat, Little32 net) + { + uint32_t tmp; + __builtin_memcpy(&tmp, &net, 4); + if (__BYTE_ORDER == __BIG_ENDIAN) + tmp = __builtin_bswap32(tmp); + *nat = tmp; + return true; + } + inline __attribute__((warn_unused_result)) + bool network_to_native(uint64_t *nat, Little64 net) + { + uint64_t tmp; + __builtin_memcpy(&tmp, &net, 8); + if (__BYTE_ORDER == __BIG_ENDIAN) + tmp = __builtin_bswap64(tmp); + *nat = tmp; + return true; + } + + + inline __attribute__((warn_unused_result)) + bool native_to_network(Byte *net, int8_t nat) + { + net->value = nat; + return true; + } + inline __attribute__((warn_unused_result)) + bool native_to_network(Little16 *net, int16_t nat) + { + if (__BYTE_ORDER == __BIG_ENDIAN) + nat = bswap16(nat); + __builtin_memcpy(net, &nat, 2); + return true; + } + inline __attribute__((warn_unused_result)) + bool native_to_network(Little32 *net, int32_t nat) + { + if (__BYTE_ORDER == __BIG_ENDIAN) + nat = __builtin_bswap32(nat); + __builtin_memcpy(net, &nat, 4); + return true; + } + inline __attribute__((warn_unused_result)) + bool native_to_network(Little64 *net, int64_t nat) + { + if (__BYTE_ORDER == __BIG_ENDIAN) + nat = __builtin_bswap64(nat); + __builtin_memcpy(net, &nat, 8); + return true; + } + + inline __attribute__((warn_unused_result)) + bool network_to_native(int8_t *nat, Byte net) + { + *nat = net.value; + return true; + } + inline __attribute__((warn_unused_result)) + bool network_to_native(int16_t *nat, Little16 net) + { + int16_t tmp; + __builtin_memcpy(&tmp, &net, 2); + if (__BYTE_ORDER == __BIG_ENDIAN) + tmp = bswap16(tmp); + *nat = tmp; + return true; + } + inline __attribute__((warn_unused_result)) + bool network_to_native(int32_t *nat, Little32 net) + { + int32_t tmp; + __builtin_memcpy(&tmp, &net, 4); + if (__BYTE_ORDER == __BIG_ENDIAN) + tmp = __builtin_bswap32(tmp); + *nat = tmp; + return true; + } + inline __attribute__((warn_unused_result)) + bool network_to_native(int64_t *nat, Little64 net) + { + int64_t tmp; + __builtin_memcpy(&tmp, &net, 8); + if (__BYTE_ORDER == __BIG_ENDIAN) + tmp = __builtin_bswap64(tmp); + *nat = tmp; + return true; + } +} // namespace ints + +using ints::Byte; +using ints::Little16; +using ints::Little32; +using ints::Little64; +} // namespace tmwa diff --git a/src/ints/udl.cpp b/src/ints/udl.cpp new file mode 100644 index 0000000..3988903 --- /dev/null +++ b/src/ints/udl.cpp @@ -0,0 +1,26 @@ +#include "udl.hpp" +// udl.cpp - user-defined literals for integers. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/ints/udl.hpp b/src/ints/udl.hpp new file mode 100644 index 0000000..f85a186 --- /dev/null +++ b/src/ints/udl.hpp @@ -0,0 +1,227 @@ +#pragma once +// udl.hpp - user-defined literals for integers. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include <cstdint> + +#include <type_traits> + + +namespace tmwa +{ +namespace ints +{ + namespace + { + typedef unsigned long long ullong; + template<char C> + struct CharParser + { + constexpr static + bool is_dec = '0' <= C && C <= '9'; + constexpr static + bool is_upper = 'A' <= C && C <= 'F'; + constexpr static + bool is_lower = 'a' <= C && C <= 'f'; + + static_assert(is_dec || is_upper || is_lower, "char base"); + + constexpr static + ullong value = is_upper ? (C - 'A' + 10) : is_lower ? (C - 'a' + 10) : C - '0'; + }; + + template<ullong base, ullong accum, char... C> + struct BaseParser; + template<ullong base, ullong accum, char F, char... R> + struct BaseParser<base, accum, F, R...> + { + constexpr static + ullong mulled = accum * base; + constexpr static + ullong add = CharParser<F>::value; + static_assert(add < base, "parse base"); + constexpr static + ullong added = mulled + add; + static_assert(added > accum || accum == 0, "parse overflow"); + + constexpr static + ullong value = BaseParser<base, added, R...>::value; + }; + template<ullong base, ullong accum> + struct BaseParser<base, accum> + { + constexpr static + ullong value = accum; + }; + + template<char... C> + struct IntParser + { + constexpr static + ullong value = BaseParser<10, 0, C...>::value; + }; + + template<char... C> + struct IntParser<'0', C...> + { + constexpr static + ullong value = BaseParser<8, 0, C...>::value; + }; + + template<char... C> + struct IntParser<'0', 'x', C...> + { + constexpr static + ullong value = BaseParser<16, 0, C...>::value; + }; + + template<char... C> + struct IntParser<'0', 'X', C...> + { + constexpr static + ullong value = BaseParser<16, 0, C...>::value; + }; + + template<char... C> + struct IntParser<'0', 'b', C...> + { + constexpr static + ullong value = BaseParser<2, 0, C...>::value; + }; + + template<char... C> + struct IntParser<'0', 'B', C...> + { + constexpr static + ullong value = BaseParser<2, 0, C...>::value; + }; + + template<bool S, ullong V> + struct SignedMagnitudeConstant + { + static constexpr + bool sign = S; + static constexpr + ullong magnitude = V; + + template<class T> + constexpr + operator T() const + { + typedef typename std::make_unsigned<T>::type U; + // boo, body of constexpr function can't use variables +#define is_signed bool(T(-1) < T(0)) + static_assert(is_signed >= (sign && magnitude), "signed"); +#define max ullong(ullong(U(-1) >> is_signed)) + static_assert(magnitude <= max || (sign && magnitude == max + 1), "magna"); +#undef is_signed +#undef max + return sign ? T(ullong(-magnitude)) : T(magnitude); + } + }; + + template<bool S1, ullong V1, bool S2, ullong V2> + constexpr + bool operator == (SignedMagnitudeConstant<S1, V1>, SignedMagnitudeConstant<S2, V2>) + { + return V1 == V2 && (S1 == S2 || !V1); + } + template<bool S1, ullong V1, bool S2, ullong V2> + constexpr + bool operator != (SignedMagnitudeConstant<S1, V1> lhs, SignedMagnitudeConstant<S2, V2> rhs) + { + return !(lhs == rhs); + } + template<bool S, ullong V> + constexpr + SignedMagnitudeConstant<!S, V> operator -(SignedMagnitudeConstant<S, V>) + { + return {}; + } + + struct pint8 { int8_t value; int8_t operator +() { return value; } }; + struct pint16 { int16_t value; int16_t operator +() { return value; } }; + struct pint32 { int32_t value; int32_t operator +() { return value; } }; + struct pint64 { int64_t value; int64_t operator +() { return value; } }; + struct nint8 { int8_t value; int8_t operator -() { return value; } }; + struct nint16 { int16_t value; int16_t operator -() { return value; } }; + struct nint32 { int32_t value; int32_t operator -() { return value; } }; + struct nint64 { int64_t value; int64_t operator -() { return value; } }; + + template<char... C> + constexpr + SignedMagnitudeConstant<false, IntParser<C...>::value> operator "" _const() + { return {}; } + + template<char... C> + constexpr + uint8_t operator "" _u8 () { return operator "" _const<C...>(); } + template<char... C> + constexpr + uint16_t operator "" _u16 () { return operator "" _const<C...>(); } + template<char... C> + constexpr + uint32_t operator "" _u32 () { return operator "" _const<C...>(); } + template<char... C> + constexpr + uint64_t operator "" _u64 () { return operator "" _const<C...>(); } + template<char... C> + constexpr + pint8 operator "" _p8 () { return pint8{operator "" _const<C...>()}; } + template<char... C> + constexpr + pint16 operator "" _p16 () { return pint16{operator "" _const<C...>()}; } + template<char... C> + constexpr + pint32 operator "" _p32 () { return pint32{operator "" _const<C...>()}; } + template<char... C> + constexpr + pint64 operator "" _p64 () { return pint64{operator "" _const<C...>()}; } + template<char... C> + constexpr + nint8 operator "" _n8 () { return nint8{-operator "" _const<C...>()}; } + template<char... C> + constexpr + nint16 operator "" _n16 () { return nint16{-operator "" _const<C...>()}; } + template<char... C> + constexpr + nint32 operator "" _n32 () { return nint32{-operator "" _const<C...>()}; } + template<char... C> + constexpr + nint64 operator "" _n64 () { return nint64{-operator "" _const<C...>()}; } + } // anonymous namespace +} // namespace ints + +using ints::operator "" _const; + +using ints::operator "" _u8; +using ints::operator "" _u16; +using ints::operator "" _u32; +using ints::operator "" _u64; +using ints::operator "" _p8; +using ints::operator "" _p16; +using ints::operator "" _p32; +using ints::operator "" _p64; +using ints::operator "" _n8; +using ints::operator "" _n16; +using ints::operator "" _n32; +using ints::operator "" _n64; +} // namespace tmwa diff --git a/src/ints/udl_test.cpp b/src/ints/udl_test.cpp new file mode 100644 index 0000000..279edde --- /dev/null +++ b/src/ints/udl_test.cpp @@ -0,0 +1,788 @@ +#include "udl.hpp" +// udl_test.cpp - Testsuite for a user-defined integer suffixes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <gtest/gtest.h> + +#include "../compat/cast.hpp" + +#include "../diagnostics.hpp" +#include "../poison.hpp" + + +namespace tmwa +{ +DIAG_PUSH(); +DIAG_I(unused_variable); + +TEST(ints, smc) +{ + { + ints::SignedMagnitudeConstant<false, 0> i; + (void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + (void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0> i; + (void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + (void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x7e> i; + (void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + (void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x7e> i; + (void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x7f> i; + (void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + (void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x7f> i; + (void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x80> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + (void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x80> i; + (void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0xfe> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + (void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0xfe> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0xff> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + (void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0xff> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false,0x100> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x100> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x7ffe> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x7ffe> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x7fff> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x7fff> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x8000> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x8000> i; + //(void)static_cast<int8_t>(i); + (void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0xfffe> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0xfffe> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0xffff> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + (void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0xffff> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false,0x10000> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x10000> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x7ffffffe> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x7ffffffe> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x7fffffff> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x7fffffff> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x80000000> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x80000000> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + (void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0xfffffffe> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0xfffffffe> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0xffffffff> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + (void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0xffffffff> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false,0x100000000> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + //(void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x100000000> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x7ffffffffffffffe> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + //(void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x7ffffffffffffffe> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x7fffffffffffffff> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + //(void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x7fffffffffffffff> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0x8000000000000000> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + //(void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + //(void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0x8000000000000000> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + (void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0xfffffffffffffffe> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + //(void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + //(void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0xfffffffffffffffe> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + //(void)static_cast<int64_t>(i); + } + { + ints::SignedMagnitudeConstant<false, 0xffffffffffffffff> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + //(void)static_cast<int64_t>(i); + //(void)static_cast<uint8_t>(i); + //(void)static_cast<uint16_t>(i); + //(void)static_cast<uint32_t>(i); + (void)static_cast<uint64_t>(i); + } + { + ints::SignedMagnitudeConstant<true, 0xffffffffffffffff> i; + //(void)static_cast<int8_t>(i); + //(void)static_cast<int16_t>(i); + //(void)static_cast<int32_t>(i); + //(void)static_cast<int64_t>(i); + } + { + //ints::SignedMagnitudeConstant<false,0x10000000000000000> i; + } + { + //ints::SignedMagnitudeConstant<true, 0x10000000000000000> i; + } +} +DIAG_POP(); + +TEST(ints, constant) +{ + // gtest is funny with conversions + assert(0_const == (ints::SignedMagnitudeConstant<false, 0>{})); + assert(1_const == (ints::SignedMagnitudeConstant<false, 1>{})); + assert(1_const == (ints::SignedMagnitudeConstant<false, 1>{})); +} + +TEST(ints, udl8) +{ + EXPECT_EQ(0b00000000_u8, maybe_cast<uint8_t>(0b00000000U)); + EXPECT_EQ(0b00000001_u8, maybe_cast<uint8_t>(0b00000001U)); + EXPECT_EQ(0b11111110_u8, maybe_cast<uint8_t>(0b11111110U)); + EXPECT_EQ(0b11111111_u8, maybe_cast<uint8_t>(0b11111111U)); + EXPECT_EQ(-0b10000000_n8, maybe_cast<int8_t>(-0b10000000)); + EXPECT_EQ(-0b01111111_n8, maybe_cast<int8_t>(-0b01111111)); + EXPECT_EQ(-0b00000001_n8, maybe_cast<int8_t>(-0b00000001)); + EXPECT_EQ(+0b00000000_p8, maybe_cast<int8_t>(0b00000000)); + EXPECT_EQ(+0b00000001_p8, maybe_cast<int8_t>(0b00000001)); + EXPECT_EQ(+0b01111110_p8, maybe_cast<int8_t>(0b01111110)); + EXPECT_EQ(+0b01111111_p8, maybe_cast<int8_t>(0b01111111)); + + EXPECT_EQ(0B00000000_u8, maybe_cast<uint8_t>(0B00000000U)); + EXPECT_EQ(0B00000001_u8, maybe_cast<uint8_t>(0B00000001U)); + EXPECT_EQ(0B11111110_u8, maybe_cast<uint8_t>(0B11111110U)); + EXPECT_EQ(0B11111111_u8, maybe_cast<uint8_t>(0B11111111U)); + EXPECT_EQ(-0B10000000_n8, maybe_cast<int8_t>(-0B10000000)); + EXPECT_EQ(-0B01111111_n8, maybe_cast<int8_t>(-0B01111111)); + EXPECT_EQ(-0B00000001_n8, maybe_cast<int8_t>(-0B00000001)); + EXPECT_EQ(+0B00000000_p8, maybe_cast<int8_t>(0B00000000)); + EXPECT_EQ(+0B00000001_p8, maybe_cast<int8_t>(0B00000001)); + EXPECT_EQ(+0B01111110_p8, maybe_cast<int8_t>(0B01111110)); + EXPECT_EQ(+0B01111111_p8, maybe_cast<int8_t>(0B01111111)); + + EXPECT_EQ(0000_u8, maybe_cast<uint8_t>(0000U)); + EXPECT_EQ(0001_u8, maybe_cast<uint8_t>(0001U)); + EXPECT_EQ(0376_u8, maybe_cast<uint8_t>(0376U)); + EXPECT_EQ(0377_u8, maybe_cast<uint8_t>(0377U)); + EXPECT_EQ(-0200_n8, maybe_cast<int8_t>(-0200)); + EXPECT_EQ(-0177_n8, maybe_cast<int8_t>(-0177)); + EXPECT_EQ(-0001_n8, maybe_cast<int8_t>(-0001)); + EXPECT_EQ(+0000_p8, maybe_cast<int8_t>(0000)); + EXPECT_EQ(+0001_p8, maybe_cast<int8_t>(0001)); + EXPECT_EQ(+0176_p8, maybe_cast<int8_t>(0176)); + EXPECT_EQ(+0177_p8, maybe_cast<int8_t>(0177)); + + EXPECT_EQ(0_u8, maybe_cast<uint8_t>(0U)); + EXPECT_EQ(1_u8, maybe_cast<uint8_t>(1U)); + EXPECT_EQ(254_u8, maybe_cast<uint8_t>(254U)); + EXPECT_EQ(255_u8, maybe_cast<uint8_t>(255U)); + EXPECT_EQ(-128_n8, maybe_cast<int8_t>(-128)); + EXPECT_EQ(-127_n8, maybe_cast<int8_t>(-127)); + EXPECT_EQ(-1_n8, maybe_cast<int8_t>(-1)); + EXPECT_EQ(+0_p8, maybe_cast<int8_t>(0)); + EXPECT_EQ(+1_p8, maybe_cast<int8_t>(1)); + EXPECT_EQ(+126_p8, maybe_cast<int8_t>(126)); + EXPECT_EQ(+127_p8, maybe_cast<int8_t>(127)); + + EXPECT_EQ(0x00_u8, maybe_cast<uint8_t>(0x00U)); + EXPECT_EQ(0x01_u8, maybe_cast<uint8_t>(0x01U)); + EXPECT_EQ(0xfe_u8, maybe_cast<uint8_t>(0xfeU)); + EXPECT_EQ(0xff_u8, maybe_cast<uint8_t>(0xffU)); + EXPECT_EQ(-0x80_n8, maybe_cast<int8_t>(-0x80)); + EXPECT_EQ(-0x7f_n8, maybe_cast<int8_t>(-0x7f)); + EXPECT_EQ(-0x01_n8, maybe_cast<int8_t>(-0x01)); + EXPECT_EQ(+0x00_p8, maybe_cast<int8_t>(0x00)); + EXPECT_EQ(+0x01_p8, maybe_cast<int8_t>(0x01)); + EXPECT_EQ(+0x7e_p8, maybe_cast<int8_t>(0x7e)); + EXPECT_EQ(+0x7f_p8, maybe_cast<int8_t>(0x7f)); + + EXPECT_EQ(0X00_u8, maybe_cast<uint8_t>(0X00U)); + EXPECT_EQ(0X01_u8, maybe_cast<uint8_t>(0X01U)); + EXPECT_EQ(0XFE_u8, maybe_cast<uint8_t>(0XFEU)); + EXPECT_EQ(0XFF_u8, maybe_cast<uint8_t>(0XFFU)); + EXPECT_EQ(-0X80_n8, maybe_cast<int8_t>(-0X80)); + EXPECT_EQ(-0X7F_n8, maybe_cast<int8_t>(-0X7F)); + EXPECT_EQ(-0X01_n8, maybe_cast<int8_t>(-0X01)); + EXPECT_EQ(+0X00_p8, maybe_cast<int8_t>(0X00)); + EXPECT_EQ(+0X01_p8, maybe_cast<int8_t>(0X01)); + EXPECT_EQ(+0X7E_p8, maybe_cast<int8_t>(0X7E)); + EXPECT_EQ(+0X7F_p8, maybe_cast<int8_t>(0X7F)); +} + +TEST(ints, udl16) +{ + EXPECT_EQ(0b0000000000000000_u16, maybe_cast<uint16_t>(0b0000000000000000U)); + EXPECT_EQ(0b0000000000000001_u16, maybe_cast<uint16_t>(0b0000000000000001U)); + EXPECT_EQ(0b1111111111111110_u16, maybe_cast<uint16_t>(0b1111111111111110U)); + EXPECT_EQ(0b1111111111111111_u16, maybe_cast<uint16_t>(0b1111111111111111U)); + EXPECT_EQ(-0b1000000000000000_n16, maybe_cast<int16_t>(-0b1000000000000000)); + EXPECT_EQ(-0b0111111111111111_n16, maybe_cast<int16_t>(-0b0111111111111111)); + EXPECT_EQ(-0b0000000000000001_n16, maybe_cast<int16_t>(-0b0000000000000001)); + EXPECT_EQ(+0b0000000000000000_p16, maybe_cast<int16_t>(0b0000000000000000)); + EXPECT_EQ(+0b0000000000000001_p16, maybe_cast<int16_t>(0b0000000000000001)); + EXPECT_EQ(+0b0111111111111110_p16, maybe_cast<int16_t>(0b0111111111111110)); + EXPECT_EQ(+0b0111111111111111_p16, maybe_cast<int16_t>(0b0111111111111111)); + + EXPECT_EQ(0B0000000000000000_u16, maybe_cast<uint16_t>(0B0000000000000000U)); + EXPECT_EQ(0B0000000000000001_u16, maybe_cast<uint16_t>(0B0000000000000001U)); + EXPECT_EQ(0B1111111111111110_u16, maybe_cast<uint16_t>(0B1111111111111110U)); + EXPECT_EQ(0B1111111111111111_u16, maybe_cast<uint16_t>(0B1111111111111111U)); + EXPECT_EQ(-0B1000000000000000_n16, maybe_cast<int16_t>(-0B1000000000000000)); + EXPECT_EQ(-0B0111111111111111_n16, maybe_cast<int16_t>(-0B0111111111111111)); + EXPECT_EQ(-0B0000000000000001_n16, maybe_cast<int16_t>(-0B0000000000000001)); + EXPECT_EQ(+0B0000000000000000_p16, maybe_cast<int16_t>(0B0000000000000000)); + EXPECT_EQ(+0B0000000000000001_p16, maybe_cast<int16_t>(0B0000000000000001)); + EXPECT_EQ(+0B0111111111111110_p16, maybe_cast<int16_t>(0B0111111111111110)); + EXPECT_EQ(+0B0111111111111111_p16, maybe_cast<int16_t>(0B0111111111111111)); + + EXPECT_EQ(0000000_u16, maybe_cast<uint16_t>(0000000U)); + EXPECT_EQ(0000001_u16, maybe_cast<uint16_t>(0000001U)); + EXPECT_EQ(0177776_u16, maybe_cast<uint16_t>(0177776U)); + EXPECT_EQ(0177777_u16, maybe_cast<uint16_t>(0177777U)); + EXPECT_EQ(-0100000_n16, maybe_cast<int16_t>(-0100000)); + EXPECT_EQ(-0077777_n16, maybe_cast<int16_t>(-0077777)); + EXPECT_EQ(-0000001_n16, maybe_cast<int16_t>(-0000001)); + EXPECT_EQ(+000000_p16, maybe_cast<int16_t>(000000)); + EXPECT_EQ(+000001_p16, maybe_cast<int16_t>(000001)); + EXPECT_EQ(+077776_p16, maybe_cast<int16_t>(077776)); + EXPECT_EQ(+077777_p16, maybe_cast<int16_t>(077777)); + + EXPECT_EQ(0_u16, maybe_cast<uint16_t>(0U)); + EXPECT_EQ(1_u16, maybe_cast<uint16_t>(1U)); + EXPECT_EQ(65534_u16, maybe_cast<uint16_t>(65534U)); + EXPECT_EQ(65535_u16, maybe_cast<uint16_t>(65535U)); + EXPECT_EQ(-32768_n16, maybe_cast<int16_t>(-32768)); + EXPECT_EQ(-32767_n16, maybe_cast<int16_t>(-32767)); + EXPECT_EQ(-1_n16, maybe_cast<int16_t>(-1)); + EXPECT_EQ(+0_p16, maybe_cast<int16_t>(0)); + EXPECT_EQ(+1_p16, maybe_cast<int16_t>(1)); + EXPECT_EQ(+32766_p16, maybe_cast<int16_t>(32766)); + EXPECT_EQ(+32767_p16, maybe_cast<int16_t>(32767)); + + EXPECT_EQ(0x0000_u16, maybe_cast<uint16_t>(0x0000U)); + EXPECT_EQ(0x0001_u16, maybe_cast<uint16_t>(0x0001U)); + EXPECT_EQ(0xfffe_u16, maybe_cast<uint16_t>(0xfffeU)); + EXPECT_EQ(0xffff_u16, maybe_cast<uint16_t>(0xffffU)); + EXPECT_EQ(-0x8000_n16, maybe_cast<int16_t>(-0x8000)); + EXPECT_EQ(-0x7fff_n16, maybe_cast<int16_t>(-0x7fff)); + EXPECT_EQ(-0x0001_n16, maybe_cast<int16_t>(-0x0001)); + EXPECT_EQ(+0x0000_p16, maybe_cast<int16_t>(0x0000)); + EXPECT_EQ(+0x0001_p16, maybe_cast<int16_t>(0x0001)); + EXPECT_EQ(+0x7ffe_p16, maybe_cast<int16_t>(0x7ffe)); + EXPECT_EQ(+0x7fff_p16, maybe_cast<int16_t>(0x7fff)); + + EXPECT_EQ(0X0000_u16, maybe_cast<uint16_t>(0X0000U)); + EXPECT_EQ(0X0001_u16, maybe_cast<uint16_t>(0X0001U)); + EXPECT_EQ(0XFFFE_u16, maybe_cast<uint16_t>(0XFFFEU)); + EXPECT_EQ(0XFFFF_u16, maybe_cast<uint16_t>(0XFFFFU)); + EXPECT_EQ(-0X8000_n16, maybe_cast<int16_t>(-0X8000)); + EXPECT_EQ(-0X7FFF_n16, maybe_cast<int16_t>(-0X7FFF)); + EXPECT_EQ(-0X0001_n16, maybe_cast<int16_t>(-0X0001)); + EXPECT_EQ(+0X0000_p16, maybe_cast<int16_t>(0X0000)); + EXPECT_EQ(+0X0001_p16, maybe_cast<int16_t>(0X0001)); + EXPECT_EQ(+0X7FFE_p16, maybe_cast<int16_t>(0X7FFE)); + EXPECT_EQ(+0X7FFF_p16, maybe_cast<int16_t>(0X7FFF)); +} + +TEST(ints, udl32) +{ + EXPECT_EQ(0b00000000000000000000000000000000_u32, maybe_cast<uint32_t>(0b00000000000000000000000000000000U)); + EXPECT_EQ(0b00000000000000000000000000000001_u32, maybe_cast<uint32_t>(0b00000000000000000000000000000001U)); + EXPECT_EQ(0b11111111111111111111111111111110_u32, maybe_cast<uint32_t>(0b11111111111111111111111111111110U)); + EXPECT_EQ(0b11111111111111111111111111111111_u32, maybe_cast<uint32_t>(0b11111111111111111111111111111111U)); + EXPECT_EQ(-0b10000000000000000000000000000000_n32, maybe_cast<int32_t>(-0b10000000000000000000000000000000)); + EXPECT_EQ(-0b01111111111111111111111111111111_n32, maybe_cast<int32_t>(-0b01111111111111111111111111111111)); + EXPECT_EQ(-0b00000000000000000000000000000001_n32, maybe_cast<int32_t>(-0b00000000000000000000000000000001)); + EXPECT_EQ(+0b00000000000000000000000000000000_p32, maybe_cast<int32_t>(0b00000000000000000000000000000000)); + EXPECT_EQ(+0b00000000000000000000000000000001_p32, maybe_cast<int32_t>(0b00000000000000000000000000000001)); + EXPECT_EQ(+0b01111111111111111111111111111110_p32, maybe_cast<int32_t>(0b01111111111111111111111111111110)); + EXPECT_EQ(+0b01111111111111111111111111111111_p32, maybe_cast<int32_t>(0b01111111111111111111111111111111)); + + EXPECT_EQ(0B00000000000000000000000000000000_u32, maybe_cast<uint32_t>(0B00000000000000000000000000000000U)); + EXPECT_EQ(0B00000000000000000000000000000001_u32, maybe_cast<uint32_t>(0B00000000000000000000000000000001U)); + EXPECT_EQ(0B11111111111111111111111111111110_u32, maybe_cast<uint32_t>(0B11111111111111111111111111111110U)); + EXPECT_EQ(0B11111111111111111111111111111111_u32, maybe_cast<uint32_t>(0B11111111111111111111111111111111U)); + EXPECT_EQ(-0B10000000000000000000000000000000_n32, maybe_cast<int32_t>(-0B10000000000000000000000000000000)); + EXPECT_EQ(-0B01111111111111111111111111111111_n32, maybe_cast<int32_t>(-0B01111111111111111111111111111111)); + EXPECT_EQ(-0B00000000000000000000000000000001_n32, maybe_cast<int32_t>(-0B00000000000000000000000000000001)); + EXPECT_EQ(+0B00000000000000000000000000000000_p32, maybe_cast<int32_t>(0B00000000000000000000000000000000)); + EXPECT_EQ(+0B00000000000000000000000000000001_p32, maybe_cast<int32_t>(0B00000000000000000000000000000001)); + EXPECT_EQ(+0B01111111111111111111111111111110_p32, maybe_cast<int32_t>(0B01111111111111111111111111111110)); + EXPECT_EQ(+0B01111111111111111111111111111111_p32, maybe_cast<int32_t>(0B01111111111111111111111111111111)); + + EXPECT_EQ(000000000000_u32, maybe_cast<uint32_t>(000000000000U)); + EXPECT_EQ(000000000001_u32, maybe_cast<uint32_t>(000000000001U)); + EXPECT_EQ(037777777776_u32, maybe_cast<uint32_t>(037777777776U)); + EXPECT_EQ(037777777777_u32, maybe_cast<uint32_t>(037777777777U)); + EXPECT_EQ(-020000000000_n32, maybe_cast<int32_t>(-020000000000)); + EXPECT_EQ(-017777777777_n32, maybe_cast<int32_t>(-017777777777)); + EXPECT_EQ(-000000000001_n32, maybe_cast<int32_t>(-000000000001)); + EXPECT_EQ(+000000000000_p32, maybe_cast<int32_t>(000000000000)); + EXPECT_EQ(+000000000001_p32, maybe_cast<int32_t>(000000000001)); + EXPECT_EQ(+017777777776_p32, maybe_cast<int32_t>(017777777776)); + EXPECT_EQ(+017777777777_p32, maybe_cast<int32_t>(017777777777)); + + EXPECT_EQ(0_u32, maybe_cast<uint32_t>(0U)); + EXPECT_EQ(1_u32, maybe_cast<uint32_t>(1U)); + EXPECT_EQ(4294967294_u32, maybe_cast<uint32_t>(4294967294U)); + EXPECT_EQ(4294967295_u32, maybe_cast<uint32_t>(4294967295U)); + EXPECT_EQ(-2147483648_n32, maybe_cast<int32_t>(-2147483648)); + EXPECT_EQ(-2147483647_n32, maybe_cast<int32_t>(-2147483647)); + EXPECT_EQ(-1_n32, maybe_cast<int32_t>(-1)); + EXPECT_EQ(+0_p32, maybe_cast<int32_t>(0)); + EXPECT_EQ(+1_p32, maybe_cast<int32_t>(1)); + EXPECT_EQ(+2147483646_p32, maybe_cast<int32_t>(2147483646)); + EXPECT_EQ(+2147483647_p32, maybe_cast<int32_t>(2147483647)); + + EXPECT_EQ(0x00000000_u32, maybe_cast<uint32_t>(0x00000000U)); + EXPECT_EQ(0x00000001_u32, maybe_cast<uint32_t>(0x00000001U)); + EXPECT_EQ(0xfffffffe_u32, maybe_cast<uint32_t>(0xfffffffeU)); + EXPECT_EQ(0xffffffff_u32, maybe_cast<uint32_t>(0xffffffffU)); + EXPECT_EQ(-0x80000000_n32, maybe_cast<int32_t>(-0x80000000)); + EXPECT_EQ(-0x7fffffff_n32, maybe_cast<int32_t>(-0x7fffffff)); + EXPECT_EQ(-0x00000001_n32, maybe_cast<int32_t>(-0x00000001)); + EXPECT_EQ(+0x00000000_p32, maybe_cast<int32_t>(0x00000000)); + EXPECT_EQ(+0x00000001_p32, maybe_cast<int32_t>(0x00000001)); + EXPECT_EQ(+0x7ffffffe_p32, maybe_cast<int32_t>(0x7ffffffe)); + EXPECT_EQ(+0x7fffffff_p32, maybe_cast<int32_t>(0x7fffffff)); + + EXPECT_EQ(0X00000000_u32, maybe_cast<uint32_t>(0X00000000U)); + EXPECT_EQ(0X00000001_u32, maybe_cast<uint32_t>(0X00000001U)); + EXPECT_EQ(0XFFFFFFFE_u32, maybe_cast<uint32_t>(0XFFFFFFFEU)); + EXPECT_EQ(0XFFFFFFFF_u32, maybe_cast<uint32_t>(0XFFFFFFFFU)); + EXPECT_EQ(-0X80000000_n32, maybe_cast<int32_t>(-0X80000000)); + EXPECT_EQ(-0X7FFFFFFF_n32, maybe_cast<int32_t>(-0X7FFFFFFF)); + EXPECT_EQ(-0X00000001_n32, maybe_cast<int32_t>(-0X00000001)); + EXPECT_EQ(+0X00000000_p32, maybe_cast<int32_t>(0X00000000)); + EXPECT_EQ(+0X00000001_p32, maybe_cast<int32_t>(0X00000001)); + EXPECT_EQ(+0X7FFFFFFE_p32, maybe_cast<int32_t>(0X7FFFFFFE)); + EXPECT_EQ(+0X7FFFFFFF_p32, maybe_cast<int32_t>(0X7FFFFFFF)); +} + +TEST(ints, udl64) +{ + EXPECT_EQ(0b0000000000000000000000000000000000000000000000000000000000000000_u64, maybe_cast<uint64_t>(0b0000000000000000000000000000000000000000000000000000000000000000U)); + EXPECT_EQ(0b0000000000000000000000000000000000000000000000000000000000000001_u64, maybe_cast<uint64_t>(0b0000000000000000000000000000000000000000000000000000000000000001U)); + EXPECT_EQ(0b1111111111111111111111111111111111111111111111111111111111111110_u64, maybe_cast<uint64_t>(0b1111111111111111111111111111111111111111111111111111111111111110U)); + EXPECT_EQ(0b1111111111111111111111111111111111111111111111111111111111111111_u64, maybe_cast<uint64_t>(0b1111111111111111111111111111111111111111111111111111111111111111U)); + EXPECT_EQ(-0b1000000000000000000000000000000000000000000000000000000000000000_n64, maybe_cast<int64_t>(-0b1000000000000000000000000000000000000000000000000000000000000000)); + EXPECT_EQ(-0b0111111111111111111111111111111111111111111111111111111111111111_n64, maybe_cast<int64_t>(-0b0111111111111111111111111111111111111111111111111111111111111111)); + EXPECT_EQ(-0b0000000000000000000000000000000000000000000000000000000000000001_n64, maybe_cast<int64_t>(-0b0000000000000000000000000000000000000000000000000000000000000001)); + EXPECT_EQ(+0b0000000000000000000000000000000000000000000000000000000000000000_p64, maybe_cast<int64_t>(0b0000000000000000000000000000000000000000000000000000000000000000)); + EXPECT_EQ(+0b0000000000000000000000000000000000000000000000000000000000000001_p64, maybe_cast<int64_t>(0b0000000000000000000000000000000000000000000000000000000000000001)); + EXPECT_EQ(+0b0111111111111111111111111111111111111111111111111111111111111110_p64, maybe_cast<int64_t>(0b0111111111111111111111111111111111111111111111111111111111111110)); + EXPECT_EQ(+0b0111111111111111111111111111111111111111111111111111111111111111_p64, maybe_cast<int64_t>(0b0111111111111111111111111111111111111111111111111111111111111111)); + + EXPECT_EQ(0B0000000000000000000000000000000000000000000000000000000000000000_u64, maybe_cast<uint64_t>(0B0000000000000000000000000000000000000000000000000000000000000000U)); + EXPECT_EQ(0B0000000000000000000000000000000000000000000000000000000000000001_u64, maybe_cast<uint64_t>(0B0000000000000000000000000000000000000000000000000000000000000001U)); + EXPECT_EQ(0B1111111111111111111111111111111111111111111111111111111111111110_u64, maybe_cast<uint64_t>(0B1111111111111111111111111111111111111111111111111111111111111110U)); + EXPECT_EQ(0B1111111111111111111111111111111111111111111111111111111111111111_u64, maybe_cast<uint64_t>(0B1111111111111111111111111111111111111111111111111111111111111111U)); + EXPECT_EQ(-0B1000000000000000000000000000000000000000000000000000000000000000_n64, maybe_cast<int64_t>(-0B1000000000000000000000000000000000000000000000000000000000000000)); + EXPECT_EQ(-0B0111111111111111111111111111111111111111111111111111111111111111_n64, maybe_cast<int64_t>(-0B0111111111111111111111111111111111111111111111111111111111111111)); + EXPECT_EQ(-0B0000000000000000000000000000000000000000000000000000000000000001_n64, maybe_cast<int64_t>(-0B0000000000000000000000000000000000000000000000000000000000000001)); + EXPECT_EQ(+0B0000000000000000000000000000000000000000000000000000000000000000_p64, maybe_cast<int64_t>(0B0000000000000000000000000000000000000000000000000000000000000000)); + EXPECT_EQ(+0B0000000000000000000000000000000000000000000000000000000000000001_p64, maybe_cast<int64_t>(0B0000000000000000000000000000000000000000000000000000000000000001)); + EXPECT_EQ(+0B0111111111111111111111111111111111111111111111111111111111111110_p64, maybe_cast<int64_t>(0B0111111111111111111111111111111111111111111111111111111111111110)); + EXPECT_EQ(+0B0111111111111111111111111111111111111111111111111111111111111111_p64, maybe_cast<int64_t>(0B0111111111111111111111111111111111111111111111111111111111111111)); + + EXPECT_EQ(00000000000000000000000_u64, maybe_cast<uint64_t>(00000000000000000000000U)); + EXPECT_EQ(00000000000000000000001_u64, maybe_cast<uint64_t>(00000000000000000000001U)); + EXPECT_EQ(01777777777777777777776_u64, maybe_cast<uint64_t>(01777777777777777777776U)); + EXPECT_EQ(01777777777777777777777_u64, maybe_cast<uint64_t>(01777777777777777777777U)); + EXPECT_EQ(-01000000000000000000000_n64, maybe_cast<int64_t>(-01000000000000000000000)); + EXPECT_EQ(-00777777777777777777777_n64, maybe_cast<int64_t>(-00777777777777777777777)); + EXPECT_EQ(-00000000000000000000001_n64, maybe_cast<int64_t>(-000000000000000000000001)); + EXPECT_EQ(+0000000000000000000000_p64, maybe_cast<int64_t>(0000000000000000000000)); + EXPECT_EQ(+0000000000000000000001_p64, maybe_cast<int64_t>(0000000000000000000001)); + EXPECT_EQ(+0777777777777777777776_p64, maybe_cast<int64_t>(0777777777777777777776)); + EXPECT_EQ(+0777777777777777777777_p64, maybe_cast<int64_t>(0777777777777777777777)); + + EXPECT_EQ(0_u64, maybe_cast<uint64_t>(0U)); + EXPECT_EQ(1_u64, maybe_cast<uint64_t>(1U)); + EXPECT_EQ(18446744073709551614_u64, maybe_cast<uint64_t>(18446744073709551614U)); + EXPECT_EQ(18446744073709551615_u64, maybe_cast<uint64_t>(18446744073709551615U)); + EXPECT_EQ(-9223372036854775808_n64, maybe_cast<int64_t>(-9223372036854775808U)); + EXPECT_EQ(-9223372036854775807_n64, maybe_cast<int64_t>(-9223372036854775807)); + EXPECT_EQ(-1_n64, maybe_cast<int64_t>(-1)); + EXPECT_EQ(+0_p64, maybe_cast<int64_t>(0)); + EXPECT_EQ(+1_p64, maybe_cast<int64_t>(1)); + EXPECT_EQ(+9223372036854775806_p64, maybe_cast<int64_t>(9223372036854775806)); + EXPECT_EQ(+9223372036854775807_p64, maybe_cast<int64_t>(9223372036854775807)); + + EXPECT_EQ(0x0000000000000000_u64, maybe_cast<uint64_t>(0x0000000000000000U)); + EXPECT_EQ(0x0000000000000001_u64, maybe_cast<uint64_t>(0x0000000000000001U)); + EXPECT_EQ(0xfffffffffffffffe_u64, maybe_cast<uint64_t>(0xfffffffffffffffeU)); + EXPECT_EQ(0xffffffffffffffff_u64, maybe_cast<uint64_t>(0xffffffffffffffffU)); + EXPECT_EQ(-0x8000000000000000_n64, maybe_cast<int64_t>(-0x8000000000000000)); + EXPECT_EQ(-0x7fffffffffffffff_n64, maybe_cast<int64_t>(-0x7fffffffffffffff)); + EXPECT_EQ(-0x0000000000000001_n64, maybe_cast<int64_t>(-0x0000000000000001)); + EXPECT_EQ(+0x0000000000000000_p64, maybe_cast<int64_t>(0x0000000000000000)); + EXPECT_EQ(+0x0000000000000001_p64, maybe_cast<int64_t>(0x0000000000000001)); + EXPECT_EQ(+0x7ffffffffffffffe_p64, maybe_cast<int64_t>(0x7ffffffffffffffe)); + EXPECT_EQ(+0x7fffffffffffffff_p64, maybe_cast<int64_t>(0x7fffffffffffffff)); + + EXPECT_EQ(0X0000000000000000_u64, maybe_cast<uint64_t>(0X0000000000000000U)); + EXPECT_EQ(0X0000000000000001_u64, maybe_cast<uint64_t>(0X0000000000000001U)); + EXPECT_EQ(0XFFFFFFFFFFFFFFFE_u64, maybe_cast<uint64_t>(0XFFFFFFFFFFFFFFFEU)); + EXPECT_EQ(0XFFFFFFFFFFFFFFFF_u64, maybe_cast<uint64_t>(0XFFFFFFFFFFFFFFFFU)); + EXPECT_EQ(-0X8000000000000000_n64, maybe_cast<int64_t>(-0X8000000000000000)); + EXPECT_EQ(-0X7FFFFFFFFFFFFFFF_n64, maybe_cast<int64_t>(-0X7FFFFFFFFFFFFFFF)); + EXPECT_EQ(-0X0000000000000001_n64, maybe_cast<int64_t>(-0X0000000000000001)); + EXPECT_EQ(+0X0000000000000000_p64, maybe_cast<int64_t>(0X0000000000000000)); + EXPECT_EQ(+0X0000000000000001_p64, maybe_cast<int64_t>(0X0000000000000001)); + EXPECT_EQ(+0X7FFFFFFFFFFFFFFE_p64, maybe_cast<int64_t>(0X7FFFFFFFFFFFFFFE)); + EXPECT_EQ(+0X7FFFFFFFFFFFFFFF_p64, maybe_cast<int64_t>(0X7FFFFFFFFFFFFFFF)); +} +} // namespace tmwa diff --git a/src/ints/wrap.cpp b/src/ints/wrap.cpp new file mode 100644 index 0000000..84d4b33 --- /dev/null +++ b/src/ints/wrap.cpp @@ -0,0 +1,26 @@ +#include "wrap.hpp" +// wrap.cpp - basic integer wrapper classes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/ints/wrap.hpp b/src/ints/wrap.hpp new file mode 100644 index 0000000..707c787 --- /dev/null +++ b/src/ints/wrap.hpp @@ -0,0 +1,110 @@ +#pragma once +// wrap.hpp - basic integer wrapper classes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include <cstdint> + +#include <type_traits> + + +namespace tmwa +{ +namespace ints +{ + namespace wrapped + { + template<class R> + struct Wrapped + { + typedef R wrapped_type; + R _value; + protected: + constexpr + Wrapped(uint32_t v=0) + : _value(v) + {} + public: + explicit + operator bool () const { return _value; } + bool operator !() const { return !_value; } + }; + + template<class W, typename=typename W::wrapped_type> + bool operator == (W l, W r) + { + return l._value == r._value; + } + template<class W, typename=typename W::wrapped_type> + bool operator != (W l, W r) + { + return l._value != r._value; + } + template<class W, typename=typename W::wrapped_type> + bool operator < (W l, W r) + { + return l._value < r._value; + } + + template<class T> + constexpr + typename T::wrapped_type unwrap(typename std::enable_if<true, T>::type w) + { + return w._value; + } + template<class T> + constexpr + T wrap(typename T::wrapped_type v) + { + struct Sub : T + { + constexpr + Sub(typename T::wrapped_type v2) + : T(v2) + {} + }; + return Sub(v); + } + + template<class W> + constexpr + W next(W w) + { + return wrap<W>(unwrap<W>(w) + 1); + } + template<class W> + constexpr + W prev(W w) + { + return wrap<W>(unwrap<W>(w) - 1); + } + + template<class R> + R convert_for_printf(Wrapped<R> w) + { + return w._value; + } + } // namespace wrapped +} // namespace ints + +using ints::wrapped::Wrapped; +using ints::wrapped::unwrap; +using ints::wrapped::wrap; +} // namespace tmwa diff --git a/src/io/cxxstdio.cpp b/src/io/cxxstdio.cpp index fbfdd46..ca4e880 100644 --- a/src/io/cxxstdio.cpp +++ b/src/io/cxxstdio.cpp @@ -1,5 +1,5 @@ #include "cxxstdio.hpp" -// cxxstdio.cpp - pass C++ types through scanf/printf +// cxxstdio.cpp - pass C++ types through printf // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> // @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/io/cxxstdio.hpp b/src/io/cxxstdio.hpp index 66419df..20d3a33 100644 --- a/src/io/cxxstdio.hpp +++ b/src/io/cxxstdio.hpp @@ -1,6 +1,5 @@ -#ifndef TMWA_IO_CXXSTDIO_HPP -#define TMWA_IO_CXXSTDIO_HPP -// cxxstdio.hpp - pass C++ types through scanf/printf +#pragma once +// cxxstdio.hpp - pass C++ types through printf // // Copyright © 2011-2013 Ben Longbons <b.r.longbons@gmail.com> // @@ -19,44 +18,29 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdarg> -# include <cstdio> +#include <cstdarg> +#include <cstdio> -# include "../compat/cast.hpp" +#include "../compat/cast.hpp" -# include "../generic/enum.hpp" +#include "../generic/enum.hpp" -# include "fwd.hpp" +#include "../diagnostics.hpp" +namespace tmwa +{ namespace cxxstdio { - // other implementations of do_vprint or do_vscan are injected by ADL. + // other implementations of do_vprint are injected by ADL. inline __attribute__((format(printf, 2, 0))) int do_vprint(FILE *out, const char *fmt, va_list ap) { return vfprintf(out, fmt, ap); } - inline __attribute__((format(scanf, 2, 0))) - int do_vscan(FILE *in, const char *fmt, va_list ap) - { - return vfscanf(in, fmt, ap); - } - -# if 0 - inline __attribute__((format(scanf, 2, 0))) - int do_vscan(const char *in, const char *fmt, va_list ap) - { - return vsscanf(in, fmt, ap); - } -# else - inline - int do_vscan(const char *, const char *, va_list) = delete; -# endif - template<class T> inline __attribute__((format(printf, 2, 3))) int do_print(T&& t, const char *fmt, ...) @@ -69,19 +53,6 @@ namespace cxxstdio return rv; } - template<class T> - inline __attribute__((format(scanf, 2, 3))) - int do_scan(T&& t, const char *fmt, ...) - { - int rv; - va_list ap; - va_start(ap, fmt); - rv = do_vscan(std::forward<T>(t), fmt, ap); - va_end(ap); - return rv; - } - - template<class T, typename=typename std::enable_if<!std::is_class<T>::value>::type> typename remove_enum<T>::type decay_for_printf(T v) { @@ -95,13 +66,10 @@ namespace cxxstdio return std::forward<T>(v); } - template<class T, typename = typename std::enable_if<!std::is_enum<T>::value>::type> - T& convert_for_scanf(T& v) - { - return v; - } + inline + const char *convert_for_printf(const char *) = delete; -# if 0 +#if 0 template<class E> constexpr E get_enum_min_value(decltype(E::min_value)) @@ -127,7 +95,7 @@ namespace cxxstdio { return def; } -# else +#else template<class E> constexpr E get_enum_min_value(E) @@ -140,24 +108,24 @@ namespace cxxstdio { return E::max_value; } -# endif +#endif template<class E> class EnumConverter { E& out; typedef typename underlying_type<E>::type U; -# if 0 +#if 0 constexpr static U min_value = U(get_enum_min_value<E>(E(std::numeric_limits<U>::min()))); constexpr static U max_value = U(get_enum_max_value<E>(E(std::numeric_limits<U>::max()))); -# else +#else constexpr static U min_value = U(get_enum_min_value(E())); constexpr static U max_value = U(get_enum_max_value(E())); -# endif +#endif U mid; public: EnumConverter(E& e) @@ -165,11 +133,13 @@ namespace cxxstdio {} ~EnumConverter() { -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wtype-limits" + DIAG_PUSH(); + DIAG_I(type_limits); if (min_value <= mid && mid <= max_value) -# pragma GCC diagnostic pop + { + DIAG_POP(); out = E(mid); + } } U *operator &() { @@ -177,12 +147,6 @@ namespace cxxstdio } }; - template<class T, typename = typename std::enable_if<std::is_enum<T>::value>::type> - EnumConverter<T> convert_for_scanf(T& v) - { - return v; - } - template<class Format> class PrintFormatter { @@ -192,63 +156,35 @@ namespace cxxstdio int print(T&& t, A&&... a) { constexpr static - const char *print_format = Format::print_format(); + const char *print_format = Format::print_format().format_string(); return do_print(std::forward<T>(t), print_format, decay_for_printf(convert_for_printf(std::forward<A>(a)))...); } }; - template<class Format> - class ScanFormatter - { - public: - template<class T, class... A> - static - int scan(T&& t, A&&... a) - { - constexpr static - const char *scan_format = Format::scan_format(); - return do_scan(std::forward<T>(t), scan_format, - &convert_for_scanf(*a)...); - } - }; - -# define XPRINTF(out, fmt, ...) \ +#define XPRINTF(out, fmt, ...) \ ({ \ struct format_impl \ { \ constexpr static \ - const char *print_format() { return fmt; } \ + FormatString print_format() { return fmt; } \ }; \ cxxstdio::PrintFormatter<format_impl>::print(out, ## __VA_ARGS__); \ }) -# define XSCANF(out, fmt, ...) \ - ({ \ - struct format_impl \ - { \ - constexpr static \ - const char *scan_format() { return fmt; } \ - }; \ - cxxstdio::ScanFormatter<format_impl>::scan(out, ## __VA_ARGS__); \ - }) - -# define FPRINTF(file, fmt, ...) XPRINTF(/*no_cast<FILE *>*/(file), fmt, ## __VA_ARGS__) -# define FSCANF(file, fmt, ...) XSCANF(no_cast<FILE *>(file), fmt, ## __VA_ARGS__) -# define PRINTF(fmt, ...) FPRINTF(stdout, fmt, ## __VA_ARGS__) -# define SPRINTF(str, fmt, ...) XPRINTF(base_cast<AString&>(str), fmt, ## __VA_ARGS__) -# define SNPRINTF(str, n, fmt, ...) XPRINTF(base_cast<VString<n-1>&>(str), fmt, ## __VA_ARGS__) -# define SCANF(fmt, ...) FSCANF(stdin, fmt, ## __VA_ARGS__) -# define SSCANF(str, fmt, ...) XSCANF(maybe_cast<ZString>(str), fmt, ## __VA_ARGS__) +#define FPRINTF(file, fmt, ...) XPRINTF(/*no_cast<FILE *>*/(file), fmt, ## __VA_ARGS__) +#define PRINTF(fmt, ...) FPRINTF(stdout, fmt, ## __VA_ARGS__) +#define SPRINTF(str, fmt, ...) XPRINTF(base_cast<AString&>(str), fmt, ## __VA_ARGS__) +#define SNPRINTF(str, n, fmt, ...) XPRINTF(base_cast<VString<n-1>&>(str), fmt, ## __VA_ARGS__) -# define STRPRINTF(fmt, ...) \ +#define STRPRINTF(fmt, ...) \ ({ \ AString _out_impl; \ SPRINTF(_out_impl, fmt, ## __VA_ARGS__); \ _out_impl; \ }) -# define STRNPRINTF(n, fmt, ...) \ +#define STRNPRINTF(n, fmt, ...) \ ({ \ VString<n - 1> _out_impl; \ SNPRINTF(_out_impl, n, fmt, ## __VA_ARGS__); \ @@ -256,5 +192,4 @@ namespace cxxstdio }) } // namespace cxxstdio - -#endif // TMWA_IO_CXXSTDIO_HPP +} // namespace tmwa diff --git a/src/io/dir.cpp b/src/io/dir.cpp new file mode 100644 index 0000000..2acb75a --- /dev/null +++ b/src/io/dir.cpp @@ -0,0 +1,54 @@ +#include "dir.hpp" +// io/dir.cpp - rooted file operations +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <fcntl.h> + +#include "../strings/zstring.hpp" + +#include "../poison.hpp" + + +namespace tmwa +{ +namespace io +{ + DirFd::DirFd() + : dirfd(FD::cast_dammit(AT_FDCWD)) + {} + + DirFd::DirFd(ZString path) + : dirfd(FD::open(path, O_DIRECTORY | O_RDONLY, 0)) + {} + + DirFd::DirFd(const DirFd& root, ZString path) + : dirfd(FD::openat(root.dirfd, path, O_DIRECTORY | O_RDONLY, 0)) + {} + + DirFd::~DirFd() + { + dirfd.close(); + } + + FD DirFd::open_fd(ZString name, int flags, int mode) const + { + return FD::openat(dirfd, name, flags, mode); + } +} // namespace io +} // namespace tmwa diff --git a/src/io/dir.hpp b/src/io/dir.hpp new file mode 100644 index 0000000..071f309 --- /dev/null +++ b/src/io/dir.hpp @@ -0,0 +1,50 @@ +#pragma once +// io/dir.hpp - rooted file operations +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include "../strings/fwd.hpp" + +#include "fd.hpp" + + +namespace tmwa +{ +namespace io +{ + class DirFd + { + private: + FD dirfd; + + public: + DirFd(); + explicit + DirFd(ZString); + DirFd(const DirFd&, ZString); + + DirFd(const DirFd&) = delete; + ~DirFd(); + DirFd& operator = (const DirFd&) = delete; + + FD open_fd(ZString name, int flags, int mode=FD::DEFAULT_MODE) const; + }; +} // namespace io +} // namespace tmwa diff --git a/src/io/fd.cpp b/src/io/fd.cpp index 4fc33e9..c0b44e8 100644 --- a/src/io/fd.cpp +++ b/src/io/fd.cpp @@ -25,12 +25,19 @@ #include "../poison.hpp" + +namespace tmwa +{ namespace io { FD FD::open(ZString path, int flags, int mode) { return FD(::open(path.c_str(), flags, mode)); } + FD FD::openat(FD dirfd, ZString path, int flags, int mode) + { + return FD(::openat(dirfd.fd, path.c_str(), flags, mode)); + } FD FD::socket(int domain, int type, int protocol) { return FD(::socket(domain, type, protocol)); @@ -163,3 +170,4 @@ namespace io timeout, sigmask); } } // namespace io +} // namespace tmwa diff --git a/src/io/fd.hpp b/src/io/fd.hpp index 7afb40f..d04d5bf 100644 --- a/src/io/fd.hpp +++ b/src/io/fd.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_IO_FD_HPP -#define TMWA_IO_FD_HPP +#pragma once // io/fd.hpp - typesafe (but not scopesafe) file descriptors // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,16 +18,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <sys/select.h> -# include <sys/socket.h> +#include <sys/select.h> +#include <sys/socket.h> -# include <unistd.h> +#include "../strings/fwd.hpp" -# include "../strings/fwd.hpp" +#include "../diagnostics.hpp" +namespace tmwa +{ namespace io { class FD @@ -55,8 +56,13 @@ namespace io FD stdout() { return FD(1); } static FD stderr() { return FD(2); } + + static const int DEFAULT_MODE = 0666; + static - FD open(ZString path, int flags, int mode=0666); + FD open(ZString path, int flags, int mode=DEFAULT_MODE); + static + FD openat(FD dirfd, ZString path, int flags, int mode=DEFAULT_MODE); static FD socket(int domain, int type, int protocol); FD accept(struct sockaddr *addr, socklen_t *addrlen); @@ -64,6 +70,7 @@ namespace io int pipe(FD& r, FD& w); static int pipe2(FD& r, FD& w, int flags); + static FD sysconf_SC_OPEN_MAX(); @@ -138,24 +145,24 @@ namespace io } void clr(FD fd) { -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" + DIAG_PUSH(); + DIAG_I(old_style_cast); FD_CLR(fd.uncast_dammit(), &fds); -# pragma GCC diagnostic pop + DIAG_POP(); } bool isset(FD fd) { -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" + DIAG_PUSH(); + DIAG_I(old_style_cast); return FD_ISSET(fd.uncast_dammit(), &fds); -# pragma GCC diagnostic pop + DIAG_POP(); } void set(FD fd) { -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" + DIAG_PUSH(); + DIAG_I(old_style_cast); FD_SET(fd.uncast_dammit(), &fds); -# pragma GCC diagnostic pop + DIAG_POP(); } static @@ -164,5 +171,4 @@ namespace io int pselect(int nfds, FD_Set *readfds, FD_Set *writefds, FD_Set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask); }; } // namespace io - -#endif // TMWA_IO_FD_HPP +} // namespace tmwa diff --git a/src/io/fwd.hpp b/src/io/fwd.hpp index 1e5fa82..deeb08c 100644 --- a/src/io/fwd.hpp +++ b/src/io/fwd.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_IO_FWD_HPP -#define TMWA_IO_FWD_HPP +#pragma once // io/fwd.hpp - Forward declarations of I/O classes // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,14 +18,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "../sanity.hpp" +namespace tmwa +{ namespace io { class ReadFile; class WriteFile; class AppendFile; } // namespace io - -#endif // TMWA_IO_FWD_HPP +} // namespace tmwa diff --git a/src/io/line.cpp b/src/io/line.cpp index f7470a6..a1cdf42 100644 --- a/src/io/line.cpp +++ b/src/io/line.cpp @@ -1,5 +1,5 @@ #include "line.hpp" -// io/line.hpp - Input from files, line-by-line +// io/line.cpp - Input from files, line-by-line // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> // @@ -18,44 +18,44 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <fcntl.h> -#include <unistd.h> - #include "../strings/astring.hpp" #include "../strings/mstring.hpp" #include "../strings/zstring.hpp" +#include "../strings/xstring.hpp" #include "cxxstdio.hpp" #include "../poison.hpp" +namespace tmwa +{ namespace io { AString Line::message_str(ZString cat, ZString msg) const { MString out; if (column) - out += STRPRINTF("%s:%u:%u: %s: %s\n", + out += STRPRINTF("%s:%u:%u: %s: %s\n"_fmt, filename, line, column, cat, msg); else - out += STRPRINTF("%s:%u: %s: %s\n", + out += STRPRINTF("%s:%u: %s: %s\n"_fmt, filename, line, cat, msg); - out += STRPRINTF("%s\n", text); - out += STRPRINTF("%*c\n", column, '^'); + out += STRPRINTF("%s\n"_fmt, text); + out += STRPRINTF("%*c\n"_fmt, column, '^'); return AString(out); } void Line::message(ZString cat, ZString msg) const { if (column) - FPRINTF(stderr, "%s:%u:%u: %s: %s\n", + FPRINTF(stderr, "%s:%u:%u: %s: %s\n"_fmt, filename, line, column, cat, msg); else - FPRINTF(stderr, "%s:%u: %s: %s\n", + FPRINTF(stderr, "%s:%u: %s: %s\n"_fmt, filename, line, cat, msg); - FPRINTF(stderr, "%s\n", text); - FPRINTF(stderr, "%*c\n", column, '^'); + FPRINTF(stderr, "%s\n"_fmt, text); + FPRINTF(stderr, "%*c\n"_fmt, column, '^'); } AString LineSpan::message_str(ZString cat, ZString msg) const @@ -67,24 +67,24 @@ namespace io MString out; if (begin.line == end.line) { - out += STRPRINTF("%s:%u:%u: %s: %s\n", + out += STRPRINTF("%s:%u:%u: %s: %s\n"_fmt, begin.filename, begin.line, begin.column, cat, msg); - out += STRPRINTF("%s\n", begin.text); - out += STRPRINTF("%*c", begin.column, '^'); + out += STRPRINTF("%s\n"_fmt, begin.text); + out += STRPRINTF("%*c"_fmt, begin.column, '^'); for (unsigned c = begin.column; c != end.column; ++c) out += '~'; out += '\n'; } else { - out += STRPRINTF("%s:%u:%u: %s: %s\n", + out += STRPRINTF("%s:%u:%u: %s: %s\n"_fmt, begin.filename, begin.line, begin.column, cat, msg); - out += STRPRINTF("%s\n", begin.text); - out += STRPRINTF("%*c", begin.column, '^'); + out += STRPRINTF("%s\n"_fmt, begin.text); + out += STRPRINTF("%*c"_fmt, begin.column, '^'); for (unsigned c = begin.column; c != begin.text.size(); ++c) out += '~'; - out += " ...\n"; - out += STRPRINTF("%s\n", end.text); + out += " ...\n"_s; + out += STRPRINTF("%s\n"_fmt, end.text); for (unsigned c = 0; c != end.column; ++c) out += '~'; out += '\n'; @@ -94,7 +94,7 @@ namespace io void LineSpan::message(ZString cat, ZString msg) const { - FPRINTF(stderr, "%s", message_str(cat, msg)); + FPRINTF(stderr, "%s"_fmt, message_str(cat, msg)); } LineReader::LineReader(ZString name) @@ -180,3 +180,4 @@ namespace io return line != 0; } } // namespace io +} // namespace tmwa diff --git a/src/io/line.hpp b/src/io/line.hpp index a9e8944..8244c5e 100644 --- a/src/io/line.hpp +++ b/src/io/line.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_IO_LINE_HPP -#define TMWA_IO_LINE_HPP +#pragma once // io/line.hpp - Input from files, line-by-line // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,16 +18,17 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/rstring.hpp" -# include "../strings/astring.hpp" -# include "../strings/zstring.hpp" +#include "../strings/rstring.hpp" +#include "../strings/zstring.hpp" +#include "../strings/literal.hpp" -# include "fd.hpp" -# include "read.hpp" +#include "read.hpp" +namespace tmwa +{ namespace io { // TODO split this out @@ -42,9 +42,9 @@ namespace io AString message_str(ZString cat, ZString msg) const; void message(ZString cat, ZString msg) const; - void note(ZString msg) const { message("note", msg); } - void warning(ZString msg) const { message("warning", msg); } - void error(ZString msg) const { message("error", msg); } + void note(ZString msg) const { message("note"_s, msg); } + void warning(ZString msg) const { message("warning"_s, msg); } + void error(ZString msg) const { message("error"_s, msg); } }; // psst, don't tell anyone @@ -65,9 +65,9 @@ namespace io AString message_str(ZString cat, ZString msg) const; void message(ZString cat, ZString msg) const; - void note(ZString msg) const { message("note", msg); } - void warning(ZString msg) const { message("warning", msg); } - void error(ZString msg) const { message("error", msg); } + void note(ZString msg) const { message("note"_s, msg); } + void warning(ZString msg) const { message("warning"_s, msg); } + void error(ZString msg) const { message("error"_s, msg); } }; class LineReader @@ -104,5 +104,4 @@ namespace io bool is_open(); }; } // namespace io - -#endif // TMWA_IO_LINE_HPP +} // namespace tmwa diff --git a/src/io/line_test.cpp b/src/io/line_test.cpp index feee1fb..edf60bd 100644 --- a/src/io/line_test.cpp +++ b/src/io/line_test.cpp @@ -20,10 +20,14 @@ #include <gtest/gtest.h> +#include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../poison.hpp" + +namespace tmwa +{ static io::FD string_pipe(ZString sz) { @@ -42,80 +46,80 @@ io::FD string_pipe(ZString sz) TEST(io, line1) { - io::LineReader lr("<string1>", string_pipe("Hello World\n")); + io::LineReader lr("<string1>"_s, string_pipe("Hello World\n"_s)); io::Line hi; EXPECT_TRUE(lr.read_line(hi)); - EXPECT_EQ(hi.text, "Hello World"); - EXPECT_EQ(hi.filename, "<string1>"); + EXPECT_EQ(hi.text, "Hello World"_s); + EXPECT_EQ(hi.filename, "<string1>"_s); EXPECT_EQ(hi.line, 1); EXPECT_EQ(hi.column, 0); EXPECT_FALSE(lr.read_line(hi)); } TEST(io, line2) { - io::LineReader lr("<string2>", string_pipe("Hello\nWorld")); + io::LineReader lr("<string2>"_s, string_pipe("Hello\nWorld"_s)); io::Line hi; EXPECT_TRUE(lr.read_line(hi)); - EXPECT_EQ(hi.text, "Hello"); - EXPECT_EQ(hi.filename, "<string2>"); + EXPECT_EQ(hi.text, "Hello"_s); + EXPECT_EQ(hi.filename, "<string2>"_s); EXPECT_EQ(hi.line, 1); EXPECT_EQ(hi.column, 0); EXPECT_TRUE(lr.read_line(hi)); - EXPECT_EQ(hi.text, "World"); - EXPECT_EQ(hi.filename, "<string2>"); + EXPECT_EQ(hi.text, "World"_s); + EXPECT_EQ(hi.filename, "<string2>"_s); EXPECT_EQ(hi.line, 2); EXPECT_EQ(hi.column, 0); EXPECT_FALSE(lr.read_line(hi)); } TEST(io, line3) { - io::LineReader lr("<string3>", string_pipe("Hello\rWorld")); + io::LineReader lr("<string3>"_s, string_pipe("Hello\rWorld"_s)); io::Line hi; EXPECT_TRUE(lr.read_line(hi)); - EXPECT_EQ(hi.text, "Hello"); - EXPECT_EQ(hi.filename, "<string3>"); + EXPECT_EQ(hi.text, "Hello"_s); + EXPECT_EQ(hi.filename, "<string3>"_s); EXPECT_EQ(hi.line, 1); EXPECT_EQ(hi.column, 0); EXPECT_TRUE(lr.read_line(hi)); - EXPECT_EQ(hi.text, "World"); - EXPECT_EQ(hi.filename, "<string3>"); + EXPECT_EQ(hi.text, "World"_s); + EXPECT_EQ(hi.filename, "<string3>"_s); EXPECT_EQ(hi.line, 2); EXPECT_EQ(hi.column, 0); EXPECT_FALSE(lr.read_line(hi)); } TEST(io, line4) { - io::LineReader lr("<string4>", string_pipe("Hello\r\nWorld")); + io::LineReader lr("<string4>"_s, string_pipe("Hello\r\nWorld"_s)); io::Line hi; EXPECT_TRUE(lr.read_line(hi)); - EXPECT_EQ(hi.text, "Hello"); - EXPECT_EQ(hi.filename, "<string4>"); + EXPECT_EQ(hi.text, "Hello"_s); + EXPECT_EQ(hi.filename, "<string4>"_s); EXPECT_EQ(hi.line, 1); EXPECT_EQ(hi.column, 0); EXPECT_TRUE(lr.read_line(hi)); - EXPECT_EQ(hi.text, "World"); - EXPECT_EQ(hi.filename, "<string4>"); + EXPECT_EQ(hi.text, "World"_s); + EXPECT_EQ(hi.filename, "<string4>"_s); EXPECT_EQ(hi.line, 2); EXPECT_EQ(hi.column, 0); EXPECT_FALSE(lr.read_line(hi)); } TEST(io, line5) { - io::LineReader lr("<string5>", string_pipe("Hello\n\rWorld")); + io::LineReader lr("<string5>"_s, string_pipe("Hello\n\rWorld"_s)); io::Line hi; EXPECT_TRUE(lr.read_line(hi)); - EXPECT_EQ(hi.text, "Hello"); - EXPECT_EQ(hi.filename, "<string5>"); + EXPECT_EQ(hi.text, "Hello"_s); + EXPECT_EQ(hi.filename, "<string5>"_s); EXPECT_EQ(hi.line, 1); EXPECT_EQ(hi.column, 0); EXPECT_TRUE(lr.read_line(hi)); - EXPECT_EQ(hi.text, ""); - EXPECT_EQ(hi.filename, "<string5>"); + EXPECT_EQ(hi.text, ""_s); + EXPECT_EQ(hi.filename, "<string5>"_s); EXPECT_EQ(hi.line, 2); EXPECT_EQ(hi.column, 0); EXPECT_TRUE(lr.read_line(hi)); - EXPECT_EQ(hi.text, "World"); - EXPECT_EQ(hi.filename, "<string5>"); + EXPECT_EQ(hi.text, "World"_s); + EXPECT_EQ(hi.filename, "<string5>"_s); EXPECT_EQ(hi.line, 3); EXPECT_EQ(hi.column, 0); EXPECT_FALSE(lr.read_line(hi)); @@ -123,47 +127,47 @@ TEST(io, line5) TEST(io, linechar1) { - io::LineCharReader lr("<stringchar1>", string_pipe("Hi Wu\n")); + io::LineCharReader lr("<stringchar1>"_s, string_pipe("Hi Wu\n"_s)); io::LineChar c; EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'H'); - EXPECT_EQ(c.text, "Hi Wu"); - EXPECT_EQ(c.filename, "<stringchar1>"); + EXPECT_EQ(c.text, "Hi Wu"_s); + EXPECT_EQ(c.filename, "<stringchar1>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 1); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'i'); - EXPECT_EQ(c.text, "Hi Wu"); - EXPECT_EQ(c.filename, "<stringchar1>"); + EXPECT_EQ(c.text, "Hi Wu"_s); + EXPECT_EQ(c.filename, "<stringchar1>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 2); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), ' '); - EXPECT_EQ(c.text, "Hi Wu"); - EXPECT_EQ(c.filename, "<stringchar1>"); + EXPECT_EQ(c.text, "Hi Wu"_s); + EXPECT_EQ(c.filename, "<stringchar1>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 3); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'W'); - EXPECT_EQ(c.text, "Hi Wu"); - EXPECT_EQ(c.filename, "<stringchar1>"); + EXPECT_EQ(c.text, "Hi Wu"_s); + EXPECT_EQ(c.filename, "<stringchar1>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 4); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'u'); - EXPECT_EQ(c.text, "Hi Wu"); - EXPECT_EQ(c.filename, "<stringchar1>"); + EXPECT_EQ(c.text, "Hi Wu"_s); + EXPECT_EQ(c.filename, "<stringchar1>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 5); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), '\n'); - EXPECT_EQ(c.text, "Hi Wu"); - EXPECT_EQ(c.filename, "<stringchar1>"); + EXPECT_EQ(c.text, "Hi Wu"_s); + EXPECT_EQ(c.filename, "<stringchar1>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 6); lr.adv(); @@ -171,47 +175,47 @@ TEST(io, linechar1) } TEST(io, linechar2) { - io::LineCharReader lr("<stringchar2>", string_pipe("Hi\nWu")); + io::LineCharReader lr("<stringchar2>"_s, string_pipe("Hi\nWu"_s)); io::LineChar c; EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'H'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar2>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar2>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 1); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'i'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar2>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar2>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 2); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), '\n'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar2>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar2>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 3); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'W'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar2>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar2>"_s); EXPECT_EQ(c.line, 2); EXPECT_EQ(c.column, 1); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'u'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar2>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar2>"_s); EXPECT_EQ(c.line, 2); EXPECT_EQ(c.column, 2); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), '\n'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar2>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar2>"_s); EXPECT_EQ(c.line, 2); EXPECT_EQ(c.column, 3); lr.adv(); @@ -219,47 +223,47 @@ TEST(io, linechar2) } TEST(io, linechar3) { - io::LineCharReader lr("<stringchar3>", string_pipe("Hi\rWu")); + io::LineCharReader lr("<stringchar3>"_s, string_pipe("Hi\rWu"_s)); io::LineChar c; EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'H'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar3>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar3>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 1); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'i'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar3>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar3>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 2); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), '\n'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar3>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar3>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 3); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'W'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar3>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar3>"_s); EXPECT_EQ(c.line, 2); EXPECT_EQ(c.column, 1); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'u'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar3>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar3>"_s); EXPECT_EQ(c.line, 2); EXPECT_EQ(c.column, 2); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), '\n'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar3>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar3>"_s); EXPECT_EQ(c.line, 2); EXPECT_EQ(c.column, 3); lr.adv(); @@ -267,47 +271,47 @@ TEST(io, linechar3) } TEST(io, linechar4) { - io::LineCharReader lr("<stringchar4>", string_pipe("Hi\r\nWu")); + io::LineCharReader lr("<stringchar4>"_s, string_pipe("Hi\r\nWu"_s)); io::LineChar c; EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'H'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar4>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar4>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 1); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'i'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar4>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar4>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 2); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), '\n'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar4>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar4>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 3); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'W'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar4>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar4>"_s); EXPECT_EQ(c.line, 2); EXPECT_EQ(c.column, 1); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'u'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar4>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar4>"_s); EXPECT_EQ(c.line, 2); EXPECT_EQ(c.column, 2); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), '\n'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar4>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar4>"_s); EXPECT_EQ(c.line, 2); EXPECT_EQ(c.column, 3); lr.adv(); @@ -315,54 +319,54 @@ TEST(io, linechar4) } TEST(io, linechar5) { - io::LineCharReader lr("<stringchar5>", string_pipe("Hi\n\rWu")); + io::LineCharReader lr("<stringchar5>"_s, string_pipe("Hi\n\rWu"_s)); io::LineChar c; EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'H'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar5>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar5>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 1); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'i'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar5>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar5>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 2); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), '\n'); - EXPECT_EQ(c.text, "Hi"); - EXPECT_EQ(c.filename, "<stringchar5>"); + EXPECT_EQ(c.text, "Hi"_s); + EXPECT_EQ(c.filename, "<stringchar5>"_s); EXPECT_EQ(c.line, 1); EXPECT_EQ(c.column, 3); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), '\n'); - EXPECT_EQ(c.text, ""); - EXPECT_EQ(c.filename, "<stringchar5>"); + EXPECT_EQ(c.text, ""_s); + EXPECT_EQ(c.filename, "<stringchar5>"_s); EXPECT_EQ(c.line, 2); EXPECT_EQ(c.column, 1); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'W'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar5>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar5>"_s); EXPECT_EQ(c.line, 3); EXPECT_EQ(c.column, 1); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), 'u'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar5>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar5>"_s); EXPECT_EQ(c.line, 3); EXPECT_EQ(c.column, 2); lr.adv(); EXPECT_TRUE(lr.get(c)); EXPECT_EQ(c.ch(), '\n'); - EXPECT_EQ(c.text, "Wu"); - EXPECT_EQ(c.filename, "<stringchar5>"); + EXPECT_EQ(c.text, "Wu"_s); + EXPECT_EQ(c.filename, "<stringchar5>"_s); EXPECT_EQ(c.line, 3); EXPECT_EQ(c.column, 3); lr.adv(); @@ -371,7 +375,7 @@ TEST(io, linechar5) TEST(io, linespan) { - io::LineCharReader lr("<span>", string_pipe("Hello,\nWorld!\n")); + io::LineCharReader lr("<span>"_s, string_pipe("Hello,\nWorld!\n"_s)); io::LineSpan span; do { @@ -385,10 +389,10 @@ TEST(io, linespan) lr.adv(); } while (span.end.ch() != 'o'); - EXPECT_EQ(span.message_str("info", "meh"), + EXPECT_EQ(span.message_str("info"_s, "meh"_s), "<span>:1:2: info: meh\n" "Hello,\n" - " ^~~~\n" + " ^~~~\n"_s ); span.begin = span.end; do @@ -398,21 +402,22 @@ TEST(io, linespan) } while (span.end.ch() != 'r'); - EXPECT_EQ(span.begin.message_str("note", "foo"), + EXPECT_EQ(span.begin.message_str("note"_s, "foo"_s), "<span>:1:5: note: foo\n" "Hello,\n" - " ^\n" + " ^\n"_s ); - EXPECT_EQ(span.end.message_str("warning", "bar"), + EXPECT_EQ(span.end.message_str("warning"_s, "bar"_s), "<span>:2:3: warning: bar\n" "World!\n" - " ^\n" + " ^\n"_s ); - EXPECT_EQ(span.message_str("error", "qux"), + EXPECT_EQ(span.message_str("error"_s, "qux"_s), "<span>:1:5: error: qux\n" "Hello,\n" " ^~ ...\n" "World!\n" - "~~~\n" + "~~~\n"_s ); } +} // namespace tmwa diff --git a/src/io/lock.cpp b/src/io/lock.cpp index 96c3649..911b5db 100644 --- a/src/io/lock.cpp +++ b/src/io/lock.cpp @@ -1,5 +1,5 @@ #include "lock.hpp" -// io/lock.hpp - Output to files with atomic replacement and backups. +// io/lock.cpp - Output to files with atomic replacement and backups. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> // @@ -21,7 +21,13 @@ #include <fcntl.h> #include <unistd.h> +#include <cerrno> +#include <cstdio> +#include <cstdlib> + +#include "../strings/astring.hpp" #include "../strings/zstring.hpp" +#include "../strings/literal.hpp" #include "cxxstdio.hpp" #include "fd.hpp" @@ -29,9 +35,11 @@ #include "../poison.hpp" +namespace tmwa +{ /// number of backups to keep static -const int backup_count = 10; +const int backup_count = 9; /// Protected file writing /// (Until the file is closed, it keeps the old file) @@ -49,7 +57,7 @@ namespace io AString newfile; do { - newfile = STRPRINTF("%s_%d.tmp", filename, no++); + newfile = STRPRINTF("%s_%d.tmp"_fmt, filename, no++); fd = FD::open(newfile, O_WRONLY | O_CREAT | O_EXCL, 0666); } while (fd == FD() && errno == EEXIST); @@ -67,21 +75,22 @@ namespace io if (!WriteFile::close()) { // leave partial file - FPRINTF(stderr, "Warning: failed to write replacement for %s\n", filename); + FPRINTF(stderr, "Warning: failed to write replacement for %s\n"_fmt, filename); abort(); } int n = backup_count; - AString old_filename = STRPRINTF("%s.%d", filename, n); + AString old_filename = STRPRINTF("%s.%d"_fmt, filename, n); while (--n) { - AString newer_filename = STRPRINTF("%s.%d", filename, n); + AString newer_filename = STRPRINTF("%s.%d"_fmt, filename, n); rename(newer_filename.c_str(), old_filename.c_str()); old_filename = std::move(newer_filename); } rename(filename.c_str(), old_filename.c_str()); - AString tmpfile = STRPRINTF("%s_%d.tmp", filename, tmp_suffix); + AString tmpfile = STRPRINTF("%s_%d.tmp"_fmt, filename, tmp_suffix); rename(tmpfile.c_str(), filename.c_str()); } } // namespace io +} // namespace tmwa diff --git a/src/io/lock.hpp b/src/io/lock.hpp index b879da5..005b371 100644 --- a/src/io/lock.hpp +++ b/src/io/lock.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_IO_LOCK_HPP -#define TMWA_IO_LOCK_HPP +#pragma once // io/lock.hpp - Output to files with atomic replacement and backups. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,13 +18,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "write.hpp" +#include "write.hpp" -# include "../strings/rstring.hpp" +#include "../strings/rstring.hpp" +namespace tmwa +{ namespace io { class WriteLock : public WriteFile @@ -38,5 +39,4 @@ namespace io bool close() = delete; }; } // namespace io - -#endif // TMWA_IO_LOCK_HPP +} // namespace tmwa diff --git a/src/io/read.cpp b/src/io/read.cpp index 2ef35cc..3ae5246 100644 --- a/src/io/read.cpp +++ b/src/io/read.cpp @@ -19,17 +19,19 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include <fcntl.h> -#include <unistd.h> #include "../strings/astring.hpp" #include "../strings/mstring.hpp" #include "../strings/zstring.hpp" +#include "../strings/literal.hpp" #include "../io/cxxstdio.hpp" #include "../poison.hpp" +namespace tmwa +{ namespace io { ReadFile::ReadFile(FD f) @@ -40,6 +42,10 @@ namespace io : fd(FD::open(name, O_RDONLY | O_CLOEXEC)), start(0), end(0) { } + ReadFile::ReadFile(const DirFd& dir, ZString name) + : fd(dir.open_fd(name, O_RDONLY | O_CLOEXEC)), start(0), end(0) + { + } ReadFile::~ReadFile() { fd.close(); @@ -105,12 +111,12 @@ namespace io if (unhappy) { if (happy) - PRINTF("warning: file contains CR\n"); + FPRINTF(stderr, "warning: file contains CR\n"_fmt); else - PRINTF("warning: file contains bare CR\n"); + FPRINTF(stderr, "warning: file contains bare CR\n"_fmt); } else if (!happy && anything) - PRINTF("warning: file does not contain a trailing newline\n"); + FPRINTF(stderr, "warning: file does not contain a trailing newline\n"_fmt); line = AString(tmp); return anything; } @@ -120,3 +126,4 @@ namespace io return fd != FD(); } } // namespace io +} // namespace tmwa diff --git a/src/io/read.hpp b/src/io/read.hpp index f99fb56..1ec26ca 100644 --- a/src/io/read.hpp +++ b/src/io/read.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_IO_READ_HPP -#define TMWA_IO_READ_HPP +#pragma once // io/read.hpp - Input from files. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,12 +18,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "fd.hpp" +#include "dir.hpp" +#include "fd.hpp" +namespace tmwa +{ namespace io { class ReadFile @@ -38,6 +40,8 @@ namespace io ReadFile(FD fd); explicit ReadFile(ZString name); + ReadFile(const DirFd& dir, ZString name); + ReadFile& operator = (ReadFile&&) = delete; ReadFile(ReadFile&&) = delete; ~ReadFile(); @@ -49,5 +53,4 @@ namespace io bool is_open(); }; } // namespace io - -#endif // TMWA_IO_READ_HPP +} // namespace tmwa diff --git a/src/io/read_test.cpp b/src/io/read_test.cpp index 87f95ba..8fe84b7 100644 --- a/src/io/read_test.cpp +++ b/src/io/read_test.cpp @@ -20,10 +20,15 @@ #include <gtest/gtest.h> +#include "../strings/astring.hpp" #include "../strings/zstring.hpp" +#include "../strings/literal.hpp" #include "../poison.hpp" + +namespace tmwa +{ static io::FD string_pipe(ZString sz) { @@ -42,43 +47,44 @@ io::FD string_pipe(ZString sz) TEST(io, read1) { - io::ReadFile rf(string_pipe("Hello")); + io::ReadFile rf(string_pipe("Hello"_s)); AString hi; EXPECT_TRUE(rf.getline(hi)); - EXPECT_EQ(hi, "Hello"); + EXPECT_EQ(hi, "Hello"_s); EXPECT_FALSE(rf.getline(hi)); } TEST(io, read2) { - io::ReadFile rf(string_pipe("Hello\n")); + io::ReadFile rf(string_pipe("Hello\n"_s)); AString hi; EXPECT_TRUE(rf.getline(hi)); - EXPECT_EQ(hi, "Hello"); + EXPECT_EQ(hi, "Hello"_s); EXPECT_FALSE(rf.getline(hi)); } TEST(io, read3) { - io::ReadFile rf(string_pipe("Hello\r")); + io::ReadFile rf(string_pipe("Hello\r"_s)); AString hi; EXPECT_TRUE(rf.getline(hi)); - EXPECT_EQ(hi, "Hello"); + EXPECT_EQ(hi, "Hello"_s); EXPECT_FALSE(rf.getline(hi)); } TEST(io, read4) { - io::ReadFile rf(string_pipe("Hello\r\n")); + io::ReadFile rf(string_pipe("Hello\r\n"_s)); AString hi; EXPECT_TRUE(rf.getline(hi)); - EXPECT_EQ(hi, "Hello"); + EXPECT_EQ(hi, "Hello"_s); EXPECT_FALSE(rf.getline(hi)); } TEST(io, read5) { - io::ReadFile rf(string_pipe("Hello\n\r")); + io::ReadFile rf(string_pipe("Hello\n\r"_s)); AString hi; EXPECT_TRUE(rf.getline(hi)); - EXPECT_EQ(hi, "Hello"); + EXPECT_EQ(hi, "Hello"_s); EXPECT_TRUE(rf.getline(hi)); EXPECT_FALSE(hi); EXPECT_FALSE(rf.getline(hi)); } +} // namespace tmwa diff --git a/src/io/tty.cpp b/src/io/tty.cpp index e71ee44..c498740 100644 --- a/src/io/tty.cpp +++ b/src/io/tty.cpp @@ -20,4 +20,8 @@ #include "../poison.hpp" + +namespace tmwa +{ /* Nothing to see here, move along */ +} // namespace tmwa diff --git a/src/io/tty.hpp b/src/io/tty.hpp index 97487b8..f754b91 100644 --- a/src/io/tty.hpp +++ b/src/io/tty.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_IO_TTY_HPP -#define TMWA_IO_TTY_HPP +#pragma once // io/tty.hpp - terminal escape sequences // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,20 +18,21 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# define SGR_BLACK "\e[30m" -# define SGR_RED "\e[31m" -# define SGR_GREEN "\e[32m" -# define SGR_YELLOW "\e[33m" -# define SGR_BLUE "\e[34m" -# define SGR_MAGENTA "\e[35m" -# define SGR_CYAN "\e[36m" -# define SGR_WHITE "\e[37m" +namespace tmwa +{ +#define SGR_BLACK "\e[30m" +#define SGR_RED "\e[31m" +#define SGR_GREEN "\e[32m" +#define SGR_YELLOW "\e[33m" +#define SGR_BLUE "\e[34m" +#define SGR_MAGENTA "\e[35m" +#define SGR_CYAN "\e[36m" +#define SGR_WHITE "\e[37m" -# define SGR_BOLD "\e[1m" +#define SGR_BOLD "\e[1m" -# define SGR_RESET "\e[0m" - -#endif // TMWA_IO_TTY_HPP +#define SGR_RESET "\e[0m" +} // namespace tmwa diff --git a/src/io/write.cpp b/src/io/write.cpp index 5993a69..833b173 100644 --- a/src/io/write.cpp +++ b/src/io/write.cpp @@ -18,16 +18,21 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <sys/uio.h> - #include <fcntl.h> -#include <unistd.h> +#include <cstdio> +#include <cstdlib> + +#include <algorithm> + +#include "../strings/zstring.hpp" #include "../strings/xstring.hpp" #include "../poison.hpp" +namespace tmwa +{ namespace io { WriteFile::WriteFile(FD f, bool linebuffered) @@ -36,6 +41,9 @@ namespace io WriteFile::WriteFile(ZString name, bool linebuffered) : fd(FD::open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)), lb(linebuffered), buflen(0) {} + WriteFile::WriteFile(const DirFd& dir, ZString name, bool linebuffered) + : fd(dir.open_fd(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)), lb(linebuffered), buflen(0) + {} WriteFile::~WriteFile() { if (fd != FD()) @@ -174,3 +182,4 @@ namespace io return len; } } // namespace io +} // namespace tmwa diff --git a/src/io/write.hpp b/src/io/write.hpp index 870ebb5..1ab05f3 100644 --- a/src/io/write.hpp +++ b/src/io/write.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_IO_WRITE_HPP -#define TMWA_IO_WRITE_HPP +#pragma once // io/write.hpp - Output to files. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,14 +18,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdarg> +#include <cstdarg> -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "fd.hpp" +#include "dir.hpp" +#include "fd.hpp" + +namespace tmwa +{ namespace io { class WriteFile @@ -34,7 +37,6 @@ namespace io private: FD fd; bool lb; - struct {} _unused; unsigned short buflen; char buf[4096]; public: @@ -42,6 +44,8 @@ namespace io WriteFile(FD fd, bool linebuffered=false); explicit WriteFile(ZString name, bool linebuffered=false); + WriteFile(const DirFd& dir, ZString name, bool linebuffered=false); + WriteFile(WriteFile&&) = delete; WriteFile& operator = (WriteFile&&) = delete; ~WriteFile(); @@ -65,5 +69,4 @@ namespace io __attribute__((format(printf, 2, 0))) int do_vprint(WriteFile& out, const char *fmt, va_list ap); } // namespace io - -#endif // TMWA_IO_WRITE_HPP +} // namespace tmwa diff --git a/src/io/write_test.cpp b/src/io/write_test.cpp index ae8eccd..2347e7e 100644 --- a/src/io/write_test.cpp +++ b/src/io/write_test.cpp @@ -26,9 +26,13 @@ #include "../strings/astring.hpp" #include "../strings/mstring.hpp" #include "../strings/xstring.hpp" +#include "../strings/literal.hpp" #include "../poison.hpp" + +namespace tmwa +{ static io::FD pipew(io::FD& rfd) { @@ -65,7 +69,7 @@ public: if (rv == -1) { if (errno != EAGAIN) - return {"Error, read failed :("}; + return "Error, read failed :("_s; rv = 0; } if (rv == 0) @@ -81,11 +85,11 @@ TEST(io, write1) PipeWriter pw(false); io::WriteFile& wf = pw.wf; wf.really_put("Hello, ", 7); - EXPECT_EQ("", pw.slurp()); - wf.put_line("World!\n"); - EXPECT_EQ("", pw.slurp()); + EXPECT_EQ(""_s, pw.slurp()); + wf.put_line("World!\n"_s); + EXPECT_EQ(""_s, pw.slurp()); EXPECT_TRUE(wf.close()); - EXPECT_EQ("Hello, World!\n", pw.slurp()); + EXPECT_EQ("Hello, World!\n"_s, pw.slurp()); } TEST(io, write2) @@ -93,10 +97,11 @@ TEST(io, write2) PipeWriter pw(true); io::WriteFile& wf = pw.wf; wf.really_put("Hello, ", 7); - EXPECT_EQ("", pw.slurp()); - wf.put_line("World!"); + EXPECT_EQ(""_s, pw.slurp()); + wf.put_line("World!"_s); wf.really_put("XXX", 3); - EXPECT_EQ("Hello, World!\n", pw.slurp()); + EXPECT_EQ("Hello, World!\n"_s, pw.slurp()); EXPECT_TRUE(wf.close()); - EXPECT_EQ("XXX", pw.slurp()); + EXPECT_EQ("XXX"_s, pw.slurp()); } +} // namespace tmwa diff --git a/src/login/fwd.hpp b/src/login/fwd.hpp new file mode 100644 index 0000000..94fe3c0 --- /dev/null +++ b/src/login/fwd.hpp @@ -0,0 +1,27 @@ +#pragma once +// login/fwd.hpp - list of type names for login server +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +// meh, add more when I feel like it +} // namespace tmwa diff --git a/src/login/login.cpp b/src/login/login.cpp index a60b34e..ccb68fc 100644 --- a/src/login/login.cpp +++ b/src/login/login.cpp @@ -1,3 +1,4 @@ +#include "login.hpp" // login.cpp - Core of the login server. // // Copyright © ????-2004 Athena Dev Teams @@ -20,8 +21,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <arpa/inet.h> -#include <sys/types.h> #include <sys/wait.h> #include <netdb.h> @@ -29,14 +28,12 @@ #include <sys/resource.h> -#include <cstdlib> -#include <cstring> #include <ctime> #include <algorithm> -#include <array> #include <set> -#include <type_traits> + +#include "../ints/udl.hpp" #include "../strings/mstring.hpp" #include "../strings/astring.hpp" @@ -51,24 +48,36 @@ #include "../io/lock.hpp" #include "../io/read.hpp" #include "../io/tty.hpp" +#include "../io/write.hpp" + +#include "../net/packets.hpp" +#include "../net/socket.hpp" +#include "../net/timer.hpp" #include "../mmo/config_parse.hpp" #include "../mmo/core.hpp" #include "../mmo/extract.hpp" #include "../mmo/human_time_diff.hpp" +#include "../mmo/ids.hpp" #include "../mmo/md5more.hpp" #include "../mmo/mmo.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" -#include "../mmo/version.hpp" #include "../mmo/utils.hpp" +#include "../mmo/version.hpp" + +#include "../proto2/any-user.hpp" +#include "../proto2/login-admin.hpp" +#include "../proto2/login-char.hpp" +#include "../proto2/login-user.hpp" #include "../poison.hpp" + +namespace tmwa +{ constexpr int MAX_SERVERS = 30; -constexpr int START_ACCOUNT_NUM = 2000000; -constexpr int END_ACCOUNT_NUM = 100000000; +constexpr AccountId START_ACCOUNT_NUM = wrap<AccountId>(2000000); +constexpr AccountId END_ACCOUNT_NUM = wrap<AccountId>(100000000); struct mmo_account { @@ -76,10 +85,10 @@ struct mmo_account AccountPass passwd; int passwdenc; - long account_id; - long login_id1; - long login_id2; - long char_id; + AccountId account_id; + int login_id1; + int login_id2; + AccountId char_id; timestamp_milliseconds_buffer lastlogin; SEX sex; }; @@ -93,9 +102,7 @@ struct mmo_char_server }; static -int account_id_count = START_ACCOUNT_NUM; -static -int server_num; +AccountId account_id_count = START_ACCOUNT_NUM; static int new_account = 0; static @@ -114,19 +121,19 @@ static ServerName main_server; static -AString account_filename = "save/account.txt"; +AString account_filename = "save/account.txt"_s; static -AString gm_account_filename = "save/gm_account.txt"; +AString gm_account_filename = "save/gm_account.txt"_s; static -AString login_log_filename = "log/login.log"; +AString login_log_filename = "log/login.log"_s; static -AString login_log_unknown_packets_filename = "log/login_unknown_packets.log"; +AString login_log_unknown_packets_filename = "log/login_unknown_packets.log"_s; static int save_unknown_packets = 0; static tick_t creation_time_GM_account_file; static -std::chrono::seconds gm_account_filename_check_timer = std::chrono::seconds(15); +std::chrono::seconds gm_account_filename_check_timer = 15_s; static int display_parse_login = 0; // 0: no, 1: yes @@ -144,7 +151,7 @@ Array<int, MAX_SERVERS> server_freezeflag; // Char-server anti-freeze system. static int anti_freeze_enable = 0; static -std::chrono::seconds anti_freeze_interval = std::chrono::seconds(15); +std::chrono::seconds anti_freeze_interval = 15_s; static Session *login_session; @@ -163,7 +170,7 @@ std::vector<IP4Mask> access_allow, access_deny, access_ladmin; static -int min_level_to_connect = 0; // minimum level of player/GM (0: player, 1-99: gm) to connect on the server +GmLevel min_level_to_connect = GmLevel::from(0_u32); // minimum level of player/GM (0: player, 1-99: gm) to connect on the server static int add_to_unlimited_account = 0; // Give possibility or not to adjust (ladmin command: timeadd) the time of an unlimited account. static @@ -171,30 +178,32 @@ int start_limited_time = -1; // Starting additional sec from now for the limit static int check_ip_flag = 1; // It's to check IP of a player between login-server and char-server (part of anti-hacking system) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-noreturn" +DIAG_PUSH(); +DIAG_I(missing_noreturn); void SessionDeleter::operator()(SessionData *) { - assert(false && "login server does not have sessions anymore"); + assert(false && "login server does not have sessions anymore"_s); } -#pragma GCC diagnostic pop +DIAG_POP(); constexpr int AUTH_FIFO_SIZE = 256; struct AuthFifo { - int account_id, login_id1, login_id2; + AccountId account_id; + int login_id1, login_id2; IP4Address ip; SEX sex; int delflag; }; static Array<AuthFifo, AUTH_FIFO_SIZE> auth_fifo; +// TODO replace with auto_fifo_it static int auth_fifo_pos = 0; struct AuthData { - int account_id; + AccountId account_id; SEX sex; AccountName userid; AccountCrypt pass; @@ -208,7 +217,7 @@ struct AuthData IP4Address last_ip; // save of last IP of connection VString<254> memo; // a memo field int account_reg2_num; - Array<struct global_reg, ACCOUNT_REG2_NUM> account_reg2; + Array<GlobalReg, ACCOUNT_REG2_NUM> account_reg2; }; static std::vector<AuthData> auth_data; @@ -220,28 +229,15 @@ AccountPass admin_pass; static AString gm_pass; static -int level_new_gm = 60; +GmLevel level_new_gm = GmLevel::from(60u); static -Map<int, GM_Account> gm_account_db; +Map<AccountId, GM_Account> gm_account_db; static pid_t pid = 0; // For forked DB writes -namespace e -{ -enum class VERSION_2 : uint8_t -{ - /// client supports updatehost - UPDATEHOST = 0x01, - /// send servers in forward order - SERVERORDER = 0x02, -}; -ENUM_BITWISE_OPERATORS(VERSION_2) -} -using e::VERSION_2; - //------------------------------ // Writing function of logs file //------------------------------ @@ -269,9 +265,9 @@ void delete_fromchar(Session *sess) assert (it != server_session.end()); int id = it - server_session.begin(); IP4Address ip = sess->client_ip; - PRINTF("Char-server '%s' has disconnected.\n", server[id].name); - LOGIN_LOG("Char-server '%s' has disconnected (ip: %s).\n", - server[id].name, ip); + PRINTF("Char-server '%s' has disconnected.\n"_fmt, server[id].name); + LOGIN_LOG("Char-server '%s' has disconnected (ip: %s).\n"_fmt, + server[id].name, ip); server_session[id] = nullptr; server[id] = mmo_char_server{}; } @@ -279,7 +275,7 @@ void delete_fromchar(Session *sess) static void delete_admin(Session *s) { - PRINTF("Remote administration has disconnected (session #%d).\n", + PRINTF("Remote administration has disconnected (session #%d).\n"_fmt, s); } @@ -289,11 +285,11 @@ void delete_admin(Session *s) // and returns its level (or 0 if it isn't a GM account or if not found) //---------------------------------------------------------------------- static -uint8_t isGM(int account_id) +GmLevel isGM(AccountId account_id) { GM_Account *p = gm_account_db.search(account_id); - if (p == NULL) - return 0; + if (p == nullptr) + return GmLevel(); return p->level; } @@ -304,7 +300,6 @@ static int read_gm_account(void) { int c = 0; - int GM_level; gm_account_db.clear(); @@ -313,12 +308,12 @@ int read_gm_account(void) io::ReadFile fp(gm_account_filename); if (!fp.is_open()) { - PRINTF("read_gm_account: GM accounts file [%s] not found.\n", + PRINTF("read_gm_account: GM accounts file [%s] not found.\n"_fmt, + gm_account_filename); + PRINTF(" Actually, there is no GM accounts on the server.\n"_fmt); + LOGIN_LOG("read_gm_account: GM accounts file [%s] not found.\n"_fmt, gm_account_filename); - PRINTF(" Actually, there is no GM accounts on the server.\n"); - LOGIN_LOG("read_gm_account: GM accounts file [%s] not found.\n", - gm_account_filename); - LOGIN_LOG(" Actually, there is no GM accounts on the server.\n"); + LOGIN_LOG(" Actually, there is no GM accounts on the server.\n"_fmt); return 1; } // limited to 4000, because we send information to char-servers (more than 4000 GM accounts???) @@ -330,49 +325,40 @@ int read_gm_account(void) continue; GM_Account p {}; if (!extract(line, record<' '>(&p.account_id, &p.level))) - PRINTF("read_gm_account: file [%s], invalid 'id_acount level' format: '%s'\n", - gm_account_filename, line); - else if (p.level <= 0) - PRINTF("read_gm_account: file [%s] %dth account (invalid level [0 or negative]: %d).\n", - gm_account_filename, c + 1, p.level); + PRINTF("read_gm_account: file [%s], invalid 'id_acount level' format: '%s'\n"_fmt, + gm_account_filename, line); else { - if (p.level > 99) - { - PRINTF("read_gm_account: file [%s] %dth account (invalid level, but corrected: %d->99).\n", - gm_account_filename, c + 1, p.level); - p.level = 99; - } - if ((GM_level = isGM(p.account_id)) > 0) + GmLevel GM_level = isGM(p.account_id); + if (GM_level) { // if it's not a new account if (GM_level == p.level) - PRINTF("read_gm_account: GM account %d defined twice (same level: %d).\n", - p.account_id, p.level); + PRINTF("read_gm_account: GM account %d defined twice (same level: %d).\n"_fmt, + p.account_id, p.level); else - PRINTF("read_gm_account: GM account %d defined twice (levels: %d and %d).\n", - p.account_id, GM_level, p.level); + PRINTF("read_gm_account: GM account %d defined twice (levels: %d and %d).\n"_fmt, + p.account_id, GM_level, p.level); } if (GM_level != p.level) { // if new account or new level gm_account_db.insert(p.account_id, p); - //PRINTF("GM account:%d, level: %d->%d\n", p.account_id, GM_level, p.level); - if (GM_level == 0) + if (!GM_level) { // if new account c++; if (c >= 4000) { - PRINTF("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n"); - LOGIN_LOG("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n"); + PRINTF("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n"_fmt); + LOGIN_LOG("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n"_fmt); } } } } } - PRINTF("read_gm_account: file '%s' readed (%d GM accounts found).\n", + PRINTF("read_gm_account: file '%s' readed (%d GM accounts found).\n"_fmt, + gm_account_filename, c); + LOGIN_LOG("read_gm_account: file '%s' readed (%d GM accounts found).\n"_fmt, gm_account_filename, c); - LOGIN_LOG("read_gm_account: file '%s' readed (%d GM accounts found).\n", - gm_account_filename, c); return 0; } @@ -484,7 +470,7 @@ AString mmo_auth_tostr(const AuthData *p) "%lld\t" "%s\t" "%s\t" - "%lld\t", + "%lld\t"_fmt, p->account_id, p->userid, p->pass, @@ -502,7 +488,7 @@ AString mmo_auth_tostr(const AuthData *p) assert (p->account_reg2_num < ACCOUNT_REG2_NUM); for (int i = 0; i < p->account_reg2_num; i++) if (p->account_reg2[i].str) - str += STRPRINTF("%s,%d ", + str += STRPRINTF("%s,%d "_fmt, p->account_reg2[i].str, p->account_reg2[i].value); return AString(str); @@ -511,7 +497,7 @@ AString mmo_auth_tostr(const AuthData *p) static bool extract(XString line, AuthData *ad) { - std::vector<struct global_reg> vars; + std::vector<GlobalReg> vars; VString<1> sex; VString<15> ip; if (!extract(line, @@ -531,13 +517,15 @@ bool extract(XString line, AuthData *ad) &ad->ban_until_time, vrec<' '>(&vars)))) return false; + if (ad->lastlogin == stringish<timestamp_milliseconds_buffer>("-"_s)) + stamp_time(ad->lastlogin); ad->last_ip = IP4Address(); - if (ip != "-" && !extract(ip, &ad->last_ip)) + if (ip != "-"_s && !extract(ip, &ad->last_ip)) return false; - if (ad->account_id > END_ACCOUNT_NUM) + if (!(ad->account_id < END_ACCOUNT_NUM)) return false; // TODO replace *every* lookup with a map lookup - static std::set<int> seen_ids; + static std::set<AccountId> seen_ids; static std::set<AccountName> seen_names; // we don't have to worry about deleted characters, // this is only called during startup @@ -571,7 +559,7 @@ bool extract(XString line, AuthData *ad) if (!ad->error_message || ad->state != 7) // 7, because state is packet 0x006a value + 1 - ad->error_message = stringish<timestamp_seconds_buffer>("-"); + ad->error_message = stringish<timestamp_seconds_buffer>("-"_s); if (vars.size() > ACCOUNT_REG2_NUM) return false; @@ -594,8 +582,8 @@ int mmo_auth_init(void) { // no account file -> no account -> no login, including char-server (ERROR) // not anymore! :-) - PRINTF(SGR_BOLD SGR_RED "mmo_auth_init: Accounts file [%s] not found." SGR_RESET "\n", - account_filename); + PRINTF(SGR_BOLD SGR_RED "mmo_auth_init: Accounts file [%s] not found." SGR_RESET "\n"_fmt, + account_filename); return 0; } @@ -612,28 +600,29 @@ int mmo_auth_init(void) AuthData ad {}; if (!extract(line, &ad)) { - int i = 0; - if (SSCANF(line, "%d\t%%newid%%\n%n", &ad.account_id, &i) == 1 - && i > 0 && ad.account_id > account_id_count) - account_id_count = ad.account_id; + if (extract(line, record<'\t'>(&ad.account_id, "%newid%"_s))) + { + if (account_id_count < ad.account_id) + account_id_count = ad.account_id; + } else - LOGIN_LOG("Account skipped\n%s", line); + LOGIN_LOG("Account skipped\n%s"_fmt, line); continue; } auth_data.push_back(ad); - if (isGM(ad.account_id) > 0) + if (isGM(ad.account_id)) gm_count++; - if (ad.account_id >= account_id_count) - account_id_count = ad.account_id + 1; + if (account_id_count < next(ad.account_id)) + account_id_count = next(ad.account_id); } - AString str = STRPRINTF("%s has %zu accounts (%d GMs)\n", + AString str = STRPRINTF("%s has %zu accounts (%d GMs)\n"_fmt, account_filename, auth_data.size(), gm_count); - PRINTF("%s: %s\n", __PRETTY_FUNCTION__, str); - LOGIN_LOG("%s\n", line); + PRINTF("mmo_auth_init: %s\n"_fmt, str); + LOGIN_LOG("%s\n"_fmt, line); return 0; } @@ -648,39 +637,39 @@ void mmo_auth_sync(void) if (!fp.is_open()) { - PRINTF("uh-oh - unable to save accounts\n"); + PRINTF("uh-oh - unable to save accounts\n"_fmt); return; } FPRINTF(fp, - "// Accounts file: here are saved all information about the accounts.\n"); + "// Accounts file: here are saved all information about the accounts.\n"_fmt); FPRINTF(fp, - "// Structure: ID, account name, password, last login time, sex, # of logins, state, email, error message for state 7, validity time, last (accepted) login ip, memo field, ban timestamp, repeated(register text, register value)\n"); - FPRINTF(fp, "// Some explanations:\n"); + "// Structure: ID, account name, password, last login time, sex, # of logins, state, email, error message for state 7, validity time, last (accepted) login ip, memo field, ban timestamp, repeated(register text, register value)\n"_fmt); + FPRINTF(fp, "// Some explanations:\n"_fmt); FPRINTF(fp, - "// account name : between 4 to 23 char for a normal account (standard client can't send less than 4 char).\n"); - FPRINTF(fp, "// account password: between 4 to 23 char\n"); + "// account name : between 4 to 23 char for a normal account (standard client can't send less than 4 char).\n"_fmt); + FPRINTF(fp, "// account password: between 4 to 23 char\n"_fmt); FPRINTF(fp, - "// sex : M or F for normal accounts, S for server accounts\n"); + "// sex : M or F for normal accounts, S for server accounts\n"_fmt); FPRINTF(fp, - "// state : 0: account is ok, 1 to 256: error code of packet 0x006a + 1\n"); + "// state : 0: account is ok, 1 to 256: error code of packet 0x006a + 1\n"_fmt); FPRINTF(fp, - "// email : between 3 to 39 char (a@a.com is like no email)\n"); + "// email : between 3 to 39 char (a@a.com is like no email)\n"_fmt); FPRINTF(fp, - "// error message : text for the state 7: 'Your are Prohibited to login until <text>'. Max 19 char\n"); + "// error message : text for the state 7: 'Your are Prohibited to login until <text>'. Max 19 char\n"_fmt); FPRINTF(fp, - "// valitidy time : 0: unlimited account, <other value>: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)\n"); - FPRINTF(fp, "// memo field : max 254 char\n"); + "// valitidy time : 0: unlimited account, <other value>: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)\n"_fmt); + FPRINTF(fp, "// memo field : max 254 char\n"_fmt); FPRINTF(fp, - "// ban time : 0: no ban, <other value>: banned until the date: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)\n"); + "// ban time : 0: no ban, <other value>: banned until the date: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)\n"_fmt); for (const AuthData& ad : auth_data) { - if (ad.account_id < 0) + if (!ad.account_id) continue; AString line = mmo_auth_tostr(&ad); fp.put_line(line); } - FPRINTF(fp, "%d\t%%newid%%\n", account_id_count); + FPRINTF(fp, "%d\t%%newid%%\n"_fmt, account_id_count); } // We want to sync the DB to disk as little as possible as it's fairly @@ -721,44 +710,41 @@ void check_auth_sync(TimerData *, tick_t) return; } -//-------------------------------------------------------------------- -// Packet send to all char-servers, except one (wos: without our self) -//-------------------------------------------------------------------- + static -void charif_sendallwos(Session *ss, const uint8_t *buf, size_t len) +auto iter_char_sessions() -> decltype(filter_iterator<Session *>(&server_session)) { - for (int i = 0; i < MAX_SERVERS; i++) - { - Session *s = server_session[i]; - if (s && s != ss) - { - WFIFO_BUF_CLONE(s, buf, len); - WFIFOSET(s, len); - } - } + return filter_iterator<Session *>(&server_session); } //----------------------------------------------------- // Send GM accounts to all char-server //----------------------------------------------------- static -void send_GM_accounts(void) +void send_GM_accounts(Session *only=nullptr) { - uint8_t buf[32000]; - int len; + std::vector<Packet_Repeat<0x2732>> tail; - len = 4; - WBUFW(buf, 0) = 0x2732; for (const AuthData& ad : auth_data) + { // send only existing accounts. We can not create a GM account when server is online. - if (uint8_t GM_value = isGM(ad.account_id)) + if (GmLevel GM_value = isGM(ad.account_id)) { - WBUFL(buf, len) = ad.account_id; - WBUFB(buf, len + 4) = GM_value; - len += 5; + Packet_Repeat<0x2732> item; + item.account_id = ad.account_id; + item.gm_level = GM_value; + tail.push_back(item); } - WBUFW(buf, 2) = len; - charif_sendallwos(nullptr, buf, len); + } + if (only) + { + send_packet_repeatonly<0x2732, 4, 5>(only, tail); + return; + } + for (Session *ss : iter_char_sessions()) + { + send_packet_repeatonly<0x2732, 4, 5>(ss, tail); + } } //----------------------------------------------------- @@ -785,17 +771,18 @@ void check_GM_file(TimerData *, tick_t) // Account creation (with e-mail check) //------------------------------------- static -int mmo_auth_new(struct mmo_account *account, SEX sex, AccountEmail email) +AccountId mmo_auth_new(struct mmo_account *account, SEX sex, AccountEmail email) { - while (isGM(account_id_count) > 0) - account_id_count++; + while (isGM(account_id_count)) + account_id_count = next(account_id_count); struct AuthData ad {}; - ad.account_id = account_id_count++; + ad.account_id = account_id_count; + account_id_count = next(account_id_count); ad.userid = account->userid; ad.pass = MD5_saltcrypt(account->passwd, make_salt()); - ad.lastlogin = stringish<timestamp_milliseconds_buffer>("-"); + stamp_time(ad.lastlogin); ad.sex = sex; ad.logincount = 0; ad.state = 0; @@ -805,7 +792,7 @@ int mmo_auth_new(struct mmo_account *account, SEX sex, AccountEmail email) else ad.email = email; - ad.error_message = stringish<timestamp_seconds_buffer>("-"); + ad.error_message = stringish<timestamp_seconds_buffer>("-"_s); ad.ban_until_time = TimeT(); if (start_limited_time < 0) @@ -820,7 +807,7 @@ int mmo_auth_new(struct mmo_account *account, SEX sex, AccountEmail email) } ad.last_ip = IP4Address(); - ad.memo = "!"; + ad.memo = "!"_s; ad.account_reg2_num = 0; auth_data.push_back(ad); @@ -839,8 +826,8 @@ int mmo_auth(struct mmo_account *account, Session *s) // Account creation with _M/_F if (account->passwdenc == 0 - && (account->userid.endswith("_F") || account->userid.endswith("_M")) - && new_account == 1 && account_id_count <= END_ACCOUNT_NUM + && (account->userid.endswith("_F"_s) || account->userid.endswith("_M"_s)) + && new_account == 1 && account_id_count < END_ACCOUNT_NUM && (account->userid.size() - 2) >= 4 && account->passwd.size() >= 4) { new_account_sex = account->userid.back(); @@ -855,24 +842,24 @@ int mmo_auth(struct mmo_account *account, Session *s) int encpasswdok = 0; if (new_account_sex) { - LOGIN_LOG("Attempt of creation of an already existant account (account: %s_%c, ip: %s)\n", - account->userid, new_account_sex, ip); + LOGIN_LOG("Attempt of creation of an already existant account (account: %s_%c, ip: %s)\n"_fmt, + account->userid, new_account_sex, ip); return 9; // 9 = Account already exists } if ((!pass_ok(account->passwd, ad->pass)) && !encpasswdok) { if (account->passwdenc == 0) - LOGIN_LOG("Invalid password (account: %s, ip: %s)\n", - account->userid, ip); + LOGIN_LOG("Invalid password (account: %s, ip: %s)\n"_fmt, + account->userid, ip); return 1; // 1 = Incorrect Password } if (ad->state) { - LOGIN_LOG("Connection refused (account: %s, state: %d, ip: %s)\n", - account->userid, ad->state, - ip); + LOGIN_LOG("Connection refused (account: %s, state: %d, ip: %s)\n"_fmt, + account->userid, ad->state, + ip); switch (ad->state) { // packet 0x006a value + 1 case 1: // 0 = Unregistered ID @@ -899,15 +886,15 @@ int mmo_auth(struct mmo_account *account, Session *s) if (ad->ban_until_time > TimeT::now()) { // always banned - LOGIN_LOG("Connection refused (account: %s, banned until %s, ip: %s)\n", - account->userid, tmpstr, ip); + LOGIN_LOG("Connection refused (account: %s, banned until %s, ip: %s)\n"_fmt, + account->userid, tmpstr, ip); return 6; // 6 = Your are Prohibited to log in until %s } else { // ban is finished - LOGIN_LOG("End of ban (account: %s, previously banned until %s -> not more banned, ip: %s)\n", - account->userid, tmpstr, ip); + LOGIN_LOG("End of ban (account: %s, previously banned until %s -> not more banned, ip: %s)\n"_fmt, + account->userid, tmpstr, ip); ad->ban_until_time = TimeT(); // reset the ban time } } @@ -915,28 +902,28 @@ int mmo_auth(struct mmo_account *account, Session *s) if (ad->connect_until_time && ad->connect_until_time < TimeT::now()) { - LOGIN_LOG("Connection refused (account: %s, expired ID, ip: %s)\n", - account->userid, ip); + LOGIN_LOG("Connection refused (account: %s, expired ID, ip: %s)\n"_fmt, + account->userid, ip); return 2; // 2 = This ID is expired } - LOGIN_LOG("Authentification accepted (account: %s (id: %d), ip: %s)\n", - account->userid, ad->account_id, ip); + LOGIN_LOG("Authentification accepted (account: %s (id: %d), ip: %s)\n"_fmt, + account->userid, ad->account_id, ip); } else { if (new_account_sex == '\0') { - LOGIN_LOG("Unknown account (account: %s, ip: %s)\n", - account->userid, ip); + LOGIN_LOG("Unknown account (account: %s, ip: %s)\n"_fmt, + account->userid, ip); return 0; // 0 = Unregistered ID } else { - int new_id = mmo_auth_new(account, sex_from_char(new_account_sex), DEFAULT_EMAIL); - LOGIN_LOG("Account creation and authentification accepted (account %s (id: %d), sex: %c, connection with _F/_M, ip: %s)\n", - account->userid, new_id, - new_account_sex, ip); + AccountId new_id = mmo_auth_new(account, sex_from_char(new_account_sex), DEFAULT_EMAIL); + LOGIN_LOG("Account creation and authentification accepted (account %s (id: %d), sex: %c, connection with _F/_M, ip: %s)\n"_fmt, + account->userid, new_id, + new_account_sex, ip); ad = &auth_data.back(); } } @@ -964,18 +951,16 @@ void char_anti_freeze_system(TimerData *, tick_t) { int i; - //PRINTF("Entering in char_anti_freeze_system function to check freeze of servers.\n"); for (i = 0; i < MAX_SERVERS; i++) { if (server_session[i]) { // if char-server is online - //PRINTF("char_anti_freeze_system: server #%d '%s', flag: %d.\n", i, server[i].name, server_freezeflag[i]); if (server_freezeflag[i]-- < 1) { // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed - PRINTF("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection.\n", - i, server[i].name); - LOGIN_LOG("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection.\n", - i, server[i].name); + PRINTF("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection.\n"_fmt, + i, server[i].name); + LOGIN_LOG("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection.\n"_fmt, + i, server[i].name); server_session[i]->set_eof(); } } @@ -1000,67 +985,81 @@ void parse_fromchar(Session *s) return; } - while (RFIFOREST(s) >= 2) + RecvResult rv = RecvResult::Complete; + uint16_t packet_id; + while (rv == RecvResult::Complete && packet_peek_id(s, &packet_id)) { - if (display_parse_fromchar == 2 || (display_parse_fromchar == 1 && RFIFOW(s, 0) != 0x2714)) // 0x2714 is done very often (number of players) - PRINTF("parse_fromchar: connection #%d, packet: 0x%x (with being read: %zu bytes).\n", - s, RFIFOW(s, 0), RFIFOREST(s)); + if (display_parse_fromchar == 2 || (display_parse_fromchar == 1 && packet_id != 0x2714)) // 0x2714 is done very often (number of players) + PRINTF("parse_fromchar: connection #%d, packet: 0x%x (with being read: %zu bytes).\n"_fmt, + s, packet_id, packet_avail(s)); - switch (RFIFOW(s, 0)) + switch (packet_id) { // request from map-server via char-server to reload GM accounts (by Yor). case 0x2709: - LOGIN_LOG("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n", - server[id].name, ip); + { + Packet_Fixed<0x2709> fixed; + rv = recv_fpacket<0x2709, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + LOGIN_LOG("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n"_fmt, + server[id].name, ip); read_gm_account(); // send GM accounts to all char-servers send_GM_accounts(); - RFIFOSKIP(s, 2); break; + } case 0x2712: // request from char-server to authentify an account - if (RFIFOREST(s) < 19) - return; + { + Packet_Fixed<0x2712> fixed; + rv = recv_fpacket<0x2712, 19>(s, fixed); + if (rv != RecvResult::Complete) + break; + { - int acc = RFIFOL(s, 2); + AccountId acc = fixed.account_id; int i; for (i = 0; i < AUTH_FIFO_SIZE; i++) { if (auth_fifo[i].account_id == acc && - auth_fifo[i].login_id1 == RFIFOL(s, 6) && - auth_fifo[i].login_id2 == RFIFOL(s, 10) && // relate to the versions higher than 18 - auth_fifo[i].sex == static_cast<SEX>(RFIFOB(s, 14)) && + auth_fifo[i].login_id1 == fixed.login_id1 && + auth_fifo[i].login_id2 == fixed.login_id2 && // relate to the versions higher than 18 + auth_fifo[i].sex == fixed.sex && (!check_ip_flag - || auth_fifo[i].ip == RFIFOIP(s, 15)) + || auth_fifo[i].ip == fixed.ip) && !auth_fifo[i].delflag) { - int p; auth_fifo[i].delflag = 1; - LOGIN_LOG("Char-server '%s': authentification of the account %d accepted (ip: %s).\n", - server[id].name, acc, ip); + LOGIN_LOG("Char-server '%s': authentification of the account %d accepted (ip: %s).\n"_fmt, + server[id].name, acc, ip); for (const AuthData& ad : auth_data) { if (ad.account_id == acc) { - WFIFOW(s, 0) = 0x2729; // Sending of the account_reg2 - WFIFOL(s, 4) = acc; + Packet_Head<0x2729> head_29; + head_29.account_id = acc; + std::vector<Packet_Repeat<0x2729>> repeat_29; int j; - for (p = 8, j = 0; + for (j = 0; j < ad.account_reg2_num; - p += 36, j++) + j++) { - WFIFO_STRING(s, p, ad.account_reg2[j].str, 32); - WFIFOL(s, p + 32) = ad.account_reg2[j].value; + Packet_Repeat<0x2729> item; + item.name = ad.account_reg2[j].str; + item.value = ad.account_reg2[j].value; + repeat_29.push_back(item); } - WFIFOW(s, 2) = p; - WFIFOSET(s, p); -// PRINTF("parse_fromchar: Sending of account_reg2: login->char (auth fifo)\n"); - WFIFOW(s, 0) = 0x2713; - WFIFOL(s, 2) = acc; - WFIFOB(s, 6) = 0; - WFIFO_STRING(s, 7, ad.email, 40); - WFIFOL(s, 47) = static_cast<time_t>(ad.connect_until_time); - WFIFOSET(s, 51); + send_vpacket<0x2729, 8, 36>(s, head_29, repeat_29); + + Packet_Fixed<0x2713> fixed_13; + fixed_13.account_id = acc; + fixed_13.invalid = 0; + fixed_13.email = ad.email; + fixed_13.connect_until = ad.connect_until_time; + + send_fpacket<0x2713, 51>(s, fixed_13); break; } } @@ -1070,109 +1069,91 @@ void parse_fromchar(Session *s) // authentification not found if (i == AUTH_FIFO_SIZE) { - LOGIN_LOG("Char-server '%s': authentification of the account %d REFUSED (ip: %s).\n", - server[id].name, acc, ip); - WFIFOW(s, 0) = 0x2713; - WFIFOL(s, 2) = acc; - WFIFOB(s, 6) = 1; - // It is unnecessary to send email - // It is unnecessary to send validity date of the account - WFIFOSET(s, 51); + LOGIN_LOG("Char-server '%s': authentification of the account %d REFUSED (ip: %s).\n"_fmt, + server[id].name, acc, ip); + + Packet_Fixed<0x2713> fixed_13; + fixed_13.account_id = acc; + fixed_13.invalid = 1; + // fixed_13.email + // fixed_13.connect_until + + send_fpacket<0x2713, 51>(s, fixed_13); } } - RFIFOSKIP(s, 19); break; + } case 0x2714: - if (RFIFOREST(s) < 6) - return; - //PRINTF("parse_fromchar: Receiving of the users number of the server '%s': %d\n", server[id].name, RFIFOL(fd,2)); - server[id].users = RFIFOL(s, 2); + { + Packet_Fixed<0x2714> fixed; + rv = recv_fpacket<0x2714, 6>(s, fixed); + if (rv != RecvResult::Complete) + break; + + server[id].users = fixed.users; if (anti_freeze_enable) server_freezeflag[id] = 5; // Char anti-freeze system. Counter. 5 ok, 4...0 freezed - RFIFOSKIP(s, 6); - break; - - // we receive a e-mail creation of an account with a default e-mail (no answer) - case 0x2715: - if (RFIFOREST(s) < 46) - return; - { - int acc = RFIFOL(s, 2); - AccountEmail email = stringish<AccountEmail>(RFIFO_STRING<40>(s, 6)); - if (!e_mail_check(email)) - LOGIN_LOG("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - e-mail is invalid (account: %d, ip: %s)\n", - server[id].name, acc, ip); - else - { - for (AuthData& ad : auth_data) - { - if (ad.account_id == acc - && (ad.email == DEFAULT_EMAIL || !ad.email)) - { - ad.email = email; - LOGIN_LOG("Char-server '%s': Create an e-mail on an account with a default e-mail (account: %d, new e-mail: %s, ip: %s).\n", - server[id].name, acc, email, ip); - goto x2715_out; - } - } - LOGIN_LOG("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - account doesn't exist or e-mail of account isn't default e-mail (account: %d, ip: %s).\n", - server[id].name, acc, ip); - } - x2715_out: - RFIFOSKIP(s, 46); break; + } // We receive an e-mail/limited time request, because a player comes back from a map-server to the char-server - } case 0x2716: - if (RFIFOREST(s) < 6) - return; { - int account_id = RFIFOL(s, 2); - //PRINTF("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, RFIFOL(fd,2)); + Packet_Fixed<0x2716> fixed; + rv = recv_fpacket<0x2716, 6>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; for (const AuthData& ad : auth_data) { if (ad.account_id == account_id) { - LOGIN_LOG("Char-server '%s': e-mail of the account %d found (ip: %s).\n", + LOGIN_LOG("Char-server '%s': e-mail of the account %d found (ip: %s).\n"_fmt, server[id].name, account_id, ip); - WFIFOW(s, 0) = 0x2717; - WFIFOL(s, 2) = account_id; - WFIFO_STRING(s, 6, ad.email, 40); - WFIFOL(s, 46) = static_cast<time_t>(ad.connect_until_time); - WFIFOSET(s, 50); + + Packet_Fixed<0x2717> fixed_17; + fixed_17.account_id = account_id; + fixed_17.email = ad.email; + fixed_17.connect_until = ad.connect_until_time; + + send_fpacket<0x2717, 50>(s, fixed_17); + if (rv != RecvResult::Complete) + break; goto x2716_end; } } - LOGIN_LOG("Char-server '%s': e-mail of the account %d NOT found (ip: %s).\n", + LOGIN_LOG("Char-server '%s': e-mail of the account %d NOT found (ip: %s).\n"_fmt, server[id].name, account_id, ip); - } x2716_end: - RFIFOSKIP(s, 6); break; + } case 0x2720: // To become GM request - if (RFIFOREST(s) < 4 || RFIFOREST(s) < RFIFOW(s, 2)) - return; + { + Packet_Head<0x2720> head; + AString repeat; + rv = recv_vpacket<0x2720, 8, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + break; + { - int acc; - unsigned char buf[10]; - acc = RFIFOL(s, 4); - //PRINTF("parse_fromchar: Request to become a GM acount from %d account.\n", acc); - WBUFW(buf, 0) = 0x2721; - WBUFL(buf, 2) = acc; - WBUFL(buf, 6) = 0; - size_t len = RFIFOW(s, 2) - 8; - AString pass = RFIFO_STRING(s, 8, len); + AccountId acc = head.account_id; + + Packet_Fixed<0x2721> fixed_21; + fixed_21.account_id = acc; + fixed_21.gm_level = GmLevel(); + + AString pass = repeat; if (pass == gm_pass) { // only non-GM can become GM - if (isGM(acc) == 0) + if (!isGM(acc)) { // if we autorise creation - if (level_new_gm > 0) + if (level_new_gm) { // if we can open the file to add the new GM io::AppendFile fp(gm_account_filename); @@ -1181,75 +1162,82 @@ void parse_fromchar(Session *s) timestamp_seconds_buffer tmpstr; stamp_time(tmpstr); FPRINTF(fp, - "\n// %s: @GM command on account %d\n%d %d\n", - tmpstr, - acc, acc, level_new_gm); + "\n// %s: @GM command on account %d\n%d %d\n"_fmt, + tmpstr, + acc, acc, level_new_gm); if (!fp.close()) { - PRINTF("warning: didn't actually save GM file\n"); + PRINTF("warning: didn't actually save GM file\n"_fmt); } - WBUFL(buf, 6) = level_new_gm; + fixed_21.gm_level = level_new_gm; read_gm_account(); send_GM_accounts(); - PRINTF("GM Change of the account %d: level 0 -> %d.\n", - acc, level_new_gm); - LOGIN_LOG("Char-server '%s': GM Change of the account %d: level 0 -> %d (ip: %s).\n", - server[id].name, acc, - level_new_gm, ip); + PRINTF("GM Change of the account %d: level 0 -> %d.\n"_fmt, + acc, level_new_gm); + LOGIN_LOG("Char-server '%s': GM Change of the account %d: level 0 -> %d (ip: %s).\n"_fmt, + server[id].name, acc, + level_new_gm, ip); } else { - PRINTF("Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file)\n", - acc); - LOGIN_LOG("Char-server '%s': Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file, ip: %s).\n", - server[id].name, acc, ip); + PRINTF("Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file)\n"_fmt, + acc); + LOGIN_LOG("Char-server '%s': Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file, ip: %s).\n"_fmt, + server[id].name, acc, ip); } } else { - PRINTF("Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0))\n", - acc); - LOGIN_LOG("Char-server '%s': Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0), ip: %s).\n", - server[id].name, acc, ip); + PRINTF("Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0))\n"_fmt, + acc); + LOGIN_LOG("Char-server '%s': Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0), ip: %s).\n"_fmt, + server[id].name, acc, ip); } } else { - PRINTF("Error of GM change (suggested account: %d (already GM), correct password).\n", - acc); - LOGIN_LOG("Char-server '%s': Error of GM change (suggested account: %d (already GM), correct password, ip: %s).\n", - server[id].name, acc, ip); + PRINTF("Error of GM change (suggested account: %d (already GM), correct password).\n"_fmt, + acc); + LOGIN_LOG("Char-server '%s': Error of GM change (suggested account: %d (already GM), correct password, ip: %s).\n"_fmt, + server[id].name, acc, ip); } } else { - PRINTF("Error of GM change (suggested account: %d, invalid password).\n", - acc); - LOGIN_LOG("Char-server '%s': Error of GM change (suggested account: %d, invalid password, ip: %s).\n", - server[id].name, acc, ip); + PRINTF("Error of GM change (suggested account: %d, invalid password).\n"_fmt, + acc); + LOGIN_LOG("Char-server '%s': Error of GM change (suggested account: %d, invalid password, ip: %s).\n"_fmt, + server[id].name, acc, ip); + } + for (Session *ss : iter_char_sessions()) + { + send_fpacket<0x2721, 10>(ss, fixed_21); } - charif_sendallwos(nullptr, buf, 10); } - RFIFOSKIP(s, RFIFOW(s, 2)); - return; + break; + } // Map server send information to change an email of an account via char-server case 0x2722: // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B - if (RFIFOREST(s) < 86) - return; + { + Packet_Fixed<0x2722> fixed; + rv = recv_fpacket<0x2722, 86>(s, fixed); + if (rv != RecvResult::Complete) + break; + { - int acc = RFIFOL(s, 2); - AccountEmail actual_email = stringish<AccountEmail>(RFIFO_STRING<40>(s, 6).to_print()); - AccountEmail new_email = stringish<AccountEmail>(RFIFO_STRING<40>(s, 46)); + AccountId acc = fixed.account_id; + AccountEmail actual_email = stringish<AccountEmail>(fixed.old_email.to_print()); + AccountEmail new_email = fixed.new_email; if (!e_mail_check(actual_email)) - LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n", - server[id].name, acc, ip); + LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n"_fmt, + server[id].name, acc, ip); else if (!e_mail_check(new_email)) - LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n", - server[id].name, acc, ip); + LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n"_fmt, + server[id].name, acc, ip); else if (new_email == DEFAULT_EMAIL) - LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n", - server[id].name, acc, ip); + LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n"_fmt, + server[id].name, acc, ip); else { for (AuthData& ad : auth_data) @@ -1259,77 +1247,90 @@ void parse_fromchar(Session *s) if (ad.email == actual_email) { ad.email = new_email; - LOGIN_LOG("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n", - server[id].name, acc, - ad.userid, new_email, ip); + LOGIN_LOG("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n"_fmt, + server[id].name, acc, + ad.userid, new_email, ip); } else - LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", - server[id].name, acc, - ad.userid, - ad.email, actual_email, ip); + LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n"_fmt, + server[id].name, acc, + ad.userid, + ad.email, actual_email, ip); goto x2722_out; } } - LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", + LOGIN_LOG("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n"_fmt, server[id].name, acc, ip); } } x2722_out: - RFIFOSKIP(s, 86); break; + } // Receiving of map-server via char-server a status change resquest (by Yor) case 0x2724: - if (RFIFOREST(s) < 10) - return; + { + Packet_Fixed<0x2724> fixed; + rv = recv_fpacket<0x2724, 10>(s, fixed); + if (rv != RecvResult::Complete) + break; + { - int acc, statut; - acc = RFIFOL(s, 2); - statut = RFIFOL(s, 6); + AccountId acc = fixed.account_id; + int statut = fixed.status; for (AuthData& ad : auth_data) { if (ad.account_id == acc) { if (ad.state != statut) { - LOGIN_LOG("Char-server '%s': Status change (account: %d, new status %d, ip: %s).\n", - server[id].name, acc, statut, - ip); + LOGIN_LOG("Char-server '%s': Status change (account: %d, new status %d, ip: %s).\n"_fmt, + server[id].name, acc, statut, + ip); if (statut != 0) { - unsigned char buf[16]; - WBUFW(buf, 0) = 0x2731; - WBUFL(buf, 2) = acc; - WBUFB(buf, 6) = 0; // 0: change of statut, 1: ban - WBUFL(buf, 7) = statut; // status or final date of a banishment - charif_sendallwos(nullptr, buf, 11); + Packet_Fixed<0x2731> fixed_31; + fixed_31.account_id = acc; + fixed_31.ban_not_status = 0; + fixed_31.status_or_ban_until = static_cast<time_t>(statut); + + for (Session *ss : iter_char_sessions()) + { + send_fpacket<0x2731, 11>(ss, fixed_31); + } + for (int j = 0; j < AUTH_FIFO_SIZE; j++) + { if (auth_fifo[j].account_id == acc) auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) + } } ad.state = statut; } else - LOGIN_LOG("Char-server '%s': Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s).\n", - server[id].name, acc, statut, - ip); + LOGIN_LOG("Char-server '%s': Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s).\n"_fmt, + server[id].name, acc, statut, + ip); goto x2724_out; } } - LOGIN_LOG("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s).\n", + LOGIN_LOG("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s).\n"_fmt, server[id].name, acc, statut, ip); x2724_out: - RFIFOSKIP(s, 10); + ; } - return; + break; + } case 0x2725: // Receiving of map-server via char-server a ban resquest (by Yor) - if (RFIFOREST(s) < 18) - return; + { + Packet_Fixed<0x2725> fixed; + rv = recv_fpacket<0x2725, 18>(s, fixed); + if (rv != RecvResult::Complete) + break; + { - int acc; - acc = RFIFOL(s, 2); + AccountId acc = fixed.account_id; for (AuthData& ad : auth_data) { if (ad.account_id == acc) @@ -1342,8 +1343,7 @@ void parse_fromchar(Session *s) else timestamp = ad.ban_until_time; struct tm tmtime = timestamp; - HumanTimeDiff ban_diff; - RFIFO_STRUCT(s, 6, ban_diff); + HumanTimeDiff ban_diff = fixed.ban_add; tmtime.tm_year += ban_diff.year; tmtime.tm_mon += ban_diff.month; tmtime.tm_mday += ban_diff.day; @@ -1359,137 +1359,170 @@ void parse_fromchar(Session *s) { if (timestamp) { - unsigned char buf[16]; timestamp_seconds_buffer tmpstr; if (timestamp) stamp_time(tmpstr, ×tamp); - LOGIN_LOG("Char-server '%s': Ban request (account: %d, new final date of banishment: %lld (%s), ip: %s).\n", + LOGIN_LOG("Char-server '%s': Ban request (account: %d, new final date of banishment: %lld (%s), ip: %s).\n"_fmt, server[id].name, acc, timestamp, tmpstr, ip); - WBUFW(buf, 0) = 0x2731; - WBUFL(buf, 2) = ad.account_id; - WBUFB(buf, 6) = 1; // 0: change of statut, 1: ban - WBUFL(buf, 7) = static_cast<time_t>(timestamp); // status or final date of a banishment - charif_sendallwos(nullptr, buf, 11); + Packet_Fixed<0x2731> fixed_31; + fixed_31.account_id = ad.account_id; + fixed_31.ban_not_status = 1; + fixed_31.status_or_ban_until = timestamp; + + for (Session *ss : iter_char_sessions()) + { + send_fpacket<0x2731, 11>(ss, fixed_31); + } + for (int j = 0; j < AUTH_FIFO_SIZE; j++) - if (auth_fifo[j].account_id == - acc) + { + if (auth_fifo[j].account_id == acc) auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) + } } else { - LOGIN_LOG("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", - server[id].name, acc, - ip); + LOGIN_LOG("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n"_fmt, + server[id].name, acc, + ip); } ad.ban_until_time = timestamp; } else { - LOGIN_LOG("Char-server '%s': Error of ban request (account: %d, no change for ban date, ip: %s).\n", - server[id].name, acc, ip); + LOGIN_LOG("Char-server '%s': Error of ban request (account: %d, no change for ban date, ip: %s).\n"_fmt, + server[id].name, acc, ip); } } else { - LOGIN_LOG("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", - server[id].name, acc, ip); + LOGIN_LOG("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n"_fmt, + server[id].name, acc, ip); } goto x2725_out; } } - LOGIN_LOG("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", + LOGIN_LOG("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n"_fmt, server[id].name, acc, ip); x2725_out: - RFIFOSKIP(s, 18); + ; } - return; + break; + } case 0x2727: // Change of sex (sex is reversed) - if (RFIFOREST(s) < 6) - return; + { + Packet_Fixed<0x2727> fixed; + rv = recv_fpacket<0x2727, 6>(s, fixed); + if (rv != RecvResult::Complete) + break; + { - int acc; - acc = RFIFOL(s, 2); + AccountId acc = fixed.account_id; for (AuthData& ad : auth_data) { if (ad.account_id == acc) { { - unsigned char buf[16]; SEX sex; if (ad.sex == SEX::FEMALE) sex = SEX::MALE; else sex = SEX::FEMALE; - LOGIN_LOG("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", - server[id].name, acc, - sex_to_char(sex), - ip); + LOGIN_LOG("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n"_fmt, + server[id].name, acc, + sex_to_char(sex), + ip); for (int j = 0; j < AUTH_FIFO_SIZE; j++) + { if (auth_fifo[j].account_id == acc) auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) + } ad.sex = sex; - WBUFW(buf, 0) = 0x2723; - WBUFL(buf, 2) = acc; - WBUFB(buf, 6) = static_cast<uint8_t>(sex); - charif_sendallwos(nullptr, buf, 7); + + Packet_Fixed<0x2723> fixed_23; + fixed_23.account_id = acc; + fixed_23.sex = sex; + + for (Session *ss : iter_char_sessions()) + { + send_fpacket<0x2723, 7>(ss, fixed_23); + } } goto x2727_out; } } - LOGIN_LOG("Char-server '%s': Error of sex change (account: %d not found, sex would be reversed, ip: %s).\n", + LOGIN_LOG("Char-server '%s': Error of sex change (account: %d not found, sex would be reversed, ip: %s).\n"_fmt, server[id].name, acc, ip); x2727_out: - RFIFOSKIP(s, 6); + ; } - return; + break; + } case 0x2728: // We receive account_reg2 from a char-server, and we send them to other char-servers. - if (RFIFOREST(s) < 4 || RFIFOREST(s) < RFIFOW(s, 2)) - return; + { + Packet_Head<0x2728> head; + std::vector<Packet_Repeat<0x2728>> repeat; + rv = recv_vpacket<0x2728, 8, 36>(s, head, repeat); + if (rv != RecvResult::Complete) + break; + { - int acc, p; - acc = RFIFOL(s, 4); + AccountId acc = head.account_id; for (AuthData& ad : auth_data) { if (ad.account_id == acc) { - LOGIN_LOG("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", - server[id].name, acc, ip); - size_t len = RFIFOW(s, 2); - int j; - for (p = 8, j = 0; - p < len && j < ACCOUNT_REG2_NUM; - p += 36, j++) + LOGIN_LOG("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n"_fmt, + server[id].name, acc, ip); + + const size_t count = std::min(ACCOUNT_REG2_NUM, repeat.size()); + for (size_t j = 0; j < count; ++j) { - ad.account_reg2[j].str = stringish<VarName>(RFIFO_STRING<32>(s, p).to_print()); - ad.account_reg2[j].value = RFIFOL(s, p + 32); + ad.account_reg2[j].str = repeat[j].name; + ad.account_reg2[j].value = repeat[j].value; } - ad.account_reg2_num = j; + ad.account_reg2_num = count; + // Sending information towards the other char-servers. - uint8_t buf[len]; - RFIFO_BUF_CLONE(s, buf, len); - WBUFW(buf, 0) = 0x2729; - charif_sendallwos(s, buf, WBUFW(buf, 2)); -// PRINTF("parse_fromchar: receiving (from the char-server) of account_reg2 (account id: %d).\n", acc); + Packet_Head<0x2729> head_29; + std::vector<Packet_Repeat<0x2729>> repeat_29(repeat.size()); + head_29.account_id = head.account_id; + for (size_t j = 0; j < count; ++j) + { + repeat_29[j].name = repeat[j].name; + repeat_29[j].value = repeat[j].value; + } + + for (Session *ss : iter_char_sessions()) + { + if (ss == s) + continue; + send_vpacket<0x2729, 8, 36>(ss, head_29, repeat_29); + } goto x2728_out; } } - LOGIN_LOG("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", + LOGIN_LOG("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n"_fmt, server[id].name, acc, ip); } x2728_out: - RFIFOSKIP(s, RFIFOW(s, 2)); break; + } case 0x272a: // Receiving of map-server via char-server a unban resquest (by Yor) - if (RFIFOREST(s) < 6) - return; + { + Packet_Fixed<0x272a> fixed; + rv = recv_fpacket<0x272a, 6>(s, fixed); + if (rv != RecvResult::Complete) + break; + { - int acc = RFIFOL(s, 2); + AccountId acc = fixed.account_id; for (AuthData& ad : auth_data) { if (ad.account_id == acc) @@ -1497,32 +1530,37 @@ void parse_fromchar(Session *s) if (ad.ban_until_time) { ad.ban_until_time = TimeT(); - LOGIN_LOG("Char-server '%s': UnBan request (account: %d, ip: %s).\n", - server[id].name, acc, ip); + LOGIN_LOG("Char-server '%s': UnBan request (account: %d, ip: %s).\n"_fmt, + server[id].name, acc, ip); } else { - LOGIN_LOG("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n", - server[id].name, acc, ip); + LOGIN_LOG("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n"_fmt, + server[id].name, acc, ip); } goto x272a_out; } } - LOGIN_LOG("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n", + LOGIN_LOG("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n"_fmt, server[id].name, acc, ip); x272a_out: - RFIFOSKIP(s, 6); + ; } - return; + break; + } // request from char-server to change account password case 0x2740: // 0x2740 <account_id>.L <actual_password>.24B <new_password>.24B - if (RFIFOREST(s) < 54) - return; + { + Packet_Fixed<0x2740> fixed; + rv = recv_fpacket<0x2740, 54>(s, fixed); + if (rv != RecvResult::Complete) + break; + { - int acc = RFIFOL(s, 2); - AccountPass actual_pass = stringish<AccountPass>(RFIFO_STRING<24>(s, 6).to_print()); - AccountPass new_pass = stringish<AccountPass>(RFIFO_STRING<24>(s, 30).to_print()); + AccountId acc = fixed.account_id; + AccountPass actual_pass = stringish<AccountPass>(fixed.old_pass.to_print()); + AccountPass new_pass = stringish<AccountPass>(fixed.new_pass.to_print()); int status = 0; @@ -1538,30 +1576,30 @@ void parse_fromchar(Session *s) { status = 1; ad.pass = MD5_saltcrypt(new_pass, make_salt()); - LOGIN_LOG("Char-server '%s': Change pass success (account: %d (%s), ip: %s.\n", - server[id].name, acc, - ad.userid, ip); + LOGIN_LOG("Char-server '%s': Change pass success (account: %d (%s), ip: %s.\n"_fmt, + server[id].name, acc, + ad.userid, ip); } } else { status = 2; - LOGIN_LOG("Char-server '%s': Attempt to modify a pass failed, wrong password. (account: %d (%s), ip: %s).\n", - server[id].name, acc, - ad.userid, ip); + LOGIN_LOG("Char-server '%s': Attempt to modify a pass failed, wrong password. (account: %d (%s), ip: %s).\n"_fmt, + server[id].name, acc, + ad.userid, ip); } goto x2740_out; } } x2740_out: - WFIFOW(s, 0) = 0x2741; - WFIFOL(s, 2) = acc; - WFIFOB(s, 6) = status; // 0: acc not found, 1: success, 2: password mismatch, 3: pass too short - WFIFOSET(s, 7); + Packet_Fixed<0x2741> fixed_41; + fixed_41.account_id = acc; + fixed_41.status = status; + send_fpacket<0x2741, 7>(s, fixed_41); } - RFIFOSKIP(s, 54); break; + } default: { @@ -1571,53 +1609,24 @@ void parse_fromchar(Session *s) timestamp_milliseconds_buffer timestr; stamp_time(timestr); FPRINTF(logfp, - "%s: receiving of an unknown packet -> disconnection\n", - timestr); - FPRINTF(logfp, - "parse_fromchar: connection #%d (ip: %s), packet: 0x%x (with being read: %zu).\n", - s, ip, RFIFOW(s, 0), RFIFOREST(s)); - FPRINTF(logfp, "Detail (in hex):\n"); + "%s: receiving of an unknown packet -> disconnection\n"_fmt, + timestr); FPRINTF(logfp, - "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F\n"); - char tmpstr[16 + 1] {}; - int i; - for (i = 0; i < RFIFOREST(s); i++) - { - if ((i & 15) == 0) - FPRINTF(logfp, "%04X ", i); - FPRINTF(logfp, "%02x ", RFIFOB(s, i)); - if (RFIFOB(s, i) > 0x1f) - tmpstr[i % 16] = RFIFOB(s, i); - else - tmpstr[i % 16] = '.'; - if ((i - 7) % 16 == 0) // -8 + 1 - FPRINTF(logfp, " "); - else if ((i + 1) % 16 == 0) - { - FPRINTF(logfp, " %s\n", tmpstr); - std::fill(tmpstr + 0, tmpstr + 17, '\0'); - } - } - if (i % 16 != 0) - { - for (int j = i; j % 16 != 0; j++) - { - FPRINTF(logfp, " "); - if ((j - 7) % 16 == 0) // -8 + 1 - FPRINTF(logfp, " "); - } - FPRINTF(logfp, " %s\n", tmpstr); - } - FPRINTF(logfp, "\n"); + "parse_fromchar: connection #%d (ip: %s), packet: 0x%x (with being read: %zu).\n"_fmt, + s, ip, packet_id, packet_avail(s)); + FPRINTF(logfp, "Detail (in hex):\n"_fmt); + packet_dump(logfp, s); } - } - PRINTF("parse_fromchar: Unknown packet 0x%x (from a char-server)! -> disconnection.\n", - RFIFOW(s, 0)); + PRINTF("parse_fromchar: Unknown packet 0x%x (from a char-server)! -> disconnection.\n"_fmt, + packet_id); s->set_eof(); - PRINTF("Char-server has been disconnected (unknown packet).\n"); + PRINTF("Char-server has been disconnected (unknown packet).\n"_fmt); return; + } } } + if (rv == RecvResult::Error) + s->set_eof(); return; } @@ -1628,112 +1637,136 @@ static void parse_admin(Session *s) { IP4Address ip = s->client_ip; - - while (RFIFOREST(s) >= 2) + RecvResult rv = RecvResult::Complete; + uint16_t packet_id; + while (rv == RecvResult::Complete && packet_peek_id(s, &packet_id)) { if (display_parse_admin == 1) - PRINTF("parse_admin: connection #%d, packet: 0x%x (with being read: %zu).\n", - s, RFIFOW(s, 0), RFIFOREST(s)); + PRINTF("parse_admin: connection #%d, packet: 0x%x (with being read: %zu bytes).\n"_fmt, + s, packet_id, packet_avail(s)); - switch (RFIFOW(s, 0)) + switch (packet_id) { case 0x7530: // Request of the server version - LOGIN_LOG("'ladmin': Sending of the server version (ip: %s)\n", - ip); - WFIFOW(s, 0) = 0x7531; - WFIFO_STRUCT(s, 2, CURRENT_LOGIN_SERVER_VERSION); - WFIFOSET(s, 10); - RFIFOSKIP(s, 2); + { + Packet_Fixed<0x7530> fixed; + rv = recv_fpacket<0x7530, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + LOGIN_LOG("'ladmin': Sending of the server version (ip: %s)\n"_fmt, + ip); + + Packet_Fixed<0x7531> fixed_31; + fixed_31.version = CURRENT_LOGIN_SERVER_VERSION; + send_fpacket<0x7531, 10>(s, fixed_31); break; + } case 0x7532: // Request of end of connection - LOGIN_LOG("'ladmin': End of connection (ip: %s)\n", - ip); - RFIFOSKIP(s, 2); + { + Packet_Fixed<0x7532> fixed; + rv = recv_fpacket<0x7532, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + LOGIN_LOG("'ladmin': End of connection (ip: %s)\n"_fmt, + ip); s->set_eof(); - break; + return; + } case 0x7920: // Request of an accounts list - if (RFIFOREST(s) < 10) - return; + { + Packet_Fixed<0x7920> fixed; + rv = recv_fpacket<0x7920, 10>(s, fixed); + if (rv != RecvResult::Complete) + break; + { - int st, ed, len; - st = RFIFOL(s, 2); - ed = RFIFOL(s, 6); - RFIFOSKIP(s, 10); - WFIFOW(s, 0) = 0x7921; - if (st < 0) - st = 0; - if (ed > END_ACCOUNT_NUM || ed < st || ed <= 0) + AccountId st = fixed.start_account_id; + AccountId ed = fixed.end_account_id; + if (!(ed < END_ACCOUNT_NUM) || ed < st || !ed) ed = END_ACCOUNT_NUM; - LOGIN_LOG("'ladmin': Sending an accounts list (ask: from %d to %d, ip: %s)\n", - st, ed, ip); + + LOGIN_LOG("'ladmin': Sending an accounts list (ask: from %d to %d, ip: %s)\n"_fmt, + st, ed, ip); + // Sending accounts information - len = 4; + std::vector<Packet_Repeat<0x7921>> repeat_21; + for (const AuthData& ad : auth_data) { - if (len >= 30000) - break; - int account_id = ad.account_id; - if (account_id >= st && account_id <= ed) + AccountId account_id = ad.account_id; + if (!(account_id < st) && !(ed < account_id)) { - WFIFOL(s, len) = account_id; - WFIFOB(s, len + 4) = isGM(account_id); - WFIFO_STRING(s, len + 5, ad.userid, 24); - WFIFOB(s, len + 29) = static_cast<uint8_t>(ad.sex); - WFIFOL(s, len + 30) = ad.logincount; + Packet_Repeat<0x7921> info; + info.account_id = account_id; + info.gm_level = isGM(account_id); + info.account_name = ad.userid; + info.sex = ad.sex; + info.login_count = ad.logincount; if (ad.state == 0 && ad.ban_until_time) // if no state and banished - WFIFOL(s, len + 34) = 7; // 6 = Your are Prohibited to log in until %s + info.status = 7; // 6 = Your are Prohibited to log in until %s else - WFIFOL(s, len + 34) = ad.state; - len += 38; + info.status = ad.state; + repeat_21.push_back(info); } } - WFIFOW(s, 2) = len; - WFIFOSET(s, len); + send_packet_repeatonly<0x7921, 4, 38>(s, repeat_21); } break; + } case 0x7924: { // [Fate] Itemfrob package: change item IDs - if (RFIFOREST(s) < 10) - return; - uint8_t buf[10]; - RFIFO_BUF_CLONE(s, buf, 10); - // forward package to char servers - charif_sendallwos(nullptr, buf, 10); - RFIFOSKIP(s, 10); - WFIFOW(s, 0) = 0x7925; - WFIFOSET(s, 2); + Packet_Fixed<0x7924> fixed; + rv = recv_fpacket<0x7924, 10>(s, fixed); + if (rv != RecvResult::Complete) + break; + + for (Session *ss : iter_char_sessions()) + { + send_fpacket<0x7924, 10>(ss, fixed); + } + + Packet_Fixed<0x7925> fixed_25; + send_fpacket<0x7925, 2>(s, fixed_25); break; } case 0x7930: // Request for an account creation - if (RFIFOREST(s) < 91) - return; + { + Packet_Fixed<0x7930> fixed; + rv = recv_fpacket<0x7930, 91>(s, fixed); + if (rv != RecvResult::Complete) + break; + { struct mmo_account ma; - ma.userid = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); - ma.passwd = stringish<AccountPass>(RFIFO_STRING<24>(s, 26).to_print()); - ma.lastlogin = stringish<timestamp_milliseconds_buffer>("-"); - ma.sex = sex_from_char(RFIFOB(s, 50)); - WFIFOW(s, 0) = 0x7931; - WFIFOL(s, 2) = -1; - WFIFO_STRING(s, 6, ma.userid, 24); + // TODO make this a 'return false' bit of the network_to_native + ma.userid = stringish<AccountName>(fixed.account_name.to_print()); + ma.passwd = stringish<AccountPass>(fixed.password.to_print()); + stamp_time(ma.lastlogin); + ma.sex = fixed.sex; + + Packet_Fixed<0x7931> fixed_31; + fixed_31.account_id = AccountId(); + fixed_31.account_name = ma.userid; if (ma.userid.size() < 4 || ma.passwd.size() < 4) { - LOGIN_LOG("'ladmin': Attempt to create an invalid account (account or pass is too short, ip: %s)\n", - ip); + LOGIN_LOG("'ladmin': Attempt to create an invalid account (account or pass is too short, ip: %s)\n"_fmt, + ip); } else if (ma.sex != SEX::FEMALE && ma.sex != SEX::MALE) { - LOGIN_LOG("'ladmin': Attempt to create an invalid account (account: %s, invalid sex, ip: %s)\n", - ma.userid, ip); + LOGIN_LOG("'ladmin': Attempt to create an invalid account (account: %s, invalid sex, ip: %s)\n"_fmt, + ma.userid, ip); } - else if (account_id_count > END_ACCOUNT_NUM) + else if (!(account_id_count < END_ACCOUNT_NUM)) { - LOGIN_LOG("'ladmin': Attempt to create an account, but there is no more available id number (account: %s, sex: %c, ip: %s)\n", - ma.userid, ma.sex, ip); + LOGIN_LOG("'ladmin': Attempt to create an account, but there is no more available id number (account: %s, sex: %c, ip: %s)\n"_fmt, + ma.userid, sex_to_char(ma.sex), ip); } else { @@ -1741,135 +1774,151 @@ void parse_admin(Session *s) { if (ad.userid == ma.userid) { - LOGIN_LOG("'ladmin': Attempt to create an already existing account (account: %s ip: %s)\n", - ad.userid, ip); + LOGIN_LOG("'ladmin': Attempt to create an already existing account (account: %s ip: %s)\n"_fmt, + ad.userid, ip); goto x7930_out; } } { - AccountEmail email = stringish<AccountEmail>(RFIFO_STRING<40>(s, 51)); - int new_id = mmo_auth_new(&ma, ma.sex, email); - LOGIN_LOG("'ladmin': Account creation (account: %s (id: %d), sex: %c, email: %s, ip: %s)\n", - ma.userid, new_id, - ma.sex, auth_data.back().email, ip); - WFIFOL(s, 2) = new_id; + AccountEmail email = fixed.email; + AccountId new_id = mmo_auth_new(&ma, ma.sex, email); + LOGIN_LOG("'ladmin': Account creation (account: %s (id: %d), sex: %c, email: %s, ip: %s)\n"_fmt, + ma.userid, new_id, + sex_to_char(ma.sex), auth_data.back().email, ip); + fixed_31.account_id = new_id; } } x7930_out: - WFIFOSET(s, 30); - RFIFOSKIP(s, 91); + send_fpacket<0x7931, 30>(s, fixed_31); } break; + } case 0x7932: // Request for an account deletion - if (RFIFOREST(s) < 26) - return; { - WFIFOW(s, 0) = 0x7933; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); + Packet_Fixed<0x7932> fixed; + rv = recv_fpacket<0x7932, 26>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x7933> fixed_33; + fixed_33.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); AuthData *ad = search_account(account_name); if (ad) { // Char-server is notified of deletion (for characters deletion). - uint8_t buf[6]; - WBUFW(buf, 0) = 0x2730; - WBUFL(buf, 2) = ad->account_id; - charif_sendallwos(nullptr, buf, 6); + Packet_Fixed<0x2730> fixed_30; + fixed_30.account_id = ad->account_id; + + for (Session *ss : iter_char_sessions()) + { + send_fpacket<0x2730, 6>(ss, fixed_30); + } + // send answer - WFIFO_STRING(s, 6, ad->userid, 24); - WFIFOL(s, 2) = ad->account_id; + fixed_33.account_name = ad->userid; + fixed_33.account_id = ad->account_id; // save deleted account in log file - LOGIN_LOG("'ladmin': Account deletion (account: %s, id: %d, ip: %s) - saved in next line:\n", - ad->userid, ad->account_id, - ip); + LOGIN_LOG("'ladmin': Account deletion (account: %s, id: %d, ip: %s) - saved in next line:\n"_fmt, + ad->userid, ad->account_id, + ip); { AString buf2 = mmo_auth_tostr(ad); - LOGIN_LOG("%s\n", buf2); + LOGIN_LOG("%s\n"_fmt, buf2); } // delete account ad->userid = AccountName(); - ad->account_id = -1; + ad->account_id = AccountId(); } else { - WFIFO_STRING(s, 6, account_name, 24); - LOGIN_LOG("'ladmin': Attempt to delete an unknown account (account: %s, ip: %s)\n", - account_name, ip); + fixed_33.account_name = account_name; + LOGIN_LOG("'ladmin': Attempt to delete an unknown account (account: %s, ip: %s)\n"_fmt, + account_name, ip); } - WFIFOSET(s, 30); - } - RFIFOSKIP(s, 26); + send_fpacket<0x7933, 30>(s, fixed_33); break; + } case 0x7934: // Request to change a password - if (RFIFOREST(s) < 50) - return; { - WFIFOW(s, 0) = 0x7935; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); + Packet_Fixed<0x7934> fixed; + rv = recv_fpacket<0x7934, 50>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x7935> fixed_35; + fixed_35.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); AuthData *ad = search_account(account_name); if (ad) { - WFIFO_STRING(s, 6, ad->userid, 24); - AccountPass plain = stringish<AccountPass>(RFIFO_STRING<24>(s, 26)); + fixed_35.account_name = ad->userid; + AccountPass plain = stringish<AccountPass>(fixed.password); ad->pass = MD5_saltcrypt(plain, make_salt()); - WFIFOL(s, 2) = ad->account_id; - LOGIN_LOG("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n", - ad->userid, ad->pass, ip); + fixed_35.account_id = ad->account_id; + LOGIN_LOG("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n"_fmt, + ad->userid, ad->pass, ip); } else { - WFIFO_STRING(s, 6, account_name, 24); - LOGIN_LOG("'ladmin': Attempt to modify the password of an unknown account (account: %s, ip: %s)\n", - account_name, ip); + fixed_35.account_name = account_name; + LOGIN_LOG("'ladmin': Attempt to modify the password of an unknown account (account: %s, ip: %s)\n"_fmt, + account_name, ip); } - WFIFOSET(s, 30); - } - RFIFOSKIP(s, 50); + send_fpacket<0x7935, 30>(s, fixed_35); break; + } case 0x7936: // Request to modify a state - if (RFIFOREST(s) < 50) - return; + { + Packet_Fixed<0x7936> fixed; + rv = recv_fpacket<0x7936, 50>(s, fixed); + if (rv != RecvResult::Complete) + break; + { - WFIFOW(s, 0) = 0x7937; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); - int statut = RFIFOL(s, 26); - timestamp_seconds_buffer error_message = stringish<timestamp_seconds_buffer>(RFIFO_STRING<20>(s, 30).to_print()); + Packet_Fixed<0x7937> fixed_37; + fixed_37.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); + int statut = fixed.status; + timestamp_seconds_buffer error_message = stringish<timestamp_seconds_buffer>(fixed.error_message.to_print()); if (statut != 7 || !error_message) { // 7: // 6 = Your are Prohibited to log in until %s - error_message = stringish<timestamp_seconds_buffer>("-"); + error_message = stringish<timestamp_seconds_buffer>("-"_s); } AuthData *ad = search_account(account_name); if (ad) { - WFIFO_STRING(s, 6, ad->userid, 24); - WFIFOL(s, 2) = ad->account_id; + fixed_37.account_name = ad->userid; + fixed_37.account_id = ad->account_id; if (ad->state == statut && ad->error_message == error_message) - LOGIN_LOG("'ladmin': Modification of a state, but the state of the account is already the good state (account: %s, received state: %d, ip: %s)\n", - account_name, statut, ip); + LOGIN_LOG("'ladmin': Modification of a state, but the state of the account is already the good state (account: %s, received state: %d, ip: %s)\n"_fmt, + account_name, statut, ip); else { if (statut == 7) - LOGIN_LOG("'ladmin': Modification of a state (account: %s, new state: %d - prohibited to login until '%s', ip: %s)\n", - ad->userid, statut, - error_message, ip); + LOGIN_LOG("'ladmin': Modification of a state (account: %s, new state: %d - prohibited to login until '%s', ip: %s)\n"_fmt, + ad->userid, statut, + error_message, ip); else - LOGIN_LOG("'ladmin': Modification of a state (account: %s, new state: %d, ip: %s)\n", - ad->userid, statut, ip); + LOGIN_LOG("'ladmin': Modification of a state (account: %s, new state: %d, ip: %s)\n"_fmt, + ad->userid, statut, ip); if (ad->state == 0) { - unsigned char buf[16]; - WBUFW(buf, 0) = 0x2731; - WBUFL(buf, 2) = ad->account_id; - WBUFB(buf, 6) = 0; // 0: change of statut, 1: ban - WBUFL(buf, 7) = statut; // status or final date of a banishment - charif_sendallwos(nullptr, buf, 11); + Packet_Fixed<0x2731> fixed_31; + fixed_31.account_id = ad->account_id; + fixed_31.ban_not_status = 0; + fixed_31.status_or_ban_until = static_cast<time_t>(statut); + + for (Session *ss : iter_char_sessions()) + { + send_fpacket<0x2731, 11>(ss, fixed_31); + } + for (int j = 0; j < AUTH_FIFO_SIZE; j++) if (auth_fifo[j].account_id == ad->account_id) @@ -1881,87 +1930,98 @@ void parse_admin(Session *s) } else { - WFIFO_STRING(s, 6, account_name, 24); - LOGIN_LOG("'ladmin': Attempt to modify the state of an unknown account (account: %s, received state: %d, ip: %s)\n", - account_name, statut, ip); + fixed_37.account_name = account_name; + LOGIN_LOG("'ladmin': Attempt to modify the state of an unknown account (account: %s, received state: %d, ip: %s)\n"_fmt, + account_name, statut, ip); } - WFIFOL(s, 30) = statut; + fixed_37.status = statut; + send_fpacket<0x7937, 34>(s, fixed_37); } - WFIFOSET(s, 34); - RFIFOSKIP(s, 50); break; + } case 0x7938: // Request for servers list and # of online players - LOGIN_LOG("'ladmin': Sending of servers list (ip: %s)\n", ip); - server_num = 0; + { + Packet_Fixed<0x7938> fixed; + rv = recv_fpacket<0x7938, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + LOGIN_LOG("'ladmin': Sending of servers list (ip: %s)\n"_fmt, ip); + std::vector<Packet_Repeat<0x7939>> repeat_39; for (int i = 0; i < MAX_SERVERS; i++) { if (server_session[i]) { - WFIFOIP(s, 4 + server_num * 32) = server[i].ip; - WFIFOW(s, 4 + server_num * 32 + 4) = server[i].port; - WFIFO_STRING(s, 4 + server_num * 32 + 6, server[i].name, 20); - WFIFOW(s, 4 + server_num * 32 + 26) = server[i].users; - WFIFOW(s, 4 + server_num * 32 + 28) = 0; //maintenance; - WFIFOW(s, 4 + server_num * 32 + 30) = 0; //is_new; - server_num++; + Packet_Repeat<0x7939> info; + info.ip = server[i].ip; + info.port = server[i].port; + info.name = server[i].name; + info.users = server[i].users; + info.maintenance = 0; + info.is_new = 0; + repeat_39.push_back(info); } } - WFIFOW(s, 0) = 0x7939; - WFIFOW(s, 2) = 4 + 32 * server_num; - WFIFOSET(s, 4 + 32 * server_num); - RFIFOSKIP(s, 2); + send_packet_repeatonly<0x7939, 4, 32>(s, repeat_39); break; + } case 0x793a: // Request to password check - if (RFIFOREST(s) < 50) - return; { - WFIFOW(s, 0) = 0x793b; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); + Packet_Fixed<0x793a> fixed; + rv = recv_fpacket<0x793a, 50>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x793b> fixed_3b; + fixed_3b.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); const AuthData *ad = search_account(account_name); if (ad) { - WFIFO_STRING(s, 6, ad->userid, 24); - AccountPass pass = stringish<AccountPass>(RFIFO_STRING<24>(s, 26)); + fixed_3b.account_name = ad->userid; + AccountPass pass = stringish<AccountPass>(fixed.password); if (pass_ok(pass, ad->pass)) { - WFIFOL(s, 2) = ad->account_id; - LOGIN_LOG("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)\n", - ad->userid, ad->pass, - ip); + fixed_3b.account_id = ad->account_id; + LOGIN_LOG("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)\n"_fmt, + ad->userid, ad->pass, + ip); } else { - LOGIN_LOG("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)\n", - ad->userid, pass.to_print(), ip); + LOGIN_LOG("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)\n"_fmt, + ad->userid, pass.to_print(), ip); } } else { - WFIFO_STRING(s, 6, account_name, 24); - LOGIN_LOG("'ladmin': Attempt to check the password of an unknown account (account: %s, ip: %s)\n", - account_name, ip); + fixed_3b.account_name = account_name; + LOGIN_LOG("'ladmin': Attempt to check the password of an unknown account (account: %s, ip: %s)\n"_fmt, + account_name, ip); } - WFIFOSET(s, 30); - } - RFIFOSKIP(s, 50); + send_fpacket<0x793b, 30>(s, fixed_3b); break; + } case 0x793c: // Request to modify sex - if (RFIFOREST(s) < 27) - return; { - WFIFOW(s, 0) = 0x793d; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); - WFIFO_STRING(s, 6, account_name, 24); + Packet_Fixed<0x793c> fixed; + rv = recv_fpacket<0x793c, 27>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x793d> fixed_3d; + fixed_3d.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); + fixed_3d.account_name = account_name; + { - SEX sex = sex_from_char(RFIFOB(s, 26)); + SEX sex = fixed.sex; if (sex != SEX::FEMALE && sex != SEX::MALE) { - LOGIN_LOG("'ladmin': Attempt to give an invalid sex (account: %s, received sex: %c, ip: %s)\n", + LOGIN_LOG("'ladmin': Attempt to give an invalid sex (account: %s, received sex: %c, ip: %s)\n"_fmt, account_name, sex_to_char(sex), ip); } else @@ -1969,70 +2029,72 @@ void parse_admin(Session *s) AuthData *ad = search_account(account_name); if (ad) { - WFIFO_STRING(s, 6, ad->userid, 24); + fixed_3d.account_name = ad->userid; if (ad->sex != sex) { - unsigned char buf[16]; - WFIFOL(s, 2) = ad->account_id; + fixed_3d.account_id = ad->account_id; for (int j = 0; j < AUTH_FIFO_SIZE; j++) + { if (auth_fifo[j].account_id == ad->account_id) auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) + } ad->sex = sex; - LOGIN_LOG("'ladmin': Modification of a sex (account: %s, new sex: %c, ip: %s)\n", - ad->userid, sex_to_char(sex), ip); + LOGIN_LOG("'ladmin': Modification of a sex (account: %s, new sex: %c, ip: %s)\n"_fmt, + ad->userid, sex_to_char(sex), ip); + // send to all char-server the change - WBUFW(buf, 0) = 0x2723; - WBUFL(buf, 2) = ad->account_id; - WBUFB(buf, 6) = static_cast<uint8_t>(ad->sex); - charif_sendallwos(nullptr, buf, 7); + Packet_Fixed<0x2723> fixed_23; + fixed_23.account_id = ad->account_id; + fixed_23.sex = ad->sex; + + for (Session *ss : iter_char_sessions()) + { + send_fpacket<0x2723, 7>(ss, fixed_23); + } } else { - LOGIN_LOG("'ladmin': Modification of a sex, but the sex is already the good sex (account: %s, sex: %c, ip: %s)\n", - ad->userid, sex_to_char(sex), ip); + LOGIN_LOG("'ladmin': Modification of a sex, but the sex is already the good sex (account: %s, sex: %c, ip: %s)\n"_fmt, + ad->userid, sex_to_char(sex), ip); } } else { - LOGIN_LOG("'ladmin': Attempt to modify the sex of an unknown account (account: %s, received sex: %c, ip: %s)\n", - account_name, sex_to_char(sex), ip); + LOGIN_LOG("'ladmin': Attempt to modify the sex of an unknown account (account: %s, received sex: %c, ip: %s)\n"_fmt, + account_name, sex_to_char(sex), ip); } } } - WFIFOSET(s, 30); - } - RFIFOSKIP(s, 27); + send_fpacket<0x793d, 30>(s, fixed_3d); break; + } case 0x793e: // Request to modify GM level - if (RFIFOREST(s) < 27) - return; { - WFIFOW(s, 0) = 0x793f; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); - WFIFO_STRING(s, 6, account_name, 24); + Packet_Fixed<0x793e> fixed; + rv = recv_fpacket<0x793e, 27>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x793f> fixed_3f; + fixed_3f.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); + fixed_3f.account_name = account_name; bool reread = false; { - char new_gm_level; - new_gm_level = RFIFOB(s, 26); - if (new_gm_level < 0 || new_gm_level > 99) - { - LOGIN_LOG("'ladmin': Attempt to give an invalid GM level (account: %s, received GM level: %d, ip: %s)\n", - account_name, new_gm_level, ip); - } - else + GmLevel new_gm_level = fixed.gm_level; { const AuthData *ad = search_account(account_name); if (ad) { - int acc = ad->account_id; - WFIFO_STRING(s, 6, ad->userid, 24); + AccountId acc = ad->account_id; + fixed_3f.account_name = ad->userid; if (isGM(acc) != new_gm_level) { // modification of the file - int GM_account, GM_level; + AccountId GM_account; + GmLevel GM_level; int modify_flag; io::WriteLock fp2(gm_account_filename); if (fp2.is_open()) @@ -2055,68 +2117,68 @@ void parse_admin(Session *s) fp2.put_line(line); else if (GM_account != acc) fp2.put_line(line); - else if (new_gm_level == 0) + else if (!new_gm_level) { FPRINTF(fp2, - "// %s: 'ladmin' GM level removed on account %d '%s' (previous level: %d)\n//%d %d\n", - tmpstr, - acc, - ad->userid, - GM_level, acc, - new_gm_level); + "// %s: 'ladmin' GM level removed on account %d '%s' (previous level: %d)\n//%d %d\n"_fmt, + tmpstr, + acc, + ad->userid, + GM_level, acc, + new_gm_level); modify_flag = 1; } else { FPRINTF(fp2, - "// %s: 'ladmin' GM level on account %d '%s' (previous level: %d)\n%d %d\n", - tmpstr, - acc, - ad->userid, - GM_level, acc, - new_gm_level); + "// %s: 'ladmin' GM level on account %d '%s' (previous level: %d)\n%d %d\n"_fmt, + tmpstr, + acc, + ad->userid, + GM_level, acc, + new_gm_level); modify_flag = 1; } } } if (modify_flag == 0) FPRINTF(fp2, - "// %s: 'ladmin' GM level on account %d '%s' (previous level: 0)\n%d %d\n", - tmpstr, acc, - ad->userid, acc, - new_gm_level); + "// %s: 'ladmin' GM level on account %d '%s' (previous level: 0)\n%d %d\n"_fmt, + tmpstr, acc, + ad->userid, acc, + new_gm_level); } else { - LOGIN_LOG("'ladmin': Attempt to modify of a GM level - impossible to read GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n", - ad->userid, acc, - new_gm_level, ip); + LOGIN_LOG("'ladmin': Attempt to modify of a GM level - impossible to read GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n"_fmt, + ad->userid, acc, + new_gm_level, ip); } - WFIFOL(s, 2) = acc; - LOGIN_LOG("'ladmin': Modification of a GM level (account: %s (%d), new GM level: %d, ip: %s)\n", - ad->userid, acc, - new_gm_level, ip); + fixed_3f.account_id = acc; + LOGIN_LOG("'ladmin': Modification of a GM level (account: %s (%d), new GM level: %d, ip: %s)\n"_fmt, + ad->userid, acc, + new_gm_level, ip); reread = true; } else { - LOGIN_LOG("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n", - ad->userid, acc, - new_gm_level, ip); + LOGIN_LOG("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n"_fmt, + ad->userid, acc, + new_gm_level, ip); } } else { - LOGIN_LOG("'ladmin': Attempt to modify of a GM level, but the GM level is already the good GM level (account: %s (%d), GM level: %d, ip: %s)\n", - ad->userid, acc, - new_gm_level, ip); + LOGIN_LOG("'ladmin': Attempt to modify of a GM level, but the GM level is already the good GM level (account: %s (%d), GM level: %d, ip: %s)\n"_fmt, + ad->userid, acc, + new_gm_level, ip); } } else { - LOGIN_LOG("'ladmin': Attempt to modify the GM level of an unknown account (account: %s, received GM level: %d, ip: %s)\n", - account_name, new_gm_level, - ip); + LOGIN_LOG("'ladmin': Attempt to modify the GM level of an unknown account (account: %s, received GM level: %d, ip: %s)\n"_fmt, + account_name, new_gm_level, + ip); } } } @@ -2126,199 +2188,213 @@ void parse_admin(Session *s) read_gm_account(); send_GM_accounts(); } - WFIFOSET(s, 30); - } - RFIFOSKIP(s, 27); + send_fpacket<0x793f, 30>(s, fixed_3f); break; + } case 0x7940: // Request to modify e-mail - if (RFIFOREST(s) < 66) - return; { - WFIFOW(s, 0) = 0x7941; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); - WFIFO_STRING(s, 6, account_name, 24); + Packet_Fixed<0x7940> fixed; + rv = recv_fpacket<0x7940, 66>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x7941> fixed_41; + fixed_41.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); + fixed_41.account_name = account_name; { - AccountEmail email = stringish<AccountEmail>(RFIFO_STRING<40>(s, 26)); + AccountEmail email = stringish<AccountEmail>(fixed.email); if (!e_mail_check(email)) { - LOGIN_LOG("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)\n", - account_name, ip); + LOGIN_LOG("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)\n"_fmt, + account_name, ip); } else { AuthData *ad = search_account(account_name); if (ad) { - WFIFO_STRING(s, 6, ad->userid, 24); + fixed_41.account_name = ad->userid; ad->email = email; - WFIFOL(s, 2) = ad->account_id; - LOGIN_LOG("'ladmin': Modification of an email (account: %s, new e-mail: %s, ip: %s)\n", - ad->userid, email, ip); + fixed_41.account_id = ad->account_id; + LOGIN_LOG("'ladmin': Modification of an email (account: %s, new e-mail: %s, ip: %s)\n"_fmt, + ad->userid, email, ip); } else { - LOGIN_LOG("'ladmin': Attempt to modify the e-mail of an unknown account (account: %s, received e-mail: %s, ip: %s)\n", - account_name, email, ip); + LOGIN_LOG("'ladmin': Attempt to modify the e-mail of an unknown account (account: %s, received e-mail: %s, ip: %s)\n"_fmt, + account_name, email, ip); } } } - WFIFOSET(s, 30); - } - RFIFOSKIP(s, 66); + send_fpacket<0x7941, 30>(s, fixed_41); break; + } case 0x7942: // Request to modify memo field - if (RFIFOREST(s) < 28 - || RFIFOREST(s) < (28 + RFIFOW(s, 26))) - return; { - WFIFOW(s, 0) = 0x7943; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); + Packet_Head<0x7942> head; + AString repeat; + rv = recv_vpacket<0x7942, 28, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x7943> fixed_43; + fixed_43.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(head.account_name.to_print()); AuthData *ad = search_account(account_name); if (ad) { - WFIFO_STRING(s, 6, ad->userid, 24); - ad->memo = ""; - if (RFIFOW(s, 26) == 0) + fixed_43.account_name = ad->userid; + ad->memo = ""_s; + if (!repeat/*.startswith('!')*/) { - ad->memo = "!"; + ad->memo = "!"_s; } else { - size_t len = RFIFOW(s, 26); // may truncate - ad->memo = RFIFO_STRING(s, 28, len); + ad->memo = repeat; } ad->memo = ad->memo.to_print(); - WFIFOL(s, 2) = ad->account_id; - LOGIN_LOG("'ladmin': Modification of a memo field (account: %s, new memo: %s, ip: %s)\n", - ad->userid, ad->memo, ip); + fixed_43.account_id = ad->account_id; + LOGIN_LOG("'ladmin': Modification of a memo field (account: %s, new memo: %s, ip: %s)\n"_fmt, + ad->userid, ad->memo, ip); } else { - WFIFO_STRING(s, 6, account_name, 24); - LOGIN_LOG("'ladmin': Attempt to modify the memo field of an unknown account (account: %s, ip: %s)\n", - account_name, ip); + fixed_43.account_name = account_name; + LOGIN_LOG("'ladmin': Attempt to modify the memo field of an unknown account (account: %s, ip: %s)\n"_fmt, + account_name, ip); } - WFIFOSET(s, 30); - } - RFIFOSKIP(s, 28 + RFIFOW(s, 26)); + send_fpacket<0x7943, 30>(s, fixed_43); break; + } case 0x7944: // Request to found an account id - if (RFIFOREST(s) < 26) - return; { - WFIFOW(s, 0) = 0x7945; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); + Packet_Fixed<0x7944> fixed; + rv = recv_fpacket<0x7944, 26>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x7945> fixed_45; + fixed_45.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); const AuthData *ad = search_account(account_name); if (ad) { - WFIFO_STRING(s, 6, ad->userid, 24); - WFIFOL(s, 2) = ad->account_id; - LOGIN_LOG("'ladmin': Request (by the name) of an account id (account: %s, id: %d, ip: %s)\n", + fixed_45.account_name = ad->userid; + fixed_45.account_id = ad->account_id; + LOGIN_LOG("'ladmin': Request (by the name) of an account id (account: %s, id: %d, ip: %s)\n"_fmt, ad->userid, ad->account_id, ip); } else { - WFIFO_STRING(s, 6, account_name, 24); - LOGIN_LOG("'ladmin': ID request (by the name) of an unknown account (account: %s, ip: %s)\n", + fixed_45.account_name = account_name; + LOGIN_LOG("'ladmin': ID request (by the name) of an unknown account (account: %s, ip: %s)\n"_fmt, account_name, ip); } - WFIFOSET(s, 30); - } - RFIFOSKIP(s, 26); + send_fpacket<0x7945, 30>(s, fixed_45); break; + } case 0x7946: // Request to found an account name - if (RFIFOREST(s) < 6) - return; { - int account_id = RFIFOL(s, 2); - WFIFOW(s, 0) = 0x7947; - WFIFOL(s, 2) = account_id; - WFIFO_ZERO(s, 6, 24); + Packet_Fixed<0x7946> fixed; + rv = recv_fpacket<0x7946, 6>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + Packet_Fixed<0x7947> fixed_47; + fixed_47.account_id = account_id; + fixed_47.account_name = {}; for (const AuthData& ad : auth_data) { if (ad.account_id == account_id) { - WFIFO_STRING(s, 6, ad.userid, 24); - LOGIN_LOG("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)\n", + fixed_47.account_name = ad.userid; + LOGIN_LOG("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)\n"_fmt, ad.userid, account_id, ip); goto x7946_out; } } - LOGIN_LOG("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)\n", + LOGIN_LOG("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)\n"_fmt, account_id, ip); - WFIFO_STRING(s, 6, "", 24); + fixed_47.account_name = stringish<AccountName>(""_s); x7946_out: - WFIFOSET(s, 30); - } - RFIFOSKIP(s, 6); + send_fpacket<0x7947, 30>(s, fixed_47); break; + } case 0x7948: // Request to change the validity limit (timestamp) (absolute value) - if (RFIFOREST(s) < 30) - return; + { + Packet_Fixed<0x7948> fixed; + rv = recv_fpacket<0x7948, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x7949> fixed_49; { - WFIFOW(s, 0) = 0x7949; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); - TimeT timestamp = static_cast<time_t>(RFIFOL(s, 26)); - timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited"); + fixed_49.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); + TimeT timestamp = fixed.valid_until; + timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited"_s); if (timestamp) stamp_time(tmpstr, ×tamp); AuthData *ad = search_account(account_name); if (ad) { - WFIFO_STRING(s, 6, ad->userid, 24); - LOGIN_LOG("'ladmin': Change of a validity limit (account: %s, new validity: %lld (%s), ip: %s)\n", + fixed_49.account_name = ad->userid; + LOGIN_LOG("'ladmin': Change of a validity limit (account: %s, new validity: %lld (%s), ip: %s)\n"_fmt, ad->userid, timestamp, tmpstr, ip); ad->connect_until_time = timestamp; - WFIFOL(s, 2) = ad->account_id; + fixed_49.account_id = ad->account_id; } else { - WFIFO_STRING(s, 6, account_name, 24); - LOGIN_LOG("'ladmin': Attempt to change the validity limit of an unknown account (account: %s, received validity: %lld (%s), ip: %s)\n", + fixed_49.account_name = account_name; + LOGIN_LOG("'ladmin': Attempt to change the validity limit of an unknown account (account: %s, received validity: %lld (%s), ip: %s)\n"_fmt, account_name, timestamp, tmpstr, ip); } - WFIFOL(s, 30) = static_cast<time_t>(timestamp); + fixed_49.valid_until = timestamp; } - WFIFOSET(s, 34); - RFIFOSKIP(s, 30); + send_fpacket<0x7949, 34>(s, fixed_49); break; + } case 0x794a: // Request to change the final date of a banishment (timestamp) (absolute value) - if (RFIFOREST(s) < 30) - return; + { + Packet_Fixed<0x794a> fixed; + rv = recv_fpacket<0x794a, 30>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x794b> fixed_4b; { - WFIFOW(s, 0) = 0x794b; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); - TimeT timestamp = static_cast<time_t>(RFIFOL(s, 26)); + fixed_4b.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); + TimeT timestamp = fixed.ban_until; if (timestamp <= TimeT::now()) timestamp = TimeT(); - timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("no banishment"); + timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("no banishment"_s); if (timestamp) stamp_time(tmpstr, ×tamp); AuthData *ad = search_account(account_name); if (ad) { - WFIFO_STRING(s, 6, ad->userid, 24); - WFIFOL(s, 2) = ad->account_id; - LOGIN_LOG("'ladmin': Change of the final date of a banishment (account: %s, new final date of banishment: %lld (%s), ip: %s)\n", + fixed_4b.account_name = ad->userid; + fixed_4b.account_id = ad->account_id; + LOGIN_LOG("'ladmin': Change of the final date of a banishment (account: %s, new final date of banishment: %lld (%s), ip: %s)\n"_fmt, ad->userid, timestamp, tmpstr, ip); @@ -2326,46 +2402,56 @@ void parse_admin(Session *s) { if (timestamp) { - unsigned char buf[16]; - WBUFW(buf, 0) = 0x2731; - WBUFL(buf, 2) = ad->account_id; - WBUFB(buf, 6) = 1; // 0: change of statut, 1: ban - WBUFL(buf, 7) = static_cast<time_t>(timestamp); // status or final date of a banishment - charif_sendallwos(nullptr, buf, 11); + Packet_Fixed<0x2731> fixed_31; + fixed_31.account_id = ad->account_id; + fixed_31.ban_not_status = 1; + fixed_31.status_or_ban_until = timestamp; + + for (Session *ss : iter_char_sessions()) + { + send_fpacket<0x2731, 11>(ss, fixed_31); + } + for (int j = 0; j < AUTH_FIFO_SIZE; j++) + { if (auth_fifo[j].account_id == ad->account_id) auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) + } } ad->ban_until_time = timestamp; } } else { - WFIFO_STRING(s, 6, account_name, 24); - LOGIN_LOG("'ladmin': Attempt to change the final date of a banishment of an unknown account (account: %s, received final date of banishment: %lld (%s), ip: %s)\n", + fixed_4b.account_name = account_name; + LOGIN_LOG("'ladmin': Attempt to change the final date of a banishment of an unknown account (account: %s, received final date of banishment: %lld (%s), ip: %s)\n"_fmt, account_name, timestamp, tmpstr, ip); } - WFIFOL(s, 30) = static_cast<time_t>(timestamp); + fixed_4b.ban_until = timestamp; } - WFIFOSET(s, 34); - RFIFOSKIP(s, 30); + send_fpacket<0x794b, 34>(s, fixed_4b); break; + } case 0x794c: // Request to change the final date of a banishment (timestamp) (relative change) - if (RFIFOREST(s) < 38) - return; + { + Packet_Fixed<0x794c> fixed; + rv = recv_fpacket<0x794c, 38>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x794d> fixed_4d; { - WFIFOW(s, 0) = 0x794d; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); + fixed_4d.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); AuthData *ad = search_account(account_name); if (ad) { - WFIFOL(s, 2) = ad->account_id; - WFIFO_STRING(s, 6, ad->userid, 24); + fixed_4d.account_id = ad->account_id; + fixed_4d.account_name = ad->userid; TimeT timestamp; TimeT now = TimeT::now(); if (!ad->ban_until_time @@ -2374,8 +2460,7 @@ void parse_admin(Session *s) else timestamp = ad->ban_until_time; struct tm tmtime = timestamp; - HumanTimeDiff ban_diff; - RFIFO_STRUCT(s, 26, ban_diff); + HumanTimeDiff ban_diff = fixed.ban_add; tmtime.tm_year += ban_diff.year; tmtime.tm_mon += ban_diff.month; tmtime.tm_mday += ban_diff.day; @@ -2387,10 +2472,10 @@ void parse_admin(Session *s) { if (timestamp <= now) timestamp = TimeT(); - timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("no banishment"); + timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("no banishment"_s); if (timestamp) stamp_time(tmpstr, ×tamp); - LOGIN_LOG("'ladmin': Adjustment of a final date of a banishment (account: %s, (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %lld (%s), ip: %s)\n", + LOGIN_LOG("'ladmin': Adjustment of a final date of a banishment (account: %s, (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %lld (%s), ip: %s)\n"_fmt, ad->userid, ban_diff.year, ban_diff.month, ban_diff.day, ban_diff.hour, @@ -2402,26 +2487,32 @@ void parse_admin(Session *s) { if (timestamp) { - unsigned char buf[16]; - WBUFW(buf, 0) = 0x2731; - WBUFL(buf, 2) = ad->account_id; - WBUFB(buf, 6) = 1; // 0: change of statut, 1: ban - WBUFL(buf, 7) = static_cast<time_t>(timestamp); // status or final date of a banishment - charif_sendallwos(nullptr, buf, 11); + Packet_Fixed<0x2731> fixed_31; + fixed_31.account_id = ad->account_id; + fixed_31.ban_not_status = 1; + fixed_31.status_or_ban_until = timestamp; + + for (Session *ss : iter_char_sessions()) + { + send_fpacket<0x2731, 11>(ss, fixed_31); + } + for (int j = 0; j < AUTH_FIFO_SIZE; j++) + { if (auth_fifo[j].account_id == ad->account_id) auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) + } } ad->ban_until_time = timestamp; } } else { - timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("no banishment"); + timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("no banishment"_s); if (ad->ban_until_time) stamp_time(tmpstr, &ad->ban_until_time); - LOGIN_LOG("'ladmin': Impossible to adjust the final date of a banishment (account: %s, %lld (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", + LOGIN_LOG("'ladmin': Impossible to adjust the final date of a banishment (account: %s, %lld (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n"_fmt, ad->userid, ad->ban_until_time, tmpstr, @@ -2430,30 +2521,34 @@ void parse_admin(Session *s) ban_diff.minute, ban_diff.second, ip); } - WFIFOL(s, 30) = static_cast<time_t>(ad->ban_until_time); + fixed_4d.ban_until = ad->ban_until_time; } else { - WFIFO_STRING(s, 6, account_name, 24); - LOGIN_LOG("'ladmin': Attempt to adjust the final date of a banishment of an unknown account (account: %s, ip: %s)\n", + fixed_4d.account_name = account_name; + LOGIN_LOG("'ladmin': Attempt to adjust the final date of a banishment of an unknown account (account: %s, ip: %s)\n"_fmt, account_name, ip); - WFIFOL(s, 30) = 0; + fixed_4d.ban_until = TimeT(); } } - WFIFOSET(s, 34); - RFIFOSKIP(s, 38); + send_fpacket<0x794d, 34>(s, fixed_4d); break; + } case 0x794e: // Request to send a broadcast message - if (RFIFOREST(s) < 8 - || RFIFOREST(s) < (8 + RFIFOL(s, 4))) - return; - WFIFOW(s, 0) = 0x794f; - WFIFOW(s, 2) = -1; - if (RFIFOL(s, 4) < 1) + { + Packet_Head<0x794e> head; + AString repeat; + rv = recv_vpacket<0x794e, 8, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x794f> fixed_4f; + fixed_4f.error = -1; + if (!repeat) { - LOGIN_LOG("'ladmin': Receiving a message for broadcast, but message is void (ip: %s)\n", - ip); + LOGIN_LOG("'ladmin': Receiving a message for broadcast, but message is void (ip: %s)\n"_fmt, + ip); } else { @@ -2461,47 +2556,54 @@ void parse_admin(Session *s) for (int i = 0; i < MAX_SERVERS; i++) if (server_session[i]) goto x794e_have_server; - LOGIN_LOG("'ladmin': Receiving a message for broadcast, but no char-server is online (ip: %s)\n", + LOGIN_LOG("'ladmin': Receiving a message for broadcast, but no char-server is online (ip: %s)\n"_fmt, ip); goto x794e_have_no_server; { x794e_have_server: // overwrite the -1 - WFIFOW(s, 2) = 0; + fixed_4f.error = 0; - size_t len = RFIFOL(s, 4); - AString message = RFIFO_STRING(s, 8, len).to_print(); - LOGIN_LOG("'ladmin': Receiving a message for broadcast (message: %s, ip: %s)\n", + AString& message = repeat; + LOGIN_LOG("'ladmin': Receiving a message for broadcast (message: %s, ip: %s)\n"_fmt, message, ip); + // send same message to all char-servers (no answer) - uint8_t buf[len + 8]; - RFIFO_BUF_CLONE(s, buf, 8 + len); - WBUFW(buf, 0) = 0x2726; - charif_sendallwos(nullptr, buf, 8 + len); + Packet_Head<0x2726> head_26; + head_26.unused = head.unused; + + for (Session *ss : iter_char_sessions()) + { + send_vpacket<0x2726, 8, 1>(ss, head_26, message); + } } } x794e_have_no_server: - WFIFOSET(s, 4); - RFIFOSKIP(s, 8 + RFIFOL(s, 4)); + send_fpacket<0x794f, 4>(s, fixed_4f); break; + } case 0x7950: // Request to change the validity limite (timestamp) (relative change) - if (RFIFOREST(s) < 38) - return; + { + Packet_Fixed<0x7950> fixed; + rv = recv_fpacket<0x7950, 38>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x7951> fixed_51; { - WFIFOW(s, 0) = 0x7951; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); + fixed_51.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); AuthData *ad = search_account(account_name); if (ad) { - WFIFOL(s, 2) = ad->account_id; - WFIFO_STRING(s, 6, ad->userid, 24); + fixed_51.account_id = ad->account_id; + fixed_51.account_name = ad->userid; if (add_to_unlimited_account == 0 && !ad->connect_until_time) { - LOGIN_LOG("'ladmin': Attempt to adjust the validity limit of an unlimited account (account: %s, ip: %s)\n", - ad->userid, ip); - WFIFOL(s, 30) = 0; + LOGIN_LOG("'ladmin': Attempt to adjust the validity limit of an unlimited account (account: %s, ip: %s)\n"_fmt, + ad->userid, ip); + fixed_51.valid_until = TimeT(); } else { @@ -2510,8 +2612,7 @@ void parse_admin(Session *s) if (!timestamp || timestamp < now) timestamp = now; struct tm tmtime = timestamp; - HumanTimeDiff v_diff; - RFIFO_STRUCT(s, 26, v_diff); + HumanTimeDiff v_diff = fixed.valid_add; tmtime.tm_year += v_diff.year; tmtime.tm_mon += v_diff.month; tmtime.tm_mday += v_diff.day; @@ -2521,13 +2622,13 @@ void parse_admin(Session *s) timestamp = tmtime; if (timestamp.okay()) { - timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited"); - timestamp_seconds_buffer tmpstr2 = stringish<timestamp_seconds_buffer>("unlimited"); + timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited"_s); + timestamp_seconds_buffer tmpstr2 = stringish<timestamp_seconds_buffer>("unlimited"_s); if (ad->connect_until_time) stamp_time(tmpstr, &ad->connect_until_time); if (timestamp) stamp_time(tmpstr2, ×tamp); - LOGIN_LOG("'ladmin': Adjustment of a validity limit (account: %s, %lld (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %lld (%s), ip: %s)\n", + LOGIN_LOG("'ladmin': Adjustment of a validity limit (account: %s, %lld (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %lld (%s), ip: %s)\n"_fmt, ad->userid, ad->connect_until_time, tmpstr, @@ -2541,14 +2642,14 @@ void parse_admin(Session *s) tmpstr2, ip); ad->connect_until_time = timestamp; - WFIFOL(s, 30) = static_cast<time_t>(timestamp); + fixed_51.valid_until = timestamp; } else { - timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited"); + timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited"_s); if (ad->connect_until_time) stamp_time(tmpstr, &ad->connect_until_time); - LOGIN_LOG("'ladmin': Impossible to adjust a validity limit (account: %s, %lld (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", + LOGIN_LOG("'ladmin': Impossible to adjust a validity limit (account: %s, %lld (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n"_fmt, ad->userid, ad->connect_until_time, tmpstr, @@ -2559,116 +2660,122 @@ void parse_admin(Session *s) v_diff.minute, v_diff.second, ip); - WFIFOL(s, 30) = 0; + fixed_51.valid_until = TimeT(); } } } else { - WFIFO_STRING(s, 6, account_name, 24); - LOGIN_LOG("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)\n", - account_name, ip); - WFIFOL(s, 30) = 0; + fixed_51.account_name = account_name; + LOGIN_LOG("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)\n"_fmt, + account_name, ip); + fixed_51.valid_until = TimeT(); } } - WFIFOSET(s, 34); - RFIFOSKIP(s, 38); + send_fpacket<0x7951, 34>(s, fixed_51); break; + } case 0x7952: // Request about informations of an account (by account name) - if (RFIFOREST(s) < 26) - return; { - WFIFOW(s, 0) = 0x7953; - WFIFOL(s, 2) = -1; - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); + Packet_Fixed<0x7952> fixed; + rv = recv_fpacket<0x7952, 26>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Head<0x7953> head_53; + head_53.account_id = AccountId(); + AccountName account_name = stringish<AccountName>(fixed.account_name.to_print()); const AuthData *ad = search_account(account_name); if (ad) { - WFIFOL(s, 2) = ad->account_id; - WFIFOB(s, 6) = isGM(ad->account_id); - WFIFO_STRING(s, 7, ad->userid, 24); - WFIFOB(s, 31) = static_cast<uint8_t>(ad->sex); - WFIFOL(s, 32) = ad->logincount; - WFIFOL(s, 36) = ad->state; - WFIFO_STRING(s, 40, ad->error_message, 20); - WFIFO_STRING(s, 60, ad->lastlogin, 24); - WFIFO_STRING(s, 84, convert_for_printf(ad->last_ip), 16); - WFIFO_STRING(s, 100, ad->email, 40); - WFIFOL(s, 140) = static_cast<time_t>(ad->connect_until_time); - WFIFOL(s, 144) = static_cast<time_t>(ad->ban_until_time); - size_t len = ad->memo.size() + 1; - WFIFOW(s, 148) = len; - WFIFO_STRING(s, 150, ad->memo, len); - LOGIN_LOG("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n", - ad->userid, ad->account_id, - ip); - WFIFOSET(s, 150 + len); + head_53.account_id = ad->account_id; + head_53.gm_level = isGM(ad->account_id); + head_53.account_name = ad->userid; + head_53.sex = ad->sex; + head_53.login_count = ad->logincount; + head_53.state = ad->state; + head_53.error_message = ad->error_message; + head_53.last_login_string = ad->lastlogin; + head_53.ip_string = convert_for_printf(ad->last_ip); + head_53.email = ad->email; + head_53.connect_until = ad->connect_until_time; + head_53.ban_until = ad->ban_until_time; + + XString repeat_53 = ad->memo; + LOGIN_LOG("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n"_fmt, + ad->userid, ad->account_id, + ip); + + send_vpacket<0x7953, 150, 1>(s, head_53, repeat_53); } else { - WFIFO_STRING(s, 7, account_name, 24); - WFIFOW(s, 148) = 0; - LOGIN_LOG("'ladmin': Attempt to obtain information (by the name) of an unknown account (account: %s, ip: %s)\n", - account_name, ip); - WFIFOSET(s, 150); + head_53.account_name = account_name; + LOGIN_LOG("'ladmin': Attempt to obtain information (by the name) of an unknown account (account: %s, ip: %s)\n"_fmt, + account_name, ip); + send_vpacket<0x7953, 150, 1>(s, head_53, ""_s); } - } - RFIFOSKIP(s, 26); break; + } case 0x7954: // Request about information of an account (by account id) - if (RFIFOREST(s) < 6) - return; { - int account_id = RFIFOL(s, 2); - WFIFOW(s, 0) = 0x7953; - WFIFOL(s, 2) = account_id; - WFIFO_ZERO(s, 7, 24); + Packet_Fixed<0x7954> fixed; + rv = recv_fpacket<0x7954, 6>(s, fixed); + if (rv != RecvResult::Complete) + break; + + AccountId account_id = fixed.account_id; + Packet_Head<0x7953> head_53; + head_53.account_id = account_id; + head_53.account_name = AccountName(); for (const AuthData& ad : auth_data) { if (ad.account_id == account_id) { - LOGIN_LOG("'ladmin': Sending information of an account (request by the id; account: %s, id: %d, ip: %s)\n", - ad.userid, RFIFOL(s, 2), ip); - WFIFOB(s, 6) = isGM(ad.account_id); - WFIFO_STRING(s, 7, ad.userid, 24); - WFIFOB(s, 31) = static_cast<uint8_t>(ad.sex); - WFIFOL(s, 32) = ad.logincount; - WFIFOL(s, 36) = ad.state; - WFIFO_STRING(s, 40, ad.error_message, 20); - WFIFO_STRING(s, 60, ad.lastlogin, 24); - WFIFO_STRING(s, 84, convert_for_printf(ad.last_ip), 16); - WFIFO_STRING(s, 100, ad.email, 40); - WFIFOL(s, 140) = static_cast<time_t>(ad.connect_until_time); - WFIFOL(s, 144) = static_cast<time_t>(ad.ban_until_time); - size_t len = ad.memo.size() + 1; - WFIFOW(s, 148) = len; - WFIFO_STRING(s, 150, ad.memo, len); - WFIFOSET(s, 150 + len); + LOGIN_LOG("'ladmin': Sending information of an account (request by the id; account: %s, id: %d, ip: %s)\n"_fmt, + ad.userid, account_id, ip); + head_53.gm_level = isGM(ad.account_id); + head_53.account_name = ad.userid; + head_53.sex = ad.sex; + head_53.login_count = ad.logincount; + head_53.state = ad.state; + head_53.error_message = ad.error_message; + head_53.last_login_string = ad.lastlogin; + head_53.ip_string = convert_for_printf(ad.last_ip); + head_53.email = ad.email; + head_53.connect_until = ad.connect_until_time; + head_53.ban_until = ad.ban_until_time; + XString repeat_53 = ad.memo; + send_vpacket<0x7953, 150, 1>(s, head_53, repeat_53); goto x7954_out; } } { - LOGIN_LOG("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)\n", - RFIFOL(s, 2), ip); - WFIFO_STRING(s, 7, "", 24); - WFIFOW(s, 148) = 0; - WFIFOSET(s, 150); + LOGIN_LOG("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)\n"_fmt, + account_id, ip); + head_53.account_name = stringish<AccountName>(""_s); + send_vpacket<0x7953, 150, 1>(s, head_53, ""_s); } - } x7954_out: - RFIFOSKIP(s, 6); break; + } case 0x7955: // Request to reload GM file (no answer) - LOGIN_LOG("'ladmin': Request to re-load GM configuration file (ip: %s).\n", - ip); + { + Packet_Fixed<0x7955> fixed; + rv = recv_fpacket<0x7955, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + LOGIN_LOG("'ladmin': Request to re-load GM configuration file (ip: %s).\n"_fmt, + ip); read_gm_account(); // send GM accounts to all char-servers send_GM_accounts(); - RFIFOSKIP(s, 2); break; + } default: { @@ -2678,55 +2785,24 @@ void parse_admin(Session *s) timestamp_milliseconds_buffer timestr; stamp_time(timestr); FPRINTF(logfp, - "%s: receiving of an unknown packet -> disconnection\n", - timestr); - FPRINTF(logfp, - "parse_admin: connection #%d (ip: %s), packet: 0x%x (with being read: %zu).\n", - s, ip, RFIFOW(s, 0), RFIFOREST(s)); - FPRINTF(logfp, "Detail (in hex):\n"); + "%s: receiving of an unknown packet -> disconnection\n"_fmt, + timestr); FPRINTF(logfp, - "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F\n"); - char tmpstr[16 + 1] {}; - int i; - for (i = 0; i < RFIFOREST(s); i++) - { - if ((i & 15) == 0) - FPRINTF(logfp, "%04X ", i); - FPRINTF(logfp, "%02x ", RFIFOB (s, i)); - if (RFIFOB(s, i) > 0x1f) - tmpstr[i % 16] = RFIFOB(s, i); - else - tmpstr[i % 16] = '.'; - if ((i - 7) % 16 == 0) // -8 + 1 - FPRINTF(logfp, " "); - else if ((i + 1) % 16 == 0) - { - FPRINTF(logfp, " %s\n", tmpstr); - std::fill(tmpstr + 0, tmpstr + 17, '\0'); - } - } - if (i % 16 != 0) - { - for (int j = i; j % 16 != 0; j++) - { - FPRINTF(logfp, " "); - if ((j - 7) % 16 == 0) // -8 + 1 - FPRINTF(logfp, " "); - } - FPRINTF(logfp, " %s\n", tmpstr); - } - FPRINTF(logfp, "\n"); + "parse_admin: connection #%d (ip: %s), packet: 0x%x (with being read: %zu).\n"_fmt, + s, ip, packet_id, packet_avail(s)); + FPRINTF(logfp, "Detail (in hex):\n"_fmt); + packet_dump(logfp, s); } - } - LOGIN_LOG("'ladmin': End of connection, unknown packet (ip: %s)\n", - ip); + LOGIN_LOG("'ladmin': End of connection, unknown packet (ip: %s)\n"_fmt, + ip); s->set_eof(); - PRINTF("Remote administration has been disconnected (unknown packet).\n"); + PRINTF("Remote administration has been disconnected (unknown packet).\n"_fmt); return; + } } - //WFIFOW(fd,0) = 0x791f; - //WFIFOSET(fd,2); } + if (rv == RecvResult::Error) + s->set_eof(); return; } @@ -2738,8 +2814,8 @@ bool lan_ip_check(IP4Address p) { bool lancheck = lan_subnet.covers(p); - PRINTF("LAN test (result): %s.\n", - (lancheck) ? SGR_BOLD SGR_CYAN "LAN source" SGR_RESET : SGR_BOLD SGR_GREEN "WAN source" SGR_RESET); + PRINTF("LAN test (result): %s.\n"_fmt, + (lancheck) ? SGR_BOLD SGR_CYAN "LAN source" SGR_RESET ""_s : SGR_BOLD SGR_GREEN "WAN source" SGR_RESET ""_s); return lancheck; } @@ -2750,106 +2826,94 @@ static void parse_login(Session *s) { struct mmo_account account; - int result, j; + int result; IP4Address ip = s->client_ip; - - while (RFIFOREST(s) >= 2) + RecvResult rv = RecvResult::Complete; + uint16_t packet_id; + while (rv == RecvResult::Complete && packet_peek_id(s, &packet_id)) { if (display_parse_login == 1) { - if (RFIFOW(s, 0) == 0x64 || RFIFOW(s, 0) == 0x01dd) + if (packet_id == 0x64) { - if (RFIFOREST(s) >= ((RFIFOW(s, 0) == 0x64) ? 55 : 47)) - { - AccountName account_name = stringish<AccountName>(RFIFO_STRING<24>(s, 6)); - PRINTF("parse_login: connection #%d, packet: 0x%x (with being read: %zu), account: %s.\n", - s, RFIFOW(s, 0), RFIFOREST(s), - account_name); - } + // handled below to handle account name } - else if (RFIFOW(s, 0) == 0x2710) + else if (packet_id == 0x2710) { - if (RFIFOREST(s) >= 86) - { - ServerName server_name = stringish<ServerName>(RFIFO_STRING<20>(s, 60)); - PRINTF("parse_login: connection #%d, packet: 0x%x (with being read: %zu), server: %s.\n", - s, RFIFOW(s, 0), RFIFOREST(s), - server_name); - } + // handled below to handle server name } else - PRINTF("parse_login: connection #%d, packet: 0x%x (with being read: %zu).\n", - s, RFIFOW(s, 0), RFIFOREST(s)); + PRINTF("parse_login: connection #%d, packet: 0x%x (with being read: %zu).\n"_fmt, + s, packet_id, packet_avail(s)); } - switch (RFIFOW(s, 0)) + switch (packet_id) { - case 0x200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive. - if (RFIFOREST(s) < 26) - return; - RFIFOSKIP(s, 26); - break; - - case 0x204: // New alive packet: structure: 0x204 <encrypted.account.userid>.16B. (new ragexe from 22 june 2004) - if (RFIFOREST(s) < 18) - return; - RFIFOSKIP(s, 18); - break; - case 0x64: // Ask connection of a client - if (RFIFOREST(s) < 55) - return; + { + Packet_Fixed<0x0064> fixed; + rv = recv_fpacket<0x0064, 55>(s, fixed); + if (rv != RecvResult::Complete) + break; + + // formerly at top of while + { + AccountName account_name = fixed.account_name; + PRINTF("parse_login: connection #%d, packet: 0x%x (with being read: %zu), account: %s.\n"_fmt, + s, packet_id, packet_avail(s), + account_name); + } - account.userid = stringish<AccountName>(RFIFO_STRING<24>(s, 6).to_print()); - account.passwd = stringish<AccountPass>(RFIFO_STRING<24>(s, 30).to_print()); + account.userid = fixed.account_name; + account.passwd = fixed.account_pass; account.passwdenc = 0; - LOGIN_LOG("Request for connection (non encryption mode) of %s (ip: %s).\n", - account.userid, ip); + LOGIN_LOG("Request for connection (non encryption mode) of %s (ip: %s).\n"_fmt, + account.userid, ip); if (!check_ip(ip)) { - LOGIN_LOG("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", - ip); - WFIFOW(s, 0) = 0x6a; - WFIFOB(s, 2) = 0x03; - WFIFO_ZERO(s, 3, 20); - WFIFOSET(s, 23); - RFIFOSKIP(s, 55); + LOGIN_LOG("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n"_fmt, + ip); + + Packet_Fixed<0x006a> fixed_6a; + fixed_6a.error_code = 0x03; + fixed_6a.error_message = {}; + send_fpacket<0x006a, 23>(s, fixed_6a); break; } result = mmo_auth(&account, s); if (result == -1) { - VERSION_2 version_2 = static_cast<VERSION_2>(RFIFOB(s, 54)); + VERSION_2 version_2 = fixed.version_2_flags; if (!bool(version_2 & VERSION_2::UPDATEHOST) || !bool(version_2 & VERSION_2::SERVERORDER)) result = 5; // client too old } if (result == -1) { - int gm_level = isGM(account.account_id); - if (min_level_to_connect > gm_level) + GmLevel gm_level = isGM(account.account_id); + if (!(gm_level.satisfies(min_level_to_connect))) { - LOGIN_LOG("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d, ip: %s).\n", - min_level_to_connect, account.userid, - gm_level, ip); - WFIFOW(s, 0) = 0x81; - WFIFOB(s, 2) = 1; // 01 = Server closed - WFIFOSET(s, 3); + LOGIN_LOG("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d, ip: %s).\n"_fmt, + min_level_to_connect, account.userid, + gm_level, ip); + Packet_Fixed<0x0081> fixed_81; + fixed_81.error_code = 1; // 01 = Server closed + send_fpacket<0x0081, 3>(s, fixed_81); } else { // int version_2 = RFIFOB(fd, 54); // version 2 if (gm_level) - PRINTF("Connection of the GM (level:%d) account '%s' accepted.\n", - gm_level, account.userid); + PRINTF("Connection of the GM (level:%d) account '%s' accepted.\n"_fmt, + gm_level, account.userid); else - PRINTF("Connection of the account '%s' accepted.\n", - account.userid); + PRINTF("Connection of the account '%s' accepted.\n"_fmt, + account.userid); /* * Add a 0x0063 packet, which contains the name of the update host. The packet will only @@ -2866,45 +2930,43 @@ void parse_login(Session *s) { if (update_host) { - size_t host_len = update_host.size() + 1; - WFIFOW(s, 0) = 0x63; - WFIFOW(s, 2) = 4 + host_len; - WFIFO_STRING(s, 4, update_host, host_len); - WFIFOSET(s, 4 + host_len); + send_packet_repeatonly<0x0063, 4, 1>(s, update_host); } } // Load list of char servers into outbound packet - server_num = 0; + std::vector<Packet_Repeat<0x0069>> repeat_69; // if (version_2 & VERSION_2_SERVERORDER) for (int i = 0; i < MAX_SERVERS; i++) { if (server_session[i]) { + Packet_Repeat<0x0069> info; if (lan_ip_check(ip)) - WFIFOIP(s, 47 + server_num * 32) = lan_char_ip; + info.ip = lan_char_ip; else - WFIFOIP(s, 47 + server_num * 32) = server[i].ip; - WFIFOW(s, 47 + server_num * 32 + 4) = server[i].port; - WFIFO_STRING(s, 47 + server_num * 32 + 6, server[i].name, 20); - WFIFOW(s, 47 + server_num * 32 + 26) = server[i].users; - WFIFOW(s, 47 + server_num * 32 + 28) = 0; //maintenance; - WFIFOW(s, 47 + server_num * 32 + 30) = 0; //is_new; - server_num++; + info.ip = server[i].ip; + info.port = server[i].port; + info.server_name = server[i].name; + info.users = server[i].users; + info.maintenance = 0; //maintenance; + info.is_new = 0; //is_new; + repeat_69.push_back(info); } } // if at least 1 char-server - if (server_num > 0) + if (repeat_69.size()) { - WFIFOW(s, 0) = 0x69; - WFIFOW(s, 2) = 47 + 32 * server_num; - WFIFOL(s, 4) = account.login_id1; - WFIFOL(s, 8) = account.account_id; - WFIFOL(s, 12) = account.login_id2; - WFIFOL(s, 16) = 0; // in old version, that was for ip (not more used) - WFIFO_STRING(s, 20, account.lastlogin, 24); // in old version, that was for name (not more used) - WFIFOB(s, 46) = static_cast<uint8_t>(account.sex); - WFIFOSET(s, 47 + 32 * server_num); + Packet_Head<0x0069> head_69; + head_69.login_id1 = account.login_id1; + head_69.account_id = account.account_id; + head_69.login_id2 = account.login_id2; + head_69.unused = 0; // in old version, that was for ip (not more used) + head_69.last_login_string = account.lastlogin; // in old version, that was for name (not more used) + head_69.unused2 = 0; + head_69.sex = account.sex; + send_vpacket<0x0069, 47, 32>(s, head_69, repeat_69); + if (auth_fifo_pos >= AUTH_FIFO_SIZE) auth_fifo_pos = 0; auth_fifo[auth_fifo_pos].account_id = @@ -2922,19 +2984,18 @@ void parse_login(Session *s) } else { - LOGIN_LOG("Connection refused: there is no char-server online (account: %s, ip: %s).\n", - account.userid, ip); - WFIFOW(s, 0) = 0x81; - WFIFOB(s, 2) = 1; // 01 = Server closed - WFIFOSET(s, 3); + LOGIN_LOG("Connection refused: there is no char-server online (account: %s, ip: %s).\n"_fmt, + account.userid, ip); + Packet_Fixed<0x0081> fixed_81; + fixed_81.error_code = 1; // 01 = Server closed + send_fpacket<0x0081, 3>(s, fixed_81); } } } else { - WFIFO_ZERO(s, 0, 23); - WFIFOW(s, 0) = 0x6a; - WFIFOB(s, 2) = result; + Packet_Fixed<0x006a> fixed_6a; + fixed_6a.error_code = result; if (result == 6) { // 6 = Your are Prohibited to log in until %s @@ -2946,37 +3007,49 @@ void parse_login(Session *s) // if account is banned, we send ban timestamp timestamp_seconds_buffer tmpstr; stamp_time(tmpstr, &ad->ban_until_time); - WFIFO_STRING(s, 3, tmpstr, 20); + fixed_6a.error_message = tmpstr; } else { // we send error message - WFIFO_STRING(s, 3, ad->error_message, 20); + fixed_6a.error_message = ad->error_message; } } } - WFIFOSET(s, 23); + send_fpacket<0x006a, 23>(s, fixed_6a); } - RFIFOSKIP(s, (RFIFOW(s, 0) == 0x64) ? 55 : 47); break; + } case 0x2710: // Connection request of a char-server - if (RFIFOREST(s) < 86) - return; + { + Packet_Fixed<0x2710> fixed; + rv = recv_fpacket<0x2710, 86>(s, fixed); + if (rv != RecvResult::Complete) + break; + + // formerly at top of while { - int len; - account.userid = stringish<AccountName>(RFIFO_STRING<24>(s, 2).to_print()); - account.passwd = stringish<AccountPass>(RFIFO_STRING<24>(s, 26).to_print()); + ServerName server_name = stringish<ServerName>(fixed.server_name); + PRINTF("parse_login: connection #%d, packet: 0x%x (with being read: %zu), server: %s.\n"_fmt, + s, packet_id, packet_avail(s), + server_name); + } + + { + // TODO: this is exceptionally silly. Fix it. + account.userid = stringish<AccountName>(fixed.account_name.to_print()); + account.passwd = stringish<AccountPass>(fixed.account_pass.to_print()); account.passwdenc = 0; - ServerName server_name = stringish<ServerName>(RFIFO_STRING<20>(s, 60).to_print()); - LOGIN_LOG("Connection request of the char-server '%s' @ %s:%d (ip: %s)\n", - server_name, RFIFOIP(s, 54), RFIFOW(s, 58), ip); + ServerName server_name = stringish<ServerName>(fixed.server_name.to_print()); + LOGIN_LOG("Connection request of the char-server '%s' @ %s:%d (ip: %s)\n"_fmt, + server_name, fixed.ip, fixed.port, ip); if (account.userid == userid && account.passwd == passwd) { // If this is the main server, and we don't already have a main server if (!server_session[0] && server_name == main_server) { - account.account_id = 0; + account.account_id = wrap<AccountId>(0_u32); goto x2710_okay; } else @@ -2986,7 +3059,7 @@ void parse_login(Session *s) { if (!server_session[i]) { - account.account_id = i; + account.account_id = wrap<AccountId>(i); goto x2710_okay; } } @@ -2996,121 +3069,131 @@ void parse_login(Session *s) { x2710_okay: - LOGIN_LOG("Connection of the char-server '%s' accepted (account: %s, pass: %s, ip: %s)\n", - server_name, account.userid, - account.passwd, ip); - PRINTF("Connection of the char-server '%s' accepted.\n", - server_name); - server[account.account_id] = mmo_char_server{}; - server[account.account_id].ip = RFIFOIP(s, 54); - server[account.account_id].port = RFIFOW(s, 58); - server[account.account_id].name = server_name; - server[account.account_id].users = 0; + LOGIN_LOG("Connection of the char-server '%s' accepted (account: %s, pass: %s, ip: %s)\n"_fmt, + server_name, account.userid, + account.passwd, ip); + PRINTF("Connection of the char-server '%s' accepted.\n"_fmt, + server_name); + server[unwrap<AccountId>(account.account_id)] = mmo_char_server{}; + server[unwrap<AccountId>(account.account_id)].ip = fixed.ip; + server[unwrap<AccountId>(account.account_id)].port = fixed.port; + server[unwrap<AccountId>(account.account_id)].name = server_name; + server[unwrap<AccountId>(account.account_id)].users = 0; //maintenance = RFIFOW(fd, 82); //is_new = RFIFOW(fd, 84); - server_session[account.account_id] = s; + server_session[unwrap<AccountId>(account.account_id)] = s; if (anti_freeze_enable) - server_freezeflag[account.account_id] = 5; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed - WFIFOW(s, 0) = 0x2711; - WFIFOB(s, 2) = 0; - WFIFOSET(s, 3); - s->set_parsers(SessionParsers{func_parse: parse_fromchar, func_delete: delete_fromchar}); + server_freezeflag[unwrap<AccountId>(account.account_id)] = 5; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed + + Packet_Fixed<0x2711> fixed_11; + fixed_11.code = 0; + send_fpacket<0x2711, 3>(s, fixed_11); + + s->set_parsers(SessionParsers{.func_parse= parse_fromchar, .func_delete= delete_fromchar}); realloc_fifo(s, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); + // send GM account to char-server - len = 4; - WFIFOW(s, 0) = 0x2732; - for (const AuthData& ad : auth_data) - // send only existing accounts. We can not create a GM account when server is online. - if (uint8_t GM_value = isGM(ad.account_id)) - { - WFIFOL(s, len) = ad.account_id; - WFIFOB(s, len + 4) = GM_value; - len += 5; - } - WFIFOW(s, 2) = len; - WFIFOSET(s, len); + send_GM_accounts(s); goto x2710_done; } { x2710_refused: - LOGIN_LOG("Connexion of the char-server '%s' REFUSED (account: %s, pass: %s, ip: %s)\n", - server_name, account.userid, - account.passwd, ip); - WFIFOW(s, 0) = 0x2711; - WFIFOB(s, 2) = 3; - WFIFOSET(s, 3); + LOGIN_LOG("Connexion of the char-server '%s' REFUSED (account: %s, pass: %s, ip: %s)\n"_fmt, + server_name, account.userid, + account.passwd, ip); + Packet_Fixed<0x2711> fixed_11; + fixed_11.code = 3; + send_fpacket<0x2711, 3>(s, fixed_11); } } x2710_done: - RFIFOSKIP(s, 86); + // justification: we switching the packet parser + parse_fromchar(s); return; + } case 0x7530: // Request of the server version - LOGIN_LOG("Sending of the server version (ip: %s)\n", - ip); - WFIFOW(s, 0) = 0x7531; { + Packet_Fixed<0x7530> fixed; + rv = recv_fpacket<0x7530, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + LOGIN_LOG("Sending of the server version (ip: %s)\n"_fmt, + ip); + + Packet_Fixed<0x7531> fixed_31; Version version = CURRENT_LOGIN_SERVER_VERSION; version.flags = new_account ? 1 : 0; - WFIFO_STRUCT(s, 2, version); - WFIFOSET(s, 10); - } - RFIFOSKIP(s, 2); + fixed_31.version = version; + send_fpacket<0x7531, 10>(s, fixed_31); break; + } case 0x7532: // Request to end connection - LOGIN_LOG("End of connection (ip: %s)\n", ip); + { + Packet_Fixed<0x7532> fixed; + rv = recv_fpacket<0x7532, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + LOGIN_LOG("End of connection (ip: %s)\n"_fmt, ip); s->set_eof(); return; + } case 0x7918: // Request for administation login - if (RFIFOREST(s) < 4 - || RFIFOREST(s) < ((RFIFOW(s, 2) == 0) ? 28 : 20)) - return; - WFIFOW(s, 0) = 0x7919; - WFIFOB(s, 2) = 1; + { + Packet_Fixed<0x7918> fixed; + rv = recv_fpacket<0x7918, 28>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x7919> fixed_19; + fixed_19.error = 1; if (!check_ladminip(s->client_ip)) { - LOGIN_LOG("'ladmin'-login: Connection in administration mode refused: IP isn't authorised (ladmin_allow, ip: %s).\n", - ip); + LOGIN_LOG("'ladmin'-login: Connection in administration mode refused: IP isn't authorised (ladmin_allow, ip: %s).\n"_fmt, + ip); } else { - if (RFIFOW(s, 2) == 0) + if (fixed.encryption_zero == 0) { // non encrypted password - AccountPass password = stringish<AccountPass>(RFIFO_STRING<24>(s, 4).to_print()); + AccountPass password = stringish<AccountPass>(fixed.account_pass.to_print()); // If remote administration is enabled and password sent by client matches password read from login server configuration file if ((admin_state == 1) && (password == admin_pass)) { - LOGIN_LOG("'ladmin'-login: Connection in administration mode accepted (non encrypted password: %s, ip: %s)\n", - password, ip); - PRINTF("Connection of a remote administration accepted (non encrypted password).\n"); - WFIFOB(s, 2) = 0; - s->set_parsers(SessionParsers{func_parse: parse_admin, func_delete: delete_admin}); + LOGIN_LOG("'ladmin'-login: Connection in administration mode accepted (non encrypted password: %s, ip: %s)\n"_fmt, + password, ip); + PRINTF("Connection of a remote administration accepted (non encrypted password).\n"_fmt); + fixed_19.error = 0; + s->set_parsers(SessionParsers{.func_parse= parse_admin, .func_delete= delete_admin}); } else if (admin_state != 1) - LOGIN_LOG("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (non encrypted password: %s, ip: %s)\n", - password, ip); + LOGIN_LOG("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (non encrypted password: %s, ip: %s)\n"_fmt, + password, ip); else - LOGIN_LOG("'ladmin'-login: Connection in administration mode REFUSED - invalid password (non encrypted password: %s, ip: %s)\n", - password, ip); + LOGIN_LOG("'ladmin'-login: Connection in administration mode REFUSED - invalid password (non encrypted password: %s, ip: %s)\n"_fmt, + password, ip); } else { // encrypted password { - LOGIN_LOG("'ladmin'-login: Connection in administration mode REFUSED - encrypted login is disabled (ip: %s)\n", - ip); + LOGIN_LOG("'ladmin'-login: Connection in administration mode REFUSED - encrypted login is disabled (ip: %s)\n"_fmt, + ip); } } } - WFIFOSET(s, 3); - RFIFOSKIP(s, (RFIFOW(s, 2) == 0) ? 28 : 20); + send_fpacket<0x7919, 3>(s, fixed_19); break; + } default: + { if (save_unknown_packets) { io::AppendFile logfp(login_log_unknown_packets_filename); @@ -3119,55 +3202,24 @@ void parse_login(Session *s) timestamp_milliseconds_buffer timestr; stamp_time(timestr); FPRINTF(logfp, - "%s: receiving of an unknown packet -> disconnection\n", - timestr); - FPRINTF(logfp, - "parse_login: connection #%d (ip: %s), packet: 0x%x (with being read: %zu).\n", - s, ip, RFIFOW(s, 0), - RFIFOREST(s)); - FPRINTF(logfp, "Detail (in hex):\n"); + "%s: receiving of an unknown packet -> disconnection\n"_fmt, + timestr); FPRINTF(logfp, - "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F\n"); - - char tmpstr[16 + 1] {}; - - int i; - for (i = 0; i < RFIFOREST(s); i++) - { - if ((i & 15) == 0) - FPRINTF(logfp, "%04X ", i); - FPRINTF(logfp, "%02x ", RFIFOB(s, i)); - if (RFIFOB(s, i) > 0x1f) - tmpstr[i % 16] = RFIFOB(s, i); - else - tmpstr[i % 16] = '.'; - if ((i - 7) % 16 == 0) // -8 + 1 - FPRINTF(logfp, " "); - else if ((i + 1) % 16 == 0) - { - FPRINTF(logfp, " %s\n", tmpstr); - std::fill(tmpstr + 0, tmpstr + 17, '\0'); - } - } - if (i % 16 != 0) - { - for (j = i; j % 16 != 0; j++) - { - FPRINTF(logfp, " "); - if ((j - 7) % 16 == 0) // -8 + 1 - FPRINTF(logfp, " "); - } - FPRINTF(logfp, " %s\n", tmpstr); - } - FPRINTF(logfp, "\n"); + "parse_login: connection #%d (ip: %s), packet: 0x%x (with being read: %zu).\n"_fmt, + s, ip, packet_id, + packet_avail(s)); + FPRINTF(logfp, "Detail (in hex):\n"_fmt); + packet_dump(logfp, s); } } - LOGIN_LOG("End of connection, unknown packet (ip: %s)\n", ip); + LOGIN_LOG("End of connection, unknown packet (ip: %s)\n"_fmt, ip); s->set_eof(); return; + } } } - return; + if (rv == RecvResult::Error) + s->set_eof(); } //---------------------------------- @@ -3176,14 +3228,14 @@ void parse_login(Session *s) static bool login_lan_config(XString w1, ZString w2) { - struct hostent *h = NULL; + struct hostent *h = nullptr; { - if (w1 == "lan_char_ip") + if (w1 == "lan_char_ip"_s) { // Read Char-Server Lan IP Address h = gethostbyname(w2.c_str()); - if (h != NULL) + if (h != nullptr) { lan_char_ip = IP4Address({ static_cast<uint8_t>(h->h_addr[0]), @@ -3194,20 +3246,20 @@ bool login_lan_config(XString w1, ZString w2) } else { - PRINTF("Bad IP value: %s\n", w2); + PRINTF("Bad IP value: %s\n"_fmt, w2); return false; } - PRINTF("LAN IP of char-server: %s.\n", lan_char_ip); + PRINTF("LAN IP of char-server: %s.\n"_fmt, lan_char_ip); } - else if (w1 == "subnet" /*backward compatibility*/ - || w1 == "lan_subnet") + else if (w1 == "subnet"_s /*backward compatibility*/ + || w1 == "lan_subnet"_s) { if (!extract(w2, &lan_subnet)) { - PRINTF("Bad IP mask: %s\n", w2); + PRINTF("Bad IP mask: %s\n"_fmt, w2); return false; } - PRINTF("Sub-network of the char-server: %s.\n", + PRINTF("Sub-network of the char-server: %s.\n"_fmt, lan_subnet); } else @@ -3222,18 +3274,18 @@ static bool lan_check() { // log the LAN configuration - LOGIN_LOG("The LAN configuration of the server is set:\n"); - LOGIN_LOG("- with LAN IP of char-server: %s.\n", lan_char_ip); - LOGIN_LOG("- with the sub-network of the char-server: %s.\n", + LOGIN_LOG("The LAN configuration of the server is set:\n"_fmt); + LOGIN_LOG("- with LAN IP of char-server: %s.\n"_fmt, lan_char_ip); + LOGIN_LOG("- with the sub-network of the char-server: %s.\n"_fmt, lan_subnet); // sub-network check of the char-server { - PRINTF("LAN test of LAN IP of the char-server: "); + PRINTF("LAN test of LAN IP of the char-server: "_fmt); if (!lan_ip_check(lan_char_ip)) { - PRINTF(SGR_BOLD SGR_RED "***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network" SGR_RESET "\n"); - LOGIN_LOG("***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network.\n"); + PRINTF(SGR_BOLD SGR_RED "***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network"_fmt SGR_RESET "\n"); + LOGIN_LOG("***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network.\n"_fmt); return false; } } @@ -3248,24 +3300,24 @@ static bool login_config(XString w1, ZString w2) { { - if (w1 == "admin_state") + if (w1 == "admin_state"_s) { admin_state = config_switch(w2); } - else if (w1 == "admin_pass") + else if (w1 == "admin_pass"_s) { admin_pass = stringish<AccountPass>(w2); } - else if (w1 == "ladminallowip") + else if (w1 == "ladminallowip"_s) { - if (w2 == "clear") + if (w2 == "clear"_s) { access_ladmin.clear(); } else { // a.b.c.d/0.0.0.0 (canonically, 0.0.0.0/0) covers all - if (w2 == "all") + if (w2 == "all"_s) { // reset all previous values access_ladmin.clear(); @@ -3280,104 +3332,104 @@ bool login_config(XString w1, ZString w2) IP4Mask n; if (!extract(w2, &n)) { - PRINTF("Bad IP mask: %s\n", w2); + PRINTF("Bad IP mask: %s\n"_fmt, w2); return false; } access_ladmin.push_back(n); } } } - else if (w1 == "gm_pass") + else if (w1 == "gm_pass"_s) { gm_pass = w2; } - else if (w1 == "level_new_gm") + else if (w1 == "level_new_gm"_s) { - level_new_gm = atoi(w2.c_str()); + level_new_gm = GmLevel::from(static_cast<uint32_t>(atoi(w2.c_str()))); } - else if (w1 == "new_account") + else if (w1 == "new_account"_s) { new_account = config_switch(w2); } - else if (w1 == "login_port") + else if (w1 == "login_port"_s) { login_port = atoi(w2.c_str()); } - else if (w1 == "account_filename") + else if (w1 == "account_filename"_s) { account_filename = w2; } - else if (w1 == "gm_account_filename") + else if (w1 == "gm_account_filename"_s) { gm_account_filename = w2; } - else if (w1 == "gm_account_filename_check_timer") + else if (w1 == "gm_account_filename_check_timer"_s) { gm_account_filename_check_timer = std::chrono::seconds(atoi(w2.c_str())); } - else if (w1 == "login_log_filename") + else if (w1 == "login_log_filename"_s) { login_log_filename = w2; } - else if (w1 == "login_log_unknown_packets_filename") + else if (w1 == "login_log_unknown_packets_filename"_s) { login_log_unknown_packets_filename = w2; } - else if (w1 == "save_unknown_packets") + else if (w1 == "save_unknown_packets"_s) { save_unknown_packets = config_switch(w2); } - else if (w1 == "display_parse_login") + else if (w1 == "display_parse_login"_s) { display_parse_login = config_switch(w2); // 0: no, 1: yes } - else if (w1 == "display_parse_admin") + else if (w1 == "display_parse_admin"_s) { display_parse_admin = config_switch(w2); // 0: no, 1: yes } - else if (w1 == "display_parse_fromchar") + else if (w1 == "display_parse_fromchar"_s) { display_parse_fromchar = config_switch(w2); // 0: no, 1: yes (without packet 0x2714), 2: all packets } - else if (w1 == "min_level_to_connect") + else if (w1 == "min_level_to_connect"_s) { - min_level_to_connect = atoi(w2.c_str()); + min_level_to_connect = GmLevel::from(static_cast<uint32_t>(atoi(w2.c_str()))); } - else if (w1 == "add_to_unlimited_account") + else if (w1 == "add_to_unlimited_account"_s) { add_to_unlimited_account = config_switch(w2); } - else if (w1 == "start_limited_time") + else if (w1 == "start_limited_time"_s) { start_limited_time = atoi(w2.c_str()); } - else if (w1 == "check_ip_flag") + else if (w1 == "check_ip_flag"_s) { check_ip_flag = config_switch(w2); } - else if (w1 == "order") + else if (w1 == "order"_s) { - if (w2 == "deny,allow" || w2 == "deny, allow") + if (w2 == "deny,allow"_s || w2 == "deny, allow"_s) access_order = ACO::DENY_ALLOW; - else if (w2 == "allow,deny" || w2 == "allow, deny") + else if (w2 == "allow,deny"_s || w2 == "allow, deny"_s) access_order = ACO::ALLOW_DENY; - else if (w2 == "mutual-failture" || w2 == "mutual-failure") + else if (w2 == "mutual-failture"_s || w2 == "mutual-failure"_s) access_order = ACO::MUTUAL_FAILURE; else { - PRINTF("Bad order: %s\n", w2); + PRINTF("Bad order: %s\n"_fmt, w2); return false; } } - else if (w1 == "allow") + else if (w1 == "allow"_s) { - if (w2 == "clear") + if (w2 == "clear"_s) { access_allow.clear(); } else { - if (w2 == "all") + if (w2 == "all"_s) { // reset all previous values access_allow.clear(); @@ -3392,22 +3444,22 @@ bool login_config(XString w1, ZString w2) IP4Mask n; if (!extract(w2, &n)) { - PRINTF("Bad IP mask: %s\n", w2); + PRINTF("Bad IP mask: %s\n"_fmt, w2); return false; } access_allow.push_back(n); } } } - else if (w1 == "deny") + else if (w1 == "deny"_s) { - if (w2 == "clear") + if (w2 == "clear"_s) { access_deny.clear(); } else { - if (w2 == "all") + if (w2 == "all"_s) { // reset all previous values access_deny.clear(); @@ -3422,36 +3474,36 @@ bool login_config(XString w1, ZString w2) IP4Mask n; if (!extract(w2, &n)) { - PRINTF("Bad IP mask: %s\n", w2); + PRINTF("Bad IP mask: %s\n"_fmt, w2); return false; } access_deny.push_back(n); } } } - else if (w1 == "anti_freeze_enable") + else if (w1 == "anti_freeze_enable"_s) { anti_freeze_enable = config_switch(w2); } - else if (w1 == "anti_freeze_interval") + else if (w1 == "anti_freeze_interval"_s) { anti_freeze_interval = std::max( std::chrono::seconds(atoi(w2.c_str())), - std::chrono::seconds(5)); + 5_s); } - else if (w1 == "update_host") + else if (w1 == "update_host"_s) { update_host = w2; } - else if (w1 == "main_server") + else if (w1 == "main_server"_s) { main_server = stringish<ServerName>(w2); } - else if (w1 == "userid") + else if (w1 == "userid"_s) { userid = stringish<AccountName>(w2); } - else if (w1 == "passwd") + else if (w1 == "passwd"_s) { passwd = stringish<AccountPass>(w2); } @@ -3473,7 +3525,7 @@ bool display_conf_warnings(void) bool rv = true; if (admin_state != 0 && admin_state != 1) { - PRINTF("***WARNING: Invalid value for admin_state parameter -> set to 0 (no remote admin).\n"); + PRINTF("***WARNING: Invalid value for admin_state parameter -> set to 0 (no remote admin).\n"_fmt); admin_state = 0; rv = false; } @@ -3482,132 +3534,108 @@ bool display_conf_warnings(void) { if (!admin_pass) { - PRINTF("***WARNING: Administrator password is void (admin_pass).\n"); + PRINTF("***WARNING: Administrator password is void (admin_pass).\n"_fmt); rv = false; } - else if (admin_pass == stringish<AccountPass>("admin")) + else if (admin_pass == stringish<AccountPass>("admin"_s)) { - PRINTF("***WARNING: You are using the default administrator password (admin_pass).\n"); - PRINTF(" We highly recommend that you change it.\n"); + PRINTF("***WARNING: You are using the default administrator password (admin_pass).\n"_fmt); + PRINTF(" We highly recommend that you change it.\n"_fmt); } } if (!gm_pass) { - PRINTF("***WARNING: 'To GM become' password is void (gm_pass).\n"); - PRINTF(" We highly recommend that you set one password.\n"); + PRINTF("***WARNING: 'To GM become' password is void (gm_pass).\n"_fmt); + PRINTF(" We highly recommend that you set one password.\n"_fmt); rv = false; } - else if (gm_pass == "gm") - { - PRINTF("***WARNING: You are using the default GM password (gm_pass).\n"); - PRINTF(" We highly recommend that you change it.\n"); - } - - if (level_new_gm < 0 || level_new_gm > 99) + else if (gm_pass == "gm"_s) { - PRINTF("***WARNING: Invalid value for level_new_gm parameter -> set to 60 (default).\n"); - level_new_gm = 60; - rv = false; + PRINTF("***WARNING: You are using the default GM password (gm_pass).\n"_fmt); + PRINTF(" We highly recommend that you change it.\n"_fmt); } if (new_account != 0 && new_account != 1) { - PRINTF("***WARNING: Invalid value for new_account parameter -> set to 0 (no new account).\n"); + PRINTF("***WARNING: Invalid value for new_account parameter -> set to 0 (no new account).\n"_fmt); new_account = 0; rv = false; } if (login_port < 1024 || login_port > 65535) { - PRINTF("***WARNING: Invalid value for login_port parameter -> set to 6900 (default).\n"); + PRINTF("***WARNING: Invalid value for login_port parameter -> set to 6900 (default).\n"_fmt); login_port = 6900; rv = false; } if (gm_account_filename_check_timer.count() < 0) { - PRINTF("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n"); - PRINTF(" -> set to 15 sec (default).\n"); - gm_account_filename_check_timer = std::chrono::seconds(15); + PRINTF("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n"_fmt); + PRINTF(" -> set to 15 sec (default).\n"_fmt); + gm_account_filename_check_timer = 15_s; rv = false; } - else if (gm_account_filename_check_timer == std::chrono::seconds(1)) + else if (gm_account_filename_check_timer == 1_s) { - PRINTF("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n"); - PRINTF(" -> set to 2 sec (minimum value).\n"); - gm_account_filename_check_timer = std::chrono::seconds(2); + PRINTF("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n"_fmt); + PRINTF(" -> set to 2 sec (minimum value).\n"_fmt); + gm_account_filename_check_timer = 2_s; rv = false; } if (save_unknown_packets != 0 && save_unknown_packets != 1) { - PRINTF("WARNING: Invalid value for save_unknown_packets parameter -> set to 0-no save.\n"); + PRINTF("WARNING: Invalid value for save_unknown_packets parameter -> set to 0-no save.\n"_fmt); save_unknown_packets = 0; rv = false; } if (display_parse_login != 0 && display_parse_login != 1) { // 0: no, 1: yes - PRINTF("***WARNING: Invalid value for display_parse_login parameter\n"); - PRINTF(" -> set to 0 (no display).\n"); + PRINTF("***WARNING: Invalid value for display_parse_login parameter\n"_fmt); + PRINTF(" -> set to 0 (no display).\n"_fmt); display_parse_login = 0; rv = false; } if (display_parse_admin != 0 && display_parse_admin != 1) { // 0: no, 1: yes - PRINTF("***WARNING: Invalid value for display_parse_admin parameter\n"); - PRINTF(" -> set to 0 (no display).\n"); + PRINTF("***WARNING: Invalid value for display_parse_admin parameter\n"_fmt); + PRINTF(" -> set to 0 (no display).\n"_fmt); display_parse_admin = 0; rv = false; } if (display_parse_fromchar < 0 || display_parse_fromchar > 2) { // 0: no, 1: yes (without packet 0x2714), 2: all packets - PRINTF("***WARNING: Invalid value for display_parse_fromchar parameter\n"); - PRINTF(" -> set to 0 (no display).\n"); + PRINTF("***WARNING: Invalid value for display_parse_fromchar parameter\n"_fmt); + PRINTF(" -> set to 0 (no display).\n"_fmt); display_parse_fromchar = 0; rv = false; } - if (min_level_to_connect < 0) - { // 0: all players, 1-99 at least gm level x - PRINTF("***WARNING: Invalid value for min_level_to_connect (%d) parameter\n", - min_level_to_connect); - PRINTF(" -> set to 0 (any player).\n"); - min_level_to_connect = 0; - rv = false; - } - else if (min_level_to_connect > 99) - { // 0: all players, 1-99 at least gm level x - PRINTF("***WARNING: Invalid value for min_level_to_connect (%d) parameter\n", - min_level_to_connect); - PRINTF(" -> set to 99 (only GM level 99).\n"); - min_level_to_connect = 99; - rv = false; - } - if (add_to_unlimited_account != 0 && add_to_unlimited_account != 1) { // 0: no, 1: yes - PRINTF("***WARNING: Invalid value for add_to_unlimited_account parameter\n"); - PRINTF(" -> set to 0 (impossible to add a time to an unlimited account).\n"); + PRINTF("***WARNING: Invalid value for add_to_unlimited_account parameter\n"_fmt); + PRINTF(" -> set to 0 (impossible to add a time to an unlimited account).\n"_fmt); add_to_unlimited_account = 0; rv = false; } if (start_limited_time < -1) { // -1: create unlimited account, 0 or more: additionnal sec from now to create limited time - PRINTF("***WARNING: Invalid value for start_limited_time parameter\n"); - PRINTF(" -> set to -1 (new accounts are created with unlimited time).\n"); + PRINTF("***WARNING: Invalid value for start_limited_time parameter\n"_fmt); + PRINTF(" -> set to -1 (new accounts are created with unlimited time).\n"_fmt); start_limited_time = -1; rv = false; } if (check_ip_flag != 0 && check_ip_flag != 1) { // 0: no, 1: yes - PRINTF("***WARNING: Invalid value for check_ip_flag parameter\n"); - PRINTF(" -> set to 1 (check players ip between login-server & char-server).\n"); + PRINTF("***WARNING: Invalid value for check_ip_flag parameter\n"_fmt); + PRINTF(" -> set to 1 (check players ip between login-server & char-server).\n"_fmt); check_ip_flag = 1; rv = false; } @@ -3616,8 +3644,8 @@ bool display_conf_warnings(void) { if (access_deny.size() == 1 && access_deny.front().mask() == IP4Address()) { - PRINTF("***WARNING: The IP security order is 'deny,allow' (allow if not deny).\n"); - PRINTF(" And you refuse ALL IP.\n"); + PRINTF("***WARNING: The IP security order is 'deny,allow' (allow if not deny).\n"_fmt); + PRINTF(" And you refuse ALL IP.\n"_fmt); rv = false; } } @@ -3625,8 +3653,8 @@ bool display_conf_warnings(void) { if (access_allow.empty()) { - PRINTF("***WARNING: The IP security order is 'allow,deny' (deny if not allow).\n"); - PRINTF(" But, NO IP IS AUTHORISED!\n"); + PRINTF("***WARNING: The IP security order is 'allow,deny' (deny if not allow).\n"_fmt); + PRINTF(" But, NO IP IS AUTHORISED!\n"_fmt); rv = false; } } @@ -3635,16 +3663,16 @@ bool display_conf_warnings(void) // ACO::MUTUAL_FAILURE if (access_allow.empty()) { - PRINTF("***WARNING: The IP security order is 'mutual-failture'\n"); - PRINTF(" (allow if in the allow list and not in the deny list).\n"); - PRINTF(" But, NO IP IS AUTHORISED!\n"); + PRINTF("***WARNING: The IP security order is 'mutual-failture'\n"_fmt); + PRINTF(" (allow if in the allow list and not in the deny list).\n"_fmt); + PRINTF(" But, NO IP IS AUTHORISED!\n"_fmt); rv = false; } else if (access_deny.size() == 1 && access_deny.front().mask() == IP4Address()) { - PRINTF("***WARNING: The IP security order is mutual-failture\n"); - PRINTF(" (allow if in the allow list and not in the deny list).\n"); - PRINTF(" But, you refuse ALL IP!\n"); + PRINTF("***WARNING: The IP security order is mutual-failture\n"_fmt); + PRINTF(" (allow if in the allow list and not in the deny list).\n"_fmt); + PRINTF(" But, you refuse ALL IP!\n"_fmt); rv = false; } } @@ -3658,168 +3686,166 @@ static void save_config_in_log(void) { // a newline in the log... - LOGIN_LOG(""); - LOGIN_LOG("The login-server starting...\n"); + LOGIN_LOG(""_fmt); + LOGIN_LOG("The login-server starting...\n"_fmt); // save configuration in log file - LOGIN_LOG("The configuration of the server is set:\n"); + LOGIN_LOG("The configuration of the server is set:\n"_fmt); if (admin_state != 1) - LOGIN_LOG("- with no remote administration.\n"); + LOGIN_LOG("- with no remote administration.\n"_fmt); else if (!admin_pass) - LOGIN_LOG("- with a remote administration with a VOID password.\n"); - else if (admin_pass == stringish<AccountPass>("admin")) - LOGIN_LOG("- with a remote administration with the DEFAULT password.\n"); + LOGIN_LOG("- with a remote administration with a VOID password.\n"_fmt); + else if (admin_pass == stringish<AccountPass>("admin"_s)) + LOGIN_LOG("- with a remote administration with the DEFAULT password.\n"_fmt); else - LOGIN_LOG("- with a remote administration with the password of %zu character(s).\n", + LOGIN_LOG("- with a remote administration with the password of %zu character(s).\n"_fmt, admin_pass.size()); if (access_ladmin.empty() || (access_ladmin.size() == 1 && access_ladmin.front().mask() == IP4Address())) { - LOGIN_LOG("- to accept any IP for remote administration\n"); + LOGIN_LOG("- to accept any IP for remote administration\n"_fmt); } else { - LOGIN_LOG("- to accept following IP for remote administration:\n"); + LOGIN_LOG("- to accept following IP for remote administration:\n"_fmt); for (const IP4Mask& ae : access_ladmin) - LOGIN_LOG(" %s\n", ae); + LOGIN_LOG(" %s\n"_fmt, ae); } if (!gm_pass) - LOGIN_LOG("- with a VOID 'To GM become' password (gm_pass).\n"); - else if (gm_pass == "gm") - LOGIN_LOG("- with the DEFAULT 'To GM become' password (gm_pass).\n"); + LOGIN_LOG("- with a VOID 'To GM become' password (gm_pass).\n"_fmt); + else if (gm_pass == "gm"_s) + LOGIN_LOG("- with the DEFAULT 'To GM become' password (gm_pass).\n"_fmt); else - LOGIN_LOG("- with a 'To GM become' password (gm_pass) of %zu character(s).\n", + LOGIN_LOG("- with a 'To GM become' password (gm_pass) of %zu character(s).\n"_fmt, gm_pass.size()); - if (level_new_gm == 0) - LOGIN_LOG("- to refuse any creation of GM with @gm.\n"); + if (!level_new_gm) + LOGIN_LOG("- to refuse any creation of GM with @gm.\n"_fmt); else - LOGIN_LOG("- to create GM with level '%d' when @gm is used.\n", - level_new_gm); + LOGIN_LOG("- to create GM with level '%d' when @gm is used.\n"_fmt, + level_new_gm); if (new_account == 1) - LOGIN_LOG("- to ALLOW new users (with _F/_M).\n"); + LOGIN_LOG("- to ALLOW new users (with _F/_M).\n"_fmt); else - LOGIN_LOG("- to NOT ALLOW new users (with _F/_M).\n"); - LOGIN_LOG("- with port: %d.\n", login_port); - LOGIN_LOG("- with the accounts file name: '%s'.\n", - account_filename); - LOGIN_LOG("- with the GM accounts file name: '%s'.\n", - gm_account_filename); + LOGIN_LOG("- to NOT ALLOW new users (with _F/_M).\n"_fmt); + LOGIN_LOG("- with port: %d.\n"_fmt, login_port); + LOGIN_LOG("- with the accounts file name: '%s'.\n"_fmt, + account_filename); + LOGIN_LOG("- with the GM accounts file name: '%s'.\n"_fmt, + gm_account_filename); if (gm_account_filename_check_timer == interval_t::zero()) - LOGIN_LOG("- to NOT check GM accounts file modifications.\n"); + LOGIN_LOG("- to NOT check GM accounts file modifications.\n"_fmt); else - LOGIN_LOG("- to check GM accounts file modifications every %lld seconds.\n", - maybe_cast<long long>(gm_account_filename_check_timer.count())); + LOGIN_LOG("- to check GM accounts file modifications every %lld seconds.\n"_fmt, + maybe_cast<long long>(gm_account_filename_check_timer.count())); // not necessary to log the 'login_log_filename', we are inside :) - LOGIN_LOG("- with the unknown packets file name: '%s'.\n", - login_log_unknown_packets_filename); + LOGIN_LOG("- with the unknown packets file name: '%s'.\n"_fmt, + login_log_unknown_packets_filename); if (save_unknown_packets) - LOGIN_LOG("- to SAVE all unkown packets.\n"); + LOGIN_LOG("- to SAVE all unkown packets.\n"_fmt); else - LOGIN_LOG("- to SAVE only unkown packets sending by a char-server or a remote administration.\n"); + LOGIN_LOG("- to SAVE only unkown packets sending by a char-server or a remote administration.\n"_fmt); if (display_parse_login) - LOGIN_LOG("- to display normal parse packets on console.\n"); + LOGIN_LOG("- to display normal parse packets on console.\n"_fmt); else - LOGIN_LOG("- to NOT display normal parse packets on console.\n"); + LOGIN_LOG("- to NOT display normal parse packets on console.\n"_fmt); if (display_parse_admin) - LOGIN_LOG("- to display administration parse packets on console.\n"); + LOGIN_LOG("- to display administration parse packets on console.\n"_fmt); else - LOGIN_LOG("- to NOT display administration parse packets on console.\n"); + LOGIN_LOG("- to NOT display administration parse packets on console.\n"_fmt); if (display_parse_fromchar) - LOGIN_LOG("- to display char-server parse packets on console.\n"); + LOGIN_LOG("- to display char-server parse packets on console.\n"_fmt); else - LOGIN_LOG("- to NOT display char-server parse packets on console.\n"); + LOGIN_LOG("- to NOT display char-server parse packets on console.\n"_fmt); - if (min_level_to_connect == 0) // 0: all players, 1-99 at least gm level x - LOGIN_LOG("- with no minimum level for connection.\n"); - else if (min_level_to_connect == 99) - LOGIN_LOG("- to accept only GM with level 99.\n"); + if (!min_level_to_connect) // 0: all players, 1-99 at least gm level x + LOGIN_LOG("- with no minimum level for connection.\n"_fmt); else - LOGIN_LOG("- to accept only GM with level %d or more.\n", - min_level_to_connect); + LOGIN_LOG("- to accept only GM with level %d or more.\n"_fmt, + min_level_to_connect); if (add_to_unlimited_account) - LOGIN_LOG("- to authorize adjustment (with timeadd ladmin) on an unlimited account.\n"); + LOGIN_LOG("- to authorize adjustment (with timeadd ladmin) on an unlimited account.\n"_fmt); else - LOGIN_LOG("- to refuse adjustment (with timeadd ladmin) on an unlimited account. You must use timeset (ladmin command) before.\n"); + LOGIN_LOG("- to refuse adjustment (with timeadd ladmin) on an unlimited account. You must use timeset (ladmin command) before.\n"_fmt); if (start_limited_time < 0) - LOGIN_LOG("- to create new accounts with an unlimited time.\n"); + LOGIN_LOG("- to create new accounts with an unlimited time.\n"_fmt); else if (start_limited_time == 0) - LOGIN_LOG("- to create new accounts with a limited time: time of creation.\n"); + LOGIN_LOG("- to create new accounts with a limited time: time of creation.\n"_fmt); else - LOGIN_LOG("- to create new accounts with a limited time: time of creation + %d second(s).\n", - start_limited_time); + LOGIN_LOG("- to create new accounts with a limited time: time of creation + %d second(s).\n"_fmt, + start_limited_time); if (check_ip_flag) - LOGIN_LOG("- with control of players IP between login-server and char-server.\n"); + LOGIN_LOG("- with control of players IP between login-server and char-server.\n"_fmt); else - LOGIN_LOG("- to not check players IP between login-server and char-server.\n"); + LOGIN_LOG("- to not check players IP between login-server and char-server.\n"_fmt); if (access_order == ACO::DENY_ALLOW) { if (access_deny.empty()) { - LOGIN_LOG("- with the IP security order: 'deny,allow' (allow if not deny). You refuse no IP.\n"); + LOGIN_LOG("- with the IP security order: 'deny,allow' (allow if not deny). You refuse no IP.\n"_fmt); } else if (access_deny.size() == 1 && access_deny.front().mask() == IP4Address()) { - LOGIN_LOG("- with the IP security order: 'deny,allow' (allow if not deny). You refuse ALL IP.\n"); + LOGIN_LOG("- with the IP security order: 'deny,allow' (allow if not deny). You refuse ALL IP.\n"_fmt); } else { - LOGIN_LOG("- with the IP security order: 'deny,allow' (allow if not deny). Refused IP are:\n"); + LOGIN_LOG("- with the IP security order: 'deny,allow' (allow if not deny). Refused IP are:\n"_fmt); for (IP4Mask ae : access_deny) - LOGIN_LOG(" %s\n", ae); + LOGIN_LOG(" %s\n"_fmt, ae); } } else if (access_order == ACO::ALLOW_DENY) { if (access_allow.empty()) { - LOGIN_LOG("- with the IP security order: 'allow,deny' (deny if not allow). But, NO IP IS AUTHORISED!\n"); + LOGIN_LOG("- with the IP security order: 'allow,deny' (deny if not allow). But, NO IP IS AUTHORISED!\n"_fmt); } else if (access_allow.size() == 1 && access_allow.front().mask() == IP4Address()) { - LOGIN_LOG("- with the IP security order: 'allow,deny' (deny if not allow). You authorise ALL IP.\n"); + LOGIN_LOG("- with the IP security order: 'allow,deny' (deny if not allow). You authorise ALL IP.\n"_fmt); } else { - LOGIN_LOG("- with the IP security order: 'allow,deny' (deny if not allow). Authorised IP are:\n"); + LOGIN_LOG("- with the IP security order: 'allow,deny' (deny if not allow). Authorised IP are:\n"_fmt); for (IP4Mask ae : access_allow) - LOGIN_LOG(" %s\n", ae); + LOGIN_LOG(" %s\n"_fmt, ae); } } else { // ACO_MUTUAL_FAILTURE - LOGIN_LOG("- with the IP security order: 'mutual-failture' (allow if in the allow list and not in the deny list).\n"); + LOGIN_LOG("- with the IP security order: 'mutual-failture' (allow if in the allow list and not in the deny list).\n"_fmt); if (access_allow.empty()) { - LOGIN_LOG(" But, NO IP IS AUTHORISED!\n"); + LOGIN_LOG(" But, NO IP IS AUTHORISED!\n"_fmt); } else if (access_deny.size() == 1 && access_deny.front().mask() == IP4Address()) { - LOGIN_LOG(" But, you refuse ALL IP!\n"); + LOGIN_LOG(" But, you refuse ALL IP!\n"_fmt); } else { if (access_allow.size() == 1 && access_allow.front().mask() == IP4Address()) { - LOGIN_LOG(" You authorise ALL IP.\n"); + LOGIN_LOG(" You authorise ALL IP.\n"_fmt); } else { - LOGIN_LOG(" Authorised IP are:\n"); + LOGIN_LOG(" Authorised IP are:\n"_fmt); for (IP4Mask ae : access_allow) - LOGIN_LOG(" %s\n", ae); + LOGIN_LOG(" %s\n"_fmt, ae); } - LOGIN_LOG(" Refused IP are:\n"); + LOGIN_LOG(" Refused IP are:\n"_fmt); for (IP4Mask ae : access_deny) - LOGIN_LOG(" %s\n", ae); + LOGIN_LOG(" %s\n"_fmt, ae); } } } @@ -3841,7 +3867,7 @@ void term_func(void) } delete_session(login_session); - LOGIN_LOG("----End of login-server (normal end with closing of all files).\n"); + LOGIN_LOG("----End of login-server (normal end with closing of all files).\n"_fmt); } static @@ -3867,20 +3893,20 @@ int do_init(Slice<ZString> argv) ZString argvi = argv.pop_front(); if (argvi.startswith('-')) { - if (argvi == "--help") + if (argvi == "--help"_s) { - PRINTF("Usage: %s [--help] [--version] [files...]\n", + PRINTF("Usage: %s [--help] [--version] [files...]\n"_fmt, argv0); exit(0); } - else if (argvi == "--version") + else if (argvi == "--version"_s) { - PRINTF("%s\n", CURRENT_VERSION_STRING); + PRINTF("%s\n"_fmt, CURRENT_VERSION_STRING); exit(0); } else { - FPRINTF(stderr, "Unknown argument: %s\n", argvi); + FPRINTF(stderr, "Unknown argument: %s\n"_fmt, argvi); runflag = false; } } @@ -3892,7 +3918,7 @@ int do_init(Slice<ZString> argv) } if (!loaded_config_yet) - runflag &= load_config_file("conf/tmwa-login.conf", login_confs); + runflag &= load_config_file("conf/tmwa-login.conf"_s, login_confs); // not in login_config_read, because we can use 'import' option, and display same message twice or more // (why is that bad?) @@ -3910,17 +3936,17 @@ int do_init(Slice<ZString> argv) read_gm_account(); mmo_auth_init(); // set_termfunc (mmo_auth_sync); - login_session = make_listen_port(login_port, SessionParsers{func_parse: parse_login, func_delete: delete_login}); + login_session = make_listen_port(login_port, SessionParsers{.func_parse= parse_login, .func_delete= delete_login}); - Timer(gettick() + std::chrono::minutes(5), + Timer(gettick() + 5_min, check_auth_sync, - std::chrono::minutes(5) + 5_min ).detach(); if (anti_freeze_enable > 0) { - Timer(gettick() + std::chrono::seconds(1), + Timer(gettick() + 1_s, char_anti_freeze_system, anti_freeze_interval ).detach(); @@ -3929,16 +3955,17 @@ int do_init(Slice<ZString> argv) // add timer to check GM accounts file modification std::chrono::seconds j = gm_account_filename_check_timer; if (j == interval_t::zero()) - j = std::chrono::minutes(1); + j = 1_min; Timer(gettick() + j, check_GM_file, j).detach(); - LOGIN_LOG("The login-server is ready (Server is listening on the port %d).\n", - login_port); + LOGIN_LOG("The login-server is ready (Server is listening on the port %d).\n"_fmt, + login_port); - PRINTF("The login-server is " SGR_BOLD SGR_GREEN "ready" SGR_RESET " (Server is listening on the port %d).\n\n", - login_port); + PRINTF("The login-server is " SGR_BOLD SGR_GREEN "ready" SGR_RESET " (Server is listening on the port %d).\n\n"_fmt, + login_port); return 0; } +} // namespace tmwa diff --git a/src/login/login.hpp b/src/login/login.hpp index 3458dab..92f3c76 100644 --- a/src/login/login.hpp +++ b/src/login/login.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_LOGIN_LOGIN_HPP -#define TMWA_LOGIN_LOGIN_HPP +#pragma once // login.hpp - dummy header to make Make dependencies work. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,6 +18,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -#endif // TMWA_LOGIN_LOGIN_HPP +#include "login.t.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/map/magic-interpreter-aux.hpp b/src/login/login.t.hpp index 1369b38..f2c775a 100644 --- a/src/map/magic-interpreter-aux.hpp +++ b/src/login/login.t.hpp @@ -1,7 +1,7 @@ -#ifndef TMWA_MAP_MAGIC_INTERPRETER_AUX_HPP -#define TMWA_MAP_MAGIC_INTERPRETER_AUX_HPP -// magic-interpreter-aux.hpp - Edge of the magic system. +#pragma once +// login.t.hpp - externally useful types from login // +// Copyright © ????-2004 Athena Dev Teams // Copyright © 2004-2011 The Mana World Development Team // Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> // @@ -20,14 +20,25 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "magic-interpreter.t.hpp" +#include <cstdint> -template<class T> -bool CHECK_TYPE(T *v, TYPE t) +#include "../generic/enum.hpp" + + +namespace tmwa +{ +namespace e { - return v->ty == t; +enum class VERSION_2 : uint8_t +{ + /// client supports updatehost + UPDATEHOST = 0x01, + /// send servers in forward order + SERVERORDER = 0x02, +}; +ENUM_BITWISE_OPERATORS(VERSION_2) } - -#endif // TMWA_MAP_MAGIC_INTERPRETER_AUX_HPP +using e::VERSION_2; +} // namespace tmwa diff --git a/src/login/main.cpp b/src/login/main.cpp index 5d51212..b1eb8dd 100644 --- a/src/login/main.cpp +++ b/src/login/main.cpp @@ -1,4 +1,3 @@ -#include "login.hpp" // login/main.cpp - dummy file to make Make dependencies work // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -18,4 +17,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include "login.hpp" + #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/main-gdb-head.py b/src/main-gdb-head.py index 8c6fe08..d8f2001 100644 --- a/src/main-gdb-head.py +++ b/src/main-gdb-head.py @@ -5,7 +5,7 @@ # gdb sticks everything in one scope. # This lets us enumerate what *we* added. -initial_globals = {id(v):v for v in globals().itervalues()} +initial_globals = {id(v):v for v in globals().values()} import re @@ -32,8 +32,8 @@ def get_basic_type(type_): def finish(): global finish, initial_globals, FastPrinters - final_globals = {id(v):v for v in globals().itervalues()} - diff = final_globals.viewkeys() - initial_globals.viewkeys() \ + final_globals = {id(v):v for v in globals().values()} + diff = final_globals.keys() - initial_globals.keys() \ - {'finish', 'initial_globals', 'FastPrinters'} fp = FastPrinters() @@ -67,7 +67,7 @@ class FastPrinters(object): @property def subprinters(self): - return self.printers.values() + return list(self.printers.values()) def strip_templates(self, name, __pattern=re.compile('<[^<>]*>')): # TODO what about '<' and '>' as non-type template parameters? diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 240df8b..11f6eb1 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -20,10 +20,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <cmath> -#include <cstring> #include <ctime> +#include <algorithm> + #include "../conf/version.hpp" #include "../compat/nullpo.hpp" @@ -35,19 +35,23 @@ #include "../strings/xstring.hpp" #include "../strings/vstring.hpp" +#include "../generic/db.hpp" #include "../generic/random.hpp" #include "../io/cxxstdio.hpp" #include "../io/read.hpp" #include "../io/write.hpp" +#include "../net/socket.hpp" +#include "../net/timer.hpp" + #include "../mmo/config_parse.hpp" #include "../mmo/core.hpp" #include "../mmo/extract.hpp" #include "../mmo/human_time_diff.hpp" +#include "../mmo/ids.hpp" #include "../mmo/mmo.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" +#include "../mmo/utils.hpp" #include "../mmo/version.hpp" #include "battle.hpp" @@ -60,7 +64,6 @@ #include "npc.hpp" #include "party.hpp" #include "pc.hpp" -#include "script.hpp" #include "skill.hpp" #include "storage.hpp" #include "tmw.hpp" @@ -69,6 +72,8 @@ #include "../poison.hpp" +namespace tmwa +{ enum class ATCE { OKAY, @@ -81,12 +86,12 @@ enum class ATCE struct AtCommandInfo { ZString args; - int level; + GmLevel level; ATCE (*proc)(Session *s, dumb_ptr<map_session_data> sd, ZString message); ZString help; - AtCommandInfo(ZString a, int l, ATCE (*p)(Session *s, dumb_ptr<map_session_data>, ZString), ZString h) - : args(a), level(l), proc(p), help(h) + AtCommandInfo(ZString a, uint32_t l, ATCE (*p)(Session *s, dumb_ptr<map_session_data>, ZString), ZString h) + : args(a), level(GmLevel::from(l)), proc(p), help(h) {} }; @@ -121,23 +126,23 @@ void atcommand_config_write(ZString cfgName) if (!out.is_open()) { - FPRINTF(stderr, "Failed to write atcommand config: %s\n", cfgName); + FPRINTF(stderr, "Failed to write atcommand config: %s\n"_fmt, cfgName); return; } - FPRINTF(out, "// Generated by %s\n", CURRENT_VERSION_STRING); + FPRINTF(out, "// Generated by %s\n"_fmt, CURRENT_VERSION_STRING); for (const auto& pair : atcommand_info) { // This XString is really a ZString, but not declared as one // in order to allow non-heterogenous lookup by XString. - const char *cmd = &*pair.first.begin(); + auto cmd = ZString(strings::really_construct_from_a_pointer, &*pair.first.begin(), nullptr); const AtCommandInfo& info = pair.second; FPRINTF(out, "\n" "// %s\n" "// Usage: @%s %s\n" - "%s: %d\n", + "%s: %d\n"_fmt, info.help, cmd, info.args, cmd, info.level); @@ -198,8 +203,8 @@ void log_atcommand(dumb_ptr<map_session_data> sd, ZString cmd) stamp_time(tmpstr); MapName map = (sd->bl_m ? sd->bl_m->name_ - : stringish<MapName>("undefined.gat")); - FPRINTF(*fp, "[%s] %s(%d,%d) %s(%d) : %s\n", + : stringish<MapName>("undefined.gat"_s)); + FPRINTF(*fp, "[%s] %s(%d,%d) %s(%d) : %s\n"_fmt, tmpstr, map, sd->bl_x, sd->bl_y, sd->status_key.name, sd->status_key.account_id, @@ -211,7 +216,7 @@ AString gm_log; io::AppendFile *get_gm_log() { if (!gm_log) - return NULL; + return nullptr; struct tm ctime = TimeT::now(); @@ -225,7 +230,7 @@ io::AppendFile *get_gm_log() return gm_logfile.get(); last_logfile_nr = logfile_nr; - AString fullname = STRPRINTF("%s.%04d-%02d", + AString fullname = STRPRINTF("%s.%04d-%02d"_fmt, gm_log, year, month); if (gm_logfile) @@ -242,7 +247,7 @@ io::AppendFile *get_gm_log() } bool is_atcommand(Session *s, dumb_ptr<map_session_data> sd, - ZString message, int gmlvl) + ZString message, GmLevel gmlvl) { nullpo_retr(false, sd); @@ -259,22 +264,22 @@ bool is_atcommand(Session *s, dumb_ptr<map_session_data> sd, gmlvl = pc_isGM(sd); if (battle_config.atcommand_gm_only != 0 && !gmlvl) { - AString output = STRPRINTF("GM command is level 0, but this server disables level 0 commands: %s", + AString output = STRPRINTF("GM command is level 0, but this server disables level 0 commands: %s"_fmt, AString(command)); clif_displaymessage(s, output); return true; } if (!info) { - AString output = STRPRINTF("GM command not found: %s", + AString output = STRPRINTF("GM command not found: %s"_fmt, AString(command)); clif_displaymessage(s, output); return true; // don't show in chat } - if (info->level > gmlvl) + if (!(gmlvl.satisfies(info->level))) { - AString output = STRPRINTF("GM command is level %d, but you are level %d: %s", + AString output = STRPRINTF("GM command is level %d, but you are level %d: %s"_fmt, info->level, gmlvl, AString(command)); clif_displaymessage(s, output); @@ -292,17 +297,17 @@ bool is_atcommand(Session *s, dumb_ptr<map_session_data> sd, log_atcommand(sd, message); break; case ATCE::USAGE: - clif_displaymessage(s, "Command failed: usage error"); - clif_displaymessage(s, STRPRINTF("Usage: %s %s", AString(command), info->args)); + clif_displaymessage(s, "Command failed: usage error"_s); + clif_displaymessage(s, STRPRINTF("Usage: %s %s"_fmt, AString(command), info->args)); break; case ATCE::EXIST: - clif_displaymessage(s, "Command failed: something does not exist (or already exists)"); + clif_displaymessage(s, "Command failed: something does not exist (or already exists)"_s); break; case ATCE::RANGE: - clif_displaymessage(s, "Command failed: value out of range"); + clif_displaymessage(s, "Command failed: value out of range"_s); break; case ATCE::PERM: - clif_displaymessage(s, "Command failed: permission denied"); + clif_displaymessage(s, "Command failed: permission denied"_s); break; default: abort(); @@ -331,7 +336,7 @@ void atkillmonster_sub(dumb_ptr<block_list> bl, int flag) dumb_ptr<mob_data> md = bl->is_mob(); if (flag) - mob_damage(NULL, md, md->hp, 2); + mob_damage(nullptr, md, md->hp, 2); else mob_delete(md); } @@ -347,7 +352,7 @@ bool atcommand_config_read(ZString cfgName) io::ReadFile in(cfgName); if (!in.is_open()) { - PRINTF("At commands configuration file not found: %s\n", cfgName); + PRINTF("At commands configuration file not found: %s\n"_fmt, cfgName); return false; } @@ -361,24 +366,20 @@ bool atcommand_config_read(ZString cfgName) ZString w2; if (!config_split(line, &w1, &w2)) { - PRINTF("Bad config line: %s\n", line); + PRINTF("Bad config line: %s\n"_fmt, line); rv = false; continue; } AtCommandInfo *p = get_atcommandinfo_byname(w1); - if (p != NULL) + if (p != nullptr) { - p->level = atoi(w2.c_str()); - if (p->level > 100) - p->level = 100; - else if (p->level < 0) - p->level = 0; + p->level = GmLevel::from(static_cast<uint32_t>(atoi(w2.c_str()))); } - else if (w1 == "import") + else if (w1 == "import"_s) rv &= atcommand_config_read(w2); else { - PRINTF("%s: bad line: %s\n", cfgName, line); + PRINTF("%s: bad line: %s\n"_fmt, cfgName, line); rv = false; } } @@ -389,14 +390,16 @@ bool atcommand_config_read(ZString cfgName) /// @ command processing functions static -void atc_do_help(Session *s, const char *cmd, const AtCommandInfo& info) +void atc_do_help(Session *s, ZString cmd, const AtCommandInfo& info) { - auto msg = STRPRINTF("\u2007\u2007%d: @%s %s", info.level, cmd, info.args); + // TODO convert to hex or something + uint32_t level = info.level.get_all_bits(); + auto msg = STRPRINTF("\u2007\u2007%d: @%s %s"_fmt, info.level, cmd, info.args); // manually padding because *space* size_t ll = 1; - if (info.level >= 10) + if (level >= 10) ++ll; - if (info.level >= 100) + if (level >= 100) ++ll; clif_displaymessage(s, msg.xslice_t((ll - 1) * 3)); } @@ -407,9 +410,9 @@ ATCE atcommand_help(Session *s, dumb_ptr<map_session_data>, { if (!message) { - clif_displaymessage(s, "There is too much help to display it all at once"); - clif_displaymessage(s, "Try @help <@command> or @help <category> or @help <level[-level]>"); - clif_displaymessage(s, "Right now the only category is 'all'"); + clif_displaymessage(s, "There is too much help to display it all at once"_s); + clif_displaymessage(s, "Try @help <@command> or @help <category> or @help <level[-level]>"_s); + clif_displaymessage(s, "Right now the only category is 'all'"_s); return ATCE::OKAY; } @@ -419,37 +422,51 @@ ATCE atcommand_help(Session *s, dumb_ptr<map_session_data>, const AtCommandInfo *info = atcommand_info.search(cmd); if (!info) return ATCE::EXIST; - clif_displaymessage(s, STRPRINTF("Usage: @%s %s", cmd, info->args)); + clif_displaymessage(s, STRPRINTF("Usage: @%s %s"_fmt, cmd, info->args)); clif_displaymessage(s, info->help); return ATCE::OKAY; } - if (message == "all") + if (message == "all"_s) { - clif_displaymessage(s, "Synopses of GM commands in category 'all':"); + clif_displaymessage(s, "Synopses of GM commands in category 'all':"_s); for (const auto& pair : atcommand_info) { - const char *cmd = &*pair.first.begin(); + auto cmd = ZString(strings::really_construct_from_a_pointer, &*pair.first.begin(), nullptr); const AtCommandInfo& info = pair.second; atc_do_help(s, cmd, info); } return ATCE::OKAY; } - int low = 0, high; + // previous logic is silly + // + // @help N: list all commands available at level N + // @help M-N: list all commands available at level N that were not at level M + GmLevel low, high; + bool pass; if (extract(message, &high)) - ++high; - else if (!extract(message, record<'-'>(&low, &high))) + { + pass = true; + } + else if (extract(message, record<'-'>(&low, &high))) + { + pass = false; + } + else return ATCE::USAGE; - if (low < 0 || high > 100 || low >= high) + if (low.obsoletes(high)) return ATCE::RANGE; - clif_displaymessage(s, STRPRINTF("Synopses of GM commands in level [%d, %d):", low, high)); + if (pass) + clif_displaymessage(s, STRPRINTF("Synopses of GM commands available at level %u:"_fmt, high)); + else + clif_displaymessage(s, STRPRINTF("Synopses of GM commands available at level %u, but not at level %u:"_fmt, high, low)); for (const auto& pair : atcommand_info) { - const char *cmd = &*pair.first.begin(); + auto cmd = ZString(strings::really_construct_from_a_pointer, &*pair.first.begin(), nullptr); const AtCommandInfo& info = pair.second; - if (low <= info.level && info.level < high) + if ((!low.satisfies(info.level) || pass) && high.satisfies(info.level)) atc_do_help(s, cmd, info); } return ATCE::OKAY; @@ -467,25 +484,25 @@ ATCE atcommand_setup(Session *s, dumb_ptr<map_session_data> sd, level--; AString buf; - buf = STRPRINTF("-255 %s", character); + buf = STRPRINTF("-255 %s"_fmt, character); atcommand_character_baselevel(s, sd, buf); - buf = STRPRINTF("%d %s", level, character); + buf = STRPRINTF("%d %s"_fmt, level, character); atcommand_character_baselevel(s, sd, buf); // Emote skill - buf = STRPRINTF("1 1 %s", character); + buf = STRPRINTF("1 1 %s"_fmt, character); atcommand_skill_learn(s, sd, buf); // Trade skill - buf = STRPRINTF("2 1 %s", character); + buf = STRPRINTF("2 1 %s"_fmt, character); atcommand_skill_learn(s, sd, buf); // Party skill - STRPRINTF("2 2 %s", character); + STRPRINTF("2 2 %s"_fmt, character); atcommand_skill_learn(s, sd, buf); - STRPRINTF("018-1.gat 24 98 %s", character); + STRPRINTF("018-1.gat 24 98 %s"_fmt, character); atcommand_charwarp(s, sd, buf); return ATCE::OKAY; @@ -510,52 +527,52 @@ ATCE atcommand_charwarp(Session *s, dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); if (pl_sd) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can rura+ only lower or same GM level if (x > 0 && x < 800 && y > 0 && y < 800) { map_local *m = map_mapname2mapid(map_name); if (m != nullptr && m->flag.get(MapFlag::NOWARPTO) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level)))) { clif_displaymessage(s, - "You are not authorised to warp someone to this map."); + "You are not authorised to warp someone to this map."_s); return ATCE::PERM; } if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARP) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp this player from its actual map."); + "You are not authorised to warp this player from its actual map."_s); return ATCE::PERM; } if (pc_setpos(pl_sd, map_name, x, y, BeingRemoveWhy::WARPED) == 0) { - clif_displaymessage(pl_sd->sess, "Warped."); - clif_displaymessage(s, "Player warped (message sends to player too)."); + clif_displaymessage(pl_sd->sess, "Warped."_s); + clif_displaymessage(s, "Player warped (message sends to player too)."_s); } else { - clif_displaymessage(s, "Map not found."); + clif_displaymessage(s, "Map not found."_s); return ATCE::EXIST; } } else { - clif_displaymessage(s, "Coordinates out of range."); + clif_displaymessage(s, "Coordinates out of range."_s); return ATCE::RANGE; } } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -573,7 +590,7 @@ ATCE atcommand_warp(Session *s, dumb_ptr<map_session_data> sd, || !extract(message, record<' ', 1>(&map_name, &x, &y))) { clif_displaymessage(s, - "Please, enter a map (usage: @warp <mapname> <x> <y>)."); + "Please, enter a map (usage: @warp <mapname> <x> <y>)."_s); return ATCE::USAGE; } @@ -586,30 +603,30 @@ ATCE atcommand_warp(Session *s, dumb_ptr<map_session_data> sd, { map_local *m = map_mapname2mapid(map_name); if (m != nullptr && m->flag.get(MapFlag::NOWARPTO) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp you to this map."); + "You are not authorised to warp you to this map."_s); return ATCE::PERM; } if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARP) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp you from your actual map."); + "You are not authorised to warp you from your actual map."_s); return ATCE::PERM; } if (pc_setpos(sd, map_name, x, y, BeingRemoveWhy::WARPED) == 0) - clif_displaymessage(s, "Warped."); + clif_displaymessage(s, "Warped."_s); else { - clif_displaymessage(s, "Map not found."); + clif_displaymessage(s, "Map not found."_s); return ATCE::EXIST; } } else { - clif_displaymessage(s, "Coordinates out of range."); + clif_displaymessage(s, "Coordinates out of range."_s); return ATCE::RANGE; } @@ -624,20 +641,20 @@ ATCE atcommand_where(Session *s, dumb_ptr<map_session_data> sd, extract(message, &character); dumb_ptr<map_session_data> pl_sd = character.to__actual() ? map_nick2sd(character) : sd; - if (pl_sd != NULL && + if (pl_sd != nullptr && !((battle_config.hide_GM_session || bool(pl_sd->status.option & Option::HIDE)) - && (pc_isGM(pl_sd) > pc_isGM(sd)))) + && !(pc_isGM(sd).detects(pc_isGM(pl_sd))))) { // you can look only lower or same level - AString output = STRPRINTF("%s: %s (%d,%d)", + AString output = STRPRINTF("%s: %s (%d,%d)"_fmt, pl_sd->status_key.name, pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y); clif_displaymessage(s, output); } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -653,34 +670,34 @@ ATCE atcommand_goto(Session *s, dumb_ptr<map_session_data> sd, if (!asplit(message, &character)) { clif_displaymessage(s, - "Please, enter a player name (usage: @jumpto/@warpto/@goto <char name>)."); + "Please, enter a player name (usage: @jumpto/@warpto/@goto <char name>)."_s); return ATCE::USAGE; } dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARPTO) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp you to the map of this player."); + "You are not authorised to warp you to the map of this player."_s); return ATCE::PERM; } if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARP) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp you from your actual map."); + "You are not authorised to warp you from your actual map."_s); return ATCE::PERM; } pc_setpos(sd, pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y, BeingRemoveWhy::WARPED); - AString output = STRPRINTF("Jump to %s", character); + AString output = STRPRINTF("Jump to %s"_fmt, character); clif_displaymessage(s, output); } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -702,26 +719,26 @@ ATCE atcommand_jump(Session *s, dumb_ptr<map_session_data> sd, if (x > 0 && x < 800 && y > 0 && y < 800) { if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARPTO) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp you to your actual map."); + "You are not authorised to warp you to your actual map."_s); return ATCE::PERM; } if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARP) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp you from your actual map."); + "You are not authorised to warp you from your actual map."_s); return ATCE::PERM; } pc_setpos(sd, sd->mapname_, x, y, BeingRemoveWhy::WARPED); - AString output = STRPRINTF("Jump to %d %d", x, y); + AString output = STRPRINTF("Jump to %d %d"_fmt, x, y); clif_displaymessage(s, output); } else { - clif_displaymessage(s, "Coordinates out of range."); + clif_displaymessage(s, "Coordinates out of range."_s); return ATCE::RANGE; } @@ -733,12 +750,11 @@ ATCE atcommand_who(Session *s, dumb_ptr<map_session_data> sd, ZString message) { int count; - int pl_GM_level, GM_level; VString<23> match_text = message; match_text = match_text.to_lower(); count = 0; - GM_level = pc_isGM(sd); + GmLevel gm_level = pc_isGM(sd); for (io::FD i : iter_fds()) { Session *s2 = get_session(i); @@ -747,11 +763,11 @@ ATCE atcommand_who(Session *s, dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get())); if (pl_sd && pl_sd->state.auth) { - pl_GM_level = pc_isGM(pl_sd); + GmLevel pl_gm_level = pc_isGM(pl_sd); if (! ((battle_config.hide_GM_session || bool(pl_sd->status.option & Option::HIDE)) - && (pl_GM_level > GM_level))) + && !(gm_level.detects(pl_gm_level)))) { // you can look only lower or same level VString<23> player_name = pl_sd->status_key.name.to__lower(); @@ -759,14 +775,14 @@ ATCE atcommand_who(Session *s, dumb_ptr<map_session_data> sd, { // search with no case sensitive AString output; - if (pl_GM_level > 0) + if (pl_gm_level) output = STRPRINTF( - "Name: %s (GM:%d) | Location: %s %d %d", - pl_sd->status_key.name, pl_GM_level, + "Name: %s (GM:%u) | Location: %s %d %d"_fmt, + pl_sd->status_key.name, pl_gm_level, pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y); else output = STRPRINTF( - "Name: %s | Location: %s %d %d", + "Name: %s | Location: %s %d %d"_fmt, pl_sd->status_key.name, pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y); clif_displaymessage(s, output); @@ -777,12 +793,12 @@ ATCE atcommand_who(Session *s, dumb_ptr<map_session_data> sd, } if (count == 0) - clif_displaymessage(s, "No player found."); + clif_displaymessage(s, "No player found."_s); else if (count == 1) - clif_displaymessage(s, "1 player found."); + clif_displaymessage(s, "1 player found."_s); else { - AString output = STRPRINTF("%d players found.", count); + AString output = STRPRINTF("%d players found."_fmt, count); clif_displaymessage(s, output); } @@ -794,14 +810,13 @@ ATCE atcommand_whogroup(Session *s, dumb_ptr<map_session_data> sd, ZString message) { int count; - int pl_GM_level, GM_level; - struct party *p; + PartyPair p; VString<23> match_text = message; match_text = match_text.to_lower(); count = 0; - GM_level = pc_isGM(sd); + GmLevel gm_level = pc_isGM(sd); for (io::FD i : iter_fds()) { Session *s2 = get_session(i); @@ -810,11 +825,11 @@ ATCE atcommand_whogroup(Session *s, dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get())); if (pl_sd && pl_sd->state.auth) { - pl_GM_level = pc_isGM(pl_sd); + GmLevel pl_gm_level = pc_isGM(pl_sd); if (! ((battle_config.hide_GM_session || bool(pl_sd->status.option & Option::HIDE)) - && (pl_GM_level > GM_level))) + && (!(gm_level.detects(pl_gm_level))))) { // you can look only lower or same level VString<23> player_name = pl_sd->status_key.name.to__lower(); @@ -822,12 +837,12 @@ ATCE atcommand_whogroup(Session *s, dumb_ptr<map_session_data> sd, { // search with no case sensitive p = party_search(pl_sd->status.party_id); - PartyName temp0 = p ? p->name : stringish<PartyName>("None"); + PartyName temp0 = p ? p->name : stringish<PartyName>("None"_s); AString output; - if (pl_GM_level > 0) + if (pl_gm_level) output = STRPRINTF( - "Name: %s (GM:%d) | Party: '%s'", - pl_sd->status_key.name, pl_GM_level, temp0); + "Name: %s (GM:%d) | Party: '%s'"_fmt, + pl_sd->status_key.name, pl_gm_level, temp0); clif_displaymessage(s, output); count++; } @@ -836,12 +851,12 @@ ATCE atcommand_whogroup(Session *s, dumb_ptr<map_session_data> sd, } if (count == 0) - clif_displaymessage(s, "No player found."); + clif_displaymessage(s, "No player found."_s); else if (count == 1) - clif_displaymessage(s, "1 player found."); + clif_displaymessage(s, "1 player found."_s); else { - AString output = STRPRINTF("%d players found.", count); + AString output = STRPRINTF("%d players found."_fmt, count); clif_displaymessage(s, output); } @@ -853,7 +868,6 @@ ATCE atcommand_whomap(Session *s, dumb_ptr<map_session_data> sd, ZString message) { int count; - int pl_GM_level, GM_level; map_local *map_id; { @@ -865,7 +879,7 @@ ATCE atcommand_whomap(Session *s, dumb_ptr<map_session_data> sd, } count = 0; - GM_level = pc_isGM(sd); + GmLevel gm_level = pc_isGM(sd); for (io::FD i : iter_fds()) { Session *s2 = get_session(i); @@ -874,24 +888,24 @@ ATCE atcommand_whomap(Session *s, dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get())); if (pl_sd && pl_sd->state.auth) { - pl_GM_level = pc_isGM(pl_sd); + GmLevel pl_gm_level = pc_isGM(pl_sd); if (! ((battle_config.hide_GM_session || bool(pl_sd->status.option & Option::HIDE)) - && (pl_GM_level > GM_level))) + && (!(gm_level.detects(pl_gm_level))))) { // you can look only lower or same level if (pl_sd->bl_m == map_id) { AString output; - if (pl_GM_level > 0) + if (pl_gm_level) output = STRPRINTF( - "Name: %s (GM:%d) | Location: %s %d %d", - pl_sd->status_key.name, pl_GM_level, + "Name: %s (GM:%d) | Location: %s %d %d"_fmt, + pl_sd->status_key.name, pl_gm_level, pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y); else output = STRPRINTF( - "Name: %s | Location: %s %d %d", + "Name: %s | Location: %s %d %d"_fmt, pl_sd->status_key.name, pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y); clif_displaymessage(s, output); @@ -901,7 +915,7 @@ ATCE atcommand_whomap(Session *s, dumb_ptr<map_session_data> sd, } } - AString output = STRPRINTF("%d players found in map '%s'.", + AString output = STRPRINTF("%d players found in map '%s'."_fmt, count, map_id->name_); clif_displaymessage(s, output); @@ -913,8 +927,7 @@ ATCE atcommand_whomapgroup(Session *s, dumb_ptr<map_session_data> sd, ZString message) { int count; - int pl_GM_level, GM_level; - struct party *p; + PartyPair p; map_local *map_id; { @@ -926,7 +939,7 @@ ATCE atcommand_whomapgroup(Session *s, dumb_ptr<map_session_data> sd, } count = 0; - GM_level = pc_isGM(sd); + GmLevel gm_level = pc_isGM(sd); for (io::FD i : iter_fds()) { Session *s2 = get_session(i); @@ -935,23 +948,23 @@ ATCE atcommand_whomapgroup(Session *s, dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get())); if (pl_sd && pl_sd->state.auth) { - pl_GM_level = pc_isGM(pl_sd); + GmLevel pl_gm_level = pc_isGM(pl_sd); if (! ((battle_config.hide_GM_session || bool(pl_sd->status.option & Option::HIDE)) - && (pl_GM_level > GM_level))) + && (!(gm_level.detects(pl_gm_level))))) { // you can look only lower or same level if (pl_sd->bl_m == map_id) { p = party_search(pl_sd->status.party_id); - PartyName temp0 = p ? p->name : stringish<PartyName>("None"); + PartyName temp0 = p ? p->name : stringish<PartyName>("None"_s); AString output; - if (pl_GM_level > 0) - output = STRPRINTF("Name: %s (GM:%d) | Party: '%s'", - pl_sd->status_key.name, pl_GM_level, temp0); + if (pl_gm_level) + output = STRPRINTF("Name: %s (GM:%d) | Party: '%s'"_fmt, + pl_sd->status_key.name, pl_gm_level, temp0); else - output = STRPRINTF("Name: %s | Party: '%s'", + output = STRPRINTF("Name: %s | Party: '%s'"_fmt, pl_sd->status_key.name, temp0); clif_displaymessage(s, output); count++; @@ -962,12 +975,12 @@ ATCE atcommand_whomapgroup(Session *s, dumb_ptr<map_session_data> sd, AString output; if (count == 0) - output = STRPRINTF("No player found in map '%s'.", map_id->name_); + output = STRPRINTF("No player found in map '%s'."_fmt, map_id->name_); else if (count == 1) - output = STRPRINTF("1 player found in map '%s'.", map_id->name_); + output = STRPRINTF("1 player found in map '%s'."_fmt, map_id->name_); else { - output = STRPRINTF("%d players found in map '%s'.", count, map_id->name_); + output = STRPRINTF("%d players found in map '%s'."_fmt, count, map_id->name_); } clif_displaymessage(s, output); @@ -979,14 +992,13 @@ ATCE atcommand_whogm(Session *s, dumb_ptr<map_session_data> sd, ZString message) { int count; - int pl_GM_level, GM_level; - struct party *p; + PartyPair p; VString<23> match_text = message; match_text = match_text.to_lower(); count = 0; - GM_level = pc_isGM(sd); + GmLevel gm_level = pc_isGM(sd); for (io::FD i : iter_fds()) { Session *s2 = get_session(i); @@ -995,13 +1007,13 @@ ATCE atcommand_whogm(Session *s, dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get())); if (pl_sd && pl_sd->state.auth) { - pl_GM_level = pc_isGM(pl_sd); - if (pl_GM_level > 0) + GmLevel pl_gm_level = pc_isGM(pl_sd); + if (pl_gm_level) { if (! ((battle_config.hide_GM_session || bool(pl_sd->status.option & Option::HIDE)) - && (pl_GM_level > GM_level))) + && (!(gm_level.detects(pl_gm_level))))) { // you can look only lower or same level VString<23> player_name = pl_sd->status_key.name.to__lower(); @@ -1010,20 +1022,20 @@ ATCE atcommand_whogm(Session *s, dumb_ptr<map_session_data> sd, // search with no case sensitive AString output; output = STRPRINTF( - "Name: %s (GM:%d) | Location: %s %d %d", - pl_sd->status_key.name, pl_GM_level, + "Name: %s (GM:%d) | Location: %s %d %d"_fmt, + pl_sd->status_key.name, pl_gm_level, pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y); clif_displaymessage(s, output); output = STRPRINTF( - " BLvl: %d | Job: %s (Lvl: %d)", + " BLvl: %d | Job: %s (Lvl: %d)"_fmt, pl_sd->status.base_level, - "Novice/Human", + "Novice/Human"_s, pl_sd->status.job_level); clif_displaymessage(s, output); p = party_search(pl_sd->status.party_id); - PartyName temp0 = p ? p->name : stringish<PartyName>("None"); + PartyName temp0 = p ? p->name : stringish<PartyName>("None"_s); output = STRPRINTF( - " Party: '%s'", + " Party: '%s'"_fmt, temp0); clif_displaymessage(s, output); count++; @@ -1034,12 +1046,12 @@ ATCE atcommand_whogm(Session *s, dumb_ptr<map_session_data> sd, } if (count == 0) - clif_displaymessage(s, "No GM found."); + clif_displaymessage(s, "No GM found."_s); else if (count == 1) - clif_displaymessage(s, "1 GM found."); + clif_displaymessage(s, "1 GM found."_s); else { - AString output = STRPRINTF("%d GMs found.", count); + AString output = STRPRINTF("%d GMs found."_fmt, count); clif_displaymessage(s, output); } @@ -1053,7 +1065,7 @@ ATCE atcommand_save(Session *s, dumb_ptr<map_session_data> sd, pc_setsavepoint(sd, sd->mapname_, sd->bl_x, sd->bl_y); pc_makesavestatus(sd); chrif_save(sd); - clif_displaymessage(s, "Character data respawn point saved."); + clif_displaymessage(s, "Character data respawn point saved."_s); return ATCE::OKAY; } @@ -1064,17 +1076,17 @@ ATCE atcommand_load(Session *s, dumb_ptr<map_session_data> sd, { map_local *m = map_mapname2mapid(sd->status.save_point.map_); if (m != nullptr && m->flag.get(MapFlag::NOWARPTO) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp you to your save map."); + "You are not authorised to warp you to your save map."_s); return ATCE::PERM; } if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARP) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp you from your actual map."); + "You are not authorised to warp you from your actual map."_s); return ATCE::PERM; } @@ -1089,7 +1101,7 @@ ATCE atcommand_load(Session *s, dumb_ptr<map_session_data> sd, pc_setpos(sd, sd->status.save_point.map_, sd->status.save_point.x, sd->status.save_point.y, BeingRemoveWhy::GONE); } - clif_displaymessage(s, "Warping to respawn point."); + clif_displaymessage(s, "Warping to respawn point."_s); return ATCE::OKAY; } @@ -1101,7 +1113,7 @@ ATCE atcommand_speed(Session *s, dumb_ptr<map_session_data> sd, if (!message) { AString output = STRPRINTF( - "Please, enter a speed value (usage: @speed <%d-%d>).", + "Please, enter a speed value (usage: @speed <%d-%d>)."_fmt, static_cast<uint32_t>(MIN_WALK_SPEED.count()), static_cast<uint32_t>(MAX_WALK_SPEED.count())); clif_displaymessage(s, output); @@ -1115,12 +1127,12 @@ ATCE atcommand_speed(Session *s, dumb_ptr<map_session_data> sd, //sd->walktimer = x; //この文を追加 by れ clif_updatestatus(sd, SP::SPEED); - clif_displaymessage(s, "Speed changed."); + clif_displaymessage(s, "Speed changed."_s); } else { AString output = STRPRINTF( - "Please, enter a valid speed value (usage: @speed <%d-%d>).", + "Please, enter a valid speed value (usage: @speed <%d-%d>)."_fmt, static_cast<uint32_t>(MIN_WALK_SPEED.count()), static_cast<uint32_t>(MAX_WALK_SPEED.count())); clif_displaymessage(s, output); @@ -1134,18 +1146,18 @@ static ATCE atcommand_storage(Session *s, dumb_ptr<map_session_data> sd, ZString) { - struct storage *stor; + Storage *stor; if (sd->state.storage_open) { - clif_displaymessage(s, "msg_table[250]"); + clif_displaymessage(s, "msg_table[250]"_s); return ATCE::EXIST; } - if ((stor = account2storage2(sd->status_key.account_id)) != NULL + if ((stor = account2storage2(sd->status_key.account_id)) != nullptr && stor->storage_status == 1) { - clif_displaymessage(s, "msg_table[250]"); + clif_displaymessage(s, "msg_table[250]"_s); return ATCE::EXIST; } @@ -1171,7 +1183,7 @@ ATCE atcommand_option(Session *s, dumb_ptr<map_session_data> sd, clif_changeoption(sd); pc_calcstatus(sd, 0); - clif_displaymessage(s, "Options changed."); + clif_displaymessage(s, "Options changed."_s); return ATCE::OKAY; } @@ -1183,12 +1195,12 @@ ATCE atcommand_hide(Session *s, dumb_ptr<map_session_data> sd, if (bool(sd->status.option & Option::HIDE)) { sd->status.option &= ~Option::HIDE; - clif_displaymessage(s, "Invisible: Off."); + clif_displaymessage(s, "Invisible: Off."_s); } else { sd->status.option |= Option::HIDE; - clif_displaymessage(s, "Invisible: On."); + clif_displaymessage(s, "Invisible: On."_s); } clif_changeoption(sd); @@ -1199,8 +1211,8 @@ static ATCE atcommand_die(Session *s, dumb_ptr<map_session_data> sd, ZString) { - pc_damage(NULL, sd, sd->status.hp + 1); - clif_displaymessage(s, "A pity! You've died."); + pc_damage(nullptr, sd, sd->status.hp + 1); + clif_displaymessage(s, "A pity! You've died."_s); return ATCE::OKAY; } @@ -1215,23 +1227,23 @@ ATCE atcommand_kill(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can kill only lower or same level - pc_damage(NULL, pl_sd, pl_sd->status.hp + 1); - clif_displaymessage(s, "Character killed."); + pc_damage(nullptr, pl_sd, pl_sd->status.hp + 1); + clif_displaymessage(s, "Character killed."_s); } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -1250,7 +1262,7 @@ ATCE atcommand_alive(Session *s, dumb_ptr<map_session_data> sd, clif_updatestatus(sd, SP::HP); clif_updatestatus(sd, SP::SP); clif_resurrection(sd, 1); - clif_displaymessage(s, "You've been revived! It's a miracle!"); + clif_displaymessage(s, "You've been revived! It's a miracle!"_s); return ATCE::OKAY; } @@ -1304,13 +1316,13 @@ ATCE atcommand_heal(Session *s, dumb_ptr<map_session_data> sd, { pc_heal(sd, hp, sp); if (hp >= 0 && sp >= 0) - clif_displaymessage(s, "HP, SP recovered."); + clif_displaymessage(s, "HP, SP recovered."_s); else - clif_displaymessage(s, "HP or/and SP modified."); + clif_displaymessage(s, "HP or/and SP modified."_s); } else { - clif_displaymessage(s, "HP and SP are already with the good value."); + clif_displaymessage(s, "HP and SP are already with the good value."_s); return ATCE::RANGE; } @@ -1322,29 +1334,29 @@ ATCE atcommand_item(Session *s, dumb_ptr<map_session_data> sd, ZString message) { XString item_name; - int number = 0, item_id; - struct item_data *item_data = NULL; + int number = 0; + ItemNameId item_id; + struct item_data *item_data = nullptr; int get_count, i; if (!extract(message, record<' ', 1>(&item_name, &number))) { clif_displaymessage(s, - "Please, enter an item name/id (usage: @item <item name or ID> [quantity])."); + "Please, enter an item name/id (usage: @item <item name or ID> [quantity])."_s); return ATCE::USAGE; } if (number <= 0) number = 1; - item_id = 0; - if ((item_data = itemdb_searchname(item_name)) != NULL) + if ((item_data = itemdb_searchname(item_name)) != nullptr) item_id = item_data->nameid; - else if (extract(item_name, &item_id) && (item_data = itemdb_exists(item_id)) != NULL) + else if (extract(item_name, &item_id) && (item_data = itemdb_exists(item_id)) != nullptr) item_id = item_data->nameid; else - item_id = 0; + return ATCE::EXIST; - if (item_id >= 500) + if (item_id) { get_count = number; if (item_data->type == ItemType::WEAPON @@ -1356,18 +1368,18 @@ ATCE atcommand_item(Session *s, dumb_ptr<map_session_data> sd, } for (i = 0; i < number; i += get_count) { - struct item item_tmp {}; + Item item_tmp {}; item_tmp.nameid = item_id; PickupFail flag; if ((flag = pc_additem(sd, &item_tmp, get_count)) != PickupFail::OKAY) - clif_additem(sd, 0, 0, flag); + clif_additem(sd, IOff0::from(0), 0, flag); } - clif_displaymessage(s, "Item created."); + clif_displaymessage(s, "Item created."_s); } else { - clif_displaymessage(s, "Invalid item ID or name."); + clif_displaymessage(s, "Invalid item ID or name."_s); return ATCE::EXIST; } @@ -1378,15 +1390,13 @@ static ATCE atcommand_itemreset(Session *s, dumb_ptr<map_session_data> sd, ZString) { - int i; - - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == EPOS::ZERO) pc_delitem(sd, i, sd->status.inventory[i].amount, 0); } - clif_displaymessage(s, "All of your items have been removed."); + clif_displaymessage(s, "All of your items have been removed."_s); return ATCE::OKAY; } @@ -1409,7 +1419,7 @@ ATCE atcommand_baselevelup(Session *s, dumb_ptr<map_session_data> sd, if (!extract(message, &level) || !level) { clif_displaymessage(s, - "Please, enter a level adjustement (usage: @blvl <number of levels>)."); + "Please, enter a level adjustement (usage: @blvl <number of levels>)."_s); return ATCE::USAGE; } @@ -1417,7 +1427,7 @@ ATCE atcommand_baselevelup(Session *s, dumb_ptr<map_session_data> sd, { if (sd->status.base_level == battle_config.maximum_level) { - clif_displaymessage(s, "Base level can't go any higher."); + clif_displaymessage(s, "Base level can't go any higher."_s); return ATCE::RANGE; } if (level > battle_config.maximum_level || level > (battle_config.maximum_level - sd->status.base_level)) @@ -1432,13 +1442,13 @@ ATCE atcommand_baselevelup(Session *s, dumb_ptr<map_session_data> sd, pc_calcstatus(sd, 0); pc_heal(sd, sd->status.max_hp, sd->status.max_sp); clif_misceffect(sd, 0); - clif_displaymessage(s, "Base level raised."); + clif_displaymessage(s, "Base level raised."_s); } else { if (sd->status.base_level == 1) { - clif_displaymessage(s, "Base level can't go any lower."); + clif_displaymessage(s, "Base level can't go any lower."_s); return ATCE::USAGE; } if (level < -battle_config.maximum_level || level < (1 - sd->status.base_level)) @@ -1458,7 +1468,7 @@ ATCE atcommand_baselevelup(Session *s, dumb_ptr<map_session_data> sd, clif_updatestatus(sd, SP::BASELEVEL); clif_updatestatus(sd, SP::NEXTBASEEXP); pc_calcstatus(sd, 0); - clif_displaymessage(s, "Base level lowered."); + clif_displaymessage(s, "Base level lowered."_s); } return ATCE::OKAY; @@ -1481,7 +1491,7 @@ ATCE atcommand_joblevelup(Session *s, dumb_ptr<map_session_data> sd, { if (sd->status.job_level == up_level) { - clif_displaymessage(s, "Job level can't go any higher."); + clif_displaymessage(s, "Job level can't go any higher."_s); return ATCE::RANGE; } if (level > up_level || level > (up_level - sd->status.job_level)) @@ -1494,13 +1504,13 @@ ATCE atcommand_joblevelup(Session *s, dumb_ptr<map_session_data> sd, clif_updatestatus(sd, SP::SKILLPOINT); pc_calcstatus(sd, 0); clif_misceffect(sd, 1); - clif_displaymessage(s, "Job level raised."); + clif_displaymessage(s, "Job level raised."_s); } else { if (sd->status.job_level == 1) { - clif_displaymessage(s, "Job level can't go any lower."); + clif_displaymessage(s, "Job level can't go any lower."_s); return ATCE::RANGE; } if (level < -up_level || level < (1 - sd->status.job_level)) @@ -1518,7 +1528,7 @@ ATCE atcommand_joblevelup(Session *s, dumb_ptr<map_session_data> sd, } // to add: remove status points from skills pc_calcstatus(sd, 0); - clif_displaymessage(s, "Job level lowered."); + clif_displaymessage(s, "Job level lowered."_s); } return ATCE::OKAY; @@ -1534,7 +1544,7 @@ ATCE atcommand_gm(Session *s, dumb_ptr<map_session_data> sd, if (pc_isGM(sd)) { // a GM can not use this function. only a normal player (become gm is not for gm!) - clif_displaymessage(s, "You already have some GM powers."); + clif_displaymessage(s, "You already have some GM powers."_s); return ATCE::PERM; } else @@ -1550,7 +1560,7 @@ ATCE atcommand_pvpoff(Session *s, dumb_ptr<map_session_data> sd, if (battle_config.pk_mode) { //disable command if server is in PK mode [Valaris] - clif_displaymessage(s, "This option cannot be used in PK Mode."); + clif_displaymessage(s, "This option cannot be used in PK Mode."_s); return ATCE::EXIST; } @@ -1571,11 +1581,11 @@ ATCE atcommand_pvpoff(Session *s, dumb_ptr<map_session_data> sd, } } } - clif_displaymessage(s, "PvP: Off."); + clif_displaymessage(s, "PvP: Off."_s); } else { - clif_displaymessage(s, "PvP is already Off."); + clif_displaymessage(s, "PvP is already Off."_s); return ATCE::EXIST; } @@ -1589,7 +1599,7 @@ ATCE atcommand_pvpon(Session *s, dumb_ptr<map_session_data> sd, if (battle_config.pk_mode) { //disable command if server is in PK mode [Valaris] - clif_displaymessage(s, "This option cannot be used in PK Mode."); + clif_displaymessage(s, "This option cannot be used in PK Mode."_s); return ATCE::EXIST; } @@ -1606,7 +1616,7 @@ ATCE atcommand_pvpon(Session *s, dumb_ptr<map_session_data> sd, { if (sd->bl_m == pl_sd->bl_m && !pl_sd->pvp_timer) { - pl_sd->pvp_timer = Timer(gettick() + std::chrono::milliseconds(200), + pl_sd->pvp_timer = Timer(gettick() + 200_ms, std::bind(pc_calc_pvprank_timer, ph::_1, ph::_2, pl_sd->bl_id)); pl_sd->pvp_rank = 0; pl_sd->pvp_lastusers = 0; @@ -1614,11 +1624,11 @@ ATCE atcommand_pvpon(Session *s, dumb_ptr<map_session_data> sd, } } } - clif_displaymessage(s, "PvP: On."); + clif_displaymessage(s, "PvP: On."_s); } else { - clif_displaymessage(s, "PvP is already On."); + clif_displaymessage(s, "PvP is already On."_s); return ATCE::EXIST; } @@ -1642,7 +1652,7 @@ ATCE atcommand_model(Session *s, dumb_ptr<map_session_data> sd, pc_changelook(sd, LOOK::HAIR, hair_style); pc_changelook(sd, LOOK::HAIR_COLOR, hair_color); pc_changelook(sd, LOOK::CLOTHES_COLOR, cloth_color); - clif_displaymessage(s, "Appearence changed."); + clif_displaymessage(s, "Appearence changed."_s); } } else @@ -1664,7 +1674,7 @@ ATCE atcommand_dye(Session *s, dumb_ptr<map_session_data> sd, { { pc_changelook(sd, LOOK::CLOTHES_COLOR, cloth_color); - clif_displaymessage(s, "Appearence changed."); + clif_displaymessage(s, "Appearence changed."_s); } } else @@ -1686,7 +1696,7 @@ ATCE atcommand_hair_style(Session *s, dumb_ptr<map_session_data> sd, { { pc_changelook(sd, LOOK::HAIR, hair_style); - clif_displaymessage(s, "Appearence changed."); + clif_displaymessage(s, "Appearence changed."_s); } } else @@ -1708,7 +1718,7 @@ ATCE atcommand_hair_color(Session *s, dumb_ptr<map_session_data> sd, { { pc_changelook(sd, LOOK::HAIR_COLOR, hair_color); - clif_displaymessage(s, "Appearence changed."); + clif_displaymessage(s, "Appearence changed."_s); } } else @@ -1722,22 +1732,21 @@ ATCE atcommand_spawn(Session *s, dumb_ptr<map_session_data> sd, ZString message) { MobName monster; - int mob_id; + Species mob_id; int number = 0; int x = 0, y = 0; int count; - int i, j, k; int mx, my, range; if (!extract(message, record<' ', 1>(&monster, &number, &x, &y))) return ATCE::USAGE; // If monster identifier/name argument is a name - if ((mob_id = mobdb_searchname(monster)) == 0) + if ((mob_id = mobdb_searchname(monster)) == Species()) // check name first (to avoid possible name begining by a number) - mob_id = mobdb_checkid(atoi(monster.c_str())); + mob_id = mobdb_checkid(wrap<Species>(atoi(monster.c_str()))); - if (mob_id == 0) + if (mob_id == Species()) return ATCE::EXIST; if (number <= 0) @@ -1749,18 +1758,18 @@ ATCE atcommand_spawn(Session *s, dumb_ptr<map_session_data> sd, number = battle_config.atcommand_spawn_quantity_limit; if (battle_config.etc_log) - PRINTF("@spawn monster='%s' id=%d count=%d (%d,%d)\n", + PRINTF("@spawn monster='%s' id=%d count=%d (%d,%d)\n"_fmt, monster, mob_id, number, x, y); count = 0; range = sqrt(number) / 2; range = range * 2 + 5; // calculation of an odd number (+ 4 area around) - for (i = 0; i < number; i++) + for (int i = 0; i < number; i++) { - j = 0; - k = 0; - while (j++ < 8 && k == 0) + int j = 0; + BlockId k; + while (j++ < 8 && !k) { // try 8 times to spawn the monster (needed for close area) if (x <= 0) @@ -1773,21 +1782,21 @@ ATCE atcommand_spawn(Session *s, dumb_ptr<map_session_data> sd, my = y; k = mob_once_spawn(sd, MOB_THIS_MAP, mx, my, MobName(), mob_id, 1, NpcEvent()); } - count += (k != 0) ? 1 : 0; + count += k ? 1 : 0; } if (count != 0) if (number == count) - clif_displaymessage(s, "All monster summoned!"); + clif_displaymessage(s, "All monster summoned!"_s); else { - AString output = STRPRINTF("%d monster(s) summoned!", + AString output = STRPRINTF("%d monster(s) summoned!"_fmt, count); clif_displaymessage(s, output); } else { - clif_displaymessage(s, "Invalid monster ID or name."); + clif_displaymessage(s, "Invalid monster ID or name."_s); return ATCE::EXIST; } @@ -1813,7 +1822,7 @@ void atcommand_killmonster_sub(Session *s, dumb_ptr<map_session_data> sd, map_id->xs, map_id->ys, BL::MOB); - clif_displaymessage(s, "All monsters killed!"); + clif_displaymessage(s, "All monsters killed!"_s); } static @@ -1830,7 +1839,7 @@ void atlist_nearby_sub(dumb_ptr<block_list> bl, Session *s) { nullpo_retv(bl); - AString buf = STRPRINTF(" - \"%s\"", + AString buf = STRPRINTF(" - \"%s\""_fmt, bl->is_player()->status_key.name); clif_displaymessage(s, buf); } @@ -1839,7 +1848,7 @@ static ATCE atcommand_list_nearby(Session *s, dumb_ptr<map_session_data> sd, ZString) { - clif_displaymessage(s, "Nearby players:"); + clif_displaymessage(s, "Nearby players:"_s); map_foreachinarea(std::bind(atlist_nearby_sub, ph::_1, s), sd->bl_m, sd->bl_x - 1, sd->bl_y - 1, @@ -1867,7 +1876,7 @@ ATCE atcommand_gat(Session *s, dumb_ptr<map_session_data> sd, for (y = 2; y >= -2; y--) { AString output = STRPRINTF( - "%s (x= %d, y= %d) %02X %02X %02X %02X %02X", + "%s (x= %d, y= %d) %02X %02X %02X %02X %02X"_fmt, sd->bl_m->name_, sd->bl_x - 2, sd->bl_y + y, map_getcell(sd->bl_m, sd->bl_x - 2, sd->bl_y + y), map_getcell(sd->bl_m, sd->bl_x - 1, sd->bl_y + y), @@ -1916,7 +1925,7 @@ ATCE atcommand_statuspoint(Session *s, dumb_ptr<map_session_data> sd, { sd->status.status_point = new_status_point; clif_updatestatus(sd, SP::STATUSPOINT); - clif_displaymessage(s, "Number of status points changed!"); + clif_displaymessage(s, "Number of status points changed!"_s); } else return ATCE::RANGE; @@ -1945,7 +1954,7 @@ ATCE atcommand_skillpoint(Session *s, dumb_ptr<map_session_data> sd, { sd->status.skill_point = new_skill_point; clif_updatestatus(sd, SP::SKILLPOINT); - clif_displaymessage(s, "Number of skill points changed!"); + clif_displaymessage(s, "Number of skill points changed!"_s); } else return ATCE::RANGE; @@ -1974,7 +1983,7 @@ ATCE atcommand_zeny(Session *s, dumb_ptr<map_session_data> sd, { sd->status.zeny = new_zeny; clif_updatestatus(sd, SP::ZENY); - clif_displaymessage(s, "Number of zenys changed!"); + clif_displaymessage(s, "Number of zenys changed!"_s); } else return ATCE::RANGE; @@ -2006,7 +2015,7 @@ ATCE atcommand_param(Session *s, dumb_ptr<map_session_data> sd, clif_updatestatus(sd, attr_to_sp(attr)); clif_updatestatus(sd, attr_to_usp(attr)); pc_calcstatus(sd, 0); - clif_displaymessage(s, "Stat changed."); + clif_displaymessage(s, "Stat changed."_s); } else return ATCE::RANGE; @@ -2047,7 +2056,7 @@ ATCE atcommand_all_stats(Session *s, dumb_ptr<map_session_data> sd, if (count > 0) // if at least 1 stat modified - clif_displaymessage(s, "All stats changed!"); + clif_displaymessage(s, "All stats changed!"_s); else return ATCE::RANGE; @@ -2064,38 +2073,38 @@ ATCE atcommand_recall(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can recall only lower or same level if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARPTO) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp somenone to your actual map."); + "You are not authorised to warp somenone to your actual map."_s); return ATCE::PERM; } if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARP) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp this player from its actual map."); + "You are not authorised to warp this player from its actual map."_s); return ATCE::PERM; } pc_setpos(pl_sd, sd->mapname_, sd->bl_x, sd->bl_y, BeingRemoveWhy::QUIT); - AString output = STRPRINTF("%s recalled!", character); + AString output = STRPRINTF("%s recalled!"_fmt, character); clif_displaymessage(s, output); } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -2112,7 +2121,7 @@ ATCE atcommand_revive(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { pl_sd->status.hp = pl_sd->status.max_hp; pc_setstand(pl_sd); @@ -2121,11 +2130,11 @@ ATCE atcommand_revive(Session *s, dumb_ptr<map_session_data> sd, clif_updatestatus(pl_sd, SP::HP); clif_updatestatus(pl_sd, SP::SP); clif_resurrection(pl_sd, 1); - clif_displaymessage(s, "Character revived."); + clif_displaymessage(s, "Character revived."_s); } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -2142,41 +2151,41 @@ ATCE atcommand_character_stats(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { AString output; - output = STRPRINTF("'%s' stats:", pl_sd->status_key.name); + output = STRPRINTF("'%s' stats:"_fmt, pl_sd->status_key.name); clif_displaymessage(s, output); - output = STRPRINTF("Base Level - %d", pl_sd->status.base_level), + output = STRPRINTF("Base Level - %d"_fmt, pl_sd->status.base_level); clif_displaymessage(s, output); - output = STRPRINTF("Job - Novice/Human (level %d)", pl_sd->status.job_level); + output = STRPRINTF("Job - Novice/Human (level %d)"_fmt, pl_sd->status.job_level); clif_displaymessage(s, output); - output = STRPRINTF("Hp - %d", pl_sd->status.hp); + output = STRPRINTF("Hp - %d"_fmt, pl_sd->status.hp); clif_displaymessage(s, output); - output = STRPRINTF("MaxHp - %d", pl_sd->status.max_hp); + output = STRPRINTF("MaxHp - %d"_fmt, pl_sd->status.max_hp); clif_displaymessage(s, output); - output = STRPRINTF("Sp - %d", pl_sd->status.sp); + output = STRPRINTF("Sp - %d"_fmt, pl_sd->status.sp); clif_displaymessage(s, output); - output = STRPRINTF("MaxSp - %d", pl_sd->status.max_sp); + output = STRPRINTF("MaxSp - %d"_fmt, pl_sd->status.max_sp); clif_displaymessage(s, output); - output = STRPRINTF("Str - %3d", pl_sd->status.attrs[ATTR::STR]); + output = STRPRINTF("Str - %3d"_fmt, pl_sd->status.attrs[ATTR::STR]); clif_displaymessage(s, output); - output = STRPRINTF("Agi - %3d", pl_sd->status.attrs[ATTR::AGI]); + output = STRPRINTF("Agi - %3d"_fmt, pl_sd->status.attrs[ATTR::AGI]); clif_displaymessage(s, output); - output = STRPRINTF("Vit - %3d", pl_sd->status.attrs[ATTR::VIT]); + output = STRPRINTF("Vit - %3d"_fmt, pl_sd->status.attrs[ATTR::VIT]); clif_displaymessage(s, output); - output = STRPRINTF("Int - %3d", pl_sd->status.attrs[ATTR::INT]); + output = STRPRINTF("Int - %3d"_fmt, pl_sd->status.attrs[ATTR::INT]); clif_displaymessage(s, output); - output = STRPRINTF("Dex - %3d", pl_sd->status.attrs[ATTR::DEX]); + output = STRPRINTF("Dex - %3d"_fmt, pl_sd->status.attrs[ATTR::DEX]); clif_displaymessage(s, output); - output = STRPRINTF("Luk - %3d", pl_sd->status.attrs[ATTR::LUK]); + output = STRPRINTF("Luk - %3d"_fmt, pl_sd->status.attrs[ATTR::LUK]); clif_displaymessage(s, output); - output = STRPRINTF("Zeny - %d", pl_sd->status.zeny); + output = STRPRINTF("Zeny - %d"_fmt, pl_sd->status.zeny); clif_displaymessage(s, output); } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -2199,41 +2208,41 @@ ATCE atcommand_character_stats_all(Session *s, dumb_ptr<map_session_data>, if (pl_sd && pl_sd->state.auth) { AString gmlevel; - if (pc_isGM(pl_sd) > 0) - gmlevel = STRPRINTF("| GM Lvl: %d", pc_isGM(pl_sd)); + if (GmLevel pl_gm_level = pc_isGM(pl_sd)) + gmlevel = STRPRINTF("| GM Lvl: %d"_fmt, pl_gm_level); else - gmlevel = " "; + gmlevel = " "_s; AString output; output = STRPRINTF( - "Name: %s | BLvl: %d | Job: Novice/Human (Lvl: %d) | HP: %d/%d | SP: %d/%d", + "Name: %s | BLvl: %d | Job: Novice/Human (Lvl: %d) | HP: %d/%d | SP: %d/%d"_fmt, pl_sd->status_key.name, pl_sd->status.base_level, pl_sd->status.job_level, pl_sd->status.hp, pl_sd->status.max_hp, pl_sd->status.sp, pl_sd->status.max_sp); clif_displaymessage(s, output); - output = STRPRINTF("STR: %d | AGI: %d | VIT: %d | INT: %d | DEX: %d | LUK: %d | Zeny: %d %s", - pl_sd->status.attrs[ATTR::STR], - pl_sd->status.attrs[ATTR::AGI], - pl_sd->status.attrs[ATTR::VIT], - pl_sd->status.attrs[ATTR::INT], - pl_sd->status.attrs[ATTR::DEX], - pl_sd->status.attrs[ATTR::LUK], - pl_sd->status.zeny, - gmlevel); + output = STRPRINTF("STR: %d | AGI: %d | VIT: %d | INT: %d | DEX: %d | LUK: %d | Zeny: %d %s"_fmt, + pl_sd->status.attrs[ATTR::STR], + pl_sd->status.attrs[ATTR::AGI], + pl_sd->status.attrs[ATTR::VIT], + pl_sd->status.attrs[ATTR::INT], + pl_sd->status.attrs[ATTR::DEX], + pl_sd->status.attrs[ATTR::LUK], + pl_sd->status.zeny, + gmlevel); clif_displaymessage(s, output); - clif_displaymessage(s, "--------"); + clif_displaymessage(s, "--------"_s); count++; } } if (count == 0) - clif_displaymessage(s, "No player found."); + clif_displaymessage(s, "No player found."_s); else if (count == 1) - clif_displaymessage(s, "1 player found."); + clif_displaymessage(s, "1 player found."_s); else { - AString output = STRPRINTF("%d players found.", count); + AString output = STRPRINTF("%d players found."_fmt, count); clif_displaymessage(s, output); } @@ -2252,9 +2261,9 @@ ATCE atcommand_character_option(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can change option only to lower or same level pl_sd->opt1 = opt1; @@ -2263,17 +2272,17 @@ ATCE atcommand_character_option(Session *s, dumb_ptr<map_session_data> sd, clif_changeoption(pl_sd); pc_calcstatus(pl_sd, 0); - clif_displaymessage(s, "Character's options changed."); + clif_displaymessage(s, "Character's options changed."_s); } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -2292,7 +2301,7 @@ ATCE atcommand_char_change_sex(Session *s, dumb_ptr<map_session_data> sd, { chrif_char_ask_name(sd->status_key.account_id, character, 5, HumanTimeDiff()); // type: 5 - changesex - clif_displaymessage(s, "Character name sends to char-server to ask it."); + clif_displaymessage(s, "Character name sends to char-server to ask it."_s); } return ATCE::OKAY; @@ -2310,7 +2319,7 @@ ATCE atcommand_char_block(Session *s, dumb_ptr<map_session_data> sd, { chrif_char_ask_name(sd->status_key.account_id, character, 1, HumanTimeDiff()); // type: 1 - block - clif_displaymessage(s, "Character name sends to char-server to ask it."); + clif_displaymessage(s, "Character name sends to char-server to ask it."_s); } return ATCE::OKAY; @@ -2330,7 +2339,7 @@ ATCE atcommand_char_ban(Session *s, dumb_ptr<map_session_data> sd, { chrif_char_ask_name(sd->status_key.account_id, character, 2, modif); // type: 2 - ban - clif_displaymessage(s, "Character name sends to char-server to ask it."); + clif_displaymessage(s, "Character name sends to char-server to ask it."_s); } return ATCE::OKAY; @@ -2349,7 +2358,7 @@ ATCE atcommand_char_unblock(Session *s, dumb_ptr<map_session_data> sd, // send answer to login server via char-server chrif_char_ask_name(sd->status_key.account_id, character, 3, HumanTimeDiff()); // type: 3 - unblock - clif_displaymessage(s, "Character name sends to char-server to ask it."); + clif_displaymessage(s, "Character name sends to char-server to ask it."_s); } return ATCE::OKAY; @@ -2368,7 +2377,7 @@ ATCE atcommand_char_unban(Session *s, dumb_ptr<map_session_data> sd, // send answer to login server via char-server chrif_char_ask_name(sd->status_key.account_id, character, 4, HumanTimeDiff()); // type: 4 - unban - clif_displaymessage(s, "Character name sends to char-server to ask it."); + clif_displaymessage(s, "Character name sends to char-server to ask it."_s); } return ATCE::OKAY; @@ -2387,39 +2396,39 @@ ATCE atcommand_character_save(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can change save point only to lower or same gm level map_local *m = map_mapname2mapid(map_name); if (m == nullptr) { - clif_displaymessage(s, "Map not found."); + clif_displaymessage(s, "Map not found."_s); return ATCE::EXIST; } else { if (m != nullptr && m->flag.get(MapFlag::NOWARPTO) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to set this map as a save map."); + "You are not authorised to set this map as a save map."_s); return ATCE::PERM; } pc_setsavepoint(pl_sd, map_name, x, y); - clif_displaymessage(s, "Character's respawn point changed."); + clif_displaymessage(s, "Character's respawn point changed."_s); } } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -2438,14 +2447,14 @@ ATCE atcommand_doom(Session *s, dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get())); if (pl_sd && pl_sd->state.auth && s2 != s - && pc_isGM(sd) >= pc_isGM(pl_sd)) + && pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can doom only lower or same gm level - pc_damage(NULL, pl_sd, pl_sd->status.hp + 1); - clif_displaymessage(pl_sd->sess, "The holy messenger has given judgement."); + pc_damage(nullptr, pl_sd, pl_sd->status.hp + 1); + clif_displaymessage(pl_sd->sess, "The holy messenger has given judgement."_s); } } - clif_displaymessage(s, "Judgement was made."); + clif_displaymessage(s, "Judgement was made."_s); return ATCE::OKAY; } @@ -2462,14 +2471,14 @@ ATCE atcommand_doommap(Session *s, dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get())); if (pl_sd && pl_sd->state.auth && s2 != s && sd->bl_m == pl_sd->bl_m - && pc_isGM(sd) >= pc_isGM(pl_sd)) + && pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can doom only lower or same gm level - pc_damage(NULL, pl_sd, pl_sd->status.hp + 1); - clif_displaymessage(pl_sd->sess, "The holy messenger has given judgement."); + pc_damage(nullptr, pl_sd, pl_sd->status.hp + 1); + clif_displaymessage(pl_sd->sess, "The holy messenger has given judgement."_s); } } - clif_displaymessage(s, "Judgement was made."); + clif_displaymessage(s, "Judgement was made."_s); return ATCE::OKAY; } @@ -2485,7 +2494,7 @@ void atcommand_raise_sub(dumb_ptr<map_session_data> sd) clif_updatestatus(sd, SP::HP); clif_updatestatus(sd, SP::SP); clif_resurrection(sd, 1); - clif_displaymessage(sd->sess, "Mercy has been shown."); + clif_displaymessage(sd->sess, "Mercy has been shown."_s); } } @@ -2501,7 +2510,7 @@ ATCE atcommand_raise(Session *s, dumb_ptr<map_session_data>, dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get())); atcommand_raise_sub(pl_sd); } - clif_displaymessage(s, "Mercy has been granted."); + clif_displaymessage(s, "Mercy has been granted."_s); return ATCE::OKAY; } @@ -2520,7 +2529,7 @@ ATCE atcommand_raisemap(Session *s, dumb_ptr<map_session_data> sd, && pl_sd->state.auth && sd->bl_m == pl_sd->bl_m) atcommand_raise_sub(pl_sd); } - clif_displaymessage(s, "Mercy has been granted."); + clif_displaymessage(s, "Mercy has been granted."_s); return ATCE::OKAY; } @@ -2537,16 +2546,16 @@ ATCE atcommand_character_baselevel(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can change base level only lower or same gm level if (level > 0) { if (pl_sd->status.base_level == battle_config.maximum_level) { - clif_displaymessage(s, "Character's base level can't go any higher."); + clif_displaymessage(s, "Character's base level can't go any higher."_s); return ATCE::RANGE; } if (level > battle_config.maximum_level || level > (battle_config.maximum_level - pl_sd->status.base_level)) @@ -2564,13 +2573,13 @@ ATCE atcommand_character_baselevel(Session *s, dumb_ptr<map_session_data> sd, pc_calcstatus(pl_sd, 0); pc_heal(pl_sd, pl_sd->status.max_hp, pl_sd->status.max_sp); clif_misceffect(pl_sd, 0); - clif_displaymessage(s, "Character's base level raised."); + clif_displaymessage(s, "Character's base level raised."_s); } else { if (pl_sd->status.base_level == 1) { - clif_displaymessage(s, "Character's base level can't go any lower."); + clif_displaymessage(s, "Character's base level can't go any lower."_s); return ATCE::RANGE; } if (level < -battle_config.maximum_level || level < (1 - pl_sd->status.base_level)) @@ -2592,20 +2601,20 @@ ATCE atcommand_character_baselevel(Session *s, dumb_ptr<map_session_data> sd, clif_updatestatus(pl_sd, SP::NEXTBASEEXP); clif_updatestatus(pl_sd, SP::BASEEXP); pc_calcstatus(pl_sd, 0); - clif_displaymessage(s, "Character's base level lowered."); + clif_displaymessage(s, "Character's base level lowered."_s); } // Reset their stat points to prevent extra points from stacking atcommand_charstreset(s, sd, character.to__actual()); } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -2624,9 +2633,9 @@ ATCE atcommand_character_joblevel(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can change job level only lower or same gm level max_level -= 40; @@ -2635,7 +2644,7 @@ ATCE atcommand_character_joblevel(Session *s, dumb_ptr<map_session_data> sd, { if (pl_sd->status.job_level == max_level) { - clif_displaymessage(s, "Character's job level can't go any higher."); + clif_displaymessage(s, "Character's job level can't go any higher."_s); return ATCE::RANGE; } if (pl_sd->status.job_level + level > max_level) @@ -2647,13 +2656,13 @@ ATCE atcommand_character_joblevel(Session *s, dumb_ptr<map_session_data> sd, clif_updatestatus(pl_sd, SP::SKILLPOINT); pc_calcstatus(pl_sd, 0); clif_misceffect(pl_sd, 1); - clif_displaymessage(s, "character's job level raised."); + clif_displaymessage(s, "character's job level raised."_s); } else { if (pl_sd->status.job_level == 1) { - clif_displaymessage(s, "Character's job level can't go any lower."); + clif_displaymessage(s, "Character's job level can't go any lower."_s); return ATCE::RANGE; } if (pl_sd->status.job_level + level < 1) @@ -2670,18 +2679,18 @@ ATCE atcommand_character_joblevel(Session *s, dumb_ptr<map_session_data> sd, } // to add: remove status points from skills pc_calcstatus(pl_sd, 0); - clif_displaymessage(s, "Character's job level lowered."); + clif_displaymessage(s, "Character's job level lowered."_s); } } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -2698,20 +2707,20 @@ ATCE atcommand_kick(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) // you can kick only lower or same gm level clif_GM_kick(sd, pl_sd, 1); else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -2729,7 +2738,7 @@ ATCE atcommand_kickall(Session *s, dumb_ptr<map_session_data> sd, continue; dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get())); if (pl_sd - && pl_sd->state.auth && pc_isGM(sd) >= pc_isGM(pl_sd)) + && pl_sd->state.auth && pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can kick only lower or same gm level if (sd->status_key.account_id != pl_sd->status_key.account_id) @@ -2737,7 +2746,7 @@ ATCE atcommand_kickall(Session *s, dumb_ptr<map_session_data> sd, } } - clif_displaymessage(s, "All players have been kicked!"); + clif_displaymessage(s, "All players have been kicked!"_s); return ATCE::OKAY; } @@ -2758,23 +2767,23 @@ ATCE atcommand_questskill(Session *s, dumb_ptr<map_session_data> sd, if (pc_checkskill(sd, skill_id) == 0) { pc_skill(sd, skill_id, 1, 0); - clif_displaymessage(s, "You have learned the skill."); + clif_displaymessage(s, "You have learned the skill."_s); } else { - clif_displaymessage(s, "You already have this quest skill."); + clif_displaymessage(s, "You already have this quest skill."_s); return ATCE::EXIST; } } else { - clif_displaymessage(s, "This skill number doesn't exist or isn't a quest skill."); + clif_displaymessage(s, "This skill number doesn't exist or isn't a quest skill."_s); return ATCE::RANGE; } } else { - clif_displaymessage(s, "This skill number doesn't exist."); + clif_displaymessage(s, "This skill number doesn't exist."_s); return ATCE::RANGE; } @@ -2796,34 +2805,34 @@ ATCE atcommand_charquestskill(Session *s, dumb_ptr<map_session_data>, if (skill_get_inf2(skill_id) & 0x01) { dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { if (pc_checkskill(pl_sd, skill_id) == 0) { pc_skill(pl_sd, skill_id, 1, 0); - clif_displaymessage(s, "This player has learned the skill."); + clif_displaymessage(s, "This player has learned the skill."_s); } else { - clif_displaymessage(s, "This player already has this quest skill."); + clif_displaymessage(s, "This player already has this quest skill."_s); return ATCE::EXIST; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } } else { - clif_displaymessage(s, "This skill number doesn't exist or isn't a quest skill."); + clif_displaymessage(s, "This skill number doesn't exist or isn't a quest skill."_s); return ATCE::RANGE; } } else { - clif_displaymessage(s, "This skill number doesn't exist."); + clif_displaymessage(s, "This skill number doesn't exist."_s); return ATCE::RANGE; } @@ -2848,23 +2857,23 @@ ATCE atcommand_lostskill(Session *s, dumb_ptr<map_session_data> sd, sd->status.skill[skill_id].lv = 0; sd->status.skill[skill_id].flags = SkillFlags::ZERO; clif_skillinfoblock(sd); - clif_displaymessage(s, "You have forgotten the skill."); + clif_displaymessage(s, "You have forgotten the skill."_s); } else { - clif_displaymessage(s, "You don't have this quest skill."); + clif_displaymessage(s, "You don't have this quest skill."_s); return ATCE::EXIST; } } else { - clif_displaymessage(s, "This skill number doesn't exist or isn't a quest skill."); + clif_displaymessage(s, "This skill number doesn't exist or isn't a quest skill."_s); return ATCE::RANGE; } } else { - clif_displaymessage(s, "This skill number doesn't exist."); + clif_displaymessage(s, "This skill number doesn't exist."_s); return ATCE::RANGE; } @@ -2886,36 +2895,36 @@ ATCE atcommand_charlostskill(Session *s, dumb_ptr<map_session_data>, if (skill_get_inf2(skill_id) & 0x01) { dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { if (pc_checkskill(pl_sd, skill_id) > 0) { pl_sd->status.skill[skill_id].lv = 0; pl_sd->status.skill[skill_id].flags = SkillFlags::ZERO; clif_skillinfoblock(pl_sd); - clif_displaymessage(s, "This player has forgotten the skill."); + clif_displaymessage(s, "This player has forgotten the skill."_s); } else { - clif_displaymessage(s, "This player doesn't have this quest skill."); + clif_displaymessage(s, "This player doesn't have this quest skill."_s); return ATCE::EXIST; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } } else { - clif_displaymessage(s, "This skill number doesn't exist or isn't a quest skill."); + clif_displaymessage(s, "This skill number doesn't exist or isn't a quest skill."_s); return ATCE::RANGE; } } else { - clif_displaymessage(s, "This skill number doesn't exist."); + clif_displaymessage(s, "This skill number doesn't exist."_s); return ATCE::RANGE; } @@ -2964,26 +2973,26 @@ ATCE atcommand_idsearch(Session *s, dumb_ptr<map_session_data>, ZString message) { ItemName item_name; - int i, match; + int match; struct item_data *item; if (!extract(message, &item_name) || !item_name) return ATCE::USAGE; - AString output = STRPRINTF("The reference result of '%s' (name: id):", item_name); + AString output = STRPRINTF("The reference result of '%s' (name: id):"_fmt, item_name); clif_displaymessage(s, output); match = 0; - for (i = 0; i < 20000; i++) + for (ItemNameId i = wrap<ItemNameId>(0); i < wrap<ItemNameId>(-1); i = next(i)) { - if ((item = itemdb_exists(i)) != NULL + if ((item = itemdb_exists(i)) != nullptr && item->jname.contains_seq(item_name)) { match++; - output = STRPRINTF("%s: %d", item->jname, item->nameid); + output = STRPRINTF("%s: %d"_fmt, item->jname, item->nameid); clif_displaymessage(s, output); } } - output = STRPRINTF("It is %d affair above.", match); + output = STRPRINTF("It is %d affair above."_fmt, match); clif_displaymessage(s, output); return ATCE::OKAY; @@ -2999,25 +3008,25 @@ ATCE atcommand_charskreset(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can reset skill points only lower or same gm level pc_resetskill(pl_sd); AString output = STRPRINTF( - "'%s' skill points reseted!", character); + "'%s' skill points reseted!"_fmt, character); clif_displaymessage(s, output); } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -3034,26 +3043,26 @@ ATCE atcommand_charstreset(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can reset stats points only lower or same gm level pc_resetstate(pl_sd); AString output = STRPRINTF( - "'%s' stats points reseted!", + "'%s' stats points reseted!"_fmt, character); clif_displaymessage(s, output); } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -3070,30 +3079,30 @@ ATCE atcommand_charreset(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can reset a character only for lower or same GM level pc_resetstate(pl_sd); pc_resetskill(pl_sd); - pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_FLAGS"), 0); + pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_FLAGS"_s), 0); // [Fate] Reset magic quest variables - pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_EXP"), 0); + pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_EXP"_s), 0); // [Fate] Reset magic experience AString output = STRPRINTF( - "'%s' skill and stats points reseted!", character); + "'%s' skill and stats points reseted!"_fmt, character); clif_displaymessage(s, output); } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -3110,12 +3119,11 @@ ATCE atcommand_char_wipe(Session *s, dumb_ptr<map_session_data> sd, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can reset a character only for lower or same GM level - int i; // Reset base level pl_sd->status.base_level = 1; @@ -3136,7 +3144,7 @@ ATCE atcommand_char_wipe(Session *s, dumb_ptr<map_session_data> sd, clif_updatestatus(pl_sd, SP::ZENY); // Clear inventory - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (sd->status.inventory[i].amount) { @@ -3147,33 +3155,33 @@ ATCE atcommand_char_wipe(Session *s, dumb_ptr<map_session_data> sd, } // Give knife and shirt - struct item item; - item.nameid = 1201; + Item item; + item.nameid = wrap<ItemNameId>(1201); pc_additem(pl_sd, &item, 1); - item.nameid = 1202; + item.nameid = wrap<ItemNameId>(1202); pc_additem(pl_sd, &item, 1); // Reset stats and skills pc_calcstatus(pl_sd, 0); pc_resetstate(pl_sd); pc_resetskill(pl_sd); - pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_FLAGS"), 0); + pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_FLAGS"_s), 0); // [Fate] Reset magic quest variables - pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_EXP"), 0); + pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_EXP"_s), 0); // [Fate] Reset magic experience - AString output = STRPRINTF("%s: wiped.", character); + AString output = STRPRINTF("%s: wiped."_fmt, character); clif_displaymessage(s, output); } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -3191,7 +3199,7 @@ ATCE atcommand_charmodel(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE && hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR && @@ -3201,7 +3209,7 @@ ATCE atcommand_charmodel(Session *s, dumb_ptr<map_session_data>, pc_changelook(pl_sd, LOOK::HAIR, hair_style); pc_changelook(pl_sd, LOOK::HAIR_COLOR, hair_color); pc_changelook(pl_sd, LOOK::CLOTHES_COLOR, cloth_color); - clif_displaymessage(s, "Appearence changed."); + clif_displaymessage(s, "Appearence changed."_s); } } else @@ -3209,7 +3217,7 @@ ATCE atcommand_charmodel(Session *s, dumb_ptr<map_session_data>, } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -3229,7 +3237,7 @@ ATCE atcommand_charskpoint(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { new_skill_point = pl_sd->status.skill_point + point; if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF)) @@ -3242,14 +3250,14 @@ ATCE atcommand_charskpoint(Session *s, dumb_ptr<map_session_data>, { pl_sd->status.skill_point = new_skill_point; clif_updatestatus(pl_sd, SP::SKILLPOINT); - clif_displaymessage(s, "Character's number of skill points changed!"); + clif_displaymessage(s, "Character's number of skill points changed!"_s); } else return ATCE::RANGE; } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -3269,7 +3277,7 @@ ATCE atcommand_charstpoint(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { new_status_point = pl_sd->status.status_point + point; if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF)) @@ -3282,14 +3290,14 @@ ATCE atcommand_charstpoint(Session *s, dumb_ptr<map_session_data>, { pl_sd->status.status_point = new_status_point; clif_updatestatus(pl_sd, SP::STATUSPOINT); - clif_displaymessage(s, "Character's number of status points changed!"); + clif_displaymessage(s, "Character's number of status points changed!"_s); } else return ATCE::RANGE; } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -3307,7 +3315,7 @@ ATCE atcommand_charzeny(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { new_zeny = pl_sd->status.zeny + zeny; if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY)) @@ -3320,14 +3328,14 @@ ATCE atcommand_charzeny(Session *s, dumb_ptr<map_session_data>, { pl_sd->status.zeny = new_zeny; clif_updatestatus(pl_sd, SP::ZENY); - clif_displaymessage(s, "Character's number of zenys changed!"); + clif_displaymessage(s, "Character's number of zenys changed!"_s); } else return ATCE::RANGE; } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -3341,10 +3349,10 @@ ATCE atcommand_recallall(Session *s, dumb_ptr<map_session_data> sd, int count; if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARPTO) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp somenone to your actual map."); + "You are not authorised to warp somenone to your actual map."_s); return ATCE::PERM; } @@ -3358,22 +3366,22 @@ ATCE atcommand_recallall(Session *s, dumb_ptr<map_session_data> sd, if (pl_sd && pl_sd->state.auth && sd->status_key.account_id != pl_sd->status_key.account_id - && pc_isGM(sd) >= pc_isGM(pl_sd)) + && pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can recall only lower or same level if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARP) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) count++; else pc_setpos(pl_sd, sd->mapname_, sd->bl_x, sd->bl_y, BeingRemoveWhy::QUIT); } } - clif_displaymessage(s, "All characters recalled!"); + clif_displaymessage(s, "All characters recalled!"_s); if (count) { AString output = STRPRINTF( - "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", + "Because you are not authorised to warp from some maps, %d player(s) have not been recalled."_fmt, count); clif_displaymessage(s, output); } @@ -3386,23 +3394,23 @@ ATCE atcommand_partyrecall(Session *s, dumb_ptr<map_session_data> sd, ZString message) { PartyName party_name; - struct party *p; + PartyPair p; int count; if (!extract(message, &party_name) || !party_name) return ATCE::USAGE; if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARPTO) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp somenone to your actual map."); + "You are not authorised to warp somenone to your actual map."_s); return ATCE::PERM; } - if ((p = party_searchname(party_name)) != NULL || + if ((p = party_searchname(party_name)) || // name first to avoid error when name begin with a number - (p = party_search(atoi(message.c_str()))) != NULL) + (p = party_search(wrap<PartyId>(static_cast<uint32_t>(atoi(message.c_str())))))) { count = 0; for (io::FD i : iter_fds()) @@ -3413,28 +3421,28 @@ ATCE atcommand_partyrecall(Session *s, dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get())); if (pl_sd && pl_sd->state.auth && sd->status_key.account_id != pl_sd->status_key.account_id - && pl_sd->status.party_id == p->party_id) + && pl_sd->status.party_id == p.party_id) { if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARP) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) count++; else pc_setpos(pl_sd, sd->mapname_, sd->bl_x, sd->bl_y, BeingRemoveWhy::QUIT); } } - AString output = STRPRINTF("All online characters of the %s party are near you.", p->name); + AString output = STRPRINTF("All online characters of the %s party are near you."_fmt, p->name); clif_displaymessage(s, output); if (count) { output = STRPRINTF( - "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", + "Because you are not authorised to warp from some maps, %d player(s) have not been recalled."_fmt, count); clif_displaymessage(s, output); } } else { - clif_displaymessage(s, "Incorrect name or ID, or no one from the party is online."); + clif_displaymessage(s, "Incorrect name or ID, or no one from the party is online."_s); return ATCE::EXIST; } @@ -3445,9 +3453,9 @@ static ATCE atcommand_mapinfo(Session *s, dumb_ptr<map_session_data> sd, ZString message) { - dumb_ptr<npc_data> nd = NULL; + dumb_ptr<npc_data> nd = nullptr; MapName map_name; - const char *direction = NULL; + LString direction = ""_s; int list = 0; extract(message, record<' '>(&list, &map_name)); @@ -3462,35 +3470,35 @@ ATCE atcommand_mapinfo(Session *s, dumb_ptr<map_session_data> sd, if (m_id != nullptr) return ATCE::EXIST; - clif_displaymessage(s, "------ Map Info ------"); - AString output = STRPRINTF("Map Name: %s", map_name); + clif_displaymessage(s, "------ Map Info ------"_s); + AString output = STRPRINTF("Map Name: %s"_fmt, map_name); clif_displaymessage(s, output); - output = STRPRINTF("Players In Map: %d", m_id->users); + output = STRPRINTF("Players In Map: %d"_fmt, m_id->users); clif_displaymessage(s, output); - output = STRPRINTF("NPCs In Map: %d", m_id->npc_num); + output = STRPRINTF("NPCs In Map: %d"_fmt, m_id->npc_num); clif_displaymessage(s, output); - clif_displaymessage(s, "------ Map Flags ------"); - output = STRPRINTF("Player vs Player: %s | No Party: %s", - (m_id->flag.get(MapFlag::PVP)) ? "True" : "False", - (m_id->flag.get(MapFlag::PVP_NOPARTY)) ? "True" : "False"); + clif_displaymessage(s, "------ Map Flags ------"_s); + output = STRPRINTF("Player vs Player: %s | No Party: %s"_fmt, + (m_id->flag.get(MapFlag::PVP)) ? "True"_s : "False"_s, + (m_id->flag.get(MapFlag::PVP_NOPARTY)) ? "True"_s : "False"_s); clif_displaymessage(s, output); - output = STRPRINTF("No Penalty: %s", - (m_id->flag.get(MapFlag::NOPENALTY)) ? "True" : "False"); + output = STRPRINTF("No Penalty: %s"_fmt, + (m_id->flag.get(MapFlag::NOPENALTY)) ? "True"_s : "False"_s); clif_displaymessage(s, output); - output = STRPRINTF("No Return: %s", - (m_id->flag.get(MapFlag::NORETURN)) ? "True" : "False"); + output = STRPRINTF("No Return: %s"_fmt, + (m_id->flag.get(MapFlag::NORETURN)) ? "True"_s : "False"_s); clif_displaymessage(s, output); - output = STRPRINTF("No Save: %s", - (m_id->flag.get(MapFlag::NOSAVE)) ? "True" : "False"); + output = STRPRINTF("No Save: %s"_fmt, + (m_id->flag.get(MapFlag::NOSAVE)) ? "True"_s : "False"_s); clif_displaymessage(s, output); - output = STRPRINTF("Re Save: %s", - (m_id->flag.get(MapFlag::RESAVE)) ? "True" : "False"); + output = STRPRINTF("Re Save: %s"_fmt, + (m_id->flag.get(MapFlag::RESAVE)) ? "True"_s : "False"_s); clif_displaymessage(s, output); - output = STRPRINTF("No Teleport: %s", - (m_id->flag.get(MapFlag::NOTELEPORT)) ? "True" : "False"); + output = STRPRINTF("No Teleport: %s"_fmt, + (m_id->flag.get(MapFlag::NOTELEPORT)) ? "True"_s : "False"_s); clif_displaymessage(s, output); - output = STRPRINTF("No Monster Teleport: %s", - (m_id->flag.get(MapFlag::MONSTER_NOTELEPORT)) ? "True" : "False"); + output = STRPRINTF("No Monster Teleport: %s"_fmt, + (m_id->flag.get(MapFlag::MONSTER_NOTELEPORT)) ? "True"_s : "False"_s); clif_displaymessage(s, output); switch (list) @@ -3499,7 +3507,7 @@ ATCE atcommand_mapinfo(Session *s, dumb_ptr<map_session_data> sd, // Do nothing. It's list 0, no additional display. break; case 1: - clif_displaymessage(s, "----- Players in Map -----"); + clif_displaymessage(s, "----- Players in Map -----"_s); for (io::FD i : iter_fds()) { Session *s2 = get_session(i); @@ -3510,54 +3518,54 @@ ATCE atcommand_mapinfo(Session *s, dumb_ptr<map_session_data> sd, && pl_sd->mapname_ == map_name) { output = STRPRINTF( - "Player '%s' (session #%d) | Location: %d,%d", + "Player '%s' (session #%d) | Location: %d,%d"_fmt, pl_sd->status_key.name, s2, pl_sd->bl_x, pl_sd->bl_y); clif_displaymessage(s, output); } } break; case 2: - clif_displaymessage(s, "----- NPCs in Map -----"); + clif_displaymessage(s, "----- NPCs in Map -----"_s); for (int i = 0; i < m_id->npc_num;) { nd = m_id->npc[i]; switch (nd->dir) { case DIR::S: - direction = "North"; + direction = "North"_s; break; case DIR::SW: - direction = "North West"; + direction = "North West"_s; break; case DIR::W: - direction = "West"; + direction = "West"_s; break; case DIR::NW: - direction = "South West"; + direction = "South West"_s; break; case DIR::N: - direction = "South"; + direction = "South"_s; break; case DIR::NE: - direction = "South East"; + direction = "South East"_s; break; case DIR::E: - direction = "East"; + direction = "East"_s; break; case DIR::SE: - direction = "North East"; + direction = "North East"_s; break; #if 0 case 9: - direction = "North"; + direction = "North"_s; break; #endif default: - direction = "Unknown"; + direction = "Unknown"_s; break; } output = STRPRINTF( - "NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d", + "NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d"_fmt, ++i, nd->name, direction, nd->npc_class, nd->bl_x, nd->bl_y); clif_displaymessage(s, output); @@ -3566,7 +3574,7 @@ ATCE atcommand_mapinfo(Session *s, dumb_ptr<map_session_data> sd, default: // normally impossible to arrive here clif_displaymessage(s, - "Please, enter at least a valid list number (usage: @mapinfo <0-2> [map])."); + "Please, enter at least a valid list number (usage: @mapinfo <0-2> [map])."_s); return ATCE::USAGE; } @@ -3582,27 +3590,27 @@ ATCE atcommand_partyspy(Session *s, dumb_ptr<map_session_data> sd, if (!extract(message, &party_name)) return ATCE::USAGE; - struct party *p; - if ((p = party_searchname(party_name)) != NULL || + PartyPair p; + if ((p = party_searchname(party_name)) || // name first to avoid error when name begin with a number - (p = party_search(atoi(message.c_str()))) != NULL) + (p = party_search(wrap<PartyId>(static_cast<uint32_t>(atoi(message.c_str())))))) { - if (sd->partyspy == p->party_id) + if (sd->partyspy == p.party_id) { - sd->partyspy = 0; - AString output = STRPRINTF("No longer spying on the %s party.", p->name); + sd->partyspy = PartyId(); + AString output = STRPRINTF("No longer spying on the %s party."_fmt, p->name); clif_displaymessage(s, output); } else { - sd->partyspy = p->party_id; - AString output = STRPRINTF("Spying on the %s party.", p->name); + sd->partyspy = p.party_id; + AString output = STRPRINTF("Spying on the %s party."_fmt, p->name); clif_displaymessage(s, output); } } else { - clif_displaymessage(s, "Incorrect name or ID, or no one from the party is online."); + clif_displaymessage(s, "Incorrect name or ID, or no one from the party is online."_s); return ATCE::EXIST; } @@ -3618,14 +3626,14 @@ ATCE atcommand_enablenpc(Session *s, dumb_ptr<map_session_data>, if (!extract(message, &NPCname) || !NPCname) return ATCE::USAGE; - if (npc_name2id(NPCname) != NULL) + if (npc_name2id(NPCname) != nullptr) { npc_enable(NPCname, 1); - clif_displaymessage(s, "Npc Enabled."); + clif_displaymessage(s, "Npc Enabled."_s); } else { - clif_displaymessage(s, "This NPC doesn't exist."); + clif_displaymessage(s, "This NPC doesn't exist."_s); return ATCE::EXIST; } @@ -3641,14 +3649,14 @@ ATCE atcommand_disablenpc(Session *s, dumb_ptr<map_session_data>, if (!extract(message, &NPCname) || !NPCname) return ATCE::USAGE; - if (npc_name2id(NPCname) != NULL) + if (npc_name2id(NPCname) != nullptr) { npc_enable(NPCname, 0); - clif_displaymessage(s, "Npc Disabled."); + clif_displaymessage(s, "Npc Disabled."_s); } else { - clif_displaymessage(s, "This NPC doesn't exist."); + clif_displaymessage(s, "This NPC doesn't exist."_s); return ATCE::EXIST; } @@ -3661,7 +3669,7 @@ ATCE atcommand_servertime(Session *s, dumb_ptr<map_session_data>, { timestamp_seconds_buffer tsbuf; stamp_time(tsbuf); - AString temp = STRPRINTF("Server time: %s", tsbuf); + AString temp = STRPRINTF("Server time: %s"_fmt, tsbuf); clif_displaymessage(s, temp); return ATCE::OKAY; @@ -3673,33 +3681,32 @@ ATCE atcommand_chardelitem(Session *s, dumb_ptr<map_session_data> sd, { CharName character; XString item_name; - int i, number = 0, item_id, item_position, count; + int i, number = 0; + ItemNameId item_id; + int count; struct item_data *item_data; if (!asplit(message, &item_name, &number, &character) || number < 1) return ATCE::USAGE; - item_id = 0; - if ((item_data = itemdb_searchname(item_name)) != NULL) + if ((item_data = itemdb_searchname(item_name)) != nullptr) item_id = item_data->nameid; - else if (extract(item_name, &item_id) && (item_data = itemdb_exists(item_id)) != NULL) + else if (extract(item_name, &item_id) && (item_data = itemdb_exists(item_id)) != nullptr) item_id = item_data->nameid; - else - item_id = 0; - if (item_id > 500) + if (item_id) { dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can kill only lower or same level - item_position = pc_search_inventory(pl_sd, item_id); - if (item_position >= 0) + IOff0 item_position = pc_search_inventory(pl_sd, item_id); + if (item_position.ok()) { count = 0; - for (i = 0; i < number && item_position >= 0; i++) + for (i = 0; i < number && item_position.ok(); i++) { pc_delitem(pl_sd, item_position, 1, 0); count++; @@ -3707,37 +3714,37 @@ ATCE atcommand_chardelitem(Session *s, dumb_ptr<map_session_data> sd, // for next loop } AString output = STRPRINTF( - "%d item(s) removed by a GM.", + "%d item(s) removed by a GM."_fmt, count); clif_displaymessage(pl_sd->sess, output); if (number == count) - output = STRPRINTF("%d item(s) removed from the player.", count); + output = STRPRINTF("%d item(s) removed from the player."_fmt, count); else - output = STRPRINTF("%d item(s) removed. Player had only %d on %d items.", count, count, number); + output = STRPRINTF("%d item(s) removed. Player had only %d on %d items."_fmt, count, count, number); clif_displaymessage(s, output); } else { - clif_displaymessage(s, "Character does not have the item."); + clif_displaymessage(s, "Character does not have the item."_s); return ATCE::EXIST; } } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } } else { - clif_displaymessage(s, "Invalid item ID or name."); + clif_displaymessage(s, "Invalid item ID or name."_s); return ATCE::RANGE; } @@ -3751,7 +3758,7 @@ ATCE atcommand_broadcast(Session *, dumb_ptr<map_session_data> sd, if (!message) return ATCE::USAGE; - AString output = STRPRINTF("%s : %s", sd->status_key.name, message); + AString output = STRPRINTF("%s : %s"_fmt, sd->status_key.name, message); intif_GMmessage(output); return ATCE::OKAY; @@ -3764,7 +3771,7 @@ ATCE atcommand_localbroadcast(Session *, dumb_ptr<map_session_data> sd, if (!message) return ATCE::USAGE; - AString output = STRPRINTF("%s : %s", sd->status_key.name, message); + AString output = STRPRINTF("%s : %s"_fmt, sd->status_key.name, message); clif_GMmessage(sd, output, 1); @@ -3783,28 +3790,28 @@ ATCE atcommand_email(Session *s, dumb_ptr<map_session_data> sd, if (!e_mail_check(actual_email)) { - clif_displaymessage(s, "Invalid actual email. If you have default e-mail, type a@a.com."); + clif_displaymessage(s, "Invalid actual email. If you have default e-mail, type a@a.com."_s); return ATCE::RANGE; } else if (!e_mail_check(new_email)) { - clif_displaymessage(s, "Invalid new email. Please enter a real e-mail."); + clif_displaymessage(s, "Invalid new email. Please enter a real e-mail."_s); return ATCE::RANGE; } else if (new_email == DEFAULT_EMAIL) { - clif_displaymessage(s, "New email must be a real e-mail."); + clif_displaymessage(s, "New email must be a real e-mail."_s); return ATCE::RANGE; } else if (actual_email == new_email) { - clif_displaymessage(s, "New email must be different of the actual e-mail."); + clif_displaymessage(s, "New email must be different of the actual e-mail."_s); return ATCE::RANGE; } else { chrif_changeemail(sd->status_key.account_id, actual_email, new_email); - clif_displaymessage(s, "Information sended to login-server via char-server."); + clif_displaymessage(s, "Information sended to login-server via char-server."_s); } return ATCE::OKAY; @@ -3821,7 +3828,7 @@ ATCE atcommand_effect(Session *s, dumb_ptr<map_session_data> sd, if (flag <= 0) { clif_specialeffect(sd, type, flag); - clif_displaymessage(s, "Your Effect Has Changed."); + clif_displaymessage(s, "Your Effect Has Changed."_s); } else { @@ -3834,7 +3841,7 @@ ATCE atcommand_effect(Session *s, dumb_ptr<map_session_data> sd, if (pl_sd && pl_sd->state.auth) { clif_specialeffect(pl_sd, type, flag); - clif_displaymessage(pl_sd->sess, "Your Effect Has Changed."); + clif_displaymessage(pl_sd->sess, "Your Effect Has Changed."_s); } } } @@ -3846,34 +3853,34 @@ static ATCE atcommand_character_item_list(Session *s, dumb_ptr<map_session_data> sd, ZString message) { - struct item_data *item_data = NULL; - int i, count, counter; + struct item_data *item_data = nullptr; + int count, counter; CharName character; if (!asplit(message, &character)) return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can look items only lower or same level counter = 0; count = 0; - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { - if (pl_sd->status.inventory[i].nameid > 0 + if (pl_sd->status.inventory[i].nameid && (item_data = itemdb_search(pl_sd->status.inventory[i].nameid)) != - NULL) + nullptr) { counter = counter + pl_sd->status.inventory[i].amount; count++; if (count == 1) { AString output = STRPRINTF( - "------ Items list of '%s' ------", + "------ Items list of '%s' ------"_fmt, pl_sd->status_key.name); clif_displaymessage(s, output); } @@ -3881,35 +3888,35 @@ ATCE atcommand_character_item_list(Session *s, dumb_ptr<map_session_data> sd, MString equipstr; if (bool(equip)) { - equipstr += "| equiped: "; + equipstr += "| equiped: "_s; if (bool(equip & EPOS::GLOVES)) - equipstr += "robe/gargment, "; + equipstr += "robe/gargment, "_s; if (bool(equip & EPOS::CAPE)) - equipstr += "left accessory, "; + equipstr += "left accessory, "_s; if (bool(equip & EPOS::MISC1)) - equipstr += "body/armor, "; + equipstr += "body/armor, "_s; if ((equip & (EPOS::WEAPON | EPOS::SHIELD)) == EPOS::WEAPON) - equipstr += "right hand, "; + equipstr += "right hand, "_s; if ((equip & (EPOS::WEAPON | EPOS::SHIELD)) == EPOS::SHIELD) - equipstr += "left hand, "; + equipstr += "left hand, "_s; if ((equip & (EPOS::WEAPON | EPOS::SHIELD)) == (EPOS::WEAPON | EPOS::SHIELD)) - equipstr += "both hands, "; + equipstr += "both hands, "_s; if (bool(equip & EPOS::SHOES)) - equipstr += "feet, "; + equipstr += "feet, "_s; if (bool(equip & EPOS::MISC2)) - equipstr += "right accessory, "; + equipstr += "right accessory, "_s; if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == EPOS::LEGS) - equipstr += "lower head, "; + equipstr += "lower head, "_s; if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == EPOS::HAT) - equipstr += "top head, "; + equipstr += "top head, "_s; if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == (EPOS::HAT | EPOS::LEGS)) - equipstr += "lower/top head, "; + equipstr += "lower/top head, "_s; if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == EPOS::TORSO) - equipstr += "mid head, "; + equipstr += "mid head, "_s; if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == (EPOS::TORSO | EPOS::LEGS)) - equipstr += "lower/mid head, "; + equipstr += "lower/mid head, "_s; if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) - equipstr += "lower/mid/top head, "; + equipstr += "lower/mid/top head, "_s; // remove final ', ' equipstr.pop_back(2); } @@ -3918,35 +3925,35 @@ ATCE atcommand_character_item_list(Session *s, dumb_ptr<map_session_data> sd, AString output; if (true) - output = STRPRINTF("%d %s (%s, id: %d) %s", - pl_sd->status.inventory[i].amount, - item_data->name, item_data->jname, - pl_sd->status.inventory[i].nameid, - AString(equipstr)); + output = STRPRINTF("%d %s (%s, id: %d) %s"_fmt, + pl_sd->status.inventory[i].amount, + item_data->name, item_data->jname, + pl_sd->status.inventory[i].nameid, + AString(equipstr)); clif_displaymessage(s, output); // snip cards } } if (count == 0) - clif_displaymessage(s, "No item found on this player."); + clif_displaymessage(s, "No item found on this player."_s); else { AString output = STRPRINTF( - "%d item(s) found in %d kind(s) of items.", + "%d item(s) found in %d kind(s) of items."_fmt, counter, count); clif_displaymessage(s, output); } } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -3957,74 +3964,74 @@ static ATCE atcommand_character_storage_list(Session *s, dumb_ptr<map_session_data> sd, ZString message) { - struct storage *stor; - struct item_data *item_data = NULL; - int i, count, counter; + Storage *stor; + struct item_data *item_data = nullptr; + int count, counter; CharName character; if (!asplit(message, &character)) return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can look items only lower or same level - if ((stor = account2storage2(pl_sd->status_key.account_id)) != NULL) + if ((stor = account2storage2(pl_sd->status_key.account_id)) != nullptr) { counter = 0; count = 0; - for (i = 0; i < MAX_STORAGE; i++) + for (SOff0 i : SOff0::iter()) { - if (stor->storage_[i].nameid > 0 + if (stor->storage_[i].nameid && (item_data = - itemdb_search(stor->storage_[i].nameid)) != NULL) + itemdb_search(stor->storage_[i].nameid)) != nullptr) { counter = counter + stor->storage_[i].amount; count++; if (count == 1) { AString output = STRPRINTF( - "------ Storage items list of '%s' ------", + "------ Storage items list of '%s' ------"_fmt, pl_sd->status_key.name); clif_displaymessage(s, output); } AString output; if (true) - output = STRPRINTF("%d %s (%s, id: %d)", - stor->storage_[i].amount, - item_data->name, item_data->jname, - stor->storage_[i].nameid); + output = STRPRINTF("%d %s (%s, id: %d)"_fmt, + stor->storage_[i].amount, + item_data->name, item_data->jname, + stor->storage_[i].nameid); clif_displaymessage(s, output); } } if (count == 0) clif_displaymessage(s, - "No item found in the storage of this player."); + "No item found in the storage of this player."_s); else { AString output = STRPRINTF( - "%d item(s) found in %d kind(s) of items.", + "%d item(s) found in %d kind(s) of items."_fmt, counter, count); clif_displaymessage(s, output); } } else { - clif_displaymessage(s, "This player has no storage."); + clif_displaymessage(s, "This player has no storage."_s); return ATCE::OKAY; } } else { - clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."); + clif_displaymessage(s, "Your GM level don't authorise you to do this action on this player."_s); return ATCE::PERM; } } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -4038,9 +4045,9 @@ ATCE atcommand_killer(Session *s, dumb_ptr<map_session_data> sd, sd->special_state.killer = !sd->special_state.killer; if (sd->special_state.killer) - clif_displaymessage(s, "You be a killa..."); + clif_displaymessage(s, "You be a killa..."_s); else - clif_displaymessage(s, "You gonna be own3d..."); + clif_displaymessage(s, "You gonna be own3d..."_s); return ATCE::OKAY; } @@ -4055,20 +4062,20 @@ ATCE atcommand_charkiller(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd == NULL) + if (pl_sd == nullptr) return ATCE::EXIST; pl_sd->special_state.killer = !pl_sd->special_state.killer; if (pl_sd->special_state.killer) { - clif_displaymessage(s, "The player is now a killer"); - clif_displaymessage(pl_sd->sess, "You are now a killer"); + clif_displaymessage(s, "The player is now a killer"_s); + clif_displaymessage(pl_sd->sess, "You are now a killer"_s); } else { - clif_displaymessage(s, "The player is no longer a killer"); - clif_displaymessage(pl_sd->sess, "You are no longer a killer"); + clif_displaymessage(s, "The player is no longer a killer"_s); + clif_displaymessage(pl_sd->sess, "You are no longer a killer"_s); } return ATCE::OKAY; @@ -4081,9 +4088,9 @@ ATCE atcommand_killable(Session *s, dumb_ptr<map_session_data> sd, sd->special_state.killable = !sd->special_state.killable; if (sd->special_state.killable) - clif_displaymessage(s, "You gonna be own3d..."); + clif_displaymessage(s, "You gonna be own3d..."_s); else - clif_displaymessage(s, "You be a killa..."); + clif_displaymessage(s, "You be a killa..."_s); return ATCE::OKAY; } @@ -4098,15 +4105,15 @@ ATCE atcommand_charkillable(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd == NULL) + if (pl_sd == nullptr) return ATCE::EXIST; pl_sd->special_state.killable = !pl_sd->special_state.killable; if (pl_sd->special_state.killable) - clif_displaymessage(s, "The player is now killable"); + clif_displaymessage(s, "The player is now killable"_s); else - clif_displaymessage(s, "The player is no longer killable"); + clif_displaymessage(s, "The player is no longer killable"_s); return ATCE::OKAY; } @@ -4117,13 +4124,13 @@ ATCE atcommand_npcmove(Session *, dumb_ptr<map_session_data>, { NpcName character; int x = 0, y = 0; - dumb_ptr<npc_data> nd = 0; + dumb_ptr<npc_data> nd = nullptr; if (!asplit(message, &x, &y, &character)) return ATCE::USAGE; nd = npc_name2id(character); - if (nd == NULL) + if (nd == nullptr) return ATCE::EXIST; npc_enable(character, 0); @@ -4146,17 +4153,17 @@ ATCE atcommand_addwarp(Session *s, dumb_ptr<map_session_data> sd, if (!extract(message, record<' '>(&mapname, &x, &y))) return ATCE::USAGE; - AString w1 = STRPRINTF("%s,%d,%d", sd->mapname_, sd->bl_x, sd->bl_y); - AString w3 = STRPRINTF("%s%d%d%d%d", mapname, sd->bl_x, sd->bl_y, x, y); - AString w4 = STRPRINTF("1,1,%s.gat,%d,%d", mapname, x, y); + AString w1 = STRPRINTF("%s,%d,%d"_fmt, sd->mapname_, sd->bl_x, sd->bl_y); + AString w3 = STRPRINTF("%s%d%d%d%d"_fmt, mapname, sd->bl_x, sd->bl_y, x, y); + AString w4 = STRPRINTF("1,1,%s.gat,%d,%d"_fmt, mapname, x, y); NpcName w3name = stringish<NpcName>(w3); - int ret = npc_parse_warp(w1, ZString("warp"), w3name, w4); + int ret = npc_parse_warp(w1, "warp"_s, w3name, w4); if (ret) // warp failed return ATCE::RANGE; - AString output = STRPRINTF("New warp NPC => %s", w3); + AString output = STRPRINTF("New warp NPC => %s"_fmt, w3); clif_displaymessage(s, output); return ATCE::OKAY; @@ -4173,11 +4180,11 @@ ATCE atcommand_chareffect(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(target); - if (pl_sd == NULL) + if (pl_sd == nullptr) return ATCE::EXIST; clif_specialeffect(pl_sd, type, 0); - clif_displaymessage(s, "Your Effect Has Changed."); + clif_displaymessage(s, "Your Effect Has Changed."_s); return ATCE::OKAY; } @@ -4186,8 +4193,7 @@ static ATCE atcommand_dropall(Session *, dumb_ptr<map_session_data> sd, ZString) { - int i; - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (sd->status.inventory[i].amount) { @@ -4208,9 +4214,9 @@ ATCE atcommand_chardropall(Session *s, dumb_ptr<map_session_data>, if (!asplit(message, &character)) return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd == NULL) + if (pl_sd == nullptr) return ATCE::EXIST; - for (int i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (pl_sd->status.inventory[i].amount) { @@ -4220,9 +4226,8 @@ ATCE atcommand_chardropall(Session *s, dumb_ptr<map_session_data>, } } - clif_displaymessage(pl_sd->sess, "Ever play 52 card pickup?"); - clif_displaymessage(s, "It is done"); - //clif_displaymessage(s, "It is offical.. your a jerk"); + clif_displaymessage(pl_sd->sess, "Ever play 52 card pickup?"_s); + clif_displaymessage(s, "It is official.. you're a jerk."_s); return ATCE::OKAY; } @@ -4231,8 +4236,6 @@ static ATCE atcommand_storeall(Session *s, dumb_ptr<map_session_data> sd, ZString) { - int i; - if (!sd->state.storage_open) { //Open storage. @@ -4240,16 +4243,16 @@ ATCE atcommand_storeall(Session *s, dumb_ptr<map_session_data> sd, { case 2: //Try again - clif_displaymessage(s, "run this command again.."); + clif_displaymessage(s, "run this command again.."_s); return ATCE::OKAY; case 1: //Failure clif_displaymessage(s, - "You can't open the storage currently."); + "You can't open the storage currently."_s); return ATCE::EXIST; } } - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (sd->status.inventory[i].amount) { @@ -4260,7 +4263,7 @@ ATCE atcommand_storeall(Session *s, dumb_ptr<map_session_data> sd, } storage_storageclose(sd); - clif_displaymessage(s, "It is done"); + clif_displaymessage(s, "It is done"_s); return ATCE::OKAY; } @@ -4273,7 +4276,7 @@ ATCE atcommand_charstoreall(Session *s, dumb_ptr<map_session_data> sd, if (!asplit(message, &character)) return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd == NULL) + if (pl_sd == nullptr) return ATCE::EXIST; if (storage_storageopen(pl_sd) == 1) @@ -4281,11 +4284,11 @@ ATCE atcommand_charstoreall(Session *s, dumb_ptr<map_session_data> sd, // TODO figure out what the hell this is talking about, // and especially why it's different from the other one. clif_displaymessage(s, - "Had to open the characters storage window..."); - clif_displaymessage(s, "run this command again.."); + "Had to open the characters storage window..."_s); + clif_displaymessage(s, "run this command again.."_s); return ATCE::OKAY; } - for (int i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (pl_sd->status.inventory[i].amount) { @@ -4297,12 +4300,12 @@ ATCE atcommand_charstoreall(Session *s, dumb_ptr<map_session_data> sd, storage_storageclose(pl_sd); clif_displaymessage(pl_sd->sess, - "Everything you own has been put away for safe keeping."); + "Everything you own has been put away for safe keeping."_s); clif_displaymessage(pl_sd->sess, - "go to the nearest kafka to retrieve it.."); - clif_displaymessage(pl_sd->sess, " -- the management"); + "go to the nearest kafka to retrieve it.."_s); + clif_displaymessage(pl_sd->sess, " -- the management"_s); - clif_displaymessage(s, "It is done"); + clif_displaymessage(s, "It is done"_s); return ATCE::OKAY; } @@ -4383,31 +4386,30 @@ ATCE atcommand_summon(Session *, dumb_ptr<map_session_data> sd, ZString message) { MobName name; - int mob_id = 0; + Species mob_id; int x = 0; int y = 0; - int id = 0; tick_t tick = gettick(); if (!extract(message, &name) || !name) return ATCE::USAGE; - if ((mob_id = atoi(name.c_str())) == 0) + if ((mob_id = wrap<Species>(static_cast<uint16_t>(atoi(name.c_str())))) == Species()) mob_id = mobdb_searchname(name); - if (mob_id == 0) + if (mob_id == Species()) return ATCE::EXIST; x = sd->bl_x + random_::in(-5, 4); y = sd->bl_y + random_::in(-5, 4); - id = mob_once_spawn(sd, MOB_THIS_MAP, x, y, JAPANESE_NAME, mob_id, 1, NpcEvent()); + BlockId id = mob_once_spawn(sd, MOB_THIS_MAP, x, y, JAPANESE_NAME, mob_id, 1, NpcEvent()); dumb_ptr<mob_data> md = map_id_is_mob(id); if (md) { md->master_id = sd->bl_id; md->state.special_mob_ai = 1; - md->mode = mob_db[md->mob_class].mode | MobMode::AGGRESSIVE; - md->deletetimer = Timer(tick + std::chrono::minutes(1), + md->mode = get_mob_db(md->mob_class).mode | MobMode::AGGRESSIVE; + md->deletetimer = Timer(tick + 1_min, std::bind(mob_timer_delete, ph::_1, ph::_2, id)); clif_misceffect(md, 344); @@ -4420,12 +4422,12 @@ static ATCE atcommand_adjcmdlvl(Session *s, dumb_ptr<map_session_data>, ZString message) { - int newlev; + GmLevel newlev; XString cmd; if (!extract(message, record<' '>(&newlev, &cmd))) { - clif_displaymessage(s, "usage: @adjcmdlvl <lvl> <command>."); + clif_displaymessage(s, "usage: @adjcmdlvl <lvl> <command>."_s); return ATCE::USAGE; } @@ -4434,12 +4436,12 @@ ATCE atcommand_adjcmdlvl(Session *s, dumb_ptr<map_session_data>, if (it) { it->level = newlev; - clif_displaymessage(s, "@command level changed."); + clif_displaymessage(s, "@command level changed."_s); return ATCE::OKAY; } } - clif_displaymessage(s, "@command not found."); + clif_displaymessage(s, "@command not found."_s); return ATCE::EXIST; } @@ -4447,18 +4449,17 @@ static ATCE atcommand_adjgmlvl(Session *s, dumb_ptr<map_session_data>, ZString message) { - int newlev; + GmLevel newlev; CharName user; - if (!asplit(message, &newlev, &user) - || newlev < 0 || newlev > 99) + if (!asplit(message, &newlev, &user)) { - clif_displaymessage(s, "usage: @adjgmlvl <lvl> <user>."); + clif_displaymessage(s, "usage: @adjgmlvl <lvl> <user>."_s); return ATCE::USAGE; } dumb_ptr<map_session_data> pl_sd = map_nick2sd(user); - if (pl_sd == NULL) + if (pl_sd == nullptr) return ATCE::EXIST; pc_set_gm_level(pl_sd->status_key.account_id, newlev); @@ -4501,14 +4502,14 @@ constexpr size_t magic_skills_nr = sizeof(magic_skills) / sizeof(magic_skills[0]); static -ZString magic_skill_names[magic_skills_nr] = +LString magic_skill_names[magic_skills_nr] = { - {"magic"}, - {"life"}, - {"war"}, - {"transmute"}, - {"nature"}, - {"astral"}, + "magic"_s, + "life"_s, + "war"_s, + "transmute"_s, + "nature"_s, + "astral"_s, }; static @@ -4524,7 +4525,7 @@ ATCE atcommand_magic_info(Session *s, dumb_ptr<map_session_data>, if (pl_sd) { AString buf = STRPRINTF( - "`%s' has the following magic skills:", + "`%s' has the following magic skills:"_fmt, character); clif_displaymessage(s, buf); @@ -4532,7 +4533,7 @@ ATCE atcommand_magic_info(Session *s, dumb_ptr<map_session_data>, { SkillID sk = magic_skills[i]; buf = STRPRINTF( - "%d in %s", + "%d in %s"_fmt, pl_sd->status.skill[sk].lv, magic_skill_names[i]); if (pl_sd->status.skill[sk].lv) @@ -4542,7 +4543,7 @@ ATCE atcommand_magic_info(Session *s, dumb_ptr<map_session_data>, return ATCE::OKAY; } - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -4563,12 +4564,12 @@ ATCE atcommand_set_magic(Session *s, dumb_ptr<map_session_data>, if (!asplit(message, &magic_type, &value, &character)) { clif_displaymessage(s, - "Usage: @setmagic <school> <value> <char-name>, where <school> is either `magic', one of the school names, or `all'."); + "Usage: @setmagic <school> <value> <char-name>, where <school> is either `magic', one of the school names, or `all'."_s); return ATCE::USAGE; } SkillID skill_index = SkillID::NEGATIVE; - if ("all" == magic_type) + if ("all"_s == magic_type) skill_index = SkillID::ZERO; else { @@ -4585,12 +4586,12 @@ ATCE atcommand_set_magic(Session *s, dumb_ptr<map_session_data>, if (skill_index == SkillID::NEGATIVE) { clif_displaymessage(s, - "Incorrect school of magic. Use `magic', `nature', `life', `war', `transmute', `ether', or `all'."); + "Incorrect school of magic. Use `magic', `nature', `life', `war', `transmute', `ether', or `all'."_s); return ATCE::RANGE; } dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { if (skill_index == SkillID::ZERO) for (SkillID sk : magic_skills) @@ -4602,7 +4603,7 @@ ATCE atcommand_set_magic(Session *s, dumb_ptr<map_session_data>, return ATCE::OKAY; } - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -4661,21 +4662,21 @@ ATCE atcommand_jump_iterate(Session *s, dumb_ptr<map_session_data> sd, } if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARPTO) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp you to the map of this player."); + "You are not authorised to warp you to the map of this player."_s); return ATCE::PERM; } if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARP) - && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, - "You are not authorised to warp you from your actual map."); + "You are not authorised to warp you from your actual map."_s); return ATCE::PERM; } pc_setpos(sd, pl_sd->bl_m->name_, pl_sd->bl_x, pl_sd->bl_y, BeingRemoveWhy::WARPED); - AString output = STRPRINTF("Jump to %s", pl_sd->status_key.name); + AString output = STRPRINTF("Jump to %s"_fmt, pl_sd->status_key.name); clif_displaymessage(s, output); sd->followtarget = pl_sd->bl_id; @@ -4702,9 +4703,9 @@ ATCE atcommand_wgm(Session *s, dumb_ptr<map_session_data> sd, if (tmw_CheckChatSpam(sd, message)) return ATCE::OKAY; - tmw_GmHackMsg(STRPRINTF("[GM] %s: %s", sd->status_key.name, message)); + tmw_GmHackMsg(STRPRINTF("[GM] %s: %s"_fmt, sd->status_key.name, message)); if (!pc_isGM(sd)) - clif_displaymessage(s, "Message sent."); + clif_displaymessage(s, "Message sent."_s); return ATCE::OKAY; } @@ -4720,26 +4721,26 @@ ATCE atcommand_skillpool_info(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { SkillID pool_skills[MAX_SKILL_POOL]; int pool_skills_nr = skill_pool(pl_sd, pool_skills); int i; AString buf = STRPRINTF( - "Active skills %d out of %d for %s:", + "Active skills %d out of %d for %s:"_fmt, pool_skills_nr, skill_pool_max(pl_sd), character); clif_displaymessage(s, buf); for (i = 0; i < pool_skills_nr; ++i) { - buf = STRPRINTF(" - %s [%d]: power %d", + buf = STRPRINTF(" - %s [%d]: power %d"_fmt, skill_name(pool_skills[i]), pool_skills[i], skill_power(pl_sd, pool_skills[i])); clif_displaymessage(s, buf); } - buf = STRPRINTF("Learned skills out of %d for %s:", + buf = STRPRINTF("Learned skills out of %d for %s:"_fmt, skill_pool_skills_size, character); clif_displaymessage(s, buf); @@ -4750,7 +4751,7 @@ ATCE atcommand_skillpool_info(Session *s, dumb_ptr<map_session_data>, if (lvl) { - buf = STRPRINTF(" - %s [%d]: lvl %d", + buf = STRPRINTF(" - %s [%d]: lvl %d"_fmt, name, skill_pool_skills[i], lvl); clif_displaymessage(s, buf); } @@ -4759,7 +4760,7 @@ ATCE atcommand_skillpool_info(Session *s, dumb_ptr<map_session_data>, } else { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -4775,20 +4776,20 @@ ATCE atcommand_skillpool_focus(Session *s, dumb_ptr<map_session_data>, if (!asplit(message, &skill, &character)) { - clif_displaymessage(s, "Usage: @sp-focus <skill-nr> <char_name>"); + clif_displaymessage(s, "Usage: @sp-focus <skill-nr> <char_name>"_s); return ATCE::USAGE; } dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { if (skill_pool_activate(pl_sd, skill)) - clif_displaymessage(s, "Activation failed."); + clif_displaymessage(s, "Activation failed."_s); else - clif_displaymessage(s, "Activation successful."); + clif_displaymessage(s, "Activation successful."_s); } else - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::OKAY; } @@ -4804,15 +4805,15 @@ ATCE atcommand_skillpool_unfocus(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { if (skill_pool_deactivate(pl_sd, skill)) - clif_displaymessage(s, "Deactivation failed."); + clif_displaymessage(s, "Deactivation failed."_s); else - clif_displaymessage(s, "Deactivation successful."); + clif_displaymessage(s, "Deactivation successful."_s); } else - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::OKAY; } @@ -4829,13 +4830,13 @@ ATCE atcommand_skill_learn(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd != NULL) + if (pl_sd != nullptr) { set_skill(pl_sd, skill, level); clif_skillinfoblock(pl_sd); } else - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::OKAY; } @@ -4850,9 +4851,9 @@ ATCE atcommand_ipcheck(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd == NULL) + if (pl_sd == nullptr) { - clif_displaymessage(s, "Character not found."); + clif_displaymessage(s, "Character not found."_s); return ATCE::EXIST; } @@ -4873,7 +4874,7 @@ ATCE atcommand_ipcheck(Session *s, dumb_ptr<map_session_data>, if (ip == pl_sd->get_ip()) { AString output = STRPRINTF( - "Name: %s | Location: %s %d %d", + "Name: %s | Location: %s %d %d"_fmt, pl_sd->status_key.name, pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y); clif_displaymessage(s, output); @@ -4881,7 +4882,7 @@ ATCE atcommand_ipcheck(Session *s, dumb_ptr<map_session_data>, } } - clif_displaymessage(s, "End of list"); + clif_displaymessage(s, "End of list"_s); return ATCE::OKAY; } @@ -4898,14 +4899,14 @@ ATCE atcommand_doomspot(Session *s, dumb_ptr<map_session_data> sd, if (pl_sd && pl_sd->state.auth && s2 != s && sd->bl_m == pl_sd->bl_m && sd->bl_x == pl_sd->bl_x && sd->bl_y == pl_sd->bl_y - && pc_isGM(sd) >= pc_isGM(pl_sd)) + && pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can doom only lower or same gm level - pc_damage(NULL, pl_sd, pl_sd->status.hp + 1); - clif_displaymessage(pl_sd->sess, "The holy messenger has given judgement."); + pc_damage(nullptr, pl_sd, pl_sd->status.hp + 1); + clif_displaymessage(pl_sd->sess, "The holy messenger has given judgement."_s); } } - clif_displaymessage(s, "Judgement was made."); + clif_displaymessage(s, "Judgement was made."_s); return ATCE::OKAY; } @@ -4915,13 +4916,13 @@ ATCE atcommand_source(Session *s, dumb_ptr<map_session_data>, ZString) { clif_displaymessage(s, - "This server code consists of Free Software under GPL3&AGPL3"); + "This server code consists of Free Software under GPL3&AGPL3"_s); clif_displaymessage(s, - "This is commit " VERSION_HASH ", also known as " VERSION_FULL); + "This is commit " VERSION_HASH ", also known as " VERSION_FULL ""_s); clif_displaymessage(s, - "The version is " VERSION_STRING); + "The version is " VERSION_STRING ""_s); clif_displaymessage(s, - "For source, see " VENDOR_SOURCE); + "For source, see " VENDOR_SOURCE ""_s); return ATCE::OKAY; } @@ -4931,424 +4932,425 @@ ATCE atcommand_source(Session *s, dumb_ptr<map_session_data>, // declared extern above Map<XString, AtCommandInfo> atcommand_info = { - {"help", {"[level[-level]|category|@command]", + {"help"_s, {"[level[-level]|category|@command]"_s, 0, atcommand_help, - "Show help"}}, - {"setup", {"<level> <charname>", + "Show help"_s}}, + {"setup"_s, {"<level> <charname>"_s, 40, atcommand_setup, - "Safely set a chars levels and warp them to a special place (for TAW)"}}, - {"charwarp", {"<mapname> <x> <y> <charname>", + "Safely set a chars levels and warp them to a special place (for TAW)"_s}}, + {"charwarp"_s, {"<mapname> <x> <y> <charname>"_s, 60, atcommand_charwarp, - "Warp a character to a point on another map"}}, - {"warp", {"<mapname> [x] [y]", + "Warp a character to a point on another map"_s}}, + {"warp"_s, {"<mapname> [x] [y]"_s, 40, atcommand_warp, - "Warp yourself to another map"}}, - {"where", {"[charname]", + "Warp yourself to another map"_s}}, + {"where"_s, {"[charname]"_s, 40, atcommand_where, - "Show location of a character or yourself"}}, - {"goto", {"<charname>", + "Show location of a character or yourself"_s}}, + {"goto"_s, {"<charname>"_s, 40, atcommand_goto, - "Warp yourself to another character"}}, - {"jump", {"[x] [y]", + "Warp yourself to another character"_s}}, + {"jump"_s, {"[x] [y]"_s, 40, atcommand_jump, - "Warp yourself within a map"}}, - {"who", {"[subsequence]", + "Warp yourself within a map"_s}}, + {"who"_s, {"[subsequence]"_s, 40, atcommand_who, - "List matching players online, with location info"}}, - {"whogroup", {"[subsequence]", + "List matching players online, with location info"_s}}, + {"whogroup"_s, {"[subsequence]"_s, 40, atcommand_whogroup, - "List matching players online, with party info"}}, - {"whomap", {"[mapname]", + "List matching players online, with party info"_s}}, + {"whomap"_s, {"[mapname]"_s, 40, atcommand_whomap, - "List all players on the map, with location info"}}, - {"whomapgroup", {"[mapname]", + "List all players on the map, with location info"_s}}, + {"whomapgroup"_s, {"[mapname]"_s, 40, atcommand_whomapgroup, - "List all players on the map, with party info"}}, - {"whogm", {"[subsequence]", + "List all players on the map, with party info"_s}}, + {"whogm"_s, {"[subsequence]"_s, 40, atcommand_whogm, - "List matching GM players, with location, level, and party info"}}, - {"save", {"", + "List matching GM players, with location, level, and party info"_s}}, + {"save"_s, {""_s, 40, atcommand_save, - "Set your respawn point to your current location"}}, - {"return", {"", + "Set your respawn point to your current location"_s}}, + {"return"_s, {""_s, 40, atcommand_load, - "Return to your respawn point"}}, - {"load", {"", + "Return to your respawn point"_s}}, + {"load"_s, {""_s, 40, atcommand_load, - "Return to your respawn point"}}, - {"speed", {"<rate>", + "Return to your respawn point"_s}}, + {"speed"_s, {"<rate>"_s, 60, atcommand_speed, - "Set walk rate"}}, - {"storage", {"", + "Set walk rate"_s}}, + {"storage"_s, {""_s, 99, atcommand_storage, - "Open your storage"}}, - {"option", {"<opt1> [opt2] [option]", + "Open your storage"_s}}, + {"option"_s, {"<opt1> [opt2] [option]"_s, 80, atcommand_option, - "Set your 'option' status flags"}}, - {"hide", {"", + "Set your 'option' status flags"_s}}, + {"hide"_s, {""_s, 40, atcommand_hide, - "Toggle invisibility from monsters and certain commands"}}, - {"die", {"", + "Toggle invisibility from monsters and certain commands"_s}}, + {"die"_s, {""_s, 40, atcommand_die, - "Cause fatal damage to yourself"}}, - {"kill", {"<charname>", + "Cause fatal damage to yourself"_s}}, + {"kill"_s, {"<charname>"_s, 60, atcommand_kill, - "Cause fatal damage to another player"}}, - {"alive", {"", + "Cause fatal damage to another player"_s}}, + {"alive"_s, {""_s, 60, atcommand_alive, - "Restore life to yourself"}}, - {"kami", {"<message ...>", + "Restore life to yourself"_s}}, + {"kami"_s, {"<message ...>"_s, 99, atcommand_kami, - "Send an anonymous broadcast"}}, - {"heal", {"[hp] [sp]", + "Send an anonymous broadcast"_s}}, + {"heal"_s, {"[hp] [sp]"_s, 40, atcommand_heal, - "Restore or destroy your health"}}, - {"item", {"<item-name-or-id> [count]", + "Restore or destroy your health"_s}}, + {"item"_s, {"<item-name-or-id> [count]"_s, 80, atcommand_item, - "Summon items out of the void"}}, - {"itemreset", {"", + "Summon items out of the void"_s}}, + {"itemreset"_s, {""_s, 40, atcommand_itemreset, - "Cast all of your itens into the void (why would you ever want this?)"}}, - {"itemcheck", {"", + "Cast all of your itens into the void (why would you ever want this?)"_s}}, + {"itemcheck"_s, {""_s, 80, atcommand_itemcheck, - "Perform an internal integrity check on your items"}}, - {"blvl", {"<delta>", + "Perform an internal integrity check on your items"_s}}, + {"blvl"_s, {"<delta>"_s, 60, atcommand_baselevelup, - "Adjust your level"}}, - {"jlvl", {"<delta>", + "Adjust your level"_s}}, + {"jlvl"_s, {"<delta>"_s, 60, atcommand_joblevelup, - "Adjust your job level"}}, - {"gm", {"<password>", + "Adjust your job level"_s}}, + {"gm"_s, {"<password>"_s, 100, atcommand_gm, - "Receive GM powers"}}, - {"pvpoff", {"", + "Receive GM powers"_s}}, + {"pvpoff"_s, {""_s, 60, atcommand_pvpoff, - "Enable PvP on your map"}}, - {"pvpon", {"", + "Enable PvP on your map"_s}}, + {"pvpon"_s, {""_s, 60, atcommand_pvpon, - "Disable PvP on your map"}}, - {"model", {"<style> [color] [dye]", + "Disable PvP on your map"_s}}, + {"model"_s, {"<style> [color] [dye]"_s, 99, atcommand_model, - "Change your hairstyle and hair color"}}, - {"spawn", {"<mob-name-or-id> [count] [x] [y]", + "Change your hairstyle and hair color"_s}}, + {"spawn"_s, {"<mob-name-or-id> [count] [x] [y]"_s, 50, atcommand_spawn, - "Spawn normal monsters at location."}}, - {"killmonster", {"[map]", + "Spawn normal monsters at location."_s}}, + {"killmonster"_s, {"[map]"_s, 60, atcommand_killmonster, - "Kill all monsters (with drops)"}}, - {"killmonster2", {"[map]", + "Kill all monsters (with drops)"_s}}, + {"killmonster2"_s, {"[map]"_s, 60, atcommand_killmonster2, - "Kill all monsters (no drops)"}}, - {"gat", {"", + "Kill all monsters (no drops)"_s}}, + {"gat"_s, {""_s, 99, atcommand_gat, - "Dump the local walkmap"}}, - {"packet", {"<type> <flag>", + "Dump the local walkmap"_s}}, + {"packet"_s, {"<type> <flag>"_s, 99, atcommand_packet, - "Force a status change"}}, - {"stpoint", {"<amount>", + "Force a status change"_s}}, + {"stpoint"_s, {"<amount>"_s, 60, atcommand_statuspoint, - "Increase your stat points"}}, - {"skpoint", {"<amount>", + "Increase your stat points"_s}}, + {"skpoint"_s, {"<amount>"_s, 60, atcommand_skillpoint, - "Increase your skill points"}}, - {"zeny", {"<amount>", + "Increase your skill points"_s}}, + {"zeny"_s, {"<amount>"_s, 80, atcommand_zeny, - "Change how much money you have"}}, - {"str", {"<delta>", + "Change how much money you have"_s}}, + {"str"_s, {"<delta>"_s, 60, atcommand_param<ATTR::STR>, - "Adjust your strength"}}, - {"agi", {"<delta>", + "Adjust your strength"_s}}, + {"agi"_s, {"<delta>"_s, 60, atcommand_param<ATTR::AGI>, - "Adjust your agility"}}, - {"vit", {"<delta>", + "Adjust your agility"_s}}, + {"vit"_s, {"<delta>"_s, 60, atcommand_param<ATTR::VIT>, - "Adjust your vitality"}}, - {"int", {"<delta>", + "Adjust your vitality"_s}}, + {"int"_s, {"<delta>"_s, 60, atcommand_param<ATTR::INT>, - "Adjust your intelligence\0(TODO make this work in real life, I'm lonely)"}}, - {"dex", {"<delta>", + "Adjust your intelligence\0(TODO make this work in real life, I'm lonely)"_s}}, + {"dex"_s, {"<delta>"_s, 60, atcommand_param<ATTR::DEX>, - "Adjust your dexterity"}}, - {"luk", {"<delta>", + "Adjust your dexterity"_s}}, + {"luk"_s, {"<delta>"_s, 60, atcommand_param<ATTR::LUK>, - "Adjust your luck"}}, - {"recall", {"<charname>", + "Adjust your luck"_s}}, + {"recall"_s, {"<charname>"_s, 60, atcommand_recall, - "Warp a player to you"}}, - {"revive", {"<charname>", + "Warp a player to you"_s}}, + {"revive"_s, {"<charname>"_s, 60, atcommand_revive, - "Restore a player to full health"}}, - {"charstats", {"<charname>", + "Restore a player to full health"_s}}, + {"charstats"_s, {"<charname>"_s, 40, atcommand_character_stats, - "Show a bunch of stats about a single user"}}, - {"charstatsall", {"", + "Show a bunch of stats about a single user"_s}}, + {"charstatsall"_s, {""_s, 60, atcommand_character_stats_all, - "Show a bunch of stats about all online users"}}, - {"charoption", {"<opt1> <opt2> <opt3> <charname>", + "Show a bunch of stats about all online users"_s}}, + {"charoption"_s, {"<opt1> <opt2> <opt3> <charname>"_s, 80, atcommand_character_option, - "Set option flags on another character"}}, - {"charsave", {"<map> <x> <y> <charname>", + "Set option flags on another character"_s}}, + {"charsave"_s, {"<map> <x> <y> <charname>"_s, 60, atcommand_character_save, - "Set another character's save point"}}, - {"doom", {"", + "Set another character's save point"_s}}, + {"doom"_s, {""_s, 80, atcommand_doom, - "Kill everyone on the server"}}, - {"doommap", {"", + "Kill everyone on the server"_s}}, + {"doommap"_s, {""_s, 80, atcommand_doommap, - "Kill everyone on your map"}}, - {"raise", {"", + "Kill everyone on your map"_s}}, + {"raise"_s, {""_s, 80, atcommand_raise, - "Resurrect all players on the server"}}, - {"raisemap", {"", + "Resurrect all players on the server"_s}}, + {"raisemap"_s, {""_s, 80, atcommand_raisemap, - "Resurrect all players on your map"}}, - {"charbaselvl", {"<delta> <charname>", + "Resurrect all players on your map"_s}}, + {"charbaselvl"_s, {"<delta> <charname>"_s, 60, atcommand_character_baselevel, - "Adjust another character's level"}}, - {"charjlvl", {"<delta> <charname>", + "Adjust another character's level"_s}}, + {"charjlvl"_s, {"<delta> <charname>"_s, 60, atcommand_character_joblevel, - "Adjust another character's job level"}}, - {"kick", {"<charname>", + "Adjust another character's job level"_s}}, + {"kick"_s, {"<charname>"_s, 40, atcommand_kick, - "Transiently kick a player off the server"}}, - {"kickall", {"", + "Transiently kick a player off the server"_s}}, + {"kickall"_s, {""_s, 99, atcommand_kickall, - "Transiently kick all players off the server"}}, - {"questskill", {"<skill-id>", + "Transiently kick all players off the server"_s}}, + {"questskill"_s, {"<skill-id>"_s, 99, atcommand_questskill, - "Give yourself a quest (?) skill"}}, - {"charquestskill", {"<skill-id> <charname>", + "Give yourself a quest (?) skill"_s}}, + {"charquestskill"_s, {"<skill-id> <charname>"_s, 99, atcommand_charquestskill, - "Give another player a quest (?) skill"}}, - {"lostskill", {"<skill-id>", + "Give another player a quest (?) skill"_s}}, + {"lostskill"_s, {"<skill-id>"_s, 80, atcommand_lostskill, - "Take away one of your quest (?) skills"}}, - {"charlostskill", {"<skill-id> <charname>", + "Take away one of your quest (?) skills"_s}}, + {"charlostskill"_s, {"<skill-id> <charname>"_s, 99, atcommand_charlostskill, - "Take away one of another player's quest (?) skills"}}, - {"party", {"<name>", + "Take away one of another player's quest (?) skills"_s}}, + {"party"_s, {"<name>"_s, 99, atcommand_party, - "Create a new party"}}, - {"mapexit", {"", + "Create a new party"_s}}, + {"mapexit"_s, {""_s, 99, atcommand_mapexit, - "Try to kill the server kindly"}}, - {"idsearch", {"<item-subseq>", + "Try to kill the server kindly"_s}}, + {"idsearch"_s, {"<item-subseq>"_s, 80, atcommand_idsearch, - "Search for some items that might match"}}, - {"mapmove", {"<mapname> [x] [y]", + "Search for some items that might match"_s}}, + {"mapmove"_s, {"<mapname> [x] [y]"_s, 40, atcommand_warp, - "Warp to a different map"}}, - {"broadcast", {"<message ...>", + "Warp to a different map"_s}}, + {"broadcast"_s, {"<message ...>"_s, 40, atcommand_broadcast, - "Broadcast a message from you"}}, - {"localbroadcast", {"<message ...>", + "Broadcast a message from you"_s}}, + {"localbroadcast"_s, {"<message ...>"_s, 40, atcommand_localbroadcast, - "Broadcast a message from you locally"}}, - {"recallall", {"", + "Broadcast a message from you locally"_s}}, + {"recallall"_s, {""_s, 80, atcommand_recallall, - "Warp every online player to your current map"}}, - {"charskreset", {"<charname>", + "Warp every online player to your current map"_s}}, + {"charskreset"_s, {"<charname>"_s, 60, atcommand_charskreset, - "Reset a player's skill points"}}, - {"charstreset", {"<charname>", + "Reset a player's skill points"_s}}, + {"charstreset"_s, {"<charname>"_s, 60, atcommand_charstreset, - "Reset a player's stat points"}}, - {"charreset", {"<charname>", + "Reset a player's stat points"_s}}, + {"charreset"_s, {"<charname>"_s, 60, atcommand_charreset, - "Reset a player's skills, stats, and magic"}}, - {"charmodel", {"<hairstyle> <hair-color> <dye> <charname>", + "Reset a player's skills, stats, and magic"_s}}, + {"charmodel"_s, {"<hairstyle> <hair-color> <dye> <charname>"_s, 99, atcommand_charmodel, - "Change another character's appearance"}}, - {"charskpoint", {"<amount> <charname>", + "Change another character's appearance"_s}}, + {"charskpoint"_s, {"<amount> <charname>"_s, 60, atcommand_charskpoint, - "Adjust another player's skill points"}}, - {"charstpoint", {"<amount> <charname>", + "Adjust another player's skill points"_s}}, + {"charstpoint"_s, {"<amount> <charname>"_s, 60, atcommand_charstpoint, - "Adjust another player's stat points"}}, - {"charzeny", {"<delta> <charname>", + "Adjust another player's stat points"_s}}, + {"charzeny"_s, {"<delta> <charname>"_s, 80, atcommand_charzeny, - "Adjust another player's money"}}, - {"mapinfo", {"<0-2> [map]", + "Adjust another player's money"_s}}, + {"mapinfo"_s, {"<0-2> [map]"_s, 99, atcommand_mapinfo, - "Show some stats for the map. 1 also shows players, 2 also shows NPCs"}}, - {"dye", {"<dye>", + "Show some stats for the map. 1 also shows players, 2 also shows NPCs"_s}}, + {"dye"_s, {"<dye>"_s, 40, atcommand_dye, - "Don't use"}}, - {"ccolor", {"<dye>", + "Don't use"_s}}, + {"ccolor"_s, {"<dye>"_s, 40, atcommand_dye, - "Don't use"}}, - {"hairstyle", {"<style>", + "Don't use"_s}}, + {"hairstyle"_s, {"<style>"_s, 40, atcommand_hair_style, - "Change your hairstyle"}}, - {"haircolor", {"<color>", + "Change your hairstyle"_s}}, + {"haircolor"_s, {"<color>"_s, 40, atcommand_hair_color, - "Change your hair color"}}, - {"allstats", {"[value]", + "Change your hair color"_s}}, + {"allstats"_s, {"[value]"_s, 60, atcommand_all_stats, - "Adjust all stats by value (or maximum)"}}, - {"charchangesex", {"<charname>", + "Adjust all stats by value (or maximum)"_s}}, + {"charchangesex"_s, {"<charname>"_s, 60, atcommand_char_change_sex, - "Flip a characters sex and disconnect them"}}, - {"block", {"<charname>", + "Flip a characters sex and disconnect them"_s}}, + {"block"_s, {"<charname>"_s, 60, atcommand_char_block, - "Permanently block a player's account from the server"}}, - {"unblock", {"<charname>", + "Permanently block a player's account from the server"_s}}, + {"unblock"_s, {"<charname>"_s, 60, atcommand_char_unblock, - "Remove a permanent block from a player's account"}}, - {"ban", {"<timedelta> <charname>", + "Remove a permanent block from a player's account"_s}}, + {"ban"_s, {"<timedelta> <charname>"_s, 60, atcommand_char_ban, - "Ban a player's account from the server for a limited time"}}, - {"unban", {"<timedelta> <charname>", + "Ban a player's account from the server for a limited time"_s}}, + {"unban"_s, {"<timedelta> <charname>"_s, 60, atcommand_char_unban, - "Remove a limited ban from a player's account"}}, - {"partyspy", {"<party-name-or-id>", + "Remove a limited ban from a player's account"_s}}, + {"partyspy"_s, {"<party-name-or-id>"_s, 99, atcommand_partyspy, - "Listen to all chat within a party"}}, - {"partyrecall", {"<party-name-or-id>", + "Listen to all chat within a party"_s}}, + {"partyrecall"_s, {"<party-name-or-id>"_s, 99, atcommand_partyrecall, - "Warp all members of a party to you"}}, - {"enablenpc", {"<npc-name>", + "Warp all members of a party to you"_s}}, + {"enablenpc"_s, {"<npc-name>"_s, 80, atcommand_enablenpc, - "Enable an NPC for visibility"}}, - {"disablenpc", {"<npc-name>", + "Enable an NPC for visibility"_s}}, + {"disablenpc"_s, {"<npc-name>"_s, 80, atcommand_disablenpc, - "Disable an NPC for visibility"}}, - {"servertime", {"", + "Disable an NPC for visibility"_s}}, + {"servertime"_s, {""_s, 0, atcommand_servertime, - "Print the server's idea of the current time"}}, - {"chardelitem", {"<item-name-or-id> <count> <charname>", + "Print the server's idea of the current time"_s}}, + {"chardelitem"_s, {"<item-name-or-id> <count> <charname>"_s, 60, atcommand_chardelitem, - "Delete items from a player's inventory"}}, - {"listnearby", {"", + "Delete items from a player's inventory"_s}}, + {"listnearby"_s, {""_s, 40, atcommand_list_nearby, - "Print name of all nearby players"}}, - {"email", {"<actual@email> <new@email>", + "Print name of all nearby players"_s}}, + {"email"_s, {"<actual@email> <new@email>"_s, 0, atcommand_email, - "Changed your account's email"}}, - {"effect", {"<type> <flag>", + "Changed your account's email"_s}}, + {"effect"_s, {"<type> <flag>"_s, 99, atcommand_effect, - "Apply a special effect to yourself (or everyone! wtf?)"}}, - {"charitemlist", {"<charname>", + "Apply a special effect to yourself (or everyone! wtf?)"_s}}, + {"charitemlist"_s, {"<charname>"_s, 99, atcommand_character_item_list, - "List a player's items"}}, - {"charstoragelist", {"<charname>", + "List a player's items"_s}}, + {"charstoragelist"_s, {"<charname>"_s, 99, atcommand_character_storage_list, - "List a player's storage"}}, - {"addwarp", {"<mapname> <x> <y>", + "List a player's storage"_s}}, + {"addwarp"_s, {"<mapname> <x> <y>"_s, 80, atcommand_addwarp, - "Create a new permanent warp"}}, - {"killer", {"", + "Create a new permanent warp"_s}}, + {"killer"_s, {""_s, 60, atcommand_killer, - "Toggle whether you are a killer"}}, - {"charkiller", {"<charname>", + "Toggle whether you are a killer"_s}}, + {"charkiller"_s, {"<charname>"_s, 60, atcommand_charkiller, - "Toggle whether a player is a killer"}}, - {"npcmove", {"<x> <y> <npc-name>", + "Toggle whether a player is a killer"_s}}, + {"npcmove"_s, {"<x> <y> <npc-name>"_s, 80, atcommand_npcmove, - "Force an NPC to move on the map"}}, - {"killable", {"", + "Force an NPC to move on the map"_s}}, + {"killable"_s, {""_s, 60, atcommand_killable, - "Toggle whether you are killable"}}, - {"charkillable", {"<charname>", + "Toggle whether you are killable"_s}}, + {"charkillable"_s, {"<charname>"_s, 60, atcommand_charkillable, - "Toggle whether a player is killable"}}, - {"chareffect", {"<type> <target>", + "Toggle whether a player is killable"_s}}, + {"chareffect"_s, {"<type> <target>"_s, 40, atcommand_chareffect, - "Apply effect type with arg 0 to a player"}}, - {"dropall", {"", + "Apply effect type with arg 0 to a player"_s}}, + {"dropall"_s, {""_s, 99, atcommand_dropall, - "Drop all of your items"}}, - {"chardropall", {"<charname>", + "Drop all of your items"_s}}, + {"chardropall"_s, {"<charname>"_s, 60, atcommand_chardropall, - "Force a player to drop all of their items"}}, - {"storeall", {"", + "Force a player to drop all of their items"_s}}, + {"storeall"_s, {""_s, 60, atcommand_storeall, - "Store all of your items"}}, - {"charstoreall", {"<charname>", + "Store all of your items"_s}}, + {"charstoreall"_s, {"<charname>"_s, 60, atcommand_charstoreall, - "Store all of a player's items"}}, - {"rain", {"", + "Store all of a player's items"_s}}, + {"rain"_s, {""_s, 99, atcommand_rain, - "Enable the rain mapflag"}}, - {"snow", {"", + "Enable the rain mapflag"_s}}, + {"snow"_s, {""_s, 99, atcommand_snow, - "Enable the snow mapflag"}}, - {"sakura", {"", + "Enable the snow mapflag"_s}}, + {"sakura"_s, {""_s, 99, atcommand_sakura, - "Enable the sakura mapflag"}}, - {"fog", {"", + "Enable the sakura mapflag"_s}}, + {"fog"_s, {""_s, 99, atcommand_fog, - "Enable the fog mapflag"}}, - {"leaves", {"", + "Enable the fog mapflag"_s}}, + {"leaves"_s, {""_s, 99, atcommand_leaves, - "Enable the leaves mapflag"}}, - {"summon", {"<mob-id-or-name>", + "Enable the leaves mapflag"_s}}, + {"summon"_s, {"<mob-id-or-name>"_s, 50, atcommand_summon, - "Summon a slave monster temporarily"}}, - {"adjgmlvl", {"<level> <cmd>", + "Summon a slave monster temporarily"_s}}, + {"adjgmlvl"_s, {"<level> <cmd>"_s, 99, atcommand_adjgmlvl, - "Temporarily adjust the GM level of a command"}}, - {"adjcmdlvl", {"<level> <charname>", + "Temporarily adjust the GM level of a command"_s}}, + {"adjcmdlvl"_s, {"<level> <charname>"_s, 99, atcommand_adjcmdlvl, - "Temporarily adjust the GM level of a player"}}, - {"trade", {"<charname>", + "Temporarily adjust the GM level of a player"_s}}, + {"trade"_s, {"<charname>"_s, 60, atcommand_trade, - "Initiate trade with a player anywhere"}}, - {"charwipe", {"<charname>", + "Initiate trade with a player anywhere"_s}}, + {"charwipe"_s, {"<charname>"_s, 60, atcommand_char_wipe, - "Reset a character almost completely"}}, - {"setmagic", {"<school> <value> <charname>", + "Reset a character almost completely"_s}}, + {"setmagic"_s, {"<school> <value> <charname>"_s, 80, atcommand_set_magic, - "Force magic skill level"}}, - {"magicinfo", {"<charname>", + "Force magic skill level"_s}}, + {"magicinfo"_s, {"<charname>"_s, 80, atcommand_magic_info, - "Show magic skills of a palyer"}}, - {"log", {"<message ...>", + "Show magic skills of a palyer"_s}}, + {"log"_s, {"<message ...>"_s, 40, atcommand_log, - "Write something directly to the log"}}, - {"l", {"<message ...>", + "Write something directly to the log"_s}}, + {"l"_s, {"<message ...>"_s, 40, atcommand_log, - "Write something directly to the log"}}, - {"tee", {"<message ...>", + "Write something directly to the log"_s}}, + {"tee"_s, {"<message ...>"_s, 40, atcommand_tee, - "Duplicate a message to the log and public chat"}}, - {"t", {"<message ...>", + "Duplicate a message to the log and public chat"_s}}, + {"t"_s, {"<message ...>"_s, 40, atcommand_tee, - "Duplicate a message to the log and public chat"}}, - {"invisible", {"", + "Duplicate a message to the log and public chat"_s}}, + {"invisible"_s, {""_s, 50, atcommand_invisible, - "Make yourself invisible to players"}}, - {"visible", {"", + "Make yourself invisible to players"_s}}, + {"visible"_s, {""_s, 50, atcommand_visible, - "Make yourself visible to players"}}, - {"hugo", {"", + "Make yourself visible to players"_s}}, + {"hugo"_s, {""_s, 60, atcommand_iterate_forward_over_players, - "Jump to the next player"}}, - {"linus", {"", + "Jump to the next player"_s}}, + {"linus"_s, {""_s, 60, atcommand_iterate_backwards_over_players, - "Jump to the previous player"}}, - {"sp-info", {"<charname>", + "Jump to the previous player"_s}}, + {"sp-info"_s, {"<charname>"_s, 40, atcommand_skillpool_info, - "Show info about pool skills"}}, - {"sp-focus", {"<skill-id> <charname>", + "Show info about pool skills"_s}}, + {"sp-focus"_s, {"<skill-id> <charname>"_s, 80, atcommand_skillpool_focus, - "Focus on a pool skill"}}, - {"sp-unfocus", {"<skill-id> <charname>", + "Focus on a pool skill"_s}}, + {"sp-unfocus"_s, {"<skill-id> <charname>"_s, 80, atcommand_skillpool_unfocus, - "Unfocus off of a pool skill"}}, - {"skill-learn", {"<skill-id> <level> <charname>", + "Unfocus off of a pool skill"_s}}, + {"skill-learn"_s, {"<skill-id> <level> <charname>"_s, 80, atcommand_skill_learn, - "Change a skill level"}}, - {"wgm", {"<message ...>", + "Change a skill level"_s}}, + {"wgm"_s, {"<message ...>"_s, 0, atcommand_wgm, - "Send a message to online GMs"}}, - {"ipcheck", {"<charname>", + "Send a message to online GMs"_s}}, + {"ipcheck"_s, {"<charname>"_s, 60, atcommand_ipcheck, - "List players on the same IP address"}}, - {"doomspot", {"", + "List players on the same IP address"_s}}, + {"doomspot"_s, {""_s, 60, atcommand_doomspot, - "Kill all players on the same tile"}}, - {"source", {"", + "Kill all players on the same tile"_s}}, + {"source"_s, {""_s, 0, atcommand_source, - "Legal information about source code (must be a level 0 command!)"}}, + "Legal information about source code (must be a level 0 command!)"_s}}, }; +} // namespace tmwa diff --git a/src/map/atcommand.hpp b/src/map/atcommand.hpp index 95e3814..4bf5277 100644 --- a/src/map/atcommand.hpp +++ b/src/map/atcommand.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_ATCOMMAND_HPP -#define TMWA_MAP_ATCOMMAND_HPP +#pragma once // atcommand.hpp - GM commands. // // Copyright © ????-2004 Athena Dev Teams @@ -21,14 +20,21 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "map.hpp" +#include "../generic/fwd.hpp" +#include "../net/fwd.hpp" + +#include "../mmo/fwd.hpp" + + +namespace tmwa +{ bool is_atcommand(Session *s, dumb_ptr<map_session_data> sd, - ZString message, int gmlvl); + ZString message, GmLevel gmlvl); bool atcommand_config_read(ZString cfgName); @@ -38,5 +44,4 @@ void log_atcommand(dumb_ptr<map_session_data> sd, ZString cmd); extern AString gm_log; void atcommand_config_write(ZString cfgName); - -#endif // TMWA_MAP_ATCOMMAND_HPP +} // namespace tmwa diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 8e4d435..eabe8a6 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -21,13 +21,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <cstring> +#include <algorithm> -#include "../compat/alg.hpp" #include "../compat/nullpo.hpp" #include "../strings/astring.hpp" #include "../strings/zstring.hpp" +#include "../strings/xstring.hpp" #include "../generic/random.hpp" @@ -47,12 +47,14 @@ #include "../poison.hpp" +namespace tmwa +{ static Battle_Config init_battle_config(); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" +DIAG_PUSH(); +DIAG_I(shadow); struct Battle_Config battle_config = init_battle_config(); -#pragma GCC diagnostic pop +DIAG_POP(); /*========================================== * 自分をロックしている対象の数を返す(汎用) @@ -63,7 +65,7 @@ static int battle_counttargeted(dumb_ptr<block_list> bl, dumb_ptr<block_list> src, ATK target_lv) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::PC) return pc_counttargeted(bl->is_player(), src, target_lv); @@ -77,15 +79,15 @@ int battle_counttargeted(dumb_ptr<block_list> bl, dumb_ptr<block_list> src, * 戻りは整数で0以上 *------------------------------------------ */ -int battle_get_class(dumb_ptr<block_list> bl) +Species battle_get_class(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retr(Species(), bl); if (bl->bl_type == BL::MOB) return bl->is_mob()->mob_class; else if (bl->bl_type == BL::PC) - return 0; + return bl->is_player()->status.species; else - return 0; + return Species(); } /*========================================== @@ -111,7 +113,7 @@ DIR battle_get_dir(dumb_ptr<block_list> bl) */ int battle_get_lv(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::MOB) return bl->is_mob()->stats[mob_stat::LV]; else if (bl->bl_type == BL::PC) @@ -127,9 +129,9 @@ int battle_get_lv(dumb_ptr<block_list> bl) */ int battle_get_range(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::MOB) - return mob_db[bl->is_mob()->mob_class].range; + return get_mob_db(bl->is_mob()->mob_class).range; else if (bl->bl_type == BL::PC) return bl->is_player()->attackrange; else @@ -189,7 +191,7 @@ int battle_get_str(dumb_ptr<block_list> bl) int str = 0; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (bl->bl_type == BL::MOB) str = bl->is_mob()->stats[mob_stat::STR]; @@ -212,7 +214,7 @@ int battle_get_agi(dumb_ptr<block_list> bl) int agi = 0; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (bl->bl_type == BL::MOB) agi = bl->is_mob()->stats[mob_stat::AGI]; @@ -234,7 +236,7 @@ int battle_get_vit(dumb_ptr<block_list> bl) int vit = 0; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (bl->bl_type == BL::MOB) vit = bl->is_mob()->stats[mob_stat::VIT]; @@ -256,7 +258,7 @@ int battle_get_int(dumb_ptr<block_list> bl) int int_ = 0; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (bl->bl_type == BL::MOB) int_ = bl->is_mob()->stats[mob_stat::INT]; @@ -278,7 +280,7 @@ int battle_get_dex(dumb_ptr<block_list> bl) int dex = 0; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (bl->bl_type == BL::MOB) dex = bl->is_mob()->stats[mob_stat::DEX]; @@ -300,7 +302,7 @@ int battle_get_luk(dumb_ptr<block_list> bl) int luk = 0; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (bl->bl_type == BL::MOB) luk = bl->is_mob()->stats[mob_stat::LUK]; @@ -466,7 +468,7 @@ int battle_get_atk(dumb_ptr<block_list> bl) eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int atk = 0; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (bl->bl_type == BL::PC) atk = bl->is_player()->watk; @@ -486,7 +488,7 @@ int battle_get_atk(dumb_ptr<block_list> bl) static int battle_get_atk_(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::PC) return bl->is_player()->watk_; else @@ -501,7 +503,7 @@ int battle_get_atk_(dumb_ptr<block_list> bl) static int battle_get_atk2(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::PC) return bl->is_player()->watk2; else @@ -524,7 +526,7 @@ int battle_get_atk2(dumb_ptr<block_list> bl) static int battle_get_atk_2(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::PC) return bl->is_player()->watk_2; else @@ -540,7 +542,7 @@ static int battle_get_matk1(dumb_ptr<block_list> bl) { eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (bl->bl_type == BL::MOB) { @@ -563,7 +565,7 @@ int battle_get_matk1(dumb_ptr<block_list> bl) static int battle_get_matk2(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::MOB) { int matk, int_ = battle_get_int(bl); @@ -587,7 +589,7 @@ int battle_get_def(dumb_ptr<block_list> bl) eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int def = 0; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (bl->bl_type == BL::PC) { @@ -623,7 +625,7 @@ int battle_get_mdef(dumb_ptr<block_list> bl) eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int mdef = 0; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (bl->bl_type == BL::PC) mdef = bl->is_player()->mdef; @@ -685,7 +687,7 @@ int battle_get_mdef2(dumb_ptr<block_list> bl) { int mdef2 = 0; - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::MOB) { dumb_ptr<mob_data> md = bl->is_mob(); @@ -710,16 +712,16 @@ int battle_get_mdef2(dumb_ptr<block_list> bl) */ interval_t battle_get_speed(dumb_ptr<block_list> bl) { - nullpo_retr(std::chrono::seconds(1), bl); + nullpo_retr(1_s, bl); if (bl->bl_type == BL::PC) return bl->is_player()->speed; else { - interval_t speed = std::chrono::seconds(1); + interval_t speed = 1_s; if (bl->bl_type == BL::MOB) speed = static_cast<interval_t>(bl->is_mob()->stats[mob_stat::SPEED]); - return std::max(speed, std::chrono::milliseconds(1)); + return std::max(speed, 1_ms); } } @@ -731,13 +733,13 @@ interval_t battle_get_speed(dumb_ptr<block_list> bl) // TODO figure out what all the doubling is about interval_t battle_get_adelay(dumb_ptr<block_list> bl) { - nullpo_retr(std::chrono::seconds(4), bl); + nullpo_retr(4_s, bl); if (bl->bl_type == BL::PC) return bl->is_player()->aspd * 2; else { eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data = battle_get_sc_data(bl); - interval_t adelay = std::chrono::seconds(4); + interval_t adelay = 4_s; int aspd_rate = 100; if (bl->bl_type == BL::MOB) adelay = static_cast<interval_t>(bl->is_mob()->stats[mob_stat::ADELAY]); @@ -759,16 +761,16 @@ interval_t battle_get_adelay(dumb_ptr<block_list> bl) interval_t battle_get_amotion(dumb_ptr<block_list> bl) { - nullpo_retr(std::chrono::seconds(2), bl); + nullpo_retr(2_s, bl); if (bl->bl_type == BL::PC) return bl->is_player()->amotion; else { eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data = battle_get_sc_data(bl); - interval_t amotion = std::chrono::seconds(2); + interval_t amotion = 2_s; int aspd_rate = 100; if (bl->bl_type == BL::MOB) - amotion = static_cast<interval_t>(mob_db[bl->is_mob()->mob_class].amotion); + amotion = static_cast<interval_t>(get_mob_db(bl->is_mob()->mob_class).amotion); if (sc_data) { @@ -789,14 +791,14 @@ interval_t battle_get_dmotion(dumb_ptr<block_list> bl) nullpo_retr(interval_t::zero(), bl); if (bl->bl_type == BL::MOB) { - return static_cast<interval_t>(mob_db[bl->is_mob()->mob_class].dmotion); + return static_cast<interval_t>(get_mob_db(bl->is_mob()->mob_class).dmotion); } else if (bl->bl_type == BL::PC) { return bl->is_player()->dmotion; } else - return std::chrono::seconds(2); + return 2_s; } LevelElement battle_get_element(dumb_ptr<block_list> bl) @@ -810,26 +812,26 @@ LevelElement battle_get_element(dumb_ptr<block_list> bl) return ret; } -int battle_get_party_id(dumb_ptr<block_list> bl) +PartyId battle_get_party_id(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retr(PartyId(), bl); if (bl->bl_type == BL::PC) return bl->is_player()->status.party_id; else if (bl->bl_type == BL::MOB) { dumb_ptr<mob_data> md = bl->is_mob(); - if (md->master_id > 0) - return -md->master_id; - return -md->bl_id; + if (md->master_id) + return wrap<PartyId>(-unwrap<BlockId>(md->master_id)); + return wrap<PartyId>(-unwrap<BlockId>(md->bl_id)); } - return 0; + return PartyId(); } Race battle_get_race(dumb_ptr<block_list> bl) { nullpo_retr(Race::formless, bl); if (bl->bl_type == BL::MOB) - return mob_db[bl->is_mob()->mob_class].race; + return get_mob_db(bl->is_mob()->mob_class).race; else if (bl->bl_type == BL::PC) return Race::demihuman; else @@ -840,7 +842,7 @@ MobMode battle_get_mode(dumb_ptr<block_list> bl) { nullpo_retr(MobMode::CAN_MOVE, bl); if (bl->bl_type == BL::MOB) - return mob_db[bl->is_mob()->mob_class].mode; + return get_mob_db(bl->is_mob()->mob_class).mode; // とりあえず動くということで1 return MobMode::CAN_MOVE; } @@ -883,60 +885,60 @@ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> battle_ short *battle_get_sc_count(dumb_ptr<block_list> bl) { - nullpo_retr(NULL, bl); + nullpo_retr(nullptr, bl); if (bl->bl_type == BL::MOB) return &bl->is_mob()->sc_count; else if (bl->bl_type == BL::PC) return &bl->is_player()->sc_count; - return NULL; + return nullptr; } Opt1 *battle_get_opt1(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retn(bl); if (bl->bl_type == BL::MOB) return &bl->is_mob()->opt1; else if (bl->bl_type == BL::PC) return &bl->is_player()->opt1; else if (bl->bl_type == BL::NPC) return &bl->is_npc()->opt1; - return 0; + return nullptr; } Opt2 *battle_get_opt2(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retn(bl); if (bl->bl_type == BL::MOB) return &bl->is_mob()->opt2; else if (bl->bl_type == BL::PC) return &bl->is_player()->opt2; else if (bl->bl_type == BL::NPC) return &bl->is_npc()->opt2; - return 0; + return nullptr; } Opt3 *battle_get_opt3(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retn(bl); if (bl->bl_type == BL::MOB) return &bl->is_mob()->opt3; else if (bl->bl_type == BL::PC) return &bl->is_player()->opt3; else if (bl->bl_type == BL::NPC) return &bl->is_npc()->opt3; - return 0; + return nullptr; } Option *battle_get_option(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retn(bl); if (bl->bl_type == BL::MOB) return &bl->is_mob()->option; else if (bl->bl_type == BL::PC) return &bl->is_player()->status.option; else if (bl->bl_type == BL::NPC) return &bl->is_npc()->option; - return 0; + return nullptr; } //------------------------------------------------------------------- @@ -953,17 +955,17 @@ struct battle_delay_damage_ int battle_damage(dumb_ptr<block_list> bl, dumb_ptr<block_list> target, int damage, int flag) { - nullpo_ret(target); //blはNULLで呼ばれることがあるので他でチェック + nullpo_retz(target); //blはNULLで呼ばれることがあるので他でチェック if (damage == 0) return 0; - if (target->bl_prev == NULL) + if (target->bl_prev == nullptr) return 0; if (bl) { - if (bl->bl_prev == NULL) + if (bl->bl_prev == nullptr) return 0; } @@ -991,7 +993,7 @@ int battle_damage(dumb_ptr<block_list> bl, dumb_ptr<block_list> target, int battle_heal(dumb_ptr<block_list> bl, dumb_ptr<block_list> target, int hp, int sp, int flag) { - nullpo_ret(target); //blはNULLで呼ばれることがあるので他でチェック + nullpo_retz(target); //blはNULLで呼ばれることがあるので他でチェック if (target->bl_type == BL::PC && pc_isdead(target->is_player())) @@ -1012,7 +1014,7 @@ int battle_heal(dumb_ptr<block_list> bl, dumb_ptr<block_list> target, int hp, // 攻撃停止 int battle_stopattack(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::MOB) return mob_stopattack(bl->is_mob()); else if (bl->bl_type == BL::PC) @@ -1023,7 +1025,7 @@ int battle_stopattack(dumb_ptr<block_list> bl) // 移動停止 int battle_stopwalking(dumb_ptr<block_list> bl, int type) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::MOB) return mob_stop_walking(bl->is_mob(), type); else if (bl->bl_type == BL::PC) @@ -1040,9 +1042,9 @@ int battle_calc_damage(dumb_ptr<block_list>, dumb_ptr<block_list> bl, int damage, int div_, SkillID, int, BF flag) { - dumb_ptr<mob_data> md = NULL; + dumb_ptr<mob_data> md = nullptr; - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::MOB) md = bl->is_mob(); @@ -1059,7 +1061,7 @@ int battle_calc_damage(dumb_ptr<block_list>, dumb_ptr<block_list> bl, damage = 3; } - if (md != NULL && md->hp > 0 && damage > 0) // 反撃などのMOBスキル判定 + if (md != nullptr && md->hp > 0 && damage > 0) // 反撃などのMOBスキル判定 mobskill_event(md, flag); return damage; @@ -1071,8 +1073,8 @@ struct Damage battle_calc_mob_weapon_attack(dumb_ptr<block_list> src, SkillID skill_num, int skill_lv, int) { - dumb_ptr<map_session_data> tsd = NULL; - dumb_ptr<mob_data> md = src->is_mob(), tmd = NULL; + dumb_ptr<map_session_data> tsd = nullptr; + dumb_ptr<mob_data> md = src->is_mob(), tmd = nullptr; int hitrate, flee, cri = 0, atkmin, atkmax; int target_count = 1; int def1 = battle_get_def(target); @@ -1143,7 +1145,7 @@ struct Damage battle_calc_mob_weapon_attack(dumb_ptr<block_list> src, atkmin = battle_get_atk(src); atkmax = battle_get_atk2(src); } - if (mob_db[md->mob_class].range > 3) + if (get_mob_db(md->mob_class).range > 3) flag = (flag & ~BF::RANGEMASK) | BF::LONG; if (atkmin > atkmax) @@ -1282,7 +1284,7 @@ struct Damage battle_calc_mob_weapon_attack(dumb_ptr<block_list> src, damage = 0; // 完全回避の判定 - if (skill_num == SkillID::ZERO && skill_lv >= 0 && tsd != NULL + if (skill_num == SkillID::ZERO && skill_lv >= 0 && tsd != nullptr && random_::chance({battle_get_flee2(target), 1000})) { damage = 0; @@ -1292,7 +1294,7 @@ struct Damage battle_calc_mob_weapon_attack(dumb_ptr<block_list> src, if (battle_config.enemy_perfect_flee) { - if (skill_num == SkillID::ZERO && skill_lv >= 0 && tmd != NULL + if (skill_num == SkillID::ZERO && skill_lv >= 0 && tmd != nullptr && random_::chance({battle_get_flee2(target), 1000})) { damage = 0; @@ -1327,9 +1329,9 @@ int battle_is_unarmed(dumb_ptr<block_list> bl) { dumb_ptr<map_session_data> sd = bl->is_player(); - int sidx = sd->equip_index_maybe[EQUIP::SHIELD]; - int widx = sd->equip_index_maybe[EQUIP::WEAPON]; - return sidx == -1 && widx == -1; + IOff0 sidx = sd->equip_index_maybe[EQUIP::SHIELD]; + IOff0 widx = sd->equip_index_maybe[EQUIP::WEAPON]; + return !sidx.ok() && !widx.ok(); } else return 0; @@ -1346,8 +1348,8 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src, SkillID skill_num, int skill_lv, int) { - dumb_ptr<map_session_data> sd = src->is_player(), tsd = NULL; - dumb_ptr<mob_data> tmd = NULL; + dumb_ptr<map_session_data> sd = src->is_player(), tsd = nullptr; + dumb_ptr<mob_data> tmd = nullptr; int hitrate, flee, cri = 0, atkmin, atkmax; int dex, target_count = 1; int def1 = battle_get_def(target); @@ -1417,9 +1419,9 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src, int dy = abs(src->bl_y - target->bl_y); int malus_dist; - target_distance = max(dx, dy); + target_distance = std::max(dx, dy); malus_dist = - max(0, target_distance - (skill_power(sd, SkillID::AC_OWL) / 75)); + std::max(0, target_distance - (skill_power(sd, SkillID::AC_OWL) / 75)); hitrate -= (malus_dist * (malus_dist + 1)); } @@ -1449,12 +1451,12 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src, atkmin = atkmin_ = dex; //最低ATKはDEXで初期化? sd->state.arrow_atk = 0; //arrow_atk初期化 - int widx = sd->equip_index_maybe[EQUIP::WEAPON]; - int sidx = sd->equip_index_maybe[EQUIP::SHIELD]; + IOff0 widx = sd->equip_index_maybe[EQUIP::WEAPON]; + IOff0 sidx = sd->equip_index_maybe[EQUIP::SHIELD]; - if (widx >= 0 && sd->inventory_data[widx]) + if (widx.ok() && sd->inventory_data[widx]) atkmin = atkmin * (80 + sd->inventory_data[widx]->wlv * 20) / 100; - if (sidx >= 0 && sd->inventory_data[sidx]) + if (sidx.ok() && sd->inventory_data[sidx]) atkmin_ = atkmin_ * (80 + sd->inventory_data[sidx]->wlv * 20) / 100; if (sd->status.weapon == ItemLook::BOW) { //武器が弓矢の場合 @@ -1708,7 +1710,7 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src, } // 完全回避の判定 - if (skill_num == SkillID::ZERO && skill_lv >= 0 && tsd != NULL && div_ < 255 + if (skill_num == SkillID::ZERO && skill_lv >= 0 && tsd != nullptr && div_ < 255 && random_::chance({battle_get_flee2(target), 1000})) { damage = damage2 = 0; @@ -1719,7 +1721,7 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src, // 対象が完全回避をする設定がONなら if (battle_config.enemy_perfect_flee) { - if (skill_num == SkillID::ZERO && skill_lv >= 0 && tmd != NULL && div_ < 255 + if (skill_num == SkillID::ZERO && skill_lv >= 0 && tmd != nullptr && div_ < 255 && random_::chance({battle_get_flee2(target), 1000})) { damage = damage2 = 0; @@ -1809,7 +1811,7 @@ struct Damage battle_calc_magic_attack(dumb_ptr<block_list> bl, int matk1, matk2, damage = 0, div_ = 1; struct Damage md {}; int normalmagic_flag = 1; - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; nullpo_retr(md, bl); nullpo_retr(md, target); @@ -1885,7 +1887,7 @@ struct Damage battle_calc_misc_attack(dumb_ptr<block_list> bl, dumb_ptr<block_list> target, SkillID skill_num, int skill_lv, int) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; int damage = 0, div_ = 1; struct Damage md {}; int damagefix = 1; @@ -1965,7 +1967,7 @@ struct Damage battle_calc_attack(BF attack_type, flag); default: if (battle_config.error_log) - PRINTF("battle_calc_attack: unknwon attack type ! %d\n", + PRINTF("battle_calc_attack: unknwon attack type ! %d\n"_fmt, attack_type); break; } @@ -1979,7 +1981,7 @@ struct Damage battle_calc_attack(BF attack_type, ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, tick_t tick) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> t_sc_data = battle_get_sc_data(target); struct Damage wd; @@ -1989,7 +1991,7 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, if (src->bl_type == BL::PC) sd = src->is_player(); - if (src->bl_prev == NULL || target->bl_prev == NULL) + if (src->bl_prev == nullptr || target->bl_prev == nullptr) return ATK::ZERO; if (src->bl_type == BL::PC && pc_isdead(sd)) return ATK::ZERO; @@ -1998,7 +2000,7 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, return ATK::ZERO; Opt1 *opt1 = battle_get_opt1(src); - if (opt1 != NULL && bool(*opt1)) + if (opt1 != nullptr && bool(*opt1)) { battle_stopattack(src); return ATK::ZERO; @@ -2010,8 +2012,8 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, // 攻撃対象となりうるので攻撃 if (sd && sd->status.weapon == ItemLook::BOW) { - int aidx = sd->equip_index_maybe[EQUIP::ARROW]; - if (aidx >= 0) + IOff0 aidx = sd->equip_index_maybe[EQUIP::ARROW]; + if (aidx.ok()) { if (battle_config.arrow_decrement) pc_delitem(sd, aidx, 1, 0); @@ -2040,7 +2042,7 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, wd.damage -= reduction; MAP_LOG_PC(target->is_player(), - "MAGIC-ABSORB-DMG %d", reduction); + "MAGIC-ABSORB-DMG %d"_fmt, reduction); } { @@ -2050,7 +2052,7 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, && (sd->status.weapon == ItemLook::_16 || sd->status.weapon >= ItemLook::SINGLE_HANDED_COUNT) && wd.damage2 == 0) - clif_damage(src, target, tick + std::chrono::milliseconds(10), + clif_damage(src, target, tick + 10_ms, wd.amotion, wd.dmotion, 0, 1, DamageType::NORMAL, 0); } @@ -2058,37 +2060,37 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, if (src->bl_type == BL::PC) { - int weapon_index = sd->equip_index_maybe[EQUIP::WEAPON]; - int weapon = 0; - if (weapon_index >= 0 && sd->inventory_data[weapon_index] + IOff0 weapon_index = sd->equip_index_maybe[EQUIP::WEAPON]; + ItemNameId weapon; + if (weapon_index.ok() && sd->inventory_data[weapon_index] && bool(sd->status.inventory[weapon_index].equip & EPOS::WEAPON)) weapon = sd->inventory_data[weapon_index]->nameid; - MAP_LOG("PC%d %s:%d,%d WPNDMG %s%d %d FOR %d WPN %d", - sd->status_key.char_id, src->bl_m->name_, src->bl_x, src->bl_y, - (target->bl_type == BL::PC) ? "PC" : "MOB", - (target->bl_type == BL::PC) - ? target->is_player()-> status_key.char_id - : target->bl_id, - battle_get_class(target), - wd.damage + wd.damage2, weapon); + MAP_LOG("PC%d %s:%d,%d WPNDMG %s%d %d FOR %d WPN %d"_fmt, + sd->status_key.char_id, src->bl_m->name_, src->bl_x, src->bl_y, + (target->bl_type == BL::PC) ? "PC"_s : "MOB"_s, + (target->bl_type == BL::PC) + ? unwrap<CharId>(target->is_player()->status_key.char_id) + : unwrap<BlockId>(target->bl_id), + battle_get_class(target), + wd.damage + wd.damage2, weapon); } if (target->bl_type == BL::PC) { dumb_ptr<map_session_data> sd2 = target->is_player(); - MAP_LOG("PC%d %s:%d,%d WPNINJURY %s%d %d FOR %d", - sd2->status_key.char_id, target->bl_m->name_, target->bl_x, target->bl_y, - (src->bl_type == BL::PC) ? "PC" : "MOB", - (src->bl_type == BL::PC) - ? src->is_player()->status_key.char_id - : src->bl_id, - battle_get_class(src), - wd.damage + wd.damage2); + MAP_LOG("PC%d %s:%d,%d WPNINJURY %s%d %d FOR %d"_fmt, + sd2->status_key.char_id, target->bl_m->name_, target->bl_x, target->bl_y, + (src->bl_type == BL::PC) ? "PC"_s : "MOB"_s, + (src->bl_type == BL::PC) + ? unwrap<CharId>(src->is_player()->status_key.char_id) + : unwrap<BlockId>(src->bl_id), + battle_get_class(src), + wd.damage + wd.damage2); } battle_damage(src, target, (wd.damage + wd.damage2), 0); - if (target->bl_prev != NULL && + if (target->bl_prev != nullptr && (target->bl_type != BL::PC || (target->bl_type == BL::PC && !pc_isdead(target->is_player())))) @@ -2161,11 +2163,11 @@ bool battle_check_undead(Race race, Element element) int battle_check_target(dumb_ptr<block_list> src, dumb_ptr<block_list> target, BCT flag) { - int s_p, t_p; + PartyId s_p, t_p; dumb_ptr<block_list> ss = src; - nullpo_ret(src); - nullpo_ret(target); + nullpo_retz(src); + nullpo_retz(target); if (flag & BCT_ENEMY) { // 反転フラグ @@ -2191,7 +2193,7 @@ int battle_check_target(dumb_ptr<block_list> src, dumb_ptr<block_list> target, if (src->bl_type == BL::MOB) { dumb_ptr<mob_data> md = src->is_mob(); - if (md && md->master_id > 0) + if (md && md->master_id) { if (md->master_id == target->bl_id) // 主なら肯定 return 1; @@ -2214,7 +2216,7 @@ int battle_check_target(dumb_ptr<block_list> src, dumb_ptr<block_list> target, } } } - if ((ss = map_id2bl(md->master_id)) == NULL) + if ((ss = map_id2bl(md->master_id)) == nullptr) return -1; } } @@ -2226,7 +2228,7 @@ int battle_check_target(dumb_ptr<block_list> src, dumb_ptr<block_list> target, && pc_isinvisible(target->is_player())) return -1; - if (src->bl_prev == NULL || // 死んでるならエラー + if (src->bl_prev == nullptr || // 死んでるならエラー (src->bl_type == BL::PC && pc_isdead(src->is_player()))) return -1; @@ -2246,9 +2248,6 @@ int battle_check_target(dumb_ptr<block_list> src, dumb_ptr<block_list> target, return 0; } -//PRINTF("ss:%d src:%d target:%d flag:0x%x %d %d ",ss->bl_id,src->bl_id,target->bl_id,flag,src->bl_type,target->bl_type); -//PRINTF("p:%d %d g:%d %d\n",s_p,t_p,s_g,t_g); - if (ss->bl_type == BL::PC && target->bl_type == BL::PC) { // 両方PVPモードなら否定(敵) if (ss->bl_m->flag.get(MapFlag::PVP) @@ -2256,7 +2255,7 @@ int battle_check_target(dumb_ptr<block_list> src, dumb_ptr<block_list> target, { // [MouseJstr] if (battle_config.pk_mode) return 1; // prevent novice engagement in pk_mode [Valaris] - else if (ss->bl_m->flag.get(MapFlag::PVP_NOPARTY) && s_p > 0 && t_p > 0 + else if (ss->bl_m->flag.get(MapFlag::PVP_NOPARTY) && s_p && t_p && s_p == t_p) return 1; return 0; @@ -2278,8 +2277,8 @@ int battle_check_range(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, struct walkpath_data wpd; int arange; - nullpo_ret(src); - nullpo_ret(bl); + nullpo_retz(src); + nullpo_retz(bl); dx = abs(bl->bl_x - src->bl_x); dy = abs(bl->bl_y - src->bl_y); @@ -2313,10 +2312,10 @@ int battle_check_range(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, Battle_Config init_battle_config() { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" + DIAG_PUSH(); + DIAG_I(shadow); Battle_Config battle_config; -#pragma GCC diagnostic pop + DIAG_POP(); { battle_config.warp_point_debug = 0; battle_config.enemy_critical = 0; @@ -2430,17 +2429,17 @@ bool battle_config_read(ZString cfgName) io::ReadFile in(cfgName); if (!in.is_open()) { - PRINTF("file not found: %s\n", cfgName); + PRINTF("file not found: %s\n"_fmt, cfgName); return false; } AString line; while (in.getline(line)) { -#define BATTLE_CONFIG_VAR(name) {{#name}, &battle_config.name} +#define BATTLE_CONFIG_VAR(name) {#name##_s, &battle_config.name} const struct { - ZString str; + LString str; int *val; } data[] = { @@ -2550,12 +2549,12 @@ bool battle_config_read(ZString cfgName) ZString w2; if (!config_split(line, &w1, &w2)) { - PRINTF("Bad config line: %s\n", line); + PRINTF("Bad config line: %s\n"_fmt, line); rv = false; continue; } - if (w1 == "import") + if (w1 == "import"_s) { battle_config_read(w2); continue; @@ -2568,7 +2567,7 @@ bool battle_config_read(ZString cfgName) goto continue_outer; } - PRINTF("WARNING: unknown battle conf key: %s\n", AString(w1)); + PRINTF("WARNING: unknown battle conf key: %s\n"_fmt, AString(w1)); rv = false; continue_outer: @@ -2581,7 +2580,7 @@ bool battle_config_read(ZString cfgName) void battle_config_check() { { - if (static_cast<interval_t>(battle_config.flooritem_lifetime) < std::chrono::seconds(1)) + if (static_cast<interval_t>(battle_config.flooritem_lifetime) < 1_s) battle_config.flooritem_lifetime = std::chrono::duration_cast<std::chrono::milliseconds>(LIFETIME_FLOORITEM).count(); if (battle_config.restart_hp_rate < 0) battle_config.restart_hp_rate = 0; @@ -2686,3 +2685,4 @@ void battle_config_check() battle_config.mask_ip_gms = 1; } } +} // namespace tmwa diff --git a/src/map/battle.hpp b/src/map/battle.hpp index b8060a9..97a4a86 100644 --- a/src/map/battle.hpp +++ b/src/map/battle.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_BATTLE_HPP -#define TMWA_MAP_BATTLE_HPP +#pragma once // battle.hpp - Not so scary code. // // Copyright © ????-2004 Athena Dev Teams @@ -21,18 +20,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "battle.t.hpp" +#include "battle.t.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "../mmo/timer.t.hpp" +#include "../generic/fwd.hpp" -# include "magic-interpreter.t.hpp" -# include "map.t.hpp" -# include "skill.t.hpp" +#include "../net/timer.t.hpp" +#include "clif.t.hpp" +#include "map.t.hpp" +#include "skill.t.hpp" + + +namespace tmwa +{ // ダメージ struct Damage { @@ -44,10 +48,6 @@ struct Damage ATK dmg_lv; }; -struct map_session_data; -struct mob_data; -struct block_list; - // ダメージ計算 struct Damage battle_calc_attack(BF attack_type, @@ -69,7 +69,7 @@ ATK battle_weapon_attack(dumb_ptr<block_list> bl, dumb_ptr<block_list> target, tick_t tick); int battle_is_unarmed(dumb_ptr<block_list> bl); -int battle_get_class(dumb_ptr<block_list> bl); +Species battle_get_class(dumb_ptr<block_list> bl); DIR battle_get_dir(dumb_ptr<block_list> bl); int battle_get_lv(dumb_ptr<block_list> bl); int battle_get_range(dumb_ptr<block_list> bl); @@ -95,7 +95,7 @@ Element battle_get_elem_type(dumb_ptr<block_list> bl) { return battle_get_element(bl).element; } -int battle_get_party_id(dumb_ptr<block_list> bl); +PartyId battle_get_party_id(dumb_ptr<block_list> bl); Race battle_get_race(dumb_ptr<block_list> bl); MobMode battle_get_mode(dumb_ptr<block_list> bl); int battle_get_stat(SP stat_id, dumb_ptr<block_list> bl); @@ -225,5 +225,4 @@ extern struct Battle_Config bool battle_config_read(ZString cfgName); void battle_config_check(); - -#endif // TMWA_MAP_BATTLE_HPP +} // namespace tmwa diff --git a/src/map/battle.t.hpp b/src/map/battle.t.hpp index 9685ae7..53c34ff 100644 --- a/src/map/battle.t.hpp +++ b/src/map/battle.t.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_BATTLE_T_HPP -#define TMWA_MAP_BATTLE_T_HPP +#pragma once // battle.t.hpp - Not so scary code. // // Copyright © ????-2004 Athena Dev Teams @@ -21,10 +20,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../generic/enum.hpp" +#include <cstdint> +#include "../generic/enum.hpp" + + +namespace tmwa +{ namespace e { enum class BF : uint16_t @@ -65,11 +69,11 @@ struct BCT }; constexpr -BCT operator & (BCT l, BCT r) { return {uint8_t(l.lo & r.lo), uint8_t(l.mid & r.mid), uint8_t(l.classic & r.classic), uint8_t(l.level & r.level), uint8_t(l.unused & r.unused) }; } +BCT operator & (BCT l, BCT r) { return {static_cast<uint8_t>(l.lo & r.lo), static_cast<uint8_t>(l.mid & r.mid), static_cast<uint8_t>(l.classic & r.classic), static_cast<uint8_t>(l.level & r.level), static_cast<uint8_t>(l.unused & r.unused) }; } constexpr -BCT operator | (BCT l, BCT r) { return {uint8_t(l.lo | r.lo), uint8_t(l.mid | r.mid), uint8_t(l.classic | r.classic), uint8_t(l.level | r.level), uint8_t(l.unused | r.unused) }; } +BCT operator | (BCT l, BCT r) { return {static_cast<uint8_t>(l.lo | r.lo), static_cast<uint8_t>(l.mid | r.mid), static_cast<uint8_t>(l.classic | r.classic), static_cast<uint8_t>(l.level | r.level), static_cast<uint8_t>(l.unused | r.unused) }; } constexpr -BCT operator ^ (BCT l, BCT r) { return {uint8_t(l.lo ^ r.lo), uint8_t(l.mid ^ r.mid), uint8_t(l.classic ^ r.classic), uint8_t(l.level ^ r.level), uint8_t(l.unused ^ r.unused) }; } +BCT operator ^ (BCT l, BCT r) { return {static_cast<uint8_t>(l.lo ^ r.lo), static_cast<uint8_t>(l.mid ^ r.mid), static_cast<uint8_t>(l.classic ^ r.classic), static_cast<uint8_t>(l.level ^ r.level), static_cast<uint8_t>(l.unused ^ r.unused) }; } inline BCT& operator &= (BCT& l, BCT r) { return l = l & r; } inline @@ -237,15 +241,4 @@ earray<Races, Race, Race::COUNT> race_shift //= Races::boss, Races::other, }}; - -enum class DamageType : uint8_t -{ - NORMAL = 0x00, - TAKEITEM = 0x01, - RETURNED = 0x04, - DOUBLED = 0x08, - CRITICAL = 0x0a, - FLEE2 = 0x0b, -}; - -#endif // TMWA_MAP_BATTLE_T_HPP +} // namespace tmwa diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp index fa95be7..0748f43 100644 --- a/src/map/chrif.cpp +++ b/src/map/chrif.cpp @@ -20,10 +20,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <arpa/inet.h> - -#include <cstring> - #include "../compat/fun.hpp" #include "../compat/nullpo.hpp" @@ -32,8 +28,15 @@ #include "../io/cxxstdio.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" +#include "../net/ip.hpp" +#include "../net/packets.hpp" +#include "../net/socket.hpp" +#include "../net/timer.hpp" + +#include "../proto2/char-map.hpp" + +#include "../mmo/human_time_diff.hpp" +#include "../mmo/mmo.hpp" #include "../mmo/utils.hpp" #include "battle.hpp" @@ -47,15 +50,9 @@ #include "../poison.hpp" -static -const int packet_len_table[0x20] = -{ - 60, 3, 10, 27, 22, -1, 6, -1, // 2af8-2aff - 6, -1, 18, 7, -1, 49, 44, 0, // 2b00-2b07 - 6, 30, -1, 10, 86, 7, 44, 34, // 2b08-2b0f - -1, -1, 10, 6, 11, -1, 0, 0, // 2b10-2b17 -}; +namespace tmwa +{ Session *char_session; static IP4Address char_ip; @@ -132,13 +129,12 @@ int chrif_save(dumb_ptr<map_session_data> sd) pc_makesavestatus(sd); - WFIFOW(char_session, 0) = 0x2b01; - WFIFOW(char_session, 2) = sizeof(sd->status_key) + sizeof(sd->status) + 12; - WFIFOL(char_session, 4) = sd->bl_id; - WFIFOL(char_session, 8) = sd->char_id; - WFIFO_STRUCT(char_session, 12, sd->status_key); - WFIFO_STRUCT(char_session, 12 + sizeof(sd->status_key), sd->status); - WFIFOSET(char_session, WFIFOW(char_session, 2)); + Packet_Payload<0x2b01> payload_01; + payload_01.account_id = block_to_account(sd->bl_id); + payload_01.char_id = sd->char_id_; + payload_01.char_key = sd->status_key; + payload_01.char_data = sd->status; + send_ppacket<0x2b01>(char_session, payload_01); //For data sync if (sd->state.storage_open) @@ -154,13 +150,13 @@ int chrif_save(dumb_ptr<map_session_data> sd) static int chrif_connect(Session *s) { - WFIFOW(s, 0) = 0x2af8; - WFIFO_STRING(s, 2, userid, 24); - WFIFO_STRING(s, 26, passwd, 24); - WFIFOL(s, 50) = 0; - WFIFOIP(s, 54) = clif_getip(); - WFIFOW(s, 58) = clif_getport(); // [Valaris] thanks to fov - WFIFOSET(s, 60); + Packet_Fixed<0x2af8> fixed_f8; + fixed_f8.account_name = userid; + fixed_f8.account_pass = passwd; + fixed_f8.unused = 0; + fixed_f8.ip = clif_getip(); + fixed_f8.port = clif_getport(); + send_fpacket<0x2af8, 60>(s, fixed_f8); return 0; } @@ -172,19 +168,17 @@ int chrif_connect(Session *s) static int chrif_sendmap(Session *s) { - int i = 0; - - WFIFOW(s, 0) = 0x2afa; + std::vector<Packet_Repeat<0x2afa>> repeat_fa; for (auto& pair : maps_db) { map_abstract *ma = pair.second.get(); if (!ma->gat) continue; - WFIFO_STRING(s, 4 + i * 16, ma->name_, 16); - i++; + Packet_Repeat<0x2afa> info; + info.map_name = ma->name_; + repeat_fa.push_back(info); } - WFIFOW(s, 2) = 4 + i * 16; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x2afa, 4, 16>(s, repeat_fa); return 0; } @@ -194,23 +188,21 @@ int chrif_sendmap(Session *s) *------------------------------------------ */ static -int chrif_recvmap(Session *s) +int chrif_recvmap(Session *, Packet_Head<0x2b04> head, const std::vector<Packet_Repeat<0x2b04>>& repeat) { - int i, j; - if (chrif_state < 2) // まだ準備中 return -1; - IP4Address ip = RFIFOIP(s, 4); - uint16_t port = RFIFOW(s, 8); - for (i = 10, j = 0; i < RFIFOW(s, 2); i += 16, j++) + IP4Address ip = head.ip; + uint16_t port = head.port; + for (const Packet_Repeat<0x2b04>& i : repeat) { - MapName map = RFIFO_STRING<16>(s, i); + MapName map = i.map_name; map_setipport(map, ip, port); } if (battle_config.etc_log) - PRINTF("recv map on %s:%d (%d maps)\n", - ip, port, j); + PRINTF("recv map on %s:%d (%zu maps)\n"_fmt, + ip, port, repeat.size()); return 0; } @@ -224,6 +216,9 @@ int chrif_changemapserver(dumb_ptr<map_session_data> sd, { nullpo_retr(-1, sd); + if (!char_session) + return -1; + IP4Address s_ip; for (io::FD i : iter_fds()) { @@ -238,19 +233,19 @@ int chrif_changemapserver(dumb_ptr<map_session_data> sd, } } - WFIFOW(char_session, 0) = 0x2b05; - WFIFOL(char_session, 2) = sd->bl_id; - WFIFOL(char_session, 6) = sd->login_id1; - WFIFOL(char_session, 10) = sd->login_id2; - WFIFOL(char_session, 14) = sd->status_key.char_id; - WFIFO_STRING(char_session, 18, name, 16); - WFIFOW(char_session, 34) = x; - WFIFOW(char_session, 36) = y; - WFIFOIP(char_session, 38) = ip; - WFIFOL(char_session, 42) = port; - WFIFOB(char_session, 44) = static_cast<uint8_t>(sd->status.sex); - WFIFOIP(char_session, 45) = s_ip; - WFIFOSET(char_session, 49); + Packet_Fixed<0x2b05> fixed_05; + fixed_05.account_id = block_to_account(sd->bl_id); + fixed_05.login_id1 = sd->login_id1; + fixed_05.login_id2 = sd->login_id2; + fixed_05.char_id = sd->status_key.char_id; + fixed_05.map_name = name; + fixed_05.x = x; + fixed_05.y = y; + fixed_05.map_ip = ip; + fixed_05.map_port = port; + fixed_05.sex = sd->status.sex; + fixed_05.client_ip = s_ip; + send_fpacket<0x2b05, 49>(char_session, fixed_05); return 0; } @@ -260,25 +255,26 @@ int chrif_changemapserver(dumb_ptr<map_session_data> sd, *------------------------------------------ */ static -int chrif_changemapserverack(Session *s) +int chrif_changemapserverack(Session *, const Packet_Fixed<0x2b06>& fixed) { - dumb_ptr<map_session_data> sd = map_id2sd(RFIFOL(s, 2)); + dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(fixed.account_id)); - if (sd == NULL || sd->status_key.char_id != RFIFOL(s, 14)) + if (sd == nullptr || sd->status_key.char_id != fixed.char_id) return -1; - if (RFIFOL(s, 6) == 1) + // I am fairly certain that this is not possible + if (fixed.error == 1) { if (battle_config.error_log) - PRINTF("map server change failed.\n"); + PRINTF("map server change failed.\n"_fmt); pc_authfail(sd->status_key.account_id); return 0; } - MapName mapname = RFIFO_STRING<16>(s, 18); - uint16_t x = RFIFOW(s, 34); - uint16_t y = RFIFOW(s, 36); - IP4Address ip = RFIFOIP(s, 38); - uint16_t port = RFIFOW(s, 42); + MapName mapname = fixed.map_name; + uint16_t x = fixed.x; + uint16_t y = fixed.y; + IP4Address ip = fixed.map_ip; + uint16_t port = fixed.map_port; clif_changemapserver(sd, mapname, x, y, ip, port); return 0; @@ -289,25 +285,22 @@ int chrif_changemapserverack(Session *s) *------------------------------------------ */ static -int chrif_connectack(Session *s) +int chrif_connectack(Session *s, const Packet_Fixed<0x2af9>& fixed) { - if (RFIFOB(s, 2)) + if (fixed.code) { - PRINTF("Connected to char-server failed %d.\n", RFIFOB(s, 2)); + PRINTF("Connected to char-server failed %d.\n"_fmt, fixed.code); exit(1); } - PRINTF("Connected to char-server (connection #%d).\n", s); + PRINTF("Connected to char-server (connection #%d).\n"_fmt, s); chrif_state = 1; chrif_sendmap(s); - PRINTF("chrif: OnCharIfInit event done. (%d events)\n", - npc_event_doall(stringish<ScriptLabel>("OnCharIfInit"))); - PRINTF("chrif: OnInterIfInit event done. (%d events)\n", - npc_event_doall(stringish<ScriptLabel>("OnInterIfInit"))); - - // <Agit> Run Event [AgitInit] -// PRINTF("NPC_Event:[OnAgitInit] do (%d) events (Agit Initialize).\n", npc_event_doall("OnAgitInit")); + PRINTF("chrif: OnCharIfInit event done. (%d events)\n"_fmt, + npc_event_doall(stringish<ScriptLabel>("OnCharIfInit"_s))); + PRINTF("chrif: OnInterIfInit event done. (%d events)\n"_fmt, + npc_event_doall(stringish<ScriptLabel>("OnInterIfInit"_s))); return 0; } @@ -317,16 +310,16 @@ int chrif_connectack(Session *s) *------------------------------------------ */ static -int chrif_sendmapack(Session *s) +int chrif_sendmapack(Session *, Packet_Fixed<0x2afb> fixed) { - if (RFIFOB(s, 2)) + if (fixed.unknown) //impossible { - PRINTF("chrif : send map list to char server failed %d\n", - RFIFOB(s, 2)); + PRINTF("chrif : send map list to char server failed %d\n"_fmt, + fixed.unknown); exit(1); } - wisp_server_name = stringish<CharName>(RFIFO_STRING<24>(s, 3)); + wisp_server_name = fixed.whisper_name; chrif_state = 2; @@ -352,13 +345,13 @@ int chrif_authreq(dumb_ptr<map_session_data> sd) if (dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())) == sd) { assert (s == sd->sess); - WFIFOW(char_session, 0) = 0x2afc; - WFIFOL(char_session, 2) = sd->bl_id; - WFIFOL(char_session, 6) = sd->char_id; - WFIFOL(char_session, 10) = sd->login_id1; - WFIFOL(char_session, 14) = sd->login_id2; - WFIFOIP(char_session, 18) = s->client_ip; - WFIFOSET(char_session, 22); + Packet_Fixed<0x2afc> fixed_fc; + fixed_fc.account_id = block_to_account(sd->bl_id); + fixed_fc.char_id = sd->char_id_; + fixed_fc.login_id1 = sd->login_id1; + fixed_fc.login_id2 = sd->login_id2; + fixed_fc.ip = s->client_ip; + send_fpacket<0x2afc, 22>(char_session, fixed_fc); break; } } @@ -391,12 +384,12 @@ int chrif_charselectreq(dumb_ptr<map_session_data> sd) } } - WFIFOW(char_session, 0) = 0x2b02; - WFIFOL(char_session, 2) = sd->bl_id; - WFIFOL(char_session, 6) = sd->login_id1; - WFIFOL(char_session, 10) = sd->login_id2; - WFIFOIP(char_session, 14) = s_ip; - WFIFOSET(char_session, 18); + Packet_Fixed<0x2b02> fixed_02; + fixed_02.account_id = block_to_account(sd->bl_id); + fixed_02.login_id1 = sd->login_id1; + fixed_02.login_id2 = sd->login_id2; + fixed_02.ip = s_ip; + send_fpacket<0x2b02, 18>(char_session, fixed_02); return 0; } @@ -405,35 +398,38 @@ int chrif_charselectreq(dumb_ptr<map_session_data> sd) * GMに変化要求 *------------------------------------------ */ -void chrif_changegm(int id, ZString pass) +void chrif_changegm(AccountId id, ZString pass) { + if (!char_session) + return; + if (battle_config.etc_log) - PRINTF("chrif_changegm: account: %d, password: '%s'.\n", id, pass); - - size_t len = pass.size() + 1; - WFIFOW(char_session, 0) = 0x2b0a; - WFIFOW(char_session, 2) = len + 8; - WFIFOL(char_session, 4) = id; - WFIFO_STRING(char_session, 8, pass, len); - WFIFOSET(char_session, len + 8); + PRINTF("chrif_changegm: account: %d, password: '%s'.\n"_fmt, id, pass); + + Packet_Head<0x2b0a> head_0a; + head_0a.account_id = id; + send_vpacket<0x2b0a, 8, 1>(char_session, head_0a, pass); } /*========================================== * Change Email *------------------------------------------ */ -void chrif_changeemail(int id, AccountEmail actual_email, +void chrif_changeemail(AccountId id, AccountEmail actual_email, AccountEmail new_email) { + if (!char_session) + return; + if (battle_config.etc_log) - PRINTF("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n", - id, actual_email, new_email); - - WFIFOW(char_session, 0) = 0x2b0c; - WFIFOL(char_session, 2) = id; - WFIFO_STRING(char_session, 6, actual_email, 40); - WFIFO_STRING(char_session, 46, new_email, 40); - WFIFOSET(char_session, 86); + PRINTF("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n"_fmt, + id, actual_email, new_email); + + Packet_Fixed<0x2b0c> fixed_0c; + fixed_0c.account_id = id; + fixed_0c.old_email = actual_email; + fixed_0c.new_email = new_email; + send_fpacket<0x2b0c, 86>(char_session, fixed_0c); } /*========================================== @@ -447,17 +443,20 @@ void chrif_changeemail(int id, AccountEmail actual_email, * 5: changesex *------------------------------------------ */ -void chrif_char_ask_name(int id, CharName character_name, short operation_type, +void chrif_char_ask_name(AccountId id, CharName character_name, short operation_type, HumanTimeDiff modif) { - WFIFOW(char_session, 0) = 0x2b0e; - WFIFOL(char_session, 2) = id; // account_id of who ask (for answer) -1 if nobody - WFIFO_STRING(char_session, 6, character_name.to__actual(), 24); - WFIFOW(char_session, 30) = operation_type; // type of operation + if (!char_session) + return; + + Packet_Fixed<0x2b0e> fixed_0e; + fixed_0e.account_id = id; // who ask, or nobody + fixed_0e.char_name = character_name; + fixed_0e.operation = operation_type; // type of operation if (operation_type == 2) - WFIFO_STRUCT(char_session, 32, modif); - PRINTF("chrif : sended 0x2b0e\n"); - WFIFOSET(char_session, 44); + fixed_0e.ban_add = modif; + PRINTF("chrif : sended 0x2b0e\n"_fmt); + send_fpacket<0x2b0e, 44>(char_session, fixed_0e); } /*========================================== @@ -477,123 +476,123 @@ void chrif_char_ask_name(int id, CharName character_name, short operation_type, *------------------------------------------ */ static -int chrif_char_ask_name_answer(Session *s) +int chrif_char_ask_name_answer(Session *, const Packet_Fixed<0x2b0f>& fixed) { - int acc = RFIFOL(s, 2); // account_id of who has asked (-1 if nobody) - CharName player_name = stringish<CharName>(RFIFO_STRING<24>(s, 6)); + AccountId acc = fixed.account_id; // who asked, or nobody + CharName player_name = fixed.char_name; - dumb_ptr<map_session_data> sd = map_id2sd(acc); - if (acc >= 0 && sd != NULL) + dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(acc)); + if (acc && sd != nullptr) { AString output; - if (RFIFOW(s, 32) == 1) // player not found - output = STRPRINTF("The player '%s' doesn't exist.", + if (fixed.error == 1) // player not found + output = STRPRINTF("The player '%s' doesn't exist."_fmt, player_name); else { - switch (RFIFOW(s, 30)) + switch (fixed.operation) { case 1: // block - switch (RFIFOW(s, 32)) + switch (fixed.error) { case 0: // login-server resquest done output = STRPRINTF( - "Login-server has been asked to block the player '%s'.", + "Login-server has been asked to block the player '%s'."_fmt, player_name); break; //case 1: // player not found case 2: // gm level too low output = STRPRINTF( - "Your GM level don't authorise you to block the player '%s'.", + "Your GM level don't authorise you to block the player '%s'."_fmt, player_name); break; case 3: // login-server offline output = STRPRINTF( - "Login-server is offline. Impossible to block the the player '%s'.", + "Login-server is offline. Impossible to block the the player '%s'."_fmt, player_name); break; } break; case 2: // ban - switch (RFIFOW(s, 32)) + switch (fixed.error) { case 0: // login-server resquest done output = STRPRINTF( - "Login-server has been asked to ban the player '%s'.", + "Login-server has been asked to ban the player '%s'."_fmt, player_name); break; //case 1: // player not found case 2: // gm level too low output = STRPRINTF( - "Your GM level don't authorise you to ban the player '%s'.", + "Your GM level don't authorise you to ban the player '%s'."_fmt, player_name); break; case 3: // login-server offline output = STRPRINTF( - "Login-server is offline. Impossible to ban the the player '%s'.", + "Login-server is offline. Impossible to ban the the player '%s'."_fmt, player_name); break; } break; case 3: // unblock - switch (RFIFOW(s, 32)) + switch (fixed.error) { case 0: // login-server resquest done output = STRPRINTF( - "Login-server has been asked to unblock the player '%s'.", + "Login-server has been asked to unblock the player '%s'."_fmt, player_name); break; //case 1: // player not found case 2: // gm level too low output = STRPRINTF( - "Your GM level don't authorise you to unblock the player '%s'.", + "Your GM level don't authorise you to unblock the player '%s'."_fmt, player_name); break; case 3: // login-server offline output = STRPRINTF( - "Login-server is offline. Impossible to unblock the the player '%s'.", + "Login-server is offline. Impossible to unblock the the player '%s'."_fmt, player_name); break; } break; case 4: // unban - switch (RFIFOW(s, 32)) + switch (fixed.error) { case 0: // login-server resquest done output = STRPRINTF( - "Login-server has been asked to unban the player '%s'.", + "Login-server has been asked to unban the player '%s'."_fmt, player_name); break; //case 1: // player not found case 2: // gm level too low output = STRPRINTF( - "Your GM level don't authorise you to unban the player '%s'.", + "Your GM level don't authorise you to unban the player '%s'."_fmt, player_name); break; case 3: // login-server offline output = STRPRINTF( - "Login-server is offline. Impossible to unban the the player '%s'.", + "Login-server is offline. Impossible to unban the the player '%s'."_fmt, player_name); break; } break; case 5: // changesex - switch (RFIFOW(s, 32)) + switch (fixed.error) { case 0: // login-server resquest done output = STRPRINTF( - "Login-server has been asked to change the sex of the player '%s'.", + "Login-server has been asked to change the sex of the player '%s'."_fmt, player_name); break; //case 1: // player not found case 2: // gm level too low output = STRPRINTF( - "Your GM level don't authorise you to change the sex of the player '%s'.", + "Your GM level don't authorise you to change the sex of the player '%s'."_fmt, player_name); break; case 3: // login-server offline output = STRPRINTF( - "Login-server is offline. Impossible to change the sex of the the player '%s'.", + "Login-server is offline. Impossible to change the sex of the the player '%s'."_fmt, player_name); break; } @@ -604,7 +603,7 @@ int chrif_char_ask_name_answer(Session *s) clif_displaymessage(sd->sess, output); } else - PRINTF("chrif_char_ask_name_answer failed - player not online.\n"); + PRINTF("chrif_char_ask_name_answer failed - player not online.\n"_fmt); return 0; } @@ -614,25 +613,22 @@ int chrif_char_ask_name_answer(Session *s) *------------------------------------------ */ static -void chrif_changedgm(Session *s) +void chrif_changedgm(Session *, const Packet_Fixed<0x2b0b>& fixed) { - int acc, level; - dumb_ptr<map_session_data> sd = NULL; - - acc = RFIFOL(s, 2); - level = RFIFOL(s, 6); + AccountId acc = fixed.account_id; + GmLevel level = fixed.gm_level; - sd = map_id2sd(acc); + dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(acc)); if (battle_config.etc_log) - PRINTF("chrif_changedgm: account: %d, GM level 0 -> %d.\n", acc, + PRINTF("chrif_changedgm: account: %d, GM level 0 -> %d.\n"_fmt, acc, level); - if (sd != NULL) + if (sd != nullptr) { - if (level > 0) - clif_displaymessage(sd->sess, "GM modification success."); + if (level) + clif_displaymessage(sd->sess, "GM modification success."_s); else - clif_displaymessage(sd->sess, "Failure of GM modification."); + clif_displaymessage(sd->sess, "Failure of GM modification."_s); } } @@ -641,26 +637,25 @@ void chrif_changedgm(Session *s) *------------------------------------------ */ static -void chrif_changedsex(Session *s) +void chrif_changedsex(Session *, const Packet_Fixed<0x2b0d>& fixed) { - int acc, i; dumb_ptr<map_session_data> sd; - acc = RFIFOL(s, 2); - SEX sex = static_cast<SEX>(RFIFOB(s, 6)); + AccountId acc = fixed.account_id; + SEX sex = fixed.sex; if (battle_config.etc_log) - PRINTF("chrif_changedsex %d.\n", acc); - sd = map_id2sd(acc); - if (acc > 0) + PRINTF("chrif_changedsex %d.\n"_fmt, acc); + sd = map_id2sd(account_to_block(acc)); + if (acc) { - if (sd != NULL && sd->status.sex != sex) + if (sd != nullptr && sd->status.sex != sex) { if (sd->status.sex == SEX::MALE) sd->sex = sd->status.sex = SEX::FEMALE; else if (sd->status.sex == SEX::FEMALE) sd->sex = sd->status.sex = SEX::MALE; // to avoid any problem with equipment and invalid sex, equipment is unequiped. - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (sd->status.inventory[i].nameid && bool(sd->status.inventory[i].equip)) @@ -671,15 +666,15 @@ void chrif_changedsex(Session *s) sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters // do same modify in login-server for the account, but no in char-server (it ask again login_id1 to login, and don't remember it) clif_displaymessage(sd->sess, - "Your sex has been changed (need disconexion by the server)..."); + "Your sex has been changed (need disconexion by the server)..."_s); clif_setwaitclose(sd->sess); // forced to disconnect for the change } } else { - if (sd != NULL) + if (sd != nullptr) { - PRINTF("chrif_changedsex failed.\n"); + PRINTF("chrif_changedsex failed.\n"_fmt); } } } @@ -690,24 +685,27 @@ void chrif_changedsex(Session *s) */ int chrif_saveaccountreg2(dumb_ptr<map_session_data> sd) { - int p, j; nullpo_retr(-1, sd); - p = 8; - for (j = 0; j < sd->status.account_reg2_num; j++) + if (!char_session) + return -1; + + std::vector<Packet_Repeat<0x2b10>> repeat_10; + for (size_t j = 0; j < sd->status.account_reg2_num; j++) { - struct global_reg *reg = &sd->status.account_reg2[j]; + GlobalReg *reg = &sd->status.account_reg2[j]; if (reg->str && reg->value != 0) { - WFIFO_STRING(char_session, p, reg->str, 32); - WFIFOL(char_session, p + 32) = reg->value; - p += 36; + Packet_Repeat<0x2b10> info; + info.name = reg->str; + info.value = reg->value; + repeat_10.push_back(info); } } - WFIFOW(char_session, 0) = 0x2b10; - WFIFOW(char_session, 2) = p; - WFIFOL(char_session, 4) = sd->bl_id; - WFIFOSET(char_session, p); + + Packet_Head<0x2b10> head_10; + head_10.account_id = block_to_account(sd->bl_id); + send_vpacket<0x2b10, 8, 36>(char_session, head_10, repeat_10); return 0; } @@ -717,20 +715,19 @@ int chrif_saveaccountreg2(dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -int chrif_accountreg2(Session *s) +int chrif_accountreg2(Session *, const Packet_Head<0x2b11>& head, const std::vector<Packet_Repeat<0x2b11>>& repeat) { - int j, p; - dumb_ptr<map_session_data> sd = map_id2sd(RFIFOL(s, 4)); - if (sd == NULL) + dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(head.account_id)); + if (sd == nullptr) return 1; - for (p = 8, j = 0; p < RFIFOW(s, 2) && j < ACCOUNT_REG2_NUM; - p += 36, j++) + size_t jlim = std::min(ACCOUNT_REG2_NUM, repeat.size()); + for (size_t j = 0; j < jlim; j++) { - sd->status.account_reg2[j].str = stringish<VarName>(RFIFO_STRING<32>(s, p)); - sd->status.account_reg2[j].value = RFIFOL(s, p + 32); + sd->status.account_reg2[j].str = repeat[j].name; + sd->status.account_reg2[j].value = repeat[j].value; } - sd->status.account_reg2_num = j; + sd->status.account_reg2_num = jlim; return 0; } @@ -742,9 +739,9 @@ int chrif_accountreg2(Session *s) *------------------------------------------ */ static -int chrif_divorce(int char_id, int partner_id) +int chrif_divorce(CharId char_id, CharId partner_id) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; if (!char_id || !partner_id) return 0; @@ -752,7 +749,7 @@ int chrif_divorce(int char_id, int partner_id) sd = map_nick2sd(map_charid2nick(char_id)); if (sd && sd->status.partner_id == partner_id) { - sd->status.partner_id = 0; + sd->status.partner_id = CharId(); if (sd->npc_flags.divorce) { @@ -762,9 +759,9 @@ int chrif_divorce(int char_id, int partner_id) } sd = map_nick2sd(map_charid2nick(partner_id)); - nullpo_ret(sd); + nullpo_retz(sd); if (sd->status.partner_id == char_id) - sd->status.partner_id = 0; + sd->status.partner_id = CharId(); return 0; } @@ -774,14 +771,14 @@ int chrif_divorce(int char_id, int partner_id) * Needed to divorce when partner is not connected to map server *------------------------------------- */ -int chrif_send_divorce(int char_id) +int chrif_send_divorce(CharId char_id) { if (!char_session) return -1; - WFIFOW(char_session, 0) = 0x2b16; - WFIFOL(char_session, 2) = char_id; - WFIFOSET(char_session, 6); + Packet_Fixed<0x2b16> fixed_16; + fixed_16.char_id = char_id; + send_fpacket<0x2b16, 6>(char_session, fixed_16); return 0; } @@ -790,29 +787,28 @@ int chrif_send_divorce(int char_id) *------------------------------------------ */ static -int chrif_accountdeletion(Session *s) +int chrif_accountdeletion(Session *, const Packet_Fixed<0x2b13>& fixed) { - int acc; dumb_ptr<map_session_data> sd; - acc = RFIFOL(s, 2); + AccountId acc = fixed.account_id; if (battle_config.etc_log) - PRINTF("chrif_accountdeletion %d.\n", acc); - sd = map_id2sd(acc); - if (acc > 0) + PRINTF("chrif_accountdeletion %d.\n"_fmt, acc); + sd = map_id2sd(account_to_block(acc)); + if (acc) { - if (sd != NULL) + if (sd != nullptr) { sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters clif_displaymessage(sd->sess, - "Your account has been deleted (disconnection)..."); + "Your account has been deleted (disconnection)..."_s); clif_setwaitclose(sd->sess); // forced to disconnect for the change } } else { - if (sd != NULL) - PRINTF("chrif_accountdeletion failed - player not online.\n"); + if (sd != nullptr) + PRINTF("chrif_accountdeletion failed - player not online.\n"_fmt); } return 0; @@ -823,85 +819,85 @@ int chrif_accountdeletion(Session *s) *------------------------------------------ */ static -int chrif_accountban(Session *s) +int chrif_accountban(Session *, const Packet_Fixed<0x2b14>& fixed) { - int acc; dumb_ptr<map_session_data> sd; - acc = RFIFOL(s, 2); + AccountId acc = fixed.account_id; if (battle_config.etc_log) - PRINTF("chrif_accountban %d.\n", acc); - sd = map_id2sd(acc); - if (acc > 0) + PRINTF("chrif_accountban %d.\n"_fmt, acc); + sd = map_id2sd(account_to_block(acc)); + if (acc) { - if (sd != NULL) + if (sd != nullptr) { sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters - if (RFIFOB(s, 6) == 0) + if (fixed.ban_not_status == 0) { // 0: change of statut, 1: ban - switch (RFIFOL(s, 7)) + switch (static_cast<time_t>(fixed.status_or_ban_until)) { // status or final date of a banishment case 1: // 0 = Unregistered ID clif_displaymessage(sd->sess, - "Your account has 'Unregistered'."); + "Your account has 'Unregistered'."_s); break; case 2: // 1 = Incorrect Password clif_displaymessage(sd->sess, - "Your account has an 'Incorrect Password'..."); + "Your account has an 'Incorrect Password'..."_s); break; case 3: // 2 = This ID is expired clif_displaymessage(sd->sess, - "Your account has expired."); + "Your account has expired."_s); break; case 4: // 3 = Rejected from Server clif_displaymessage(sd->sess, - "Your account has been rejected from server."); + "Your account has been rejected from server."_s); break; case 5: // 4 = You have been blocked by the GM Team clif_displaymessage(sd->sess, - "Your account has been blocked by the GM Team."); + "Your account has been blocked by the GM Team."_s); break; case 6: // 5 = Your Game's EXE file is not the latest version clif_displaymessage(sd->sess, - "Your Game's EXE file is not the latest version."); + "Your Game's EXE file is not the latest version."_s); break; case 7: // 6 = Your are Prohibited to log in until %s clif_displaymessage(sd->sess, - "Your account has been prohibited to log in."); + "Your account has been prohibited to log in."_s); break; case 8: // 7 = Server is jammed due to over populated clif_displaymessage(sd->sess, - "Server is jammed due to over populated."); + "Server is jammed due to over populated."_s); break; case 9: // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this) clif_displaymessage(sd->sess, - "Your account has not more authorised."); + "Your account has not more authorised."_s); break; case 100: // 99 = This ID has been totally erased clif_displaymessage(sd->sess, - "Your account has been totally erased."); + "Your account has been totally erased."_s); break; default: clif_displaymessage(sd->sess, - "Your account has not more authorised."); + "Your account has not more authorised."_s); break; } } - else if (RFIFOB(s, 6) == 1) + else if (fixed.ban_not_status == 1) { // 0: change of statut, 1: ban - TimeT timestamp = static_cast<time_t>(RFIFOL(s, 7)); // status or final date of a banishment - char tmpstr[] = WITH_TIMESTAMP("Your account has been banished until "); - REPLACE_TIMESTAMP(tmpstr, timestamp); - clif_displaymessage(sd->sess, const_(tmpstr)); + const TimeT timestamp = fixed.status_or_ban_until; // status or final date of a banishment + timestamp_seconds_buffer buffer; + stamp_time(buffer, ×tamp); + AString tmpstr = STRPRINTF("Your account has been banished until %s"_fmt, buffer); + clif_displaymessage(sd->sess, tmpstr); } clif_setwaitclose(sd->sess); // forced to disconnect for the change } } else { - if (sd != NULL) - PRINTF("chrif_accountban failed - player not online.\n"); + if (sd != nullptr) + PRINTF("chrif_accountban failed - player not online.\n"_fmt); } return 0; @@ -912,10 +908,10 @@ int chrif_accountban(Session *s) *------------------------------------------ */ static -int chrif_recvgmaccounts(Session *s) +int chrif_recvgmaccounts(Session *s, const std::vector<Packet_Repeat<0x2b15>>& repeat) { - PRINTF("From login-server: receiving of %d GM accounts information.\n", - pc_read_gm_account(s)); + PRINTF("From login-server: receiving of %d GM accounts information.\n"_fmt, + pc_read_gm_account(s, repeat)); return 0; } @@ -926,9 +922,11 @@ int chrif_recvgmaccounts(Session *s) */ int chrif_reloadGMdb(void) { + if (!char_session) + return -1; - WFIFOW(char_session, 0) = 0x2af7; - WFIFOSET(char_session, 2); + Packet_Fixed<0x2af7> fixed_f7; + send_fpacket<0x2af7, 2>(char_session, fixed_f7); return 0; } @@ -939,7 +937,7 @@ int chrif_reloadGMdb(void) */ static -void ladmin_itemfrob_fix_item(int source, int dest, struct item *item) +void ladmin_itemfrob_fix_item(ItemNameId source, ItemNameId dest, Item *item) { if (item && item->nameid == source) { @@ -949,7 +947,7 @@ void ladmin_itemfrob_fix_item(int source, int dest, struct item *item) } static -void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, int source_id, int dest_id) +void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, ItemNameId source_id, ItemNameId dest_id) { #define IFIX(v) if (v == source_id) {v = dest_id; } #define FIX(item) ladmin_itemfrob_fix_item(source_id, dest_id, &item) @@ -962,10 +960,9 @@ void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, int source_id, int dest_id) case BL::PC: { dumb_ptr<map_session_data> pc = bl->is_player(); - struct storage *stor = account2storage2(pc->status_key.account_id); - int j; + Storage *stor = account2storage2(pc->status_key.account_id); - for (j = 0; j < MAX_INVENTORY; j++) + for (IOff0 j : IOff0::iter()) IFIX(pc->status.inventory[j].nameid); // cart is no longer supported // IFIX(pc->status.weapon); @@ -975,10 +972,12 @@ void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, int source_id, int dest_id) IFIX(pc->status.head_bottom); if (stor) - for (j = 0; j < stor->storage_amount; j++) + { + for (SOff0 j : SOff0::iter()) FIX(stor->storage_[j]); + } - for (j = 0; j < MAX_INVENTORY; j++) + for (IOff0 j : IOff0::iter()) { struct item_data *item = pc->inventory_data[j]; if (item && item->nameid == source_id) @@ -996,7 +995,7 @@ void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, int source_id, int dest_id) case BL::MOB: { dumb_ptr<mob_data> mob = bl->is_mob(); - for (struct item& itm : mob->lootitemv) + for (Item& itm : mob->lootitemv) FIX(itm); break; } @@ -1013,16 +1012,16 @@ void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, int source_id, int dest_id) } static -void ladmin_itemfrob_c(dumb_ptr<block_list> bl, int source_id, int dest_id) +void ladmin_itemfrob_c(dumb_ptr<block_list> bl, ItemNameId source_id, ItemNameId dest_id) { ladmin_itemfrob_c2(bl, source_id, dest_id); } static -void ladmin_itemfrob(Session *s) +void ladmin_itemfrob(Session *, const Packet_Fixed<0x2afa>& fixed) { - int source_id = RFIFOL(s, 2); - int dest_id = RFIFOL(s, 6); + ItemNameId source_id = fixed.source_item_id; + ItemNameId dest_id = fixed.dest_item_id; dumb_ptr<block_list> bl = map_get_first_session(); // flooritems @@ -1041,7 +1040,7 @@ static void chrif_delete(Session *s) { assert (s == char_session); - PRINTF("Map-server can't connect to char-server (connection #%d).\n", + PRINTF("Map-server can't connect to char-server (connection #%d).\n"_fmt, s); char_session = nullptr; } @@ -1053,121 +1052,213 @@ void chrif_delete(Session *s) static void chrif_parse(Session *s) { - int packet_len, cmd; - - // only char-server can have an access to here. - // so, if it isn't the char-server, we disconnect the session (fd != char_fd). - if (s != char_session) - { - s->set_eof(); - return; - } + assert (s == char_session); - while (RFIFOREST(s) >= 2) + RecvResult rv = RecvResult::Complete; + uint16_t packet_id; + while (rv == RecvResult::Complete && packet_peek_id(s, &packet_id)) { - cmd = RFIFOW(s, 0); - if (cmd < 0x2af8 - || cmd >= - 0x2af8 + - (sizeof(packet_len_table) / sizeof(packet_len_table[0])) - || packet_len_table[cmd - 0x2af8] == 0) - { - - int r = intif_parse(s); // intifに渡す - - if (r == 1) - continue; // intifで処理した - if (r == 2) - return; // intifで処理したが、データが足りない - - s->set_eof(); - return; - } - packet_len = packet_len_table[cmd - 0x2af8]; - if (packet_len == -1) - { - if (RFIFOREST(s) < 4) - return; - packet_len = RFIFOW(s, 2); - } - if (RFIFOREST(s) < packet_len) - return; - - switch (cmd) + switch (packet_id) { case 0x2af9: - chrif_connectack(s); + { + Packet_Fixed<0x2af9> fixed; + rv = recv_fpacket<0x2af9, 3>(s, fixed); + if (rv != RecvResult::Complete) + break; + + chrif_connectack(s, fixed); break; + } case 0x2afa: - ladmin_itemfrob(s); + { + Packet_Fixed<0x2afa> fixed; + rv = recv_fpacket<0x2afa, 10>(s, fixed); + if (rv != RecvResult::Complete) + break; + + ladmin_itemfrob(s, fixed); break; + } case 0x2afb: - chrif_sendmapack(s); + { + Packet_Fixed<0x2afb> fixed; + rv = recv_fpacket<0x2afb, 27>(s, fixed); + if (rv != RecvResult::Complete) + break; + + chrif_sendmapack(s, fixed); break; + } case 0x2afd: { - int id = RFIFOL(s, 4); - int login_id2 = RFIFOL(s, 8); - TimeT connect_until_time = static_cast<time_t>(RFIFOL(s, 12)); - short tmw_version = RFIFOW(s, 16); - CharKey st_key; - CharData st_data; - RFIFO_STRUCT(s, 18, st_key); - RFIFO_STRUCT(s, 18 + sizeof(st_key), st_data); + Packet_Payload<0x2afd> payload; + rv = recv_ppacket<0x2afd>(s, payload); + if (rv != RecvResult::Complete) + break; + + AccountId id = payload.account_id; + int login_id2 = payload.login_id2; + TimeT connect_until_time = payload.connect_until; + short tmw_version = payload.packet_tmw_version; + CharKey st_key = payload.char_key; + CharData st_data = payload.char_data; pc_authok(id, login_id2, connect_until_time, tmw_version, &st_key, &st_data); - } break; + } case 0x2afe: - pc_authfail(RFIFOL(s, 2)); + { + Packet_Fixed<0x2afe> fixed; + rv = recv_fpacket<0x2afe, 6>(s, fixed); + if (rv != RecvResult::Complete) + break; + + pc_authfail(fixed.account_id); break; + } case 0x2b00: - map_setusers(RFIFOL(s, 2)); + { + Packet_Fixed<0x2b00> fixed; + rv = recv_fpacket<0x2b00, 6>(s, fixed); + if (rv != RecvResult::Complete) + break; + + map_setusers(fixed.users); break; + } case 0x2b03: - clif_charselectok(RFIFOL(s, 2)); + { + Packet_Fixed<0x2b03> fixed; + rv = recv_fpacket<0x2b03, 7>(s, fixed); + if (rv != RecvResult::Complete) + break; + + clif_charselectok(account_to_block(fixed.account_id)); break; + } case 0x2b04: - chrif_recvmap(s); + { + Packet_Head<0x2b04> head; + std::vector<Packet_Repeat<0x2b04>> repeat; + rv = recv_vpacket<0x2b04, 10, 16>(s, head, repeat); + if (rv != RecvResult::Complete) + break; + + chrif_recvmap(s, head, repeat); break; + } case 0x2b06: - chrif_changemapserverack(s); + { + Packet_Fixed<0x2b06> fixed; + rv = recv_fpacket<0x2b06, 44>(s, fixed); + if (rv != RecvResult::Complete) + break; + + chrif_changemapserverack(s, fixed); break; + } case 0x2b0b: - chrif_changedgm(s); + { + Packet_Fixed<0x2b0b> fixed; + rv = recv_fpacket<0x2b0b, 10>(s, fixed); + if (rv != RecvResult::Complete) + break; + + chrif_changedgm(s, fixed); break; + } case 0x2b0d: - chrif_changedsex(s); + { + Packet_Fixed<0x2b0d> fixed; + rv = recv_fpacket<0x2b0d, 7>(s, fixed); + if (rv != RecvResult::Complete) + break; + + chrif_changedsex(s, fixed); break; + } case 0x2b0f: - chrif_char_ask_name_answer(s); + { + Packet_Fixed<0x2b0f> fixed; + rv = recv_fpacket<0x2b0f, 34>(s, fixed); + if (rv != RecvResult::Complete) + break; + + chrif_char_ask_name_answer(s, fixed); break; + } case 0x2b11: - chrif_accountreg2(s); + { + Packet_Head<0x2b11> head; + std::vector<Packet_Repeat<0x2b11>> repeat; + rv = recv_vpacket<0x2b11, 8, 36>(s, head, repeat); + if (rv != RecvResult::Complete) + break; + + chrif_accountreg2(s, head, repeat); break; + } case 0x2b12: - chrif_divorce(RFIFOL(s, 2), RFIFOL(s, 6)); + { + Packet_Fixed<0x2b12> fixed; + rv = recv_fpacket<0x2b12, 10>(s, fixed); + if (rv != RecvResult::Complete) + break; + + chrif_divorce(fixed.char_id, fixed.partner_id); break; + } case 0x2b13: - chrif_accountdeletion(s); + { + Packet_Fixed<0x2b13> fixed; + rv = recv_fpacket<0x2b13, 6>(s, fixed); + if (rv != RecvResult::Complete) + break; + + chrif_accountdeletion(s, fixed); break; + } case 0x2b14: - chrif_accountban(s); + { + Packet_Fixed<0x2b14> fixed; + rv = recv_fpacket<0x2b14, 11>(s, fixed); + if (rv != RecvResult::Complete) + break; + + chrif_accountban(s, fixed); break; + } case 0x2b15: - chrif_recvgmaccounts(s); - break; + { + std::vector<Packet_Repeat<0x2b15>> repeat; + rv = recv_packet_repeatonly<0x2b15, 4, 5>(s, repeat); + if (rv != RecvResult::Complete) + break; + chrif_recvgmaccounts(s, repeat); + break; + } default: + { + RecvResult r = intif_parse(s, packet_id); + + if (r == RecvResult::Complete) + break; + if (r == RecvResult::Incomplete) + return; + if (battle_config.error_log) - PRINTF("chrif_parse : unknown packet %d %d\n", s, - RFIFOW(s, 0)); + PRINTF("chrif_parse : unknown packet %d %d\n"_fmt, s, + packet_id); s->set_eof(); return; + } } - RFIFOSKIP(s, packet_len); } + if (rv == RecvResult::Error) + s->set_eof(); } /*========================================== @@ -1178,12 +1269,11 @@ void chrif_parse(Session *s) static void send_users_tochar(TimerData *, tick_t) { - int users = 0; - if (!char_session) return; - WFIFOW(char_session, 0) = 0x2aff; + Packet_Head<0x2aff> head_ff; + std::vector<Packet_Repeat<0x2aff>> repeat_ff; for (io::FD i : iter_fds()) { Session *s = get_session(i); @@ -1195,13 +1285,13 @@ void send_users_tochar(TimerData *, tick_t) || sd->state.shroud_active || bool(sd->status.option & Option::HIDE)) && pc_isGM(sd))) { - WFIFOL(char_session, 6 + 4 * users) = sd->status_key.char_id; - users++; + Packet_Repeat<0x2aff> info; + info.char_id = sd->status_key.char_id; + repeat_ff.push_back(info); } } - WFIFOW(char_session, 2) = 6 + 4 * users; - WFIFOW(char_session, 4) = users; - WFIFOSET(char_session, 6 + 4 * users); + head_ff.users = repeat_ff.size(); + send_vpacket<0x2aff, 6, 4>(char_session, head_ff, repeat_ff); } /*========================================== @@ -1214,10 +1304,10 @@ void check_connect_char_server(TimerData *, tick_t) { if (!char_session) { - PRINTF("Attempt to connect to char-server...\n"); + PRINTF("Attempt to connect to char-server...\n"_fmt); chrif_state = 0; char_session = make_connection(char_ip, char_port, - SessionParsers{func_parse: chrif_parse, func_delete: chrif_delete}); + SessionParsers{.func_parse= chrif_parse, .func_delete= chrif_delete}); if (!char_session) return; realloc_fifo(char_session, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); @@ -1232,12 +1322,13 @@ void check_connect_char_server(TimerData *, tick_t) */ void do_init_chrif(void) { - Timer(gettick() + std::chrono::seconds(1), + Timer(gettick() + 1_s, check_connect_char_server, - std::chrono::seconds(10) + 10_s ).detach(); - Timer(gettick() + std::chrono::seconds(1), + Timer(gettick() + 1_s, send_users_tochar, - std::chrono::seconds(5) + 5_s ).detach(); } +} // namespace tmwa diff --git a/src/map/chrif.hpp b/src/map/chrif.hpp index afeba75..4711bc5 100644 --- a/src/map/chrif.hpp +++ b/src/map/chrif.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_CHRIF_HPP -#define TMWA_MAP_CHRIF_HPP +#pragma once // chrif.hpp - Network interface to the character server. // // Copyright © ????-2004 Athena Dev Teams @@ -21,16 +20,19 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "../mmo/dumb_ptr.hpp" -# include "../mmo/human_time_diff.hpp" -# include "../mmo/ip.hpp" +#include "../generic/fwd.hpp" -# include "map.hpp" +#include "../net/fwd.hpp" +#include "../mmo/fwd.hpp" + + +namespace tmwa +{ void chrif_setuserid(AccountName); void chrif_setpasswd(AccountPass); AccountPass chrif_getpasswd(void); @@ -48,18 +50,17 @@ int chrif_changemapserver(dumb_ptr<map_session_data> sd, MapName name, int x, int y, IP4Address ip, short port); -void chrif_changegm(int id, ZString pass); -void chrif_changeemail(int id, AccountEmail actual_email, AccountEmail new_email); -void chrif_char_ask_name(int id, CharName character_name, short operation_type, +void chrif_changegm(AccountId id, ZString pass); +void chrif_changeemail(AccountId id, AccountEmail actual_email, AccountEmail new_email); +void chrif_char_ask_name(AccountId id, CharName character_name, short operation_type, HumanTimeDiff modif); int chrif_saveaccountreg2(dumb_ptr<map_session_data> sd); int chrif_reloadGMdb(void); -int chrif_send_divorce(int char_id); +int chrif_send_divorce(CharId char_id); void do_init_chrif(void); // only used by intif.cpp // and clif.cpp for the new on_delete stuff ... extern Session *char_session; - -#endif // TMWA_MAP_CHRIF_HPP +} // namespace tmwa diff --git a/src/map/clif.cpp b/src/map/clif.cpp index eb008e4..e7557c8 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -20,29 +20,35 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <arpa/inet.h> - -#include <cstdlib> -#include <cstring> +#include <cassert> #include <ctime> -#include "../compat/alg.hpp" +#include <algorithm> + #include "../compat/attr.hpp" #include "../compat/fun.hpp" #include "../compat/nullpo.hpp" +#include "../ints/cmp.hpp" + #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" -#include "../generic/random.hpp" - #include "../io/cxxstdio.hpp" #include "../io/write.hpp" +#include "../net/ip.hpp" +#include "../net/packets.hpp" +#include "../net/socket.hpp" +#include "../net/timer.hpp" + +#include "../proto2/any-user.hpp" +#include "../proto2/char-map.hpp" +#include "../proto2/map-user.hpp" + #include "../mmo/md5more.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" +#include "../mmo/utils.hpp" #include "../mmo/version.hpp" #include "atcommand.hpp" @@ -51,6 +57,7 @@ #include "intif.hpp" #include "itemdb.hpp" #include "magic.hpp" +#include "magic-stmt.hpp" #include "map.hpp" #include "npc.hpp" #include "party.hpp" @@ -62,8 +69,9 @@ #include "../poison.hpp" -#define DUMP_UNKNOWN_PACKET 1 +namespace tmwa +{ constexpr int EMOTE_IGNORED = 0x0e; // functions list. Rate is how many milliseconds are required between @@ -71,20 +79,20 @@ constexpr int EMOTE_IGNORED = 0x0e; // map.h must be the same length as this table. rate 0 is default // rate -1 is unlimited -typedef void (*clif_func)(Session *s, dumb_ptr<map_session_data> sd); +typedef RecvResult (*clif_func)(Session *s, dumb_ptr<map_session_data> sd); struct func_table { interval_t rate; - int len; + uint16_t len_unused; clif_func func; // ctor exists because interval_t must be explicit - func_table(int r, int l, clif_func f) - : rate(r), len(l), func(f) + func_table(int r, uint16_t l, clif_func f) + : rate(r), len_unused(l), func(f) {} }; -constexpr int VAR = -1; +constexpr uint16_t VAR = 1; extern // not really - defined below func_table clif_parse_func_table[0x0220]; @@ -107,36 +115,6 @@ enum class SendWho SELF, }; -inline -void WBUFPOS(uint8_t *p, size_t pos, uint16_t x, uint16_t y) -{ - p += pos; - p[0] = x >> 2; - p[1] = (x << 6) | ((y >> 4) & 0x3f); - p[2] = y << 4; -} -inline -void WBUFPOS2(uint8_t *p, size_t pos, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) -{ - p += pos; - p[0] = x0 >> 2; - p[1] = (x0 << 6) | ((y0 >> 4) & 0x3f); - p[2] = (y0 << 4) | ((x1 >> 6) & 0x0f); - p[3] = (x1 << 2) | ((y1 >> 8) & 0x03); - p[4] = y1; -} - -inline -void WFIFOPOS(Session *s, size_t pos, uint16_t x, uint16_t y) -{ - WBUFPOS(static_cast<uint8_t *>(WFIFOP(s, pos)), 0, x, y); -} -inline -void WFIFOPOS2(Session *s, size_t pos, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) -{ - WBUFPOS2(static_cast<uint8_t *>(WFIFOP(s, pos)), 0, x0, y0, x1, y1); -} - static IP4Address map_ip; static @@ -159,11 +137,11 @@ void clif_delete(Session *s) pc_logout(sd); clif_quitsave(s, sd); - PRINTF("Player [%s] has logged off your server.\n", sd->status_key.name); // Player logout display [Valaris] + PRINTF("Player [%s] has logged off your server.\n"_fmt, sd->status_key.name); // Player logout display [Valaris] } else if (sd) { // not authentified! (refused by char-server or disconnect before to be authentified) - PRINTF("Player with account [%d] has logged off your server (not auth account).\n", sd->bl_id); // Player logout display [Yor] + PRINTF("Player with account [%d] has logged off your server (not auth account).\n"_fmt, sd->bl_id); // Player logout display [Yor] map_deliddb(sd); // account_id has been included in the DB before auth answer } } @@ -265,14 +243,14 @@ enum class ChatType }; static -AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type); +AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type, XString buf); /*========================================== * clif_sendでSendWho::AREA*指定時用 *------------------------------------------ */ static -void clif_send_sub(dumb_ptr<block_list> bl, const unsigned char *buf, int len, +void clif_send_sub(dumb_ptr<block_list> bl, const Buffer& buf, dumb_ptr<block_list> src_bl, SendWho type) { nullpo_retv(bl); @@ -299,14 +277,11 @@ void clif_send_sub(dumb_ptr<block_list> bl, const unsigned char *buf, int len, break; } - if (sd->sess != NULL) + if (sd->sess != nullptr) { { - if (clif_parse_func_table[RBUFW(buf, 0)].len) { - // packet must exist - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_buffer(sd->sess, buf); } } } @@ -317,14 +292,14 @@ void clif_send_sub(dumb_ptr<block_list> bl, const unsigned char *buf, int len, *------------------------------------------ */ static -int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type) +int clif_send(const Buffer& buf, dumb_ptr<block_list> bl, SendWho type) { - struct party *p = NULL; + PartyPair p; int x0 = 0, x1 = 0, y0 = 0, y1 = 0; if (type != SendWho::ALL_CLIENT) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::PC) { @@ -360,11 +335,8 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())); if (sd && sd->state.auth) { - if (clif_parse_func_table[RBUFW(buf, 0)].len) { - // packet must exist - WFIFO_BUF_CLONE(s, buf, len); - WFIFOSET(s, len); + send_buffer(s, buf); } } } @@ -378,25 +350,22 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())); if (sd && sd->state.auth && sd->bl_m == bl->bl_m) { - if (clif_parse_func_table[RBUFW(buf, 0)].len) { - // packet must exist - WFIFO_BUF_CLONE(s, buf, len); - WFIFOSET(s, len); + send_buffer(s, buf); } } } break; case SendWho::AREA: case SendWho::AREA_WOS: - map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, len, bl, type), + map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, bl, type), bl->bl_m, bl->bl_x - AREA_SIZE, bl->bl_y - AREA_SIZE, bl->bl_x + AREA_SIZE, bl->bl_y + AREA_SIZE, BL::PC); break; case SendWho::AREA_CHAT_WOC: - map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, len, bl, SendWho::AREA_CHAT_WOC), + map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, bl, SendWho::AREA_CHAT_WOC), bl->bl_m, bl->bl_x - (AREA_SIZE), bl->bl_y - (AREA_SIZE), bl->bl_x + (AREA_SIZE), bl->bl_y + (AREA_SIZE), @@ -417,13 +386,13 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type if (bl->bl_type == BL::PC) { dumb_ptr<map_session_data> sd = bl->is_player(); - if (sd->partyspy > 0) + if (sd->partyspy) { p = party_search(sd->partyspy); } else { - if (sd->status.party_id > 0) + if (sd->status.party_id) p = party_search(sd->status.party_id); } } @@ -444,11 +413,8 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type (sd->bl_x < x0 || sd->bl_y < y0 || sd->bl_x > x1 || sd->bl_y > y1)) continue; - if (clif_parse_func_table[RBUFW(buf, 0)].len) { - // packet must exist - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_buffer(sd->sess, buf); } } } @@ -460,13 +426,10 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())); if (sd && sd->state.auth) { - if (sd->partyspy == p->party_id) + if (sd->partyspy == p.party_id) { - if (clif_parse_func_table[RBUFW(buf, 0)].len) { - // packet must exist - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_buffer(sd->sess, buf); } } } @@ -476,18 +439,16 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type case SendWho::SELF: { dumb_ptr<map_session_data> sd = bl->is_player(); - if (clif_parse_func_table[RBUFW(buf, 0)].len) + { - // packet must exist - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_buffer(sd->sess, buf); } } break; default: if (battle_config.error_log) - PRINTF("clif_send まだ作ってないよー\n"); + PRINTF("clif_send まだ作ってないよー\n"_fmt); return -1; } @@ -503,7 +464,7 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type */ int clif_authok(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); if (!sd) return 0; @@ -513,12 +474,12 @@ int clif_authok(dumb_ptr<map_session_data> sd) Session *s = sd->sess; - WFIFOW(s, 0) = 0x73; - WFIFOL(s, 2) = gettick().time_since_epoch().count(); - WFIFOPOS(s, 6, sd->bl_x, sd->bl_y); - WFIFOB(s, 9) = 5; - WFIFOB(s, 10) = 5; - WFIFOSET(s, clif_parse_func_table[0x73].len); + Packet_Fixed<0x0073> fixed_73; + fixed_73.tick = gettick(); + fixed_73.pos = Position1{static_cast<uint16_t>(sd->bl_x), static_cast<uint16_t>(sd->bl_y), DIR::S}; + fixed_73.five1 = 5; + fixed_73.five2 = 5; + send_fpacket<0x0073, 11>(s, fixed_73); return 0; } @@ -532,9 +493,9 @@ int clif_authfail_fd(Session *s, int type) if (!s) return 0; - WFIFOW(s, 0) = 0x81; - WFIFOL(s, 2) = type; - WFIFOSET(s, clif_parse_func_table[0x81].len); + Packet_Fixed<0x0081> fixed_81; + fixed_81.error_code = type; + send_fpacket<0x0081, 3>(s, fixed_81); clif_setwaitclose(s); @@ -545,20 +506,20 @@ int clif_authfail_fd(Session *s, int type) * *------------------------------------------ */ -int clif_charselectok(int id) +int clif_charselectok(BlockId id) { dumb_ptr<map_session_data> sd; - if ((sd = map_id2sd(id)) == NULL) + if ((sd = map_id2sd(id)) == nullptr) return 1; if (!sd->sess) return 1; Session *s = sd->sess; - WFIFOW(s, 0) = 0xb3; - WFIFOB(s, 2) = 1; - WFIFOSET(s, clif_parse_func_table[0xb3].len); + Packet_Fixed<0x00b3> fixed_b3; + fixed_b3.one = 1; + send_fpacket<0x00b3, 3>(s, fixed_b3); return 0; } @@ -568,22 +529,21 @@ int clif_charselectok(int id) *------------------------------------------ */ static -int clif_set009e(dumb_ptr<flooritem_data> fitem, uint8_t *buf) +void clif_set009e(dumb_ptr<flooritem_data> fitem, Buffer& buf) { - nullpo_ret(fitem); + nullpo_retv(fitem); - //009e <ID>.l <name ID>.w <identify flag>.B <X>.w <Y>.w <subX>.B <subY>.B <amount>.w - WBUFW(buf, 0) = 0x9e; - WBUFL(buf, 2) = fitem->bl_id; - WBUFW(buf, 6) = fitem->item_data.nameid; - WBUFB(buf, 8) = 1; //identify; - WBUFW(buf, 9) = fitem->bl_x; - WBUFW(buf, 11) = fitem->bl_y; - WBUFB(buf, 13) = fitem->subx; - WBUFB(buf, 14) = fitem->suby; - WBUFW(buf, 15) = fitem->item_data.amount; + Packet_Fixed<0x009e> fixed_9e; + fixed_9e.block_id = fitem->bl_id; + fixed_9e.name_id = fitem->item_data.nameid; + fixed_9e.identify = 1; + fixed_9e.x = fitem->bl_x; + fixed_9e.y = fitem->bl_y; + fixed_9e.subx = fitem->subx; + fixed_9e.suby = fitem->suby; + fixed_9e.amount = fitem->item_data.amount; - return clif_parse_func_table[0x9e].len; + buf = create_fpacket<0x009e, 17>(fixed_9e); } /*========================================== @@ -592,14 +552,14 @@ int clif_set009e(dumb_ptr<flooritem_data> fitem, uint8_t *buf) */ int clif_dropflooritem(dumb_ptr<flooritem_data> fitem) { - uint8_t buf[64]; + nullpo_retz(fitem); - nullpo_ret(fitem); - - if (fitem->item_data.nameid <= 0) + if (!fitem->item_data.nameid) return 0; + + Buffer buf; clif_set009e(fitem, buf); - clif_send(buf, clif_parse_func_table[0x9e].len, fitem, SendWho::AREA); + clif_send(buf, fitem, SendWho::AREA); return 0; } @@ -610,21 +570,19 @@ int clif_dropflooritem(dumb_ptr<flooritem_data> fitem) */ int clif_clearflooritem(dumb_ptr<flooritem_data> fitem, Session *s) { - unsigned char buf[16]; - - nullpo_ret(fitem); + nullpo_retz(fitem); - WBUFW(buf, 0) = 0xa1; - WBUFL(buf, 2) = fitem->bl_id; + Packet_Fixed<0x00a1> fixed_a1; + fixed_a1.block_id = fitem->bl_id; if (!s) { - clif_send(buf, clif_parse_func_table[0xa1].len, fitem, SendWho::AREA); + Buffer buf = create_fpacket<0x00a1, 6>(fixed_a1); + clif_send(buf, fitem, SendWho::AREA); } else { - WFIFO_BUF_CLONE(s, buf, 6); - WFIFOSET(s, clif_parse_func_table[0xa1].len); + send_fpacket<0x00a1, 6>(s, fixed_a1); } return 0; @@ -636,21 +594,22 @@ int clif_clearflooritem(dumb_ptr<flooritem_data> fitem, Session *s) */ int clif_clearchar(dumb_ptr<block_list> bl, BeingRemoveWhy type) { - unsigned char buf[16]; + nullpo_retz(bl); - nullpo_ret(bl); + Packet_Fixed<0x0080> fixed_80; + fixed_80.block_id = bl->bl_id; - WBUFW(buf, 0) = 0x80; - WBUFL(buf, 2) = bl->bl_id; if (type == BeingRemoveWhy::DISGUISE) { - WBUFB(buf, 6) = static_cast<uint8_t>(BeingRemoveWhy::GONE); - clif_send(buf, clif_parse_func_table[0x80].len, bl, SendWho::AREA); + fixed_80.type = BeingRemoveWhy::GONE; + Buffer buf = create_fpacket<0x0080, 7>(fixed_80); + clif_send(buf, bl, SendWho::AREA); } else { - WBUFB(buf, 6) = static_cast<uint8_t>(type); - clif_send(buf, clif_parse_func_table[0x80].len, bl, + fixed_80.type = type; + Buffer buf = create_fpacket<0x0080, 7>(fixed_80); + clif_send(buf, bl, type == BeingRemoveWhy::DEAD ? SendWho::AREA : SendWho::AREA_WOS); } @@ -692,12 +651,12 @@ int clif_clearchar_delay(tick_t tick, * *------------------------------------------ */ -void clif_clearchar_id(int id, BeingRemoveWhy type, Session *s) +void clif_clearchar_id(BlockId id, BeingRemoveWhy type, Session *s) { - WFIFOW(s, 0) = 0x80; - WFIFOL(s, 2) = id; - WFIFOB(s, 6) = static_cast<uint8_t>(type); - WFIFOSET(s, clif_parse_func_table[0x80].len); + Packet_Fixed<0x0080> fixed_80; + fixed_80.block_id = id; + fixed_80.type = type; + send_fpacket<0x0080, 7>(s, fixed_80); } /*========================================== @@ -705,59 +664,111 @@ void clif_clearchar_id(int id, BeingRemoveWhy type, Session *s) *------------------------------------------ */ static -int clif_set0078(dumb_ptr<map_session_data> sd, unsigned char *buf) +void clif_set0078_main_1d8(dumb_ptr<map_session_data> sd, Buffer& buf) { - nullpo_ret(sd); + nullpo_retv(sd); - WBUFW(buf, 0) = 0x1d8; - WBUFL(buf, 2) = sd->bl_id; - WBUFW(buf, 6) = static_cast<uint16_t>(sd->speed.count()); - WBUFW(buf, 8) = static_cast<uint16_t>(sd->opt1); - WBUFW(buf, 10) = static_cast<uint16_t>(sd->opt2); - WBUFW(buf, 12) = static_cast<uint16_t>(sd->status.option); - WBUFW(buf, 14) = sd->status.species; - WBUFW(buf, 16) = sd->status.hair; + Packet_Fixed<0x01d8> fixed_1d8; + fixed_1d8.block_id = sd->bl_id; + fixed_1d8.speed = sd->speed; + fixed_1d8.opt1 = sd->opt1; + fixed_1d8.opt2 = sd->opt2; + fixed_1d8.option = sd->status.option; + fixed_1d8.species = sd->status.species; + fixed_1d8.hair_style = sd->status.hair; + + IOff0 widx = sd->equip_index_maybe[EQUIP::WEAPON]; + IOff0 sidx = sd->equip_index_maybe[EQUIP::SHIELD]; + if (sd->attack_spell_override) + fixed_1d8.weapon = sd->attack_spell_look_override; + else + { + if (widx.ok() && sd->inventory_data[widx]) + { + fixed_1d8.weapon = sd->status.inventory[widx].nameid; + } + else + fixed_1d8.weapon = ItemNameId(); + } + if (sidx.ok() && sidx != widx && sd->inventory_data[sidx]) + { + fixed_1d8.shield = sd->status.inventory[sidx].nameid; + } + else + fixed_1d8.shield = ItemNameId(); + fixed_1d8.head_bottom = sd->status.head_bottom; + fixed_1d8.head_top = sd->status.head_top; + fixed_1d8.head_mid = sd->status.head_mid; + fixed_1d8.hair_color = sd->status.hair_color; + fixed_1d8.clothes_color = sd->status.clothes_color; + fixed_1d8.head_dir = sd->head_dir; + fixed_1d8.guild_id = 0; + fixed_1d8.guild_emblem_id = 0; + fixed_1d8.manner = sd->status.manner; + fixed_1d8.opt3 = sd->opt3; + fixed_1d8.karma = sd->status.karma; + fixed_1d8.sex = sd->sex; + fixed_1d8.pos.x = sd->bl_x; + fixed_1d8.pos.y = sd->bl_y; + fixed_1d8.pos.dir = sd->dir; + fixed_1d8.gm_bits = pc_isGM(sd).get_public_word(); + fixed_1d8.dead_sit = sd->state.dead_sit; + fixed_1d8.unused = 0; + + buf = create_fpacket<0x01d8, 54>(fixed_1d8); +} +static +void clif_set0078_alt_1d9(dumb_ptr<map_session_data> sd, Buffer& buf) +{ + nullpo_retv(sd); - int widx = sd->equip_index_maybe[EQUIP::WEAPON]; - int sidx = sd->equip_index_maybe[EQUIP::SHIELD]; + Packet_Fixed<0x01d9> fixed_1d8; // LIES + fixed_1d8.block_id = sd->bl_id; + fixed_1d8.speed = sd->speed; + fixed_1d8.opt1 = sd->opt1; + fixed_1d8.opt2 = sd->opt2; + fixed_1d8.option = sd->status.option; + fixed_1d8.species = sd->status.species; + fixed_1d8.hair_style = sd->status.hair; + + IOff0 widx = sd->equip_index_maybe[EQUIP::WEAPON]; + IOff0 sidx = sd->equip_index_maybe[EQUIP::SHIELD]; if (sd->attack_spell_override) - WBUFW(buf, 18) = sd->attack_spell_look_override; + fixed_1d8.weapon = sd->attack_spell_look_override; else { - if (widx >= 0 && sd->inventory_data[widx]) + if (widx.ok() && sd->inventory_data[widx]) { - WBUFW(buf, 18) = sd->status.inventory[widx].nameid; + fixed_1d8.weapon = sd->status.inventory[widx].nameid; } else - WBUFW(buf, 18) = 0; + fixed_1d8.weapon = ItemNameId(); } - if (sidx >= 0 && sidx != widx && sd->inventory_data[sidx]) + if (sidx.ok() && sidx != widx && sd->inventory_data[sidx]) { - WBUFW(buf, 20) = sd->status.inventory[sidx].nameid; + fixed_1d8.shield = sd->status.inventory[sidx].nameid; } else - WBUFW(buf, 20) = 0; - WBUFW(buf, 22) = sd->status.head_bottom; - WBUFW(buf, 24) = sd->status.head_top; - WBUFW(buf, 26) = sd->status.head_mid; - WBUFW(buf, 28) = sd->status.hair_color; - WBUFW(buf, 30) = sd->status.clothes_color; - WBUFW(buf, 32) = static_cast<uint8_t>(sd->head_dir); - WBUFL(buf, 34) = 0 /*guild_id*/; - WBUFW(buf, 38) = 0 /*guild_emblem_id*/; - WBUFW(buf, 40) = sd->status.manner; - WBUFW(buf, 42) = static_cast<uint16_t>(sd->opt3); - WBUFB(buf, 44) = sd->status.karma; - WBUFB(buf, 45) = static_cast<uint8_t>(sd->sex); - WBUFPOS(buf, 46, sd->bl_x, sd->bl_y); - // work around ICE in gcc 4.6 - uint8_t dir = static_cast<uint8_t>(sd->dir); - WBUFB(buf, 48) |= dir; - WBUFW(buf, 49) = (pc_isGM(sd) == 60 || pc_isGM(sd) == 99) ? 0x80 : 0; - WBUFB(buf, 51) = sd->state.dead_sit; - WBUFW(buf, 52) = 0; - - return clif_parse_func_table[0x1d8].len; + fixed_1d8.shield = ItemNameId(); + fixed_1d8.head_bottom = sd->status.head_bottom; + fixed_1d8.head_top = sd->status.head_top; + fixed_1d8.head_mid = sd->status.head_mid; + fixed_1d8.hair_color = sd->status.hair_color; + fixed_1d8.clothes_color = sd->status.clothes_color; + fixed_1d8.head_dir = sd->head_dir; + fixed_1d8.guild_id = 0; + fixed_1d8.guild_emblem_id = 0; + fixed_1d8.manner = sd->status.manner; + fixed_1d8.opt3 = sd->opt3; + fixed_1d8.karma = sd->status.karma; + fixed_1d8.sex = sd->sex; + fixed_1d8.pos.x = sd->bl_x; + fixed_1d8.pos.y = sd->bl_y; + fixed_1d8.pos.dir = sd->dir; + fixed_1d8.gm_bits = pc_isGM(sd).get_public_word(); + fixed_1d8.unused = 0; + + buf = create_fpacket<0x01d9, 53>(fixed_1d8); } /*========================================== @@ -765,51 +776,54 @@ int clif_set0078(dumb_ptr<map_session_data> sd, unsigned char *buf) *------------------------------------------ */ static -int clif_set007b(dumb_ptr<map_session_data> sd, unsigned char *buf) -{ - nullpo_ret(sd); - - WBUFW(buf, 0) = 0x1da; - WBUFL(buf, 2) = sd->bl_id; - WBUFW(buf, 6) = static_cast<uint16_t>(sd->speed.count()); - WBUFW(buf, 8) = static_cast<uint16_t>(sd->opt1); - WBUFW(buf, 10) = static_cast<uint16_t>(sd->opt2); - WBUFW(buf, 12) = static_cast<uint16_t>(sd->status.option); - WBUFW(buf, 14) = sd->status.species; - WBUFW(buf, 16) = sd->status.hair; - int widx = sd->equip_index_maybe[EQUIP::WEAPON]; - int sidx = sd->equip_index_maybe[EQUIP::SHIELD]; - if (widx >= 0 && sd->inventory_data[widx]) +void clif_set007b(dumb_ptr<map_session_data> sd, Buffer& buf) +{ + nullpo_retv(sd); + + Packet_Fixed<0x01da> fixed_1da; + fixed_1da.block_id = sd->bl_id; + fixed_1da.speed = sd->speed; + fixed_1da.opt1 = sd->opt1; + fixed_1da.opt2 = sd->opt2; + fixed_1da.option = sd->status.option; + fixed_1da.species = sd->status.species; + fixed_1da.hair_style = sd->status.hair; + IOff0 widx = sd->equip_index_maybe[EQUIP::WEAPON]; + IOff0 sidx = sd->equip_index_maybe[EQUIP::SHIELD]; + if (widx.ok() && sd->inventory_data[widx]) { - WBUFW(buf, 18) = sd->status.inventory[widx].nameid; + fixed_1da.weapon = sd->status.inventory[widx].nameid; } else - WBUFW(buf, 18) = 0; - if (sidx >= 0 && sidx != widx && sd->inventory_data[sidx]) + fixed_1da.weapon = ItemNameId(); + if (sidx.ok() && sidx != widx && sd->inventory_data[sidx]) { - WBUFW(buf, 20) = sd->status.inventory[sidx].nameid; + fixed_1da.shield = sd->status.inventory[sidx].nameid; } else - WBUFW(buf, 20) = 0; - WBUFW(buf, 22) = sd->status.head_bottom; - WBUFL(buf, 24) = gettick().time_since_epoch().count(); - WBUFW(buf, 28) = sd->status.head_top; - WBUFW(buf, 30) = sd->status.head_mid; - WBUFW(buf, 32) = sd->status.hair_color; - WBUFW(buf, 34) = sd->status.clothes_color; - WBUFW(buf, 36) = static_cast<uint8_t>(sd->head_dir); - WBUFL(buf, 38) = 0/*guild_id*/; - WBUFW(buf, 42) = 0/*guild_emblem_id*/; - WBUFW(buf, 44) = sd->status.manner; - WBUFW(buf, 46) = static_cast<uint16_t>(sd->opt3); - WBUFB(buf, 48) = sd->status.karma; - WBUFB(buf, 49) = static_cast<uint8_t>(sd->sex); - WBUFPOS2(buf, 50, sd->bl_x, sd->bl_y, sd->to_x, sd->to_y); - WBUFW(buf, 55) = pc_isGM(sd) == 60 ? 0x80 : 0; - WBUFB(buf, 57) = 5; - WBUFW(buf, 58) = 0; - - return clif_parse_func_table[0x1da].len; + fixed_1da.shield = ItemNameId(); + fixed_1da.head_bottom = sd->status.head_bottom; + fixed_1da.tick = gettick(); + fixed_1da.head_top = sd->status.head_top; + fixed_1da.head_mid = sd->status.head_mid; + fixed_1da.hair_color = sd->status.hair_color; + fixed_1da.clothes_color = sd->status.clothes_color; + fixed_1da.head_dir = sd->head_dir; + fixed_1da.guild_id = 0; + fixed_1da.guild_emblem_id = 0; + fixed_1da.manner = sd->status.manner; + fixed_1da.opt3 = sd->opt3; + fixed_1da.karma = sd->status.karma; + fixed_1da.sex = sd->sex; + fixed_1da.pos2.x0 = sd->bl_x; + fixed_1da.pos2.y0 = sd->bl_y; + fixed_1da.pos2.x1 = sd->to_x; + fixed_1da.pos2.y1 = sd->to_y; + fixed_1da.gm_bits = pc_isGM(sd).get_public_word(); + fixed_1da.five = 5; + fixed_1da.unused = 0; + + buf = create_fpacket<0x01da, 60>(fixed_1da); } /*========================================== @@ -817,30 +831,27 @@ int clif_set007b(dumb_ptr<map_session_data> sd, unsigned char *buf) *------------------------------------------ */ static -int clif_mob0078(dumb_ptr<mob_data> md, unsigned char *buf) +void clif_mob0078(dumb_ptr<mob_data> md, Buffer& buf) { - really_memset0(buf, clif_parse_func_table[0x78].len); - - nullpo_ret(md); + nullpo_retv(md); - WBUFW(buf, 0) = 0x78; - WBUFL(buf, 2) = md->bl_id; - WBUFW(buf, 6) = static_cast<uint16_t>(battle_get_speed(md).count()); - WBUFW(buf, 8) = static_cast<uint16_t>(md->opt1); - WBUFW(buf, 10) = static_cast<uint16_t>(md->opt2); - WBUFW(buf, 12) = static_cast<uint16_t>(md->option); - WBUFW(buf, 14) = md->mob_class; + Packet_Fixed<0x0078> fixed_78; + fixed_78.block_id = md->bl_id; + fixed_78.speed = battle_get_speed(md); + fixed_78.opt1 = md->opt1; + fixed_78.opt2 = md->opt2; + fixed_78.option = md->option; + fixed_78.species = md->mob_class; // snip: stuff do do with disguise as a PC - WBUFPOS(buf, 46, md->bl_x, md->bl_y); - // work around ICE in gcc 4.6 - uint8_t dir = static_cast<uint8_t>(md->dir); - WBUFB(buf, 48) |= dir; - WBUFB(buf, 49) = 5; - WBUFB(buf, 50) = 5; + fixed_78.pos.x = md->bl_x; + fixed_78.pos.y = md->bl_y; + fixed_78.pos.dir = md->dir; + fixed_78.five1 = 5; + fixed_78.five2 = 5; int level = battle_get_lv(md); - WBUFW(buf, 52) = (level > battle_config.max_lv) ? battle_config.max_lv : level; + fixed_78.level = (level > battle_config.max_lv) ? battle_config.max_lv : level; - return clif_parse_func_table[0x78].len; + buf = create_fpacket<0x0078, 54>(fixed_78); } /*========================================== @@ -848,29 +859,30 @@ int clif_mob0078(dumb_ptr<mob_data> md, unsigned char *buf) *------------------------------------------ */ static -int clif_mob007b(dumb_ptr<mob_data> md, unsigned char *buf) +void clif_mob007b(dumb_ptr<mob_data> md, Buffer& buf) { - really_memset0(buf, clif_parse_func_table[0x7b].len); - - nullpo_ret(md); + nullpo_retv(md); - WBUFW(buf, 0) = 0x7b; - WBUFL(buf, 2) = md->bl_id; - WBUFW(buf, 6) = static_cast<uint16_t>(battle_get_speed(md).count()); - WBUFW(buf, 8) = static_cast<uint16_t>(md->opt1); - WBUFW(buf, 10) = static_cast<uint16_t>(md->opt2); - WBUFW(buf, 12) = static_cast<uint16_t>(md->option); - WBUFW(buf, 14) = md->mob_class; + Packet_Fixed<0x007b> fixed_7b; + fixed_7b.block_id = md->bl_id; + fixed_7b.speed = battle_get_speed(md); + fixed_7b.opt1 = md->opt1; + fixed_7b.opt2 = md->opt2; + fixed_7b.option = md->option; + fixed_7b.mob_class = md->mob_class; // snip: stuff for monsters disguised as PCs - WBUFL(buf, 22) = gettick().time_since_epoch().count(); - - WBUFPOS2(buf, 50, md->bl_x, md->bl_y, md->to_x, md->to_y); - WBUFB(buf, 56) = 5; - WBUFB(buf, 57) = 5; + fixed_7b.tick_and_maybe_part_of_guild_emblem = gettick(); + + fixed_7b.pos2.x0 = md->bl_x; + fixed_7b.pos2.y0 = md->bl_y; + fixed_7b.pos2.x1 = md->to_x; + fixed_7b.pos2.y1 = md->to_y; + fixed_7b.five1 = 5; + fixed_7b.five2 = 5; int level = battle_get_lv(md); - WBUFW(buf, 58) = (level > battle_config.max_lv) ? battle_config.max_lv : level; + fixed_7b.level = (level > battle_config.max_lv) ? battle_config.max_lv : level; - return clif_parse_func_table[0x7b].len; + buf = create_fpacket<0x007b, 60>(fixed_7b); } /*========================================== @@ -878,24 +890,23 @@ int clif_mob007b(dumb_ptr<mob_data> md, unsigned char *buf) *------------------------------------------ */ static -int clif_npc0078(dumb_ptr<npc_data> nd, unsigned char *buf) +void clif_npc0078(dumb_ptr<npc_data> nd, Buffer& buf) { - nullpo_ret(nd); - - really_memset0(buf, clif_parse_func_table[0x78].len); + nullpo_retv(nd); - WBUFW(buf, 0) = 0x78; - WBUFL(buf, 2) = nd->bl_id; - WBUFW(buf, 6) = static_cast<uint16_t>(nd->speed.count()); - WBUFW(buf, 14) = nd->npc_class; - WBUFPOS(buf, 46, nd->bl_x, nd->bl_y); - // work around ICE in gcc 4.6 - uint8_t dir = static_cast<uint8_t>(nd->dir); - WBUFB(buf, 48) |= dir; - WBUFB(buf, 49) = 5; - WBUFB(buf, 50) = 5; + Packet_Fixed<0x0078> fixed_78; + fixed_78.block_id = nd->bl_id; + fixed_78.speed = nd->speed; + fixed_78.species = nd->npc_class; + fixed_78.pos.x = nd->bl_x; + fixed_78.pos.y = nd->bl_y; + fixed_78.pos.dir = nd->dir; + fixed_78.five1 = 5; + fixed_78.five2 = 5; + fixed_78.zero = 0; + fixed_78.level = 0; - return clif_parse_func_table[0x78].len; + buf = create_fpacket<0x0078, 54>(fixed_78); } /* These indices are derived from equip_pos in pc.c and some guesswork */ @@ -924,15 +935,12 @@ earray<EQUIP, LOOK, LOOK::COUNT> equip_points //= */ int clif_spawnpc(dumb_ptr<map_session_data> sd) { - unsigned char buf[128]; + nullpo_retz(sd); - nullpo_ret(sd); + Buffer buf; + clif_set0078_alt_1d9(sd, buf); - clif_set0078(sd, buf); - - WBUFW(buf, 0) = 0x1d9; - WBUFW(buf, 51) = 0; - clif_send(buf, clif_parse_func_table[0x1d9].len, sd, SendWho::AREA_WOS); + clif_send(buf, sd, SendWho::AREA_WOS); if (sd->bl_m->flag.get(MapFlag::SNOW)) clif_specialeffect(sd, 162, 1); @@ -945,7 +953,7 @@ int clif_spawnpc(dumb_ptr<map_session_data> sd) if (sd->bl_m->flag.get(MapFlag::RAIN)) clif_specialeffect(sd, 161, 1); -// clif_changelook_accessories(sd, NULL); +// clif_changelook_accessories(sd, nullptr); return 0; } @@ -956,62 +964,64 @@ int clif_spawnpc(dumb_ptr<map_session_data> sd) */ int clif_spawnnpc(dumb_ptr<npc_data> nd) { - unsigned char buf[64]; - int len; - - nullpo_ret(nd); + nullpo_retz(nd); - if (nd->npc_class < 0 || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS) + if (nd->npc_class == NEGATIVE_SPECIES || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS) return 0; - really_memset0(buf, clif_parse_func_table[0x7c].len); + Packet_Fixed<0x007c> fixed_7c; + fixed_7c.block_id = nd->bl_id; + fixed_7c.speed = nd->speed; + fixed_7c.species = nd->npc_class; + fixed_7c.pos.x = nd->bl_x; + fixed_7c.pos.y = nd->bl_y; - WBUFW(buf, 0) = 0x7c; - WBUFL(buf, 2) = nd->bl_id; - WBUFW(buf, 6) = static_cast<uint16_t>(nd->speed.count()); - WBUFW(buf, 20) = nd->npc_class; - WBUFPOS(buf, 36, nd->bl_x, nd->bl_y); + Buffer buf = create_fpacket<0x007c, 41>(fixed_7c); + clif_send(buf, nd, SendWho::AREA); - clif_send(buf, clif_parse_func_table[0x7c].len, nd, SendWho::AREA); - - len = clif_npc0078(nd, buf); - clif_send(buf, len, nd, SendWho::AREA); + clif_npc0078(nd, buf); + clif_send(buf, nd, SendWho::AREA); return 0; } -int clif_spawn_fake_npc_for_player(dumb_ptr<map_session_data> sd, int fake_npc_id) +int clif_spawn_fake_npc_for_player(dumb_ptr<map_session_data> sd, BlockId fake_npc_id) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; if (!s) return 0; - WFIFOW(s, 0) = 0x7c; - WFIFOL(s, 2) = fake_npc_id; - WFIFOW(s, 6) = 0; - WFIFOW(s, 8) = 0; - WFIFOW(s, 10) = 0; - WFIFOW(s, 12) = 0; - WFIFOW(s, 20) = 127; - WFIFOPOS(s, 36, sd->bl_x, sd->bl_y); - WFIFOSET(s, clif_parse_func_table[0x7c].len); - - WFIFOW(s, 0) = 0x78; - WFIFOL(s, 2) = fake_npc_id; - WFIFOW(s, 6) = 0; - WFIFOW(s, 8) = 0; - WFIFOW(s, 10) = 0; - WFIFOW(s, 12) = 0; - WFIFOW(s, 14) = 127; // identifies as NPC - WFIFOW(s, 20) = 127; - WFIFOPOS(s, 46, sd->bl_x, sd->bl_y); - WFIFOPOS(s, 36, sd->bl_x, sd->bl_y); - WFIFOB(s, 49) = 5; - WFIFOB(s, 50) = 5; - WFIFOSET(s, clif_parse_func_table[0x78].len); + Packet_Fixed<0x007c> fixed_7c; + fixed_7c.block_id = fake_npc_id; + fixed_7c.speed = interval_t(); + fixed_7c.opt1 = Opt1::ZERO; + fixed_7c.opt2 = Opt2::ZERO; + fixed_7c.option = Option::ZERO; + fixed_7c.species = FAKE_NPC_CLASS; + fixed_7c.pos.x = sd->bl_x; + fixed_7c.pos.y = sd->bl_y; + send_fpacket<0x007c, 41>(s, fixed_7c); + + Packet_Fixed<0x0078> fixed_78; + fixed_78.block_id = fake_npc_id; + fixed_78.speed = interval_t(); + fixed_78.opt1 = Opt1::ZERO; + fixed_78.opt2 = Opt2::ZERO; + fixed_78.option = Option::ZERO; + fixed_78.species = FAKE_NPC_CLASS; + fixed_78.unused_head_bottom_or_species_again = unwrap<Species>(FAKE_NPC_CLASS); + fixed_78.pos.x = sd->bl_x; + fixed_78.pos.y = sd->bl_y; + fixed_78.unused_pos_again.x = sd->bl_x; + fixed_78.unused_pos_again.y = sd->bl_y; + fixed_78.five1 = 5; + fixed_78.five2 = 5; + fixed_78.zero = 0; + fixed_78.level = 0; + send_fpacket<0x0078, 54>(s, fixed_78); return 0; } @@ -1022,27 +1032,25 @@ int clif_spawn_fake_npc_for_player(dumb_ptr<map_session_data> sd, int fake_npc_i */ int clif_spawnmob(dumb_ptr<mob_data> md) { - unsigned char buf[64]; - int len; - - nullpo_ret(md); + nullpo_retz(md); { - really_memset0(buf, clif_parse_func_table[0x7c].len); - - WBUFW(buf, 0) = 0x7c; - WBUFL(buf, 2) = md->bl_id; - WBUFW(buf, 6) = md->stats[mob_stat::SPEED]; - WBUFW(buf, 8) = uint16_t(md->opt1); - WBUFW(buf, 10) = uint16_t(md->opt2); - WBUFW(buf, 12) = uint16_t(md->option); - WBUFW(buf, 20) = md->mob_class; - WBUFPOS(buf, 36, md->bl_x, md->bl_y); - clif_send(buf, clif_parse_func_table[0x7c].len, md, SendWho::AREA); + Packet_Fixed<0x007c> fixed_7c; + fixed_7c.block_id = md->bl_id; + fixed_7c.speed = interval_t(md->stats[mob_stat::SPEED]); + fixed_7c.opt1 = md->opt1; + fixed_7c.opt2 = md->opt2; + fixed_7c.option = md->option; + fixed_7c.species = md->mob_class; + fixed_7c.pos.x = md->bl_x; + fixed_7c.pos.y = md->bl_y; + Buffer buf = create_fpacket<0x007c, 41>(fixed_7c); + clif_send(buf, md, SendWho::AREA); } - len = clif_mob0078(md, buf); - clif_send(buf, len, md, SendWho::AREA); + Buffer buf; + clif_mob0078(md, buf); + clif_send(buf, md, SendWho::AREA); return 0; } @@ -1054,12 +1062,12 @@ int clif_spawnmob(dumb_ptr<mob_data> md) static int clif_servertick(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x7f; - WFIFOL(s, 2) = sd->server_tick.time_since_epoch().count(); - WFIFOSET(s, clif_parse_func_table[0x7f].len); + Packet_Fixed<0x007f> fixed_7f; + fixed_7f.tick = gettick(); + send_fpacket<0x007f, 6>(s, fixed_7f); return 0; } @@ -1070,14 +1078,17 @@ int clif_servertick(dumb_ptr<map_session_data> sd) */ int clif_walkok(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x87; - WFIFOL(s, 2) = gettick().time_since_epoch().count(); - WFIFOPOS2(s, 6, sd->bl_x, sd->bl_y, sd->to_x, sd->to_y); - WFIFOB(s, 11) = 0; - WFIFOSET(s, clif_parse_func_table[0x87].len); + Packet_Fixed<0x0087> fixed_87; + fixed_87.tick = gettick(); + fixed_87.pos2.x0 = sd->bl_x; + fixed_87.pos2.y0 = sd->bl_y; + fixed_87.pos2.x1 = sd->to_x; + fixed_87.pos2.y1 = sd->to_y; + fixed_87.zero = 0; + send_fpacket<0x0087, 12>(s, fixed_87); return 0; } @@ -1088,14 +1099,12 @@ int clif_walkok(dumb_ptr<map_session_data> sd) */ int clif_movechar(dumb_ptr<map_session_data> sd) { - int len; - unsigned char buf[256]; + nullpo_retz(sd); - nullpo_ret(sd); + Buffer buf; + clif_set007b(sd, buf); - len = clif_set007b(sd, buf); - - clif_send(buf, len, sd, SendWho::AREA_WOS); + clif_send(buf, sd, SendWho::AREA_WOS); if (battle_config.save_clothcolor == 1 && sd->status.clothes_color > 0) clif_changelook(sd, LOOK::CLOTHES_COLOR, @@ -1131,7 +1140,7 @@ void clif_waitclose(TimerData *, tick_t, Session *s) */ void clif_setwaitclose(Session *s) { - s->timed_close = Timer(gettick() + std::chrono::seconds(5), + s->timed_close = Timer(gettick() + 5_s, std::bind(clif_waitclose, ph::_1, ph::_2, s) ); @@ -1147,11 +1156,11 @@ void clif_changemap(dumb_ptr<map_session_data> sd, MapName mapname, int x, int y Session *s = sd->sess; - WFIFOW(s, 0) = 0x91; - WFIFO_STRING(s, 2, mapname, 16); - WFIFOW(s, 18) = x; - WFIFOW(s, 20) = y; - WFIFOSET(s, clif_parse_func_table[0x91].len); + Packet_Fixed<0x0091> fixed_91; + fixed_91.map_name = mapname; + fixed_91.x = x; + fixed_91.y = y; + send_fpacket<0x0091, 22>(s, fixed_91); } /*========================================== @@ -1164,13 +1173,13 @@ void clif_changemapserver(dumb_ptr<map_session_data> sd, nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x92; - WFIFO_STRING(s, 2, mapname, 16); - WFIFOW(s, 18) = x; - WFIFOW(s, 20) = y; - WFIFOIP(s, 22) = ip; - WFIFOW(s, 26) = port; - WFIFOSET(s, clif_parse_func_table[0x92].len); + Packet_Fixed<0x0092> fixed_92; + fixed_92.map_name = mapname; + fixed_92.x = x; + fixed_92.y = y; + fixed_92.ip = ip; + fixed_92.port = port; + send_fpacket<0x0092, 28>(s, fixed_92); } /*========================================== @@ -1179,30 +1188,29 @@ void clif_changemapserver(dumb_ptr<map_session_data> sd, */ void clif_fixpos(dumb_ptr<block_list> bl) { - uint8_t buf[16]; - nullpo_retv(bl); - WBUFW(buf, 0) = 0x88; - WBUFL(buf, 2) = bl->bl_id; - WBUFW(buf, 6) = bl->bl_x; - WBUFW(buf, 8) = bl->bl_y; + Packet_Fixed<0x0088> fixed_88; + fixed_88.block_id = bl->bl_id; + fixed_88.x = bl->bl_x; + fixed_88.y = bl->bl_y; - clif_send(buf, clif_parse_func_table[0x88].len, bl, SendWho::AREA); + Buffer buf = create_fpacket<0x0088, 10>(fixed_88); + clif_send(buf, bl, SendWho::AREA); } /*========================================== * *------------------------------------------ */ -int clif_npcbuysell(dumb_ptr<map_session_data> sd, int id) +int clif_npcbuysell(dumb_ptr<map_session_data> sd, BlockId id) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xc4; - WFIFOL(s, 2) = id; - WFIFOSET(s, clif_parse_func_table[0xc4].len); + Packet_Fixed<0x00c4> fixed_c4; + fixed_c4.block_id = id; + send_fpacket<0x00c4, 6>(s, fixed_c4); return 0; } @@ -1216,22 +1224,21 @@ int clif_buylist(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data_shop> nd) struct item_data *id; int i, val; - nullpo_ret(sd); - nullpo_ret(nd); + nullpo_retz(sd); + nullpo_retz(nd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xc6; + std::vector<Packet_Repeat<0x00c6>> repeat_c6(nd->shop_items.size()); for (i = 0; i < nd->shop_items.size(); i++) { id = itemdb_search(nd->shop_items[i].nameid); val = nd->shop_items[i].value; - WFIFOL(s, 4 + i * 11) = val; // base price - WFIFOL(s, 8 + i * 11) = val; // actual price - WFIFOB(s, 12 + i * 11) = uint8_t(id->type); - WFIFOW(s, 13 + i * 11) = nd->shop_items[i].nameid; + repeat_c6[i].base_price = val; // base price + repeat_c6[i].actual_price = val; // actual price + repeat_c6[i].type = id->type; + repeat_c6[i].name_id = nd->shop_items[i].nameid; } - WFIFOW(s, 2) = i * 11 + 4; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x00c6, 4, 11>(s, repeat_c6); return 0; } @@ -1242,27 +1249,25 @@ int clif_buylist(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data_shop> nd) */ int clif_selllist(dumb_ptr<map_session_data> sd) { - int i, c = 0, val; - - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xc7; - for (i = 0; i < MAX_INVENTORY; i++) + std::vector<Packet_Repeat<0x00c7>> repeat_c7; + for (IOff0 i : IOff0::iter()) { - if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i]) + if (sd->status.inventory[i].nameid && sd->inventory_data[i]) { - val = sd->inventory_data[i]->value_sell; + int val = sd->inventory_data[i]->value_sell; if (val < 0) continue; - WFIFOW(s, 4 + c * 10) = i + 2; - WFIFOL(s, 6 + c * 10) = val; // base price - WFIFOL(s, 10 + c * 10) = val; // actual price - c++; + Packet_Repeat<0x00c7> info; + info.ioff2 = i.shift(); + info.base_price = val; + info.actual_price = val; + repeat_c7.push_back(info); } } - WFIFOW(s, 2) = c * 10 + 4; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x00c7, 4, 10>(s, repeat_c7); return 0; } @@ -1271,166 +1276,130 @@ int clif_selllist(dumb_ptr<map_session_data> sd) * *------------------------------------------ */ -void clif_scriptmes(dumb_ptr<map_session_data> sd, int npcid, XString mes) +void clif_scriptmes(dumb_ptr<map_session_data> sd, BlockId npcid, XString mes) { nullpo_retv(sd); Session *s = sd->sess; - size_t len = mes.size() + 1; - WFIFOW(s, 0) = 0xb4; - WFIFOW(s, 2) = len + 8; - WFIFOL(s, 4) = npcid; - WFIFO_STRING(s, 8, mes, len); - WFIFOSET(s, WFIFOW(s, 2)); + Packet_Head<0x00b4> head_b4; + head_b4.block_id = npcid; + send_vpacket<0x00b4, 8, 1>(s, head_b4, mes); } /*========================================== * *------------------------------------------ */ -void clif_scriptnext(dumb_ptr<map_session_data> sd, int npcid) +void clif_scriptnext(dumb_ptr<map_session_data> sd, BlockId npcid) { nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xb5; - WFIFOL(s, 2) = npcid; - WFIFOSET(s, clif_parse_func_table[0xb5].len); + Packet_Fixed<0x00b5> fixed_b5; + fixed_b5.block_id = npcid; + send_fpacket<0x00b5, 6>(s, fixed_b5); } /*========================================== * *------------------------------------------ */ -void clif_scriptclose(dumb_ptr<map_session_data> sd, int npcid) +void clif_scriptclose(dumb_ptr<map_session_data> sd, BlockId npcid) { nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xb6; - WFIFOL(s, 2) = npcid; - WFIFOSET(s, clif_parse_func_table[0xb6].len); + Packet_Fixed<0x00b6> fixed_b6; + fixed_b6.block_id = npcid; + send_fpacket<0x00b6, 6>(s, fixed_b6); } /*========================================== * *------------------------------------------ */ -void clif_scriptmenu(dumb_ptr<map_session_data> sd, int npcid, XString mes) +void clif_scriptmenu(dumb_ptr<map_session_data> sd, BlockId npcid, XString mes) { nullpo_retv(sd); Session *s = sd->sess; - size_t len = mes.size() + 1; - WFIFOW(s, 0) = 0xb7; - WFIFOW(s, 2) = len + 8; - WFIFOL(s, 4) = npcid; - WFIFO_STRING(s, 8, mes, len); - WFIFOSET(s, WFIFOW(s, 2)); + Packet_Head<0x00b7> head_b7; + head_b7.block_id = npcid; + send_vpacket<0x00b7, 8, 1>(s, head_b7, mes); } /*========================================== * *------------------------------------------ */ -void clif_scriptinput(dumb_ptr<map_session_data> sd, int npcid) +void clif_scriptinput(dumb_ptr<map_session_data> sd, BlockId npcid) { nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x142; - WFIFOL(s, 2) = npcid; - WFIFOSET(s, clif_parse_func_table[0x142].len); + Packet_Fixed<0x0142> fixed_142; + fixed_142.block_id = npcid; + send_fpacket<0x0142, 6>(s, fixed_142); } /*========================================== * *------------------------------------------ */ -void clif_scriptinputstr(dumb_ptr<map_session_data> sd, int npcid) +void clif_scriptinputstr(dumb_ptr<map_session_data> sd, BlockId npcid) { nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x1d4; - WFIFOL(s, 2) = npcid; - WFIFOSET(s, clif_parse_func_table[0x1d4].len); + Packet_Fixed<0x01d4> fixed_1d4; + fixed_1d4.block_id = npcid; + send_fpacket<0x01d4, 6>(s, fixed_1d4); } /*========================================== * *------------------------------------------ */ -void clif_viewpoint(dumb_ptr<map_session_data> sd, int npc_id, int type, - int x, int y, int id, int color) +int clif_additem(dumb_ptr<map_session_data> sd, IOff0 n, int amount, PickupFail fail) { - nullpo_retv(sd); - - Session *s = sd->sess; - WFIFOW(s, 0) = 0x144; - WFIFOL(s, 2) = npc_id; - WFIFOL(s, 6) = type; - WFIFOL(s, 10) = x; - WFIFOL(s, 14) = y; - WFIFOB(s, 18) = id; - WFIFOL(s, 19) = color; - WFIFOSET(s, clif_parse_func_table[0x144].len); -} - -/*========================================== - * - *------------------------------------------ - */ -int clif_additem(dumb_ptr<map_session_data> sd, int n, int amount, PickupFail fail) -{ - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; + Packet_Fixed<0x00a0> fixed_a0; if (fail != PickupFail::OKAY) { - WFIFOW(s, 0) = 0xa0; - WFIFOW(s, 2) = n + 2; - WFIFOW(s, 4) = amount; - WFIFOW(s, 6) = 0; - WFIFOB(s, 8) = 0; - WFIFOB(s, 9) = 0; - WFIFOB(s, 10) = 0; - WFIFOW(s, 11) = 0; - WFIFOW(s, 13) = 0; - WFIFOW(s, 15) = 0; - WFIFOW(s, 17) = 0; - WFIFOW(s, 19) = 0; - WFIFOB(s, 21) = 0; - WFIFOB(s, 22) = uint8_t(fail); + fixed_a0.ioff2 = n.shift(); + fixed_a0.amount = amount; + fixed_a0.name_id = ItemNameId(); + fixed_a0.pickup_fail = fail; } else { - if (n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <= 0 - || sd->inventory_data[n] == NULL) + if (!n.ok() || !sd->status.inventory[n].nameid + || sd->inventory_data[n] == nullptr) return 1; - WFIFOW(s, 0) = 0xa0; - WFIFOW(s, 2) = n + 2; - WFIFOW(s, 4) = amount; - WFIFOW(s, 6) = sd->status.inventory[n].nameid; - WFIFOB(s, 8) = 1; //identify; - WFIFOB(s, 9) = 0; // broken or attribute; - WFIFOB(s, 10) = 0; //refine; + fixed_a0.ioff2 = n.shift(); + fixed_a0.amount = amount; + fixed_a0.name_id = sd->status.inventory[n].nameid; + fixed_a0.identify = 1; + fixed_a0.broken_or_attribute = 0; + fixed_a0.refine = 0; { - WFIFOW(s, 11) = 0; //card[0]; - WFIFOW(s, 13) = 0; //card[1]; - WFIFOW(s, 15) = 0; //card[2]; - WFIFOW(s, 17) = 0; //card[3]; + fixed_a0.card0 = 0; + fixed_a0.card1 = 0; + fixed_a0.card2 = 0; + fixed_a0.card3 = 0; } - WFIFOW(s, 19) = uint16_t(pc_equippoint(sd, n)); - WFIFOB(s, 21) = uint8_t(sd->inventory_data[n]->type == ItemType::_7 + fixed_a0.epos = pc_equippoint(sd, n); + fixed_a0.item_type = (sd->inventory_data[n]->type == ItemType::_7 ? ItemType::WEAPON : sd->inventory_data[n]->type); - WFIFOB(s, 22) = uint8_t(fail); + fixed_a0.pickup_fail = fail; } - WFIFOSET(s, clif_parse_func_table[0xa0].len); + send_fpacket<0x00a0, 23>(s, fixed_a0); return 0; } @@ -1438,16 +1407,16 @@ int clif_additem(dumb_ptr<map_session_data> sd, int n, int amount, PickupFail fa * *------------------------------------------ */ -void clif_delitem(dumb_ptr<map_session_data> sd, int n, int amount) +void clif_delitem(dumb_ptr<map_session_data> sd, IOff0 n, int amount) { nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xaf; - WFIFOW(s, 2) = n + 2; - WFIFOW(s, 4) = amount; + Packet_Fixed<0x00af> fixed_af; + fixed_af.ioff2 = n.shift(); + fixed_af.amount = amount; - WFIFOSET(s, clif_parse_func_table[0xaf].len); + send_fpacket<0x00af, 6>(s, fixed_af); } /*========================================== @@ -1458,41 +1427,40 @@ void clif_itemlist(dumb_ptr<map_session_data> sd) { nullpo_retv(sd); - int n = 0; - int arrow = -1; + IOff0 arrow = IOff0::from(-1); Session *s = sd->sess; - WFIFOW(s, 0) = 0x1ee; - for (int i = 0; i < MAX_INVENTORY; i++) + std::vector<Packet_Repeat<0x01ee>> repeat_1ee; + for (IOff0 i : IOff0::iter()) { - if (sd->status.inventory[i].nameid <= 0 - || sd->inventory_data[i] == NULL + if (!sd->status.inventory[i].nameid + || sd->inventory_data[i] == nullptr || itemdb_isequip2(sd->inventory_data[i])) continue; - WFIFOW(s, n * 18 + 4) = i + 2; - WFIFOW(s, n * 18 + 6) = sd->status.inventory[i].nameid; - WFIFOB(s, n * 18 + 8) = uint8_t(sd->inventory_data[i]->type); - WFIFOB(s, n * 18 + 9) = 1; //identify; - WFIFOW(s, n * 18 + 10) = sd->status.inventory[i].amount; + Packet_Repeat<0x01ee> info; + info.ioff2 = i.shift(); + info.name_id = sd->status.inventory[i].nameid; + info.item_type = sd->inventory_data[i]->type; + info.identify = 1; + info.amount = sd->status.inventory[i].amount; if (sd->inventory_data[i]->equip == EPOS::ARROW) { - WFIFOW(s, n * 18 + 12) = uint16_t(EPOS::ARROW); + info.epos = EPOS::ARROW; if (bool(sd->status.inventory[i].equip)) - arrow = i; // ついでに矢装備チェック + arrow = i; } else - WFIFOW(s, n * 18 + 12) = uint16_t(EPOS::ZERO); - WFIFOW(s, n * 18 + 14) = 0; //card[0]; - WFIFOW(s, n * 18 + 16) = 0; //card[1]; - WFIFOW(s, n * 18 + 18) = 0; //card[2]; - WFIFOW(s, n * 18 + 20) = 0; //card[3]; - n++; + info.epos = EPOS::ZERO; + info.card0 = 0; + info.card1 = 0; + info.card2 = 0; + info.card3 = 0; + repeat_1ee.push_back(info); } - if (n) + if (!repeat_1ee.empty()) { - WFIFOW(s, 2) = 4 + n * 18; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x01ee, 4, 18>(s, repeat_1ee); } - if (arrow >= 0) + if (arrow.ok()) clif_arrowequip(sd, arrow); } @@ -1505,37 +1473,36 @@ void clif_equiplist(dumb_ptr<map_session_data> sd) nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xa4; - int n = 0; - for (int i = 0; i < MAX_INVENTORY; i++) + std::vector<Packet_Repeat<0x00a4>> repeat_a4; + for (IOff0 i : IOff0::iter()) { - if (sd->status.inventory[i].nameid <= 0 - || sd->inventory_data[i] == NULL + if (!sd->status.inventory[i].nameid + || sd->inventory_data[i] == nullptr || !itemdb_isequip2(sd->inventory_data[i])) continue; - WFIFOW(s, n * 20 + 4) = i + 2; - WFIFOW(s, n * 20 + 6) = sd->status.inventory[i].nameid; - WFIFOB(s, n * 20 + 8) = uint8_t( + Packet_Repeat<0x00a4> info; + info.ioff2 = i.shift(); + info.name_id = sd->status.inventory[i].nameid; + info.item_type = ( sd->inventory_data[i]->type == ItemType::_7 ? ItemType::WEAPON : sd->inventory_data[i]->type); - WFIFOB(s, n * 20 + 9) = 0; //identify; - WFIFOW(s, n * 20 + 10) = uint16_t(pc_equippoint(sd, i)); - WFIFOW(s, n * 20 + 12) = uint16_t(sd->status.inventory[i].equip); - WFIFOB(s, n * 20 + 14) = 0; //broken or attribute; - WFIFOB(s, n * 20 + 15) = 0; //refine; + info.identify = 0; + info.epos_pc = pc_equippoint(sd, i); + info.epos_inv = sd->status.inventory[i].equip; + info.broken_or_attribute = 0; + info.refine = 0; { - WFIFOW(s, n * 20 + 16) = 0; //card[0]; - WFIFOW(s, n * 20 + 18) = 0; //card[1]; - WFIFOW(s, n * 20 + 20) = 0; //card[2]; - WFIFOW(s, n * 20 + 22) = 0; //card[3]; + info.card0 = 0; + info.card1 = 0; + info.card2 = 0; + info.card3 = 0; } - n++; + repeat_a4.push_back(info); } - if (n) + if (!repeat_a4.empty()) { - WFIFOW(s, 2) = 4 + n * 20; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x00a4, 4, 20>(s, repeat_a4); } } @@ -1543,41 +1510,40 @@ void clif_equiplist(dumb_ptr<map_session_data> sd) * カプラさんに預けてある消耗品&収集品リスト *------------------------------------------ */ -int clif_storageitemlist(dumb_ptr<map_session_data> sd, struct storage *stor) +int clif_storageitemlist(dumb_ptr<map_session_data> sd, Storage *stor) { - nullpo_ret(sd); - nullpo_ret(stor); + nullpo_retz(sd); + nullpo_retz(stor); Session *s = sd->sess; - WFIFOW(s, 0) = 0x1f0; - int n = 0; - for (int i = 0; i < MAX_STORAGE; i++) + std::vector<Packet_Repeat<0x01f0>> repeat_1f0; + for (SOff0 i : SOff0::iter()) { - if (stor->storage_[i].nameid <= 0) + if (!stor->storage_[i].nameid) continue; struct item_data *id; id = itemdb_search(stor->storage_[i].nameid); - nullpo_ret(id); + nullpo_retz(id); if (itemdb_isequip2(id)) continue; - WFIFOW(s, n * 18 + 4) = i + 1; - WFIFOW(s, n * 18 + 6) = stor->storage_[i].nameid; - WFIFOB(s, n * 18 + 8) = uint8_t(id->type); - WFIFOB(s, n * 18 + 9) = 0; //identify; - WFIFOW(s, n * 18 + 10) = stor->storage_[i].amount; - WFIFOW(s, n * 18 + 12) = 0; - WFIFOW(s, n * 18 + 14) = 0; //card[0]; - WFIFOW(s, n * 18 + 16) = 0; //card[1]; - WFIFOW(s, n * 18 + 18) = 0; //card[2]; - WFIFOW(s, n * 18 + 20) = 0; //card[3]; - n++; + Packet_Repeat<0x01f0> info; + info.soff1 = i.shift(); + info.name_id = stor->storage_[i].nameid; + info.item_type = id->type; + info.identify = 0; + info.amount = stor->storage_[i].amount; + info.epos_zero = EPOS::ZERO; + info.card0 = 0; + info.card1 = 0; + info.card2 = 0; + info.card3 = 0; + repeat_1f0.push_back(info); } - if (n) + if (!repeat_1f0.empty()) { - WFIFOW(s, 2) = 4 + n * 18; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x01f0, 4, 18>(s, repeat_1f0); } return 0; } @@ -1586,44 +1552,43 @@ int clif_storageitemlist(dumb_ptr<map_session_data> sd, struct storage *stor) * カプラさんに預けてある装備リスト *------------------------------------------ */ -int clif_storageequiplist(dumb_ptr<map_session_data> sd, struct storage *stor) +int clif_storageequiplist(dumb_ptr<map_session_data> sd, Storage *stor) { - nullpo_ret(sd); - nullpo_ret(stor); + nullpo_retz(sd); + nullpo_retz(stor); Session *s = sd->sess; - WFIFOW(s, 0) = 0xa6; - int n = 0; - for (int i = 0; i < MAX_STORAGE; i++) + std::vector<Packet_Repeat<0x00a6>> repeat_a6; + for (SOff0 i : SOff0::iter()) { - if (stor->storage_[i].nameid <= 0) + if (!stor->storage_[i].nameid) continue; struct item_data *id; id = itemdb_search(stor->storage_[i].nameid); - nullpo_ret(id); + nullpo_retz(id); if (!itemdb_isequip2(id)) continue; - WFIFOW(s, n * 20 + 4) = i + 1; - WFIFOW(s, n * 20 + 6) = stor->storage_[i].nameid; - WFIFOB(s, n * 20 + 8) = uint8_t(id->type); - WFIFOB(s, n * 20 + 9) = 0; //identify; - WFIFOW(s, n * 20 + 10) = uint16_t(id->equip); - WFIFOW(s, n * 20 + 12) = uint16_t(stor->storage_[i].equip); - WFIFOB(s, n * 20 + 14) = 0; //broken or attribute - WFIFOB(s, n * 20 + 15) = 0; //refine; + Packet_Repeat<0x00a6> info; + info.soff1 = i.shift(); + info.name_id = stor->storage_[i].nameid; + info.item_type = id->type; + info.identify = 0; + info.epos_id = id->equip; + info.epos_stor = stor->storage_[i].equip; + info.broken_or_attribute = 0; + info.refine = 0; { - WFIFOW(s, n * 20 + 16) = 0; //card[0]; - WFIFOW(s, n * 20 + 18) = 0; //card[1]; - WFIFOW(s, n * 20 + 20) = 0; //card[2]; - WFIFOW(s, n * 20 + 22) = 0; //card[3]; + info.card0 = 0; + info.card1 = 0; + info.card2 = 0; + info.card3 = 0; } - n++; + repeat_a6.push_back(info); } - if (n) + if (!repeat_a6.empty()) { - WFIFOW(s, 2) = 4 + n * 20; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x00a6, 4, 20>(s, repeat_a6); } return 0; } @@ -1635,140 +1600,183 @@ int clif_storageequiplist(dumb_ptr<map_session_data> sd, struct storage *stor) */ int clif_updatestatus(dumb_ptr<map_session_data> sd, SP type) { - int len = 8; - - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xb0; - WFIFOW(s, 2) = static_cast<uint16_t>(type); - switch (type) { - // 00b0 + Packet_Fixed<0x00b0> fixed_b0; + fixed_b0.sp_type = type; + switch (type) + { case SP::WEIGHT: pc_checkweighticon(sd); - // is this because pc_checkweighticon can send other packets? - WFIFOW(s, 0) = 0xb0; - WFIFOW(s, 2) = static_cast<uint16_t>(type); - WFIFOL(s, 4) = sd->weight; + fixed_b0.value = sd->weight; break; case SP::MAXWEIGHT: - WFIFOL(s, 4) = sd->max_weight; + fixed_b0.value = sd->max_weight; break; case SP::SPEED: - // ... - WFIFOL(s, 4) = static_cast<uint16_t>(sd->speed.count()); + // 'speed' is actually delay, in milliseconds + fixed_b0.value = sd->speed.count(); break; case SP::BASELEVEL: - WFIFOL(s, 4) = sd->status.base_level; + fixed_b0.value = sd->status.base_level; break; case SP::JOBLEVEL: - WFIFOL(s, 4) = 0; + fixed_b0.value = sd->status.job_level; break; case SP::STATUSPOINT: - WFIFOL(s, 4) = sd->status.status_point; + fixed_b0.value = sd->status.status_point; break; case SP::SKILLPOINT: - WFIFOL(s, 4) = sd->status.skill_point; + fixed_b0.value = sd->status.skill_point; break; case SP::HIT: - WFIFOL(s, 4) = sd->hit; + fixed_b0.value = sd->hit; break; case SP::FLEE1: - WFIFOL(s, 4) = sd->flee; + fixed_b0.value = sd->flee; break; case SP::FLEE2: - WFIFOL(s, 4) = sd->flee2 / 10; + fixed_b0.value = sd->flee2 / 10; break; case SP::MAXHP: - WFIFOL(s, 4) = sd->status.max_hp; + fixed_b0.value = sd->status.max_hp; break; case SP::MAXSP: - WFIFOL(s, 4) = sd->status.max_sp; + fixed_b0.value = sd->status.max_sp; break; case SP::HP: - WFIFOL(s, 4) = sd->status.hp; + fixed_b0.value = sd->status.hp; break; case SP::SP: - WFIFOL(s, 4) = sd->status.sp; + fixed_b0.value = sd->status.sp; break; case SP::ASPD: - WFIFOL(s, 4) = static_cast<uint16_t>(sd->aspd.count()); + fixed_b0.value = sd->aspd.count(); break; case SP::ATK1: - WFIFOL(s, 4) = sd->base_atk + sd->watk; + fixed_b0.value = sd->base_atk + sd->watk; break; case SP::DEF1: - WFIFOL(s, 4) = sd->def; + fixed_b0.value = sd->def; break; case SP::MDEF1: - WFIFOL(s, 4) = sd->mdef; + fixed_b0.value = sd->mdef; break; case SP::ATK2: - WFIFOL(s, 4) = sd->watk2; + fixed_b0.value = sd->watk2; break; case SP::DEF2: - WFIFOL(s, 4) = sd->def2; + fixed_b0.value = sd->def2; break; case SP::MDEF2: - WFIFOL(s, 4) = sd->mdef2; + fixed_b0.value = sd->mdef2; break; case SP::CRITICAL: - WFIFOL(s, 4) = sd->critical / 10; + fixed_b0.value = sd->critical / 10; break; case SP::MATK1: - WFIFOL(s, 4) = sd->matk1; + fixed_b0.value = sd->matk1; break; case SP::MATK2: - WFIFOL(s, 4) = sd->matk2; + fixed_b0.value = sd->matk2; + break; + case SP::GM: + fixed_b0.value = pc_isGM(sd).get_all_bits(); break; + default: + goto not_b0; + } + + send_fpacket<0x00b0, 8>(s, fixed_b0); + return 0; + } +not_b0: + + { + Packet_Fixed<0x00b1> fixed_b1; + fixed_b1.sp_type = type; + switch (type) + { case SP::ZENY: trade_verifyzeny(sd); - WFIFOW(s, 0) = 0xb1; if (sd->status.zeny < 0) sd->status.zeny = 0; - WFIFOL(s, 4) = sd->status.zeny; + fixed_b1.value = sd->status.zeny; break; + case SP::BASEEXP: - WFIFOW(s, 0) = 0xb1; - WFIFOL(s, 4) = sd->status.base_exp; + fixed_b1.value = sd->status.base_exp; break; case SP::JOBEXP: - WFIFOW(s, 0) = 0xb1; - WFIFOL(s, 4) = sd->status.job_exp; + fixed_b1.value = sd->status.job_exp; break; case SP::NEXTBASEEXP: - WFIFOW(s, 0) = 0xb1; - WFIFOL(s, 4) = pc_nextbaseexp(sd); + fixed_b1.value = pc_nextbaseexp(sd); break; case SP::NEXTJOBEXP: - WFIFOW(s, 0) = 0xb1; - WFIFOL(s, 4) = pc_nextjobexp(sd); + fixed_b1.value = pc_nextjobexp(sd); break; - // 00be 終了 + default: + goto not_b1; + } + + send_fpacket<0x00b1, 8>(s, fixed_b1); + return 0; + } +not_b1: + + { + Packet_Fixed<0x00be> fixed_be; + fixed_be.sp_type = type; + switch (type) + { case SP::USTR: case SP::UAGI: case SP::UVIT: case SP::UINT: case SP::UDEX: case SP::ULUK: - WFIFOW(s, 0) = 0xbe; - WFIFOB(s, 4) = pc_need_status_point(sd, usp_to_sp(type)); - len = 5; + fixed_be.value = pc_need_status_point(sd, usp_to_sp(type)); break; - // 013a 終了 + default: + goto not_be; + } + + send_fpacket<0x00be, 5>(s, fixed_be); + return 0; + } +not_be: + + { + Packet_Fixed<0x013a> fixed_13a; + switch (type) + { case SP::ATTACKRANGE: - WFIFOW(s, 0) = 0x13a; - WFIFOW(s, 2) = (sd->attack_spell_override) - ? sd->attack_spell_range : sd->attackrange; - len = 4; + fixed_13a.attack_range = (sd->attack_spell_override + ? sd->attack_spell_range + : sd->attackrange); break; - // 0141 終了 + default: + goto not_13a; + } + + send_fpacket<0x013a, 4>(s, fixed_13a); + return 0; + } +not_13a: + + { + Packet_Fixed<0x00141> fixed_141; + fixed_141.sp_type = type; + switch (type) + { case SP::STR: case SP::AGI: case SP::VIT: @@ -1777,27 +1785,28 @@ int clif_updatestatus(dumb_ptr<map_session_data> sd, SP type) case SP::LUK: { ATTR attr = sp_to_attr(type); - WFIFOW(s, 0) = 0x141; - WFIFOL(s, 2) = uint16_t(type); - WFIFOL(s, 6) = sd->status.attrs[attr]; - WFIFOL(s, 10) = sd->paramb[attr] + sd->parame[attr]; - len = 14; + fixed_141.value_status = sd->status.attrs[attr]; + fixed_141.value_b_e = sd->paramb[attr] + sd->parame[attr]; } break; - case SP::GM: - WFIFOL(s, 4) = pc_isGM(sd); - break; - default: + goto not_141; + } + + send_fpacket<0x0141, 14>(s, fixed_141); + return 0; + } + +not_141: + { + { if (battle_config.error_log) - PRINTF("clif_updatestatus : make %d routine\n", + PRINTF("clif_updatestatus : make %d routine\n"_fmt, type); return 1; + } } - WFIFOSET(s, len); - - return 0; } /*========================================== @@ -1806,16 +1815,15 @@ int clif_updatestatus(dumb_ptr<map_session_data> sd, SP type) */ int clif_changelook(dumb_ptr<block_list> bl, LOOK type, int val) { - return clif_changelook_towards(bl, type, val, NULL); + return clif_changelook_towards(bl, type, val, nullptr); } int clif_changelook_towards(dumb_ptr<block_list> bl, LOOK type, int val, dumb_ptr<map_session_data> dstsd) { - unsigned char buf[32]; - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::PC) sd = bl->is_player(); @@ -1826,61 +1834,65 @@ int clif_changelook_towards(dumb_ptr<block_list> bl, LOOK type, int val, if (sd && (type == LOOK::WEAPON || type == LOOK::SHIELD || type >= LOOK::SHOES)) { - WBUFW(buf, 0) = 0x1d7; - WBUFL(buf, 2) = bl->bl_id; + Packet_Fixed<0x01d7> fixed_1d7; + fixed_1d7.block_id = bl->bl_id; if (type >= LOOK::SHOES) { EQUIP equip_point = equip_points[type]; - WBUFB(buf, 6) = uint16_t(type); - int idx = sd->equip_index_maybe[equip_point]; - if (idx >= 0 && sd->inventory_data[idx]) + fixed_1d7.look_type = type; + IOff0 idx = sd->equip_index_maybe[equip_point]; + if (idx.ok() && sd->inventory_data[idx]) { - WBUFW(buf, 7) = sd->status.inventory[idx].nameid; + fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(sd->status.inventory[idx].nameid); } else - WBUFW(buf, 7) = 0; - WBUFW(buf, 9) = 0; + fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(ItemNameId()); + fixed_1d7.shield = ItemNameId(); } else { - WBUFB(buf, 6) = 2; - int widx = sd->equip_index_maybe[EQUIP::WEAPON]; - int sidx = sd->equip_index_maybe[EQUIP::SHIELD]; + fixed_1d7.look_type = LOOK::WEAPON; + IOff0 widx = sd->equip_index_maybe[EQUIP::WEAPON]; + IOff0 sidx = sd->equip_index_maybe[EQUIP::SHIELD]; if (sd->attack_spell_override) - WBUFW(buf, 7) = sd->attack_spell_look_override; + fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(sd->attack_spell_look_override); else { - if (widx >= 0 && sd->inventory_data[widx]) + if (widx.ok() && sd->inventory_data[widx]) { - WBUFW(buf, 7) = sd->status.inventory[widx].nameid; + fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(sd->status.inventory[widx].nameid); } else - WBUFW(buf, 7) = 0; + fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(ItemNameId()); } - if (sidx >= 0 && sidx != widx && sd->inventory_data[sidx]) + if (sidx.ok() && sidx != widx && sd->inventory_data[sidx]) { - WBUFW(buf, 9) = sd->status.inventory[sidx].nameid; + fixed_1d7.shield = sd->status.inventory[sidx].nameid; } else - WBUFW(buf, 9) = 0; + fixed_1d7.shield = ItemNameId(); } + + Buffer buf = create_fpacket<0x01d7, 11>(fixed_1d7); if (dstsd) - clif_send(buf, clif_parse_func_table[0x1d7].len, dstsd, SendWho::SELF); + clif_send(buf, dstsd, SendWho::SELF); else - clif_send(buf, clif_parse_func_table[0x1d7].len, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); } else { - WBUFW(buf, 0) = 0x1d7; - WBUFL(buf, 2) = bl->bl_id; - WBUFB(buf, 6) = uint8_t(type); - WBUFW(buf, 7) = val; - WBUFW(buf, 9) = 0; + Packet_Fixed<0x01d7> fixed_1d7; + fixed_1d7.block_id = bl->bl_id; + fixed_1d7.look_type = type; + fixed_1d7.weapon_or_name_id_or_value = val; + fixed_1d7.shield = ItemNameId(); + + Buffer buf = create_fpacket<0x01d7, 11>(fixed_1d7); if (dstsd) - clif_send(buf, clif_parse_func_table[0x1d7].len, dstsd, SendWho::SELF); + clif_send(buf, dstsd, SendWho::SELF); else - clif_send(buf, clif_parse_func_table[0x1d7].len, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); } return 0; } @@ -1892,42 +1904,42 @@ int clif_changelook_towards(dumb_ptr<block_list> bl, LOOK type, int val, static int clif_initialstatus(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xbd; - WFIFOW(s, 2) = sd->status.status_point; - - WFIFOB(s, 4) = min(sd->status.attrs[ATTR::STR], 255); - WFIFOB(s, 5) = pc_need_status_point(sd, SP::STR); - WFIFOB(s, 6) = min(sd->status.attrs[ATTR::AGI], 255); - WFIFOB(s, 7) = pc_need_status_point(sd, SP::AGI); - WFIFOB(s, 8) = min(sd->status.attrs[ATTR::VIT], 255); - WFIFOB(s, 9) = pc_need_status_point(sd, SP::VIT); - WFIFOB(s, 10) = min(sd->status.attrs[ATTR::INT], 255); - WFIFOB(s, 11) = pc_need_status_point(sd, SP::INT); - WFIFOB(s, 12) = min(sd->status.attrs[ATTR::DEX], 255); - WFIFOB(s, 13) = pc_need_status_point(sd, SP::DEX); - WFIFOB(s, 14) = min(sd->status.attrs[ATTR::LUK], 255); - WFIFOB(s, 15) = pc_need_status_point(sd, SP::LUK); - - WFIFOW(s, 16) = sd->base_atk + sd->watk; - WFIFOW(s, 18) = sd->watk2; //atk bonus - WFIFOW(s, 20) = sd->matk1; - WFIFOW(s, 22) = sd->matk2; - WFIFOW(s, 24) = sd->def; // def - WFIFOW(s, 26) = sd->def2; - WFIFOW(s, 28) = sd->mdef; // mdef - WFIFOW(s, 30) = sd->mdef2; - WFIFOW(s, 32) = sd->hit; - WFIFOW(s, 34) = sd->flee; - WFIFOW(s, 36) = sd->flee2 / 10; - WFIFOW(s, 38) = sd->critical / 10; - WFIFOW(s, 40) = sd->status.karma; - WFIFOW(s, 42) = sd->status.manner; - - WFIFOSET(s, clif_parse_func_table[0xbd].len); + Packet_Fixed<0x00bd> fixed_bd; + fixed_bd.status_point = sd->status.status_point; + + fixed_bd.str_attr = saturate<uint8_t>(sd->status.attrs[ATTR::STR]); + fixed_bd.str_upd = pc_need_status_point(sd, SP::STR); + fixed_bd.agi_attr = saturate<uint8_t>(sd->status.attrs[ATTR::AGI]); + fixed_bd.agi_upd = pc_need_status_point(sd, SP::AGI); + fixed_bd.vit_attr = saturate<uint8_t>(sd->status.attrs[ATTR::VIT]); + fixed_bd.vit_upd = pc_need_status_point(sd, SP::VIT); + fixed_bd.int_attr = saturate<uint8_t>(sd->status.attrs[ATTR::INT]); + fixed_bd.int_upd = pc_need_status_point(sd, SP::INT); + fixed_bd.dex_attr = saturate<uint8_t>(sd->status.attrs[ATTR::DEX]); + fixed_bd.dex_upd = pc_need_status_point(sd, SP::DEX); + fixed_bd.luk_attr = saturate<uint8_t>(sd->status.attrs[ATTR::LUK]); + fixed_bd.luk_upd = pc_need_status_point(sd, SP::LUK); + + fixed_bd.atk_sum = sd->base_atk + sd->watk; + fixed_bd.watk2 = sd->watk2; //atk bonus + fixed_bd.matk1 = sd->matk1; + fixed_bd.matk2 = sd->matk2; + fixed_bd.def = sd->def; + fixed_bd.def2 = sd->def2; + fixed_bd.mdef = sd->mdef; + fixed_bd.mdef2 = sd->mdef2; + fixed_bd.hit = sd->hit; + fixed_bd.flee = sd->flee; + fixed_bd.flee2 = sd->flee2 / 10; + fixed_bd.critical = sd->critical / 10; + fixed_bd.karma = sd->status.karma; + fixed_bd.manner = sd->status.manner; + + send_fpacket<0x00bd, 44>(s, fixed_bd); clif_updatestatus(sd, SP::STR); clif_updatestatus(sd, SP::AGI); @@ -1946,18 +1958,16 @@ int clif_initialstatus(dumb_ptr<map_session_data> sd) *矢装備 *------------------------------------------ */ -int clif_arrowequip(dumb_ptr<map_session_data> sd, int val) +int clif_arrowequip(dumb_ptr<map_session_data> sd, IOff0 val) { - nullpo_ret(sd); + nullpo_retz(sd); - if (sd->attacktarget && sd->attacktarget > 0) // [Valaris] - sd->attacktarget = 0; + sd->attacktarget = BlockId(); Session *s = sd->sess; - WFIFOW(s, 0) = 0x013c; - WFIFOW(s, 2) = val + 2; //矢のアイテムID - - WFIFOSET(s, clif_parse_func_table[0x013c].len); + Packet_Fixed<0x013c> fixed_13c; + fixed_13c.ioff2 = val.shift(); + send_fpacket<0x013c, 4>(s, fixed_13c); return 0; } @@ -1968,14 +1978,13 @@ int clif_arrowequip(dumb_ptr<map_session_data> sd, int val) */ int clif_arrow_fail(dumb_ptr<map_session_data> sd, int type) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x013b; - WFIFOW(s, 2) = type; - - WFIFOSET(s, clif_parse_func_table[0x013b].len); + Packet_Fixed<0x013b> fixed_13b; + fixed_13b.type = type; + send_fpacket<0x013b, 4>(s, fixed_13b); return 0; } @@ -1986,14 +1995,14 @@ int clif_arrow_fail(dumb_ptr<map_session_data> sd, int type) */ int clif_statusupack(dumb_ptr<map_session_data> sd, SP type, int ok, int val) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xbc; - WFIFOW(s, 2) = uint16_t(type); - WFIFOB(s, 4) = ok; - WFIFOB(s, 5) = val; - WFIFOSET(s, clif_parse_func_table[0xbc].len); + Packet_Fixed<0x00bc> fixed_bc; + fixed_bc.sp_type = type; + fixed_bc.ok = ok; + fixed_bc.val = val; + send_fpacket<0x00bc, 6>(s, fixed_bc); return 0; } @@ -2002,16 +2011,16 @@ int clif_statusupack(dumb_ptr<map_session_data> sd, SP type, int ok, int val) * *------------------------------------------ */ -int clif_equipitemack(dumb_ptr<map_session_data> sd, int n, EPOS pos, int ok) +int clif_equipitemack(dumb_ptr<map_session_data> sd, IOff0 n, EPOS pos, int ok) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xaa; - WFIFOW(s, 2) = n + 2; - WFIFOW(s, 4) = uint16_t(pos); - WFIFOB(s, 6) = ok; - WFIFOSET(s, clif_parse_func_table[0xaa].len); + Packet_Fixed<0x00aa> fixed_aa; + fixed_aa.ioff2 = n.shift(); + fixed_aa.epos = pos; + fixed_aa.ok = ok; + send_fpacket<0x00aa, 7>(s, fixed_aa); return 0; } @@ -2020,16 +2029,16 @@ int clif_equipitemack(dumb_ptr<map_session_data> sd, int n, EPOS pos, int ok) * *------------------------------------------ */ -int clif_unequipitemack(dumb_ptr<map_session_data> sd, int n, EPOS pos, int ok) +int clif_unequipitemack(dumb_ptr<map_session_data> sd, IOff0 n, EPOS pos, int ok) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xac; - WFIFOW(s, 2) = n + 2; - WFIFOW(s, 4) = uint16_t(pos); - WFIFOB(s, 6) = ok; - WFIFOSET(s, clif_parse_func_table[0xac].len); + Packet_Fixed<0x00ac> fixed_ac; + fixed_ac.ioff2 = n.shift(); + fixed_ac.epos = pos; + fixed_ac.ok = ok; + send_fpacket<0x00ac, 7>(s, fixed_ac); return 0; } @@ -2040,15 +2049,14 @@ int clif_unequipitemack(dumb_ptr<map_session_data> sd, int n, EPOS pos, int ok) */ int clif_misceffect(dumb_ptr<block_list> bl, int type) { - uint8_t buf[32]; + nullpo_retz(bl); - nullpo_ret(bl); + Packet_Fixed<0x019b> fixed_19b; + fixed_19b.block_id = bl->bl_id; + fixed_19b.type = type; + Buffer buf = create_fpacket<0x019b, 10>(fixed_19b); - WBUFW(buf, 0) = 0x19b; - WBUFL(buf, 2) = bl->bl_id; - WBUFL(buf, 6) = type; - - clif_send(buf, clif_parse_func_table[0x19b].len, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); return 0; } @@ -2059,22 +2067,22 @@ int clif_misceffect(dumb_ptr<block_list> bl, int type) */ int clif_changeoption(dumb_ptr<block_list> bl) { - uint8_t buf[32]; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; - nullpo_ret(bl); + nullpo_retz(bl); Option option = *battle_get_option(bl); sc_data = battle_get_sc_data(bl); - WBUFW(buf, 0) = 0x119; - WBUFL(buf, 2) = bl->bl_id; - WBUFW(buf, 6) = uint16_t(*battle_get_opt1(bl)); - WBUFW(buf, 8) = uint16_t(*battle_get_opt2(bl)); - WBUFW(buf, 10) = uint16_t(option); - WBUFB(buf, 12) = 0; // ?? + Packet_Fixed<0x0119> fixed_119; + fixed_119.block_id = bl->bl_id; + fixed_119.opt1 = *battle_get_opt1(bl); + fixed_119.opt2 = *battle_get_opt2(bl); + fixed_119.option = option; + fixed_119.zero = 0; + Buffer buf = create_fpacket<0x0119, 13>(fixed_119); - clif_send(buf, clif_parse_func_table[0x119].len, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); return 0; } @@ -2083,31 +2091,30 @@ int clif_changeoption(dumb_ptr<block_list> bl) * *------------------------------------------ */ -int clif_useitemack(dumb_ptr<map_session_data> sd, int index, int amount, +int clif_useitemack(dumb_ptr<map_session_data> sd, IOff0 index, int amount, int ok) { - nullpo_ret(sd); + nullpo_retz(sd); if (!ok) { Session *s = sd->sess; - WFIFOW(s, 0) = 0xa8; - WFIFOW(s, 2) = index + 2; - WFIFOW(s, 4) = amount; - WFIFOB(s, 6) = ok; - WFIFOSET(s, clif_parse_func_table[0xa8].len); + Packet_Fixed<0x00a8> fixed_a8; + fixed_a8.ioff2 = index.shift(); + fixed_a8.amount = amount; + fixed_a8.ok = ok; + send_fpacket<0x00a8, 7>(s, fixed_a8); } else { - uint8_t buf[32]; - - WBUFW(buf, 0) = 0x1c8; - WBUFW(buf, 2) = index + 2; - WBUFW(buf, 4) = sd->status.inventory[index].nameid; - WBUFL(buf, 6) = sd->bl_id; - WBUFW(buf, 10) = amount; - WBUFB(buf, 12) = ok; - clif_send(buf, clif_parse_func_table[0x1c8].len, sd, SendWho::SELF); + Packet_Fixed<0x01c8> fixed_1c8; + fixed_1c8.ioff2 = index.shift(); + fixed_1c8.name_id = sd->status.inventory[index].nameid; + fixed_1c8.block_id = sd->bl_id; + fixed_1c8.amount = amount; + fixed_1c8.ok = ok; + Buffer buf = create_fpacket<0x01c8, 13>(fixed_1c8); + clif_send(buf, sd, SendWho::SELF); } return 0; @@ -2122,9 +2129,9 @@ void clif_traderequest(dumb_ptr<map_session_data> sd, CharName name) nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xe5; - WFIFO_STRING(s, 2, name.to__actual(), 24); - WFIFOSET(s, clif_parse_func_table[0xe5].len); + Packet_Fixed<0x00e5> fixed_e5; + fixed_e5.char_name = name; + send_fpacket<0x00e5, 26>(s, fixed_e5); } /*========================================== @@ -2136,9 +2143,9 @@ void clif_tradestart(dumb_ptr<map_session_data> sd, int type) nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xe7; - WFIFOB(s, 2) = type; - WFIFOSET(s, clif_parse_func_table[0xe7].len); + Packet_Fixed<0x00e7> fixed_e7; + fixed_e7.type = type; + send_fpacket<0x00e7, 3>(s, fixed_e7); } /*========================================== @@ -2146,57 +2153,57 @@ void clif_tradestart(dumb_ptr<map_session_data> sd, int type) *------------------------------------------ */ void clif_tradeadditem(dumb_ptr<map_session_data> sd, - dumb_ptr<map_session_data> tsd, int index, int amount) + dumb_ptr<map_session_data> tsd, IOff2 index2, int amount) { nullpo_retv(sd); nullpo_retv(tsd); Session *s = tsd->sess; - WFIFOW(s, 0) = 0xe9; - WFIFOL(s, 2) = amount; - if (index == 0) + Packet_Fixed<0x00e9> fixed_e9; + fixed_e9.amount = amount; + if (!index2.ok()) { - WFIFOW(s, 6) = 0; // type id - WFIFOB(s, 8) = 0; //identify flag - WFIFOB(s, 9) = 0; // attribute - WFIFOB(s, 10) = 0; //refine - WFIFOW(s, 11) = 0; //card (4w) - WFIFOW(s, 13) = 0; //card (4w) - WFIFOW(s, 15) = 0; //card (4w) - WFIFOW(s, 17) = 0; //card (4w) + fixed_e9.name_id = ItemNameId(); + fixed_e9.identify = 0; + fixed_e9.broken_or_attribute = 0; + fixed_e9.refine = 0; + fixed_e9.card0 = 0; + fixed_e9.card1 = 0; + fixed_e9.card2 = 0; + fixed_e9.card3 = 0; } else { - index -= 2; - WFIFOW(s, 6) = sd->status.inventory[index].nameid; // type id - WFIFOB(s, 8) = 0; //identify; - WFIFOB(s, 9) = 0; //broken or attribute; - WFIFOB(s, 10) = 0; //refine; + IOff0 index0 = index2.unshift(); + fixed_e9.name_id = sd->status.inventory[index0].nameid; + fixed_e9.identify = 0; + fixed_e9.broken_or_attribute = 0; + fixed_e9.refine = 0; { - WFIFOW(s, 11) = 0; //card[0]; - WFIFOW(s, 13) = 0; //card[1]; - WFIFOW(s, 15) = 0; //card[2]; - WFIFOW(s, 17) = 0; //card[3]; + fixed_e9.card0 = 0; + fixed_e9.card1 = 0; + fixed_e9.card2 = 0; + fixed_e9.card3 = 0; } } - WFIFOSET(s, clif_parse_func_table[0xe9].len); + send_fpacket<0x00e9, 19>(s, fixed_e9); } /*========================================== * アイテム追加成功/失敗 *------------------------------------------ */ -int clif_tradeitemok(dumb_ptr<map_session_data> sd, int index, int amount, +int clif_tradeitemok(dumb_ptr<map_session_data> sd, IOff2 index2, int amount, int fail) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x1b1; - WFIFOW(s, 2) = index; - WFIFOW(s, 4) = amount; - WFIFOB(s, 6) = fail; - WFIFOSET(s, clif_parse_func_table[0x1b1].len); + Packet_Fixed<0x01b1> fixed_1b1; + fixed_1b1.ioff2 = index2; + fixed_1b1.amount = amount; + fixed_1b1.fail = fail; + send_fpacket<0x01b1, 7>(s, fixed_1b1); return 0; } @@ -2207,12 +2214,12 @@ int clif_tradeitemok(dumb_ptr<map_session_data> sd, int index, int amount, */ int clif_tradedeal_lock(dumb_ptr<map_session_data> sd, int fail) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xec; - WFIFOB(s, 2) = fail; // 0=you 1=the other person - WFIFOSET(s, clif_parse_func_table[0xec].len); + Packet_Fixed<0x00ec> fixed_ec; + fixed_ec.fail = fail; // 0=you 1=the other person + send_fpacket<0x00ec, 3>(s, fixed_ec); return 0; } @@ -2223,11 +2230,11 @@ int clif_tradedeal_lock(dumb_ptr<map_session_data> sd, int fail) */ int clif_tradecancelled(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xee; - WFIFOSET(s, clif_parse_func_table[0xee].len); + Packet_Fixed<0x00ee> fixed_ee; + send_fpacket<0x00ee, 2>(s, fixed_ee); return 0; } @@ -2238,12 +2245,12 @@ int clif_tradecancelled(dumb_ptr<map_session_data> sd) */ int clif_tradecompleted(dumb_ptr<map_session_data> sd, int fail) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xf0; - WFIFOB(s, 2) = fail; - WFIFOSET(s, clif_parse_func_table[0xf0].len); + Packet_Fixed<0x00f0> fixed_f0; + fixed_f0.fail = fail; + send_fpacket<0x00f0, 3>(s, fixed_f0); return 0; } @@ -2253,16 +2260,16 @@ int clif_tradecompleted(dumb_ptr<map_session_data> sd, int fail) *------------------------------------------ */ int clif_updatestorageamount(dumb_ptr<map_session_data> sd, - struct storage *stor) + Storage *stor) { - nullpo_ret(sd); - nullpo_ret(stor); + nullpo_retz(sd); + nullpo_retz(stor); Session *s = sd->sess; - WFIFOW(s, 0) = 0xf2; // update storage amount - WFIFOW(s, 2) = stor->storage_amount; //items - WFIFOW(s, 4) = MAX_STORAGE; //items max - WFIFOSET(s, clif_parse_func_table[0xf2].len); + Packet_Fixed<0x00f2> fixed_f2; + fixed_f2.current_slots = stor->storage_amount; //items + fixed_f2.max_slots = MAX_STORAGE; //items max + send_fpacket<0x00f2, 6>(s, fixed_f2); return 0; } @@ -2271,30 +2278,27 @@ int clif_updatestorageamount(dumb_ptr<map_session_data> sd, * カプラ倉庫にアイテムを追加する *------------------------------------------ */ -int clif_storageitemadded(dumb_ptr<map_session_data> sd, struct storage *stor, - int index, int amount) +int clif_storageitemadded(dumb_ptr<map_session_data> sd, Storage *stor, + SOff0 index, int amount) { - nullpo_ret(sd); - nullpo_ret(stor); + nullpo_retz(sd); + nullpo_retz(stor); Session *s = sd->sess; - WFIFOW(s, 0) = 0xf4; // Storage item added - WFIFOW(s, 2) = index + 1; // index - WFIFOL(s, 4) = amount; // amount -/* if ((view = itemdb_viewid(stor->storage_[index].nameid)) > 0) - WFIFOW(fd,8) =view; - else*/ - WFIFOW(s, 8) = stor->storage_[index].nameid; - WFIFOB(s, 10) = 0; //identify; - WFIFOB(s, 11) = 0; //broken or attribute; - WFIFOB(s, 12) = 0; //refine; + Packet_Fixed<0x00f4> fixed_f4; + fixed_f4.soff1 = index.shift(); + fixed_f4.amount = amount; + fixed_f4.name_id = stor->storage_[index].nameid; + fixed_f4.identify = 0; + fixed_f4.broken_or_attribute = 0; + fixed_f4.refine = 0; { - WFIFOW(s, 13) = 0; //card[0]; - WFIFOW(s, 15) = 0; //card[1]; - WFIFOW(s, 17) = 0; //card[2]; - WFIFOW(s, 19) = 0; //card[3]; + fixed_f4.card0 = 0; + fixed_f4.card1 = 0; + fixed_f4.card2 = 0; + fixed_f4.card3 = 0; } - WFIFOSET(s, clif_parse_func_table[0xf4].len); + send_fpacket<0x00f4, 21>(s, fixed_f4); return 0; } @@ -2303,16 +2307,16 @@ int clif_storageitemadded(dumb_ptr<map_session_data> sd, struct storage *stor, * カプラ倉庫からアイテムを取り去る *------------------------------------------ */ -int clif_storageitemremoved(dumb_ptr<map_session_data> sd, int index, +int clif_storageitemremoved(dumb_ptr<map_session_data> sd, SOff0 index, int amount) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xf6; // Storage item removed - WFIFOW(s, 2) = index + 1; - WFIFOL(s, 4) = amount; - WFIFOSET(s, clif_parse_func_table[0xf6].len); + Packet_Fixed<0x00f6> fixed_f6; + fixed_f6.soff1 = index.shift(); + fixed_f6.amount = amount; + send_fpacket<0x00f6, 8>(s, fixed_f6); return 0; } @@ -2323,11 +2327,11 @@ int clif_storageitemremoved(dumb_ptr<map_session_data> sd, int index, */ int clif_storageclose(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xf8; // Storage Closed - WFIFOSET(s, clif_parse_func_table[0xf8].len); + Packet_Fixed<0x00f8> fixed_f8; + send_fpacket<0x00f8, 2>(s, fixed_f8); return 0; } @@ -2335,7 +2339,7 @@ int clif_storageclose(dumb_ptr<map_session_data> sd) void clif_changelook_accessories(dumb_ptr<block_list> bl, dumb_ptr<map_session_data> dest) { - for (LOOK i = LOOK::SHOES; i < LOOK::COUNT; i = LOOK(uint8_t(i) + 1)) + for (LOOK i = LOOK::SHOES; i < LOOK::COUNT; i = LOOK(static_cast<uint8_t>(i) + 1)) clif_changelook_towards(bl, i, 0, dest); } @@ -2350,25 +2354,22 @@ static void clif_getareachar_pc(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> dstsd) { - int len; - if (bool(dstsd->status.option & Option::INVISIBILITY)) return; nullpo_retv(sd); nullpo_retv(dstsd); - uint8_t buf[256]; + Buffer buf; if (dstsd->walktimer) { - len = clif_set007b(dstsd, buf); + clif_set007b(dstsd, buf); } else { - len = clif_set0078(dstsd, buf); + clif_set0078_main_1d8(dstsd, buf); } - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_buffer(sd->sess, buf); if (battle_config.save_clothcolor == 1 && dstsd->status.clothes_color > 0) clif_changelook(dstsd, LOOK::CLOTHES_COLOR, @@ -2385,16 +2386,15 @@ void clif_getareachar_pc(dumb_ptr<map_session_data> sd, static void clif_getareachar_npc(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data> nd) { - int len; - nullpo_retv(sd); nullpo_retv(nd); - if (nd->npc_class < 0 || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS) + if (nd->npc_class == NEGATIVE_SPECIES || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS) return; - len = clif_npc0078(nd, static_cast<uint8_t *>(WFIFOP(sd->sess, 0))); - WFIFOSET(sd->sess, len); + Buffer buf; + clif_npc0078(nd, buf); + send_buffer(sd->sess, buf); } /*========================================== @@ -2403,13 +2403,11 @@ void clif_getareachar_npc(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data> nd) */ int clif_movemob(dumb_ptr<mob_data> md) { - unsigned char buf[256]; - int len; + nullpo_retz(md); - nullpo_ret(md); - - len = clif_mob007b(md, buf); - clif_send(buf, len, md, SendWho::AREA); + Buffer buf; + clif_mob007b(md, buf); + clif_send(buf, md, SendWho::AREA); return 0; } @@ -2420,20 +2418,19 @@ int clif_movemob(dumb_ptr<mob_data> md) */ int clif_fixmobpos(dumb_ptr<mob_data> md) { - unsigned char buf[256]; - int len; - - nullpo_ret(md); + nullpo_retz(md); if (md->state.state == MS::WALK) { - len = clif_mob007b(md, buf); - clif_send(buf, len, md, SendWho::AREA); + Buffer buf; + clif_mob007b(md, buf); + clif_send(buf, md, SendWho::AREA); } else { - len = clif_mob0078(md, buf); - clif_send(buf, len, md, SendWho::AREA); + Buffer buf; + clif_mob0078(md, buf); + clif_send(buf, md, SendWho::AREA); } return 0; @@ -2445,22 +2442,21 @@ int clif_fixmobpos(dumb_ptr<mob_data> md) */ int clif_fixpcpos(dumb_ptr<map_session_data> sd) { - unsigned char buf[256]; - int len; - - nullpo_ret(sd); + nullpo_retz(sd); if (sd->walktimer) { - len = clif_set007b(sd, buf); - clif_send(buf, len, sd, SendWho::AREA); + Buffer buf; + clif_set007b(sd, buf); + clif_send(buf, sd, SendWho::AREA); } else { - len = clif_set0078(sd, buf); - clif_send(buf, len, sd, SendWho::AREA); + Buffer buf; + clif_set0078_main_1d8(sd, buf); + clif_send(buf, sd, SendWho::AREA); } - clif_changelook_accessories(sd, NULL); + clif_changelook_accessories(sd, nullptr); return 0; } @@ -2473,25 +2469,25 @@ int clif_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, tick_t tick, interval_t sdelay, interval_t ddelay, int damage, int div, DamageType type, int damage2) { - unsigned char buf[256]; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; - nullpo_ret(src); - nullpo_ret(dst); + nullpo_retz(src); + nullpo_retz(dst); sc_data = battle_get_sc_data(dst); - WBUFW(buf, 0) = 0x8a; - WBUFL(buf, 2) = src->bl_id; - WBUFL(buf, 6) = dst->bl_id; - WBUFL(buf, 10) = tick.time_since_epoch().count(); - WBUFL(buf, 14) = sdelay.count(); - WBUFL(buf, 18) = ddelay.count(); - WBUFW(buf, 22) = (damage > 0x7fff) ? 0x7fff : damage; - WBUFW(buf, 24) = div; - WBUFB(buf, 26) = static_cast<uint8_t>(type); - WBUFW(buf, 27) = damage2; - clif_send(buf, clif_parse_func_table[0x8a].len, src, SendWho::AREA); + Packet_Fixed<0x008a> fixed_8a; + fixed_8a.src_id = src->bl_id; + fixed_8a.dst_id = dst->bl_id; + fixed_8a.tick = tick; + fixed_8a.sdelay = sdelay; + fixed_8a.ddelay = ddelay; + fixed_8a.damage = (damage > 0x7fff) ? 0x7fff : damage; + fixed_8a.div = div; + fixed_8a.damage_type = type; + fixed_8a.damage2 = damage2; + Buffer buf = create_fpacket<0x008a, 29>(fixed_8a); + clif_send(buf, src, SendWho::AREA); return 0; } @@ -2503,19 +2499,20 @@ int clif_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, static void clif_getareachar_mob(dumb_ptr<map_session_data> sd, dumb_ptr<mob_data> md) { - int len; nullpo_retv(sd); nullpo_retv(md); if (md->state.state == MS::WALK) { - len = clif_mob007b(md, static_cast<uint8_t *>(WFIFOP(sd->sess, 0))); - WFIFOSET(sd->sess, len); + Buffer buf; + clif_mob007b(md, buf); + send_buffer(sd->sess, buf); } else { - len = clif_mob0078(md, static_cast<uint8_t *>(WFIFOP(sd->sess, 0))); - WFIFOSET(sd->sess, len); + Buffer buf; + clif_mob0078(md, buf); + send_buffer(sd->sess, buf); } } @@ -2531,18 +2528,16 @@ void clif_getareachar_item(dumb_ptr<map_session_data> sd, nullpo_retv(fitem); Session *s = sd->sess; - //009d <ID>.l <item ID>.w <identify flag>.B <X>.w <Y>.w <amount>.w <subX>.B <subY>.B - WFIFOW(s, 0) = 0x9d; - WFIFOL(s, 2) = fitem->bl_id; - WFIFOW(s, 6) = fitem->item_data.nameid; - WFIFOB(s, 8) = 0; //identify; - WFIFOW(s, 9) = fitem->bl_x; - WFIFOW(s, 11) = fitem->bl_y; - WFIFOW(s, 13) = fitem->item_data.amount; - WFIFOB(s, 15) = fitem->subx; - WFIFOB(s, 16) = fitem->suby; - - WFIFOSET(s, clif_parse_func_table[0x9d].len); + Packet_Fixed<0x009d> fixed_9d; + fixed_9d.block_id = fitem->bl_id; + fixed_9d.name_id = fitem->item_data.nameid; + fixed_9d.identify = 0; + fixed_9d.x = fitem->bl_x; + fixed_9d.y = fitem->bl_y; + fixed_9d.amount = fitem->item_data.amount; + fixed_9d.subx = fitem->subx; + fixed_9d.suby = fitem->suby; + send_fpacket<0x009d, 17>(s, fixed_9d); } /*========================================== @@ -2578,7 +2573,7 @@ void clif_getareachar(dumb_ptr<block_list> bl, dumb_ptr<map_session_data> sd) break; default: if (battle_config.error_log) - PRINTF("get area char ??? %d\n", + PRINTF("get area char ??? %d\n"_fmt, bl->bl_type); break; } @@ -2694,32 +2689,32 @@ void clif_mobinsight(dumb_ptr<block_list> bl, dumb_ptr<mob_data> md) int clif_skillinfo(dumb_ptr<map_session_data> sd, SkillID skillid, int type, int range) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; if (!sd->status.skill[skillid].lv) return 0; - WFIFOW(s, 0) = 0x147; - WFIFOW(s, 2) = static_cast<uint16_t>(skillid); + Packet_Fixed<0x0147> fixed_147; + fixed_147.info.skill_id = skillid; if (type < 0) - WFIFOW(s, 4) = skill_get_inf(skillid); + fixed_147.info.type_or_inf = skill_get_inf(skillid); else - WFIFOW(s, 4) = type; - WFIFOW(s, 6) = 0; - WFIFOW(s, 8) = sd->status.skill[skillid].lv; - WFIFOW(s, 10) = skill_get_sp(skillid, sd->status.skill[skillid].lv); + fixed_147.info.type_or_inf = type; + fixed_147.info.flags = SkillFlags::ZERO; + fixed_147.info.level = sd->status.skill[skillid].lv; + fixed_147.info.sp = skill_get_sp(skillid, sd->status.skill[skillid].lv); if (range < 0) { range = skill_get_range(skillid, sd->status.skill[skillid].lv); if (range < 0) range = battle_get_range(sd) - (range + 1); - WFIFOW(s, 12) = range; + fixed_147.info.range = range; } else - WFIFOW(s, 12) = range; - WFIFO_ZERO(s, 14, 24); - WFIFOB(s, 38) = sd->status.skill[skillid].lv < skill_get_max_raise(skillid); - WFIFOSET(s, clif_parse_func_table[0x147].len); + fixed_147.info.range = range; + fixed_147.info.unused = ""_s; + fixed_147.info.can_raise = sd->status.skill[skillid].lv < skill_get_max_raise(skillid); + send_fpacket<0x0147, 39>(s, fixed_147); return 0; } @@ -2730,35 +2725,34 @@ int clif_skillinfo(dumb_ptr<map_session_data> sd, SkillID skillid, int type, */ void clif_skillinfoblock(dumb_ptr<map_session_data> sd) { - int len = 4, range; - nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x10f; + std::vector<Packet_Repeat<0x010f>> repeat_10f; for (SkillID i : erange(SkillID(), MAX_SKILL)) { if (sd->status.skill[i].lv && sd->tmw_version >= 1) { + Packet_Repeat<0x010f> info; // [Fate] Version 1 and later don't crash because of bad skill IDs anymore - WFIFOW(s, len) = static_cast<uint16_t>(i); - WFIFOW(s, len + 2) = skill_get_inf(i); - WFIFOW(s, len + 4) = static_cast<uint16_t>( + info.info.skill_id = i; + info.info.type_or_inf = skill_get_inf(i); + info.info.flags = ( skill_db[i].poolflags | (sd->status.skill[i].flags & SkillFlags::POOL_ACTIVATED)); - WFIFOW(s, len + 6) = sd->status.skill[i].lv; - WFIFOW(s, len + 8) = skill_get_sp(i, sd->status.skill[i].lv); - range = skill_get_range(i, sd->status.skill[i].lv); + info.info.level = sd->status.skill[i].lv; + info.info.sp = skill_get_sp(i, sd->status.skill[i].lv); + int range = skill_get_range(i, sd->status.skill[i].lv); if (range < 0) range = battle_get_range(sd) - (range + 1); - WFIFOW(s, len + 10) = range; - WFIFO_ZERO(s, len + 12, 24); - WFIFOB(s, len + 36) = sd->status.skill[i].lv < skill_get_max_raise(i); - len += 37; + info.info.range = range; + info.info.unused = ""_s; + info.info.can_raise = sd->status.skill[i].lv < skill_get_max_raise(i); + + repeat_10f.push_back(info); } } - WFIFOW(s, 2) = len; - WFIFOSET(s, len); + send_packet_repeatonly<0x010f, 4, 37>(s, repeat_10f); } /*========================================== @@ -2767,21 +2761,19 @@ void clif_skillinfoblock(dumb_ptr<map_session_data> sd) */ int clif_skillup(dumb_ptr<map_session_data> sd, SkillID skill_num) { - int range; - - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x10e; - WFIFOW(s, 2) = uint16_t(skill_num); - WFIFOW(s, 4) = sd->status.skill[skill_num].lv; - WFIFOW(s, 6) = skill_get_sp(skill_num, sd->status.skill[skill_num].lv); - range = skill_get_range(skill_num, sd->status.skill[skill_num].lv); + Packet_Fixed<0x010e> fixed_10e; + fixed_10e.skill_id = skill_num; + fixed_10e.level = sd->status.skill[skill_num].lv; + fixed_10e.sp = skill_get_sp(skill_num, sd->status.skill[skill_num].lv); + int range = skill_get_range(skill_num, sd->status.skill[skill_num].lv); if (range < 0) range = battle_get_range(sd) - (range + 1); - WFIFOW(s, 8) = range; - WFIFOB(s, 10) = sd->status.skill[skill_num].lv < skill_get_max_raise(skill_num); - WFIFOSET(s, clif_parse_func_table[0x10e].len); + fixed_10e.range = range; + fixed_10e.can_raise = sd->status.skill[skill_num].lv < skill_get_max_raise(skill_num); + send_fpacket<0x010e, 11>(s, fixed_10e); return 0; } @@ -2792,14 +2784,11 @@ int clif_skillup(dumb_ptr<map_session_data> sd, SkillID skill_num) */ int clif_skillcastcancel(dumb_ptr<block_list> bl) { - unsigned char buf[16]; - - nullpo_ret(bl); - - WBUFW(buf, 0) = 0x1b9; - WBUFL(buf, 2) = bl->bl_id; - clif_send(buf, clif_parse_func_table[0x1b9].len, bl, SendWho::AREA); + // packet 0x01b9 was being sent with length 0, + // even though there were 6 bytes involved + // and the client ignores it anyway + (void)bl; return 0; } @@ -2810,7 +2799,7 @@ int clif_skillcastcancel(dumb_ptr<block_list> bl) int clif_skill_fail(dumb_ptr<map_session_data> sd, SkillID skill_id, int type, int btype) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; @@ -2819,13 +2808,13 @@ int clif_skill_fail(dumb_ptr<map_session_data> sd, SkillID skill_id, int type, return 0; } - WFIFOW(s, 0) = 0x110; - WFIFOW(s, 2) = uint16_t(skill_id); - WFIFOW(s, 4) = btype; - WFIFOW(s, 6) = 0; - WFIFOB(s, 8) = 0; - WFIFOB(s, 9) = type; - WFIFOSET(s, clif_parse_func_table[0x110].len); + Packet_Fixed<0x0110> fixed_110; + fixed_110.skill_id = skill_id; + fixed_110.btype = btype; + fixed_110.zero1 = 0; + fixed_110.zero2 = 0; + fixed_110.type = type; + send_fpacket<0x0110, 10>(s, fixed_110); return 0; } @@ -2838,26 +2827,26 @@ int clif_skill_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, tick_t tick, interval_t sdelay, interval_t ddelay, int damage, int div, SkillID skill_id, int skill_lv, int type) { - unsigned char buf[64]; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; - nullpo_ret(src); - nullpo_ret(dst); + nullpo_retz(src); + nullpo_retz(dst); sc_data = battle_get_sc_data(dst); - WBUFW(buf, 0) = 0x1de; - WBUFW(buf, 2) = uint16_t(skill_id); - WBUFL(buf, 4) = src->bl_id; - WBUFL(buf, 8) = dst->bl_id; - WBUFL(buf, 12) = static_cast<uint32_t>(tick.time_since_epoch().count()); - WBUFL(buf, 16) = static_cast<uint32_t>(sdelay.count()); - WBUFL(buf, 20) = static_cast<uint32_t>(ddelay.count()); - WBUFL(buf, 24) = damage; - WBUFW(buf, 28) = skill_lv; - WBUFW(buf, 30) = div; - WBUFB(buf, 32) = (type > 0) ? type : skill_get_hit(skill_id); - clif_send(buf, clif_parse_func_table[0x1de].len, src, SendWho::AREA); + Packet_Fixed<0x01de> fixed_1de; + fixed_1de.skill_id = skill_id; + fixed_1de.src_id = src->bl_id; + fixed_1de.dst_id = dst->bl_id; + fixed_1de.tick = tick; + fixed_1de.sdelay = sdelay; + fixed_1de.ddelay = ddelay; + fixed_1de.damage = damage; + fixed_1de.skill_level = skill_lv; + fixed_1de.div = div; + fixed_1de.type_or_hit = (type > 0) ? type : skill_get_hit(skill_id); + Buffer buf = create_fpacket<0x01de, 33>(fixed_1de); + clif_send(buf, src, SendWho::AREA); return 0; } @@ -2868,15 +2857,14 @@ int clif_skill_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, */ int clif_status_change(dumb_ptr<block_list> bl, StatusChange type, int flag) { - unsigned char buf[16]; - - nullpo_ret(bl); + nullpo_retz(bl); - WBUFW(buf, 0) = 0x0196; - WBUFW(buf, 2) = uint16_t(type); - WBUFL(buf, 4) = bl->bl_id; - WBUFB(buf, 8) = flag; - clif_send(buf, clif_parse_func_table[0x196].len, bl, SendWho::AREA); + Packet_Fixed<0x0196> fixed_196; + fixed_196.sc_type = type; + fixed_196.block_id = bl->bl_id; + fixed_196.flag = flag; + Buffer buf = create_fpacket<0x0196, 9>(fixed_196); + clif_send(buf, bl, SendWho::AREA); return 0; } @@ -2889,11 +2877,8 @@ void clif_displaymessage(Session *s, XString mes) if (mes) { // don't send a void message (it's not displaying on the client chat). @help can send void line. - WFIFOW(s, 0) = 0x8e; - size_t str_len = mes.size() + 1; // NUL (might not be NUL yet) - WFIFOW(s, 2) = 4 + str_len; - WFIFO_STRING(s, 4, mes, str_len); - WFIFOSET(s, 4 + str_len); + // This is untrue now ^ + send_packet_repeatonly<0x008e, 4, 1>(s, mes); } } @@ -2903,14 +2888,9 @@ void clif_displaymessage(Session *s, XString mes) */ void clif_GMmessage(dumb_ptr<block_list> bl, XString mes, int flag) { - size_t str_len = mes.size() + 1; - unsigned char buf[str_len + 4]; - - WBUFW(buf, 0) = 0x9a; - WBUFW(buf, 2) = str_len + 4; - WBUF_STRING(buf, 4, mes, str_len); + Buffer buf = create_packet_repeatonly<0x009a, 4, 1>(mes); flag &= 0x07; - clif_send(buf, WBUFW(buf, 2), bl, + clif_send(buf, bl, (flag == 1) ? SendWho::ALL_SAMEMAP : (flag == 2) ? SendWho::AREA : (flag == 3) ? SendWho::SELF : @@ -2923,15 +2903,14 @@ void clif_GMmessage(dumb_ptr<block_list> bl, XString mes, int flag) */ void clif_resurrection(dumb_ptr<block_list> bl, int type) { - uint8_t buf[16]; - nullpo_retv(bl); - WBUFW(buf, 0) = 0x148; - WBUFL(buf, 2) = bl->bl_id; - WBUFW(buf, 6) = type; + Packet_Fixed<0x0148> fixed_148; + fixed_148.block_id = bl->bl_id; + fixed_148.type = type; + Buffer buf = create_fpacket<0x0148, 8>(fixed_148); - clif_send(buf, clif_parse_func_table[0x148].len, bl, + clif_send(buf, bl, type == 1 ? SendWho::AREA : SendWho::AREA_WOS); } @@ -2941,12 +2920,9 @@ void clif_resurrection(dumb_ptr<block_list> bl, int type) */ void clif_wis_message(Session *s, CharName nick, XString mes) // R 0097 <len>.w <nick>.24B <message>.?B { - size_t mes_len = mes.size() + 1; - WFIFOW(s, 0) = 0x97; - WFIFOW(s, 2) = mes_len + 24 + 4; - WFIFO_STRING(s, 4, nick.to__actual(), 24); - WFIFO_STRING(s, 28, mes, mes_len); - WFIFOSET(s, WFIFOW(s, 2)); + Packet_Head<0x0097> head_97; + head_97.char_name = nick; + send_vpacket<0x0097, 28, 1>(s, head_97, mes); } /*========================================== @@ -2955,9 +2931,9 @@ void clif_wis_message(Session *s, CharName nick, XString mes) // R 0097 <len>. */ void clif_wis_end(Session *s, int flag) // R 0098 <type>.B: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target { - WFIFOW(s, 0) = 0x98; - WFIFOW(s, 2) = flag; - WFIFOSET(s, clif_parse_func_table[0x98].len); + Packet_Fixed<0x0098> fixed_98; + fixed_98.flag = flag; + send_fpacket<0x0098, 3>(s, fixed_98); } /*========================================== @@ -2974,12 +2950,12 @@ void clif_wis_end(Session *s, int flag) // R 0098 <type>.B: 0: success to send w */ int clif_party_created(dumb_ptr<map_session_data> sd, int flag) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xfa; - WFIFOB(s, 2) = flag; - WFIFOSET(s, clif_parse_func_table[0xfa].len); + Packet_Fixed<0x00fa> fixed_fa; + fixed_fa.flag = flag; + send_fpacket<0x00fa, 3>(s, fixed_fa); return 0; } @@ -2987,43 +2963,45 @@ int clif_party_created(dumb_ptr<map_session_data> sd, int flag) * パーティ情報送信 *------------------------------------------ */ -int clif_party_info(struct party *p, Session *s) +int clif_party_info(PartyPair p, Session *s) { - unsigned char buf[1024]; - int i, c; - dumb_ptr<map_session_data> sd = NULL; + int i; + dumb_ptr<map_session_data> sd = nullptr; - nullpo_ret(p); + nullpo_retz(p); - WBUFW(buf, 0) = 0xfb; - WBUF_STRING(buf, 4, p->name, 24); - for (i = c = 0; i < MAX_PARTY; i++) + Packet_Head<0x00fb> head_fb; + std::vector<Packet_Repeat<0x00fb>> repeat_fb; + head_fb.party_name = p->name; + for (i = 0; i < MAX_PARTY; i++) { - struct party_member *m = &p->member[i]; - if (m->account_id > 0) + PartyMember *m = &p->member[i]; + if (m->account_id) { - if (sd == NULL) + Packet_Repeat<0x00fb> info; + if (sd == nullptr) sd = dumb_ptr<map_session_data>(m->sd); - WBUFL(buf, 28 + c * 46) = m->account_id; - WBUF_STRING(buf, 28 + c * 46 + 4, m->name.to__actual(), 24); - WBUF_STRING(buf, 28 + c * 46 + 28, m->map, 16); - WBUFB(buf, 28 + c * 46 + 44) = (m->leader) ? 0 : 1; - WBUFB(buf, 28 + c * 46 + 45) = (m->online) ? 0 : 1; - c++; + + info.account_id = m->account_id; + info.char_name = m->name; + info.map_name = m->map; + info.leader = (m->leader) ? 0 : 1; + info.online = (m->online) ? 0 : 1; + repeat_fb.push_back(info); } } - size_t len = 28 + c * 46; - WBUFW(buf, 2) = len; if (s) { // If set, send only to fd. - WFIFO_BUF_CLONE(s, buf, len); - WFIFOSET(s, len); + send_vpacket<0x00fb, 28, 46>(s, head_fb, repeat_fb); return 9; } // else, send it to all the party, if they exist. - if (sd != NULL) - clif_send(buf, len, sd, SendWho::PARTY); + if (sd != nullptr) + { + Buffer buf = create_vpacket<0x00fb, 28, 46>(head_fb, repeat_fb); + clif_send(buf, sd, SendWho::PARTY); + } return 0; } @@ -3037,7 +3015,7 @@ int clif_party_info(struct party *p, Session *s) void clif_party_invite(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd) { - struct party *p; + PartyPair p; nullpo_retv(sd); nullpo_retv(tsd); @@ -3047,10 +3025,10 @@ void clif_party_invite(dumb_ptr<map_session_data> sd, if (!(p = party_search(sd->status.party_id))) return; - WFIFOW(s, 0) = 0xfe; - WFIFOL(s, 2) = sd->status_key.account_id; - WFIFO_STRING(s, 6, p->name, 24); - WFIFOSET(s, clif_parse_func_table[0xfe].len); + Packet_Fixed<0x00fe> fixed_fe; + fixed_fe.account_id = sd->status_key.account_id; + fixed_fe.party_name = p->name; + send_fpacket<0x00fe, 30>(s, fixed_fe); } /*========================================== @@ -3072,10 +3050,10 @@ void clif_party_inviteack(dumb_ptr<map_session_data> sd, CharName nick, int flag nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xfd; - WFIFO_STRING(s, 2, nick.to__actual(), 24); - WFIFOB(s, 26) = flag; - WFIFOSET(s, clif_parse_func_table[0xfd].len); + Packet_Fixed<0x00fd> fixed_fd; + fixed_fd.char_name = nick; + fixed_fd.flag = flag; + send_fpacket<0x00fd, 27>(s, fixed_fd); } /*========================================== @@ -3085,32 +3063,30 @@ void clif_party_inviteack(dumb_ptr<map_session_data> sd, CharName nick, int flag * 0x100=一人にのみ送信 *------------------------------------------ */ -void clif_party_option(struct party *p, dumb_ptr<map_session_data> sd, int flag) +void clif_party_option(PartyPair p, dumb_ptr<map_session_data> sd, int flag) { - unsigned char buf[16]; - nullpo_retv(p); -// if(battle_config.etc_log) -// PRINTF("clif_party_option: %d %d %d\n",p->exp,p->item,flag); - if (sd == NULL && flag == 0) + if (sd == nullptr && flag == 0) { int i; for (i = 0; i < MAX_PARTY; i++) - if ((sd = map_id2sd(p->member[i].account_id)) != NULL) + if ((sd = map_id2sd(account_to_block(p->member[i].account_id))) != nullptr) break; } - if (sd == NULL) + if (sd == nullptr) return; - WBUFW(buf, 0) = 0x101; - WBUFW(buf, 2) = ((flag & 0x01) ? 2 : p->exp); - WBUFW(buf, 4) = ((flag & 0x10) ? 2 : p->item); + Packet_Fixed<0x0101> fixed_101; + fixed_101.exp = ((flag & 0x01) ? 2 : p->exp); + fixed_101.item = ((flag & 0x10) ? 2 : p->item); if (flag == 0) - clif_send(buf, clif_parse_func_table[0x101].len, sd, SendWho::PARTY); + { + Buffer buf = create_fpacket<0x0101, 6>(fixed_101); + clif_send(buf, sd, SendWho::PARTY); + } else { - WFIFO_BUF_CLONE(sd->sess, buf, clif_parse_func_table[0x101].len); - WFIFOSET(sd->sess, clif_parse_func_table[0x101].len); + send_fpacket<0x0101, 6>(sd->sess, fixed_101); } } @@ -3118,35 +3094,36 @@ void clif_party_option(struct party *p, dumb_ptr<map_session_data> sd, int flag) * パーティ脱退(脱退前に呼ぶこと) *------------------------------------------ */ -void clif_party_leaved(struct party *p, dumb_ptr<map_session_data> sd, - int account_id, CharName name, int flag) +void clif_party_leaved(PartyPair p, dumb_ptr<map_session_data> sd, + AccountId account_id, CharName name, int flag) { - unsigned char buf[64]; int i; nullpo_retv(p); - WBUFW(buf, 0) = 0x105; - WBUFL(buf, 2) = account_id; - WBUF_STRING(buf, 6, name.to__actual(), 24); - WBUFB(buf, 30) = flag & 0x0f; + Packet_Fixed<0x0105> fixed_105; + fixed_105.account_id = account_id; + fixed_105.char_name = name; + fixed_105.flag = flag & 0x0f; if ((flag & 0xf0) == 0) { - if (sd == NULL) + if (sd == nullptr) for (i = 0; i < MAX_PARTY; i++) { sd = dumb_ptr<map_session_data>(p->member[i].sd); - if (sd != NULL) + if (sd != nullptr) break; } - if (sd != NULL) - clif_send(buf, clif_parse_func_table[0x105].len, sd, SendWho::PARTY); + if (sd != nullptr) + { + Buffer buf = create_fpacket<0x0105, 31>(fixed_105); + clif_send(buf, sd, SendWho::PARTY); + } } - else if (sd != NULL) + else if (sd != nullptr) { - WFIFO_BUF_CLONE(sd->sess, buf, clif_parse_func_table[0x105].len); - WFIFOSET(sd->sess, clif_parse_func_table[0x105].len); + send_fpacket<0x0105, 31>(sd->sess, fixed_105); } } @@ -3154,7 +3131,7 @@ void clif_party_leaved(struct party *p, dumb_ptr<map_session_data> sd, * パーティメッセージ送信 *------------------------------------------ */ -void clif_party_message(struct party *p, int account_id, XString mes) +void clif_party_message(PartyPair p, AccountId account_id, XString mes) { // always set, but clang is not smart enough dumb_ptr<map_session_data> sd = nullptr; @@ -3165,18 +3142,15 @@ void clif_party_message(struct party *p, int account_id, XString mes) for (i = 0; i < MAX_PARTY; i++) { sd = dumb_ptr<map_session_data>(p->member[i].sd); - if (sd != NULL) + if (sd != nullptr) break; } - if (sd != NULL) + if (sd != nullptr) { - size_t len = mes.size() + 1; - unsigned char buf[len + 8]; - WBUFW(buf, 0) = 0x109; - WBUFW(buf, 2) = len + 8; - WBUFL(buf, 4) = account_id; - WBUF_STRING(buf, 8, mes, len); - clif_send(buf, len + 8, sd, SendWho::PARTY); + Packet_Head<0x0109> head_109; + head_109.account_id = account_id; + Buffer buf = create_vpacket<0x0109, 8, 1>(head_109, mes); + clif_send(buf, sd, SendWho::PARTY); } } @@ -3184,19 +3158,16 @@ void clif_party_message(struct party *p, int account_id, XString mes) * パーティ座標通知 *------------------------------------------ */ -int clif_party_xy(struct party *, dumb_ptr<map_session_data> sd) +int clif_party_xy(PartyPair , dumb_ptr<map_session_data> sd) { - unsigned char buf[16]; - - nullpo_ret(sd); + nullpo_retz(sd); - WBUFW(buf, 0) = 0x107; - WBUFL(buf, 2) = sd->status_key.account_id; - WBUFW(buf, 6) = sd->bl_x; - WBUFW(buf, 8) = sd->bl_y; - clif_send(buf, clif_parse_func_table[0x107].len, sd, SendWho::PARTY_SAMEMAP_WOS); -// if(battle_config.etc_log) -// PRINTF("clif_party_xy %d\n",sd->status_key.account_id); + Packet_Fixed<0x0107> fixed_107; + fixed_107.account_id = sd->status_key.account_id; + fixed_107.x = sd->bl_x; + fixed_107.y = sd->bl_y; + Buffer buf = create_fpacket<0x0107, 10>(fixed_107); + clif_send(buf, sd, SendWho::PARTY_SAMEMAP_WOS); return 0; } @@ -3204,20 +3175,17 @@ int clif_party_xy(struct party *, dumb_ptr<map_session_data> sd) * パーティHP通知 *------------------------------------------ */ -int clif_party_hp(struct party *, dumb_ptr<map_session_data> sd) +int clif_party_hp(PartyPair , dumb_ptr<map_session_data> sd) { - unsigned char buf[16]; - - nullpo_ret(sd); + nullpo_retz(sd); - WBUFW(buf, 0) = 0x106; - WBUFL(buf, 2) = sd->status_key.account_id; - WBUFW(buf, 6) = (sd->status.hp > 0x7fff) ? 0x7fff : sd->status.hp; - WBUFW(buf, 8) = + Packet_Fixed<0x0106> fixed_106; + fixed_106.account_id = sd->status_key.account_id; + fixed_106.hp = (sd->status.hp > 0x7fff) ? 0x7fff : sd->status.hp; + fixed_106.max_hp = (sd->status.max_hp > 0x7fff) ? 0x7fff : sd->status.max_hp; - clif_send(buf, clif_parse_func_table[0x106].len, sd, SendWho::PARTY_AREA_WOS); -// if(battle_config.etc_log) -// PRINTF("clif_party_hp %d\n",sd->status_key.account_id); + Buffer buf = create_fpacket<0x0106, 10>(fixed_106); + clif_send(buf, sd, SendWho::PARTY_AREA_WOS); return 0; } @@ -3227,18 +3195,18 @@ int clif_party_hp(struct party *, dumb_ptr<map_session_data> sd) */ int clif_movetoattack(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> bl) { - nullpo_ret(sd); - nullpo_ret(bl); + nullpo_retz(sd); + nullpo_retz(bl); Session *s = sd->sess; - WFIFOW(s, 0) = 0x139; - WFIFOL(s, 2) = bl->bl_id; - WFIFOW(s, 6) = bl->bl_x; - WFIFOW(s, 8) = bl->bl_y; - WFIFOW(s, 10) = sd->bl_x; - WFIFOW(s, 12) = sd->bl_y; - WFIFOW(s, 14) = sd->attackrange; - WFIFOSET(s, clif_parse_func_table[0x139].len); + Packet_Fixed<0x0139> fixed_139; + fixed_139.block_id = bl->bl_id; + fixed_139.bl_x = bl->bl_x; + fixed_139.bl_y = bl->bl_y; + fixed_139.sd_x = sd->bl_x; + fixed_139.sd_y = sd->bl_y; + fixed_139.range = sd->attackrange; + send_fpacket<0x0139, 16>(s, fixed_139); return 0; } @@ -3248,13 +3216,12 @@ int clif_movetoattack(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> bl) */ int clif_mvp_effect(dumb_ptr<map_session_data> sd) { - unsigned char buf[16]; + nullpo_retz(sd); - nullpo_ret(sd); - - WBUFW(buf, 0) = 0x10c; - WBUFL(buf, 2) = sd->bl_id; - clif_send(buf, clif_parse_func_table[0x10c].len, sd, SendWho::AREA); + Packet_Fixed<0x010c> fixed_10c; + fixed_10c.block_id = sd->bl_id; + Buffer buf = create_fpacket<0x010c, 6>(fixed_10c); + clif_send(buf, sd, SendWho::AREA); return 0; } @@ -3264,22 +3231,19 @@ int clif_mvp_effect(dumb_ptr<map_session_data> sd) */ void clif_emotion(dumb_ptr<block_list> bl, int type) { - unsigned char buf[8]; - nullpo_retv(bl); - WBUFW(buf, 0) = 0xc0; - WBUFL(buf, 2) = bl->bl_id; - WBUFB(buf, 6) = type; - clif_send(buf, clif_parse_func_table[0xc0].len, bl, SendWho::AREA); + Packet_Fixed<0x00c0> fixed_c0; + fixed_c0.block_id = bl->bl_id; + fixed_c0.type = type; + Buffer buf = create_fpacket<0x00c0, 7>(fixed_c0); + clif_send(buf, bl, SendWho::AREA); } static void clif_emotion_towards(dumb_ptr<block_list> bl, dumb_ptr<block_list> target, int type) { - unsigned char buf[8]; - int len = clif_parse_func_table[0xc0].len; dumb_ptr<map_session_data> sd = target->is_player(); nullpo_retv(bl); @@ -3288,12 +3252,11 @@ void clif_emotion_towards(dumb_ptr<block_list> bl, if (target->bl_type != BL::PC) return; - WBUFW(buf, 0) = 0xc0; - WBUFL(buf, 2) = bl->bl_id; - WBUFB(buf, 6) = type; + Packet_Fixed<0x00c0> fixed_c0; + fixed_c0.block_id = bl->bl_id; + fixed_c0.type = type; - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_fpacket<0x00c0, 7>(sd->sess, fixed_c0); } /*========================================== @@ -3302,14 +3265,13 @@ void clif_emotion_towards(dumb_ptr<block_list> bl, */ void clif_sitting(Session *, dumb_ptr<map_session_data> sd) { - unsigned char buf[64]; - nullpo_retv(sd); - WBUFW(buf, 0) = 0x8a; - WBUFL(buf, 2) = sd->bl_id; - WBUFB(buf, 26) = 2; - clif_send(buf, clif_parse_func_table[0x8a].len, sd, SendWho::AREA); + Packet_Fixed<0x008a> fixed_8a; + fixed_8a.src_id = sd->bl_id; + fixed_8a.damage_type = DamageType::SIT; + Buffer buf = create_fpacket<0x008a, 29>(fixed_8a); + clif_send(buf, sd, SendWho::AREA); } /*========================================== @@ -3317,30 +3279,30 @@ void clif_sitting(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -int clif_GM_kickack(dumb_ptr<map_session_data> sd, int id) +int clif_GM_kickack(dumb_ptr<map_session_data> sd, AccountId id) { - nullpo_ret(sd); + nullpo_retz(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xcd; - WFIFOL(s, 2) = id; - WFIFOSET(s, clif_parse_func_table[0xcd].len); + Packet_Fixed<0x00cd> fixed_cd; + fixed_cd.account_id = id; + send_fpacket<0x00cd, 6>(s, fixed_cd); return 0; } static -void clif_parse_QuitGame(Session *s, dumb_ptr<map_session_data> sd); +void clif_do_quit_game(Session *s, dumb_ptr<map_session_data> sd); int clif_GM_kick(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd, int type) { - nullpo_ret(tsd); + nullpo_retz(tsd); if (type) clif_GM_kickack(sd, tsd->status_key.account_id); tsd->opt1 = Opt1::ZERO; tsd->opt2 = Opt2::ZERO; - clif_parse_QuitGame(tsd->sess, tsd); + clif_do_quit_game(tsd->sess, tsd); return 0; } @@ -3348,15 +3310,12 @@ int clif_GM_kick(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd, // displaying special effects (npcs, weather, etc) [Valaris] int clif_specialeffect(dumb_ptr<block_list> bl, int type, int flag) { - unsigned char buf[24]; - - nullpo_ret(bl); + nullpo_retz(bl); - WBUF_ZERO(buf, 0, clif_parse_func_table[0x19b].len); - - WBUFW(buf, 0) = 0x19b; - WBUFL(buf, 2) = bl->bl_id; - WBUFL(buf, 6) = type; + Packet_Fixed<0x019b> fixed_19b; + fixed_19b.block_id = bl->bl_id; + fixed_19b.type = type; + Buffer buf = create_fpacket<0x019b, 10>(fixed_19b); if (flag == 2) { @@ -3371,9 +3330,9 @@ int clif_specialeffect(dumb_ptr<block_list> bl, int type, int flag) } } else if (flag == 1) - clif_send(buf, clif_parse_func_table[0x19b].len, bl, SendWho::SELF); + clif_send(buf, bl, SendWho::SELF); else if (!flag) - clif_send(buf, clif_parse_func_table[0x19b].len, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); return 0; @@ -3388,35 +3347,39 @@ int clif_specialeffect(dumb_ptr<block_list> bl, int type, int flag) *------------------------------------------ */ static -void clif_parse_WantToConnection(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_WantToConnection(Session *s, dumb_ptr<map_session_data> sd) { - int account_id; // account_id in the packet + AccountId account_id; // account_id in the packet if (sd) { if (battle_config.error_log) - PRINTF("clif_parse_WantToConnection : invalid request?\n"); - return; + PRINTF("clif_parse_WantToConnection : invalid request?\n"_fmt); + return RecvResult::Error; } - if (RFIFOW(s, 0) == 0x72) + Packet_Fixed<0x0072> fixed; + RecvResult rv = recv_fpacket<0x0072, 19>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + { - account_id = RFIFOL(s, 2); + account_id = fixed.account_id; } - else - return; // Not the auth packet - WFIFOL(s, 0) = account_id; - WFIFOSET(s, 4); + // formerly: account id + Packet_Payload<0x8000> special; + special.magic_packet_length = 4; + send_ppacket<0x8000>(s, special); // if same account already connected, we disconnect the 2 sessions - dumb_ptr<map_session_data> old_sd = map_id2sd(account_id); + dumb_ptr<map_session_data> old_sd = map_id2sd(account_to_block(account_id)); if (old_sd) { clif_authfail_fd(s, 2); // same id clif_authfail_fd(old_sd->sess, 2); // same id - PRINTF("clif_parse_WantToConnection: Double connection for account %d (sessions: #%d (new) and #%d (old)).\n", - account_id, s, old_sd->sess); + PRINTF("clif_parse_WantToConnection: Double connection for account %d (sessions: #%d (new) and #%d (old)).\n"_fmt, + account_id, s, old_sd->sess); } else { @@ -3424,16 +3387,16 @@ void clif_parse_WantToConnection(Session *s, dumb_ptr<map_session_data> sd) s->session_data.reset(sd.operator->()); sd->sess = s; - pc_setnewpc(sd, account_id, RFIFOL(s, 6), RFIFOL(s, 10), - tick_t(static_cast<interval_t>(RFIFOL(s, 14))), - static_cast<SEX>(RFIFOB(s, 18))); + pc_setnewpc(sd, account_id, fixed.char_id, fixed.login_id1, + fixed.client_tick, + fixed.sex); map_addiddb(sd); chrif_authreq(sd); } - return; + return RecvResult::Complete; } /*========================================== @@ -3442,12 +3405,15 @@ void clif_parse_WantToConnection(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_LoadEndAck(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_LoadEndAck(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + if (sd->bl_prev != nullptr) + return RecvResult::Error; - if (sd->bl_prev != NULL) - return; + Packet_Fixed<0x007d> fixed; + RecvResult rv = recv_fpacket<0x007d, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; // 接続ok時 //clif_authok(); @@ -3494,7 +3460,7 @@ void clif_parse_LoadEndAck(Session *, dumb_ptr<map_session_data> sd) if (!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris] - sd->pvp_timer = Timer(gettick() + std::chrono::milliseconds(200), + sd->pvp_timer = Timer(gettick() + 200_ms, std::bind(pc_calc_pvprank_timer, ph::_1, ph::_2, sd->bl_id)); sd->pvp_rank = 0; @@ -3519,7 +3485,7 @@ void clif_parse_LoadEndAck(Session *, dumb_ptr<map_session_data> sd) clif_changeoption(sd); // broken equipment -// clif_changelook_accessories(sd, NULL); +// clif_changelook_accessories(sd, nullptr); map_foreachinarea(std::bind(clif_getareachar, ph::_1, sd), sd->bl_m, @@ -3529,6 +3495,8 @@ void clif_parse_LoadEndAck(Session *, dumb_ptr<map_session_data> sd) if (!sd->state.seen_motd) pc_show_motd(sd); + + return rv; } /*========================================== @@ -3536,13 +3504,18 @@ void clif_parse_LoadEndAck(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TickSend(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TickSend(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x007e> fixed; + RecvResult rv = recv_fpacket<0x007e, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - sd->client_tick = tick_t(static_cast<interval_t>(RFIFOL(s, 2))); - sd->server_tick = gettick(); + uint32_t client_tick = fixed.client_tick; + (void)client_tick; clif_servertick(sd); + + return rv; } /*========================================== @@ -3550,71 +3523,83 @@ void clif_parse_TickSend(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_WalkToXY(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_WalkToXY(Session *s, dumb_ptr<map_session_data> sd) { - int x, y; - - nullpo_retv(sd); + Packet_Fixed<0x0085> fixed; + RecvResult rv = recv_fpacket<0x0085, 5>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } - if (sd->npc_id != 0 || sd->state.storage_open) - return; + if (sd->npc_id || sd->state.storage_open) + return rv; if (sd->canmove_tick > gettick()) - return; + return rv; // ステータス異常やハイディング中(トンネルドライブ無)で動けない if (bool(sd->opt1) && sd->opt1 != (Opt1::_stone6)) - return; + return rv; if (sd->invincible_timer) pc_delinvincibletimer(sd); pc_stopattack(sd); - x = RFIFOB(s, 2) * 4 + (RFIFOB(s, 3) >> 6); - y = ((RFIFOB(s, 3) & 0x3f) << 4) + (RFIFOB(s, 4) >> 4); + int x = fixed.pos.x; + int y = fixed.pos.y; pc_walktoxy(sd, x, y); + return rv; } /*========================================== * *------------------------------------------ */ -void clif_parse_QuitGame(Session *s, dumb_ptr<map_session_data> sd) +static +RecvResult clif_parse_QuitGame(Session *s, dumb_ptr<map_session_data> sd) { - tick_t tick = gettick(); + Packet_Fixed<0x018a> fixed; + RecvResult rv = recv_fpacket<0x018a, 4>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + clif_do_quit_game(s, sd); + return rv; +} + +void clif_do_quit_game(Session *s, dumb_ptr<map_session_data> sd) +{ + + tick_t tick = gettick(); - WFIFOW(s, 0) = 0x18b; + Packet_Fixed<0x018b> fixed_18b; if ((!pc_isdead(sd) && (sd->opt1 != Opt1::ZERO || sd->opt2 != Opt2::ZERO)) || (tick < sd->canact_tick)) { - WFIFOW(s, 2) = 1; - WFIFOSET(s, clif_parse_func_table[0x18b].len); + fixed_18b.okay = 1; + send_fpacket<0x018b, 4>(s, fixed_18b); return; } /* Rovert's prevent logout option fixed [Valaris] */ if (!battle_config.prevent_logout - || tick >= sd->canlog_tick + std::chrono::seconds(10)) + || tick >= sd->canlog_tick + 10_s) { clif_setwaitclose(s); - WFIFOW(s, 2) = 0; + fixed_18b.okay = 0; } else { - WFIFOW(s, 2) = 1; + fixed_18b.okay = 1; } - WFIFOSET(s, clif_parse_func_table[0x18b].len); - + send_fpacket<0x018b, 4>(s, fixed_18b); } /*========================================== @@ -3622,18 +3607,23 @@ void clif_parse_QuitGame(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x0094> fixed; + RecvResult rv = recv_fpacket<0x0094, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + dumb_ptr<block_list> bl; - int account_id; + BlockId account_id; - account_id = RFIFOL(s, 2); + account_id = fixed.block_id; bl = map_id2bl(account_id); - if (bl == NULL) - return; + if (bl == nullptr) + return rv; - WFIFOW(s, 0) = 0x95; - WFIFOL(s, 2) = account_id; + Packet_Fixed<0x0095> fixed_95; + fixed_95.block_id = account_id; switch (bl->bl_type) { @@ -3641,21 +3631,21 @@ void clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) { dumb_ptr<map_session_data> ssd = bl->is_player(); - nullpo_retv(ssd); + nullpo_retr(rv, ssd); if (ssd->state.shroud_active) - WFIFO_STRING(s, 6, "", 24); + fixed_95.char_name = CharName(); else - WFIFO_STRING(s, 6, ssd->status_key.name.to__actual(), 24); - WFIFOSET(s, clif_parse_func_table[0x95].len); + fixed_95.char_name = ssd->status_key.name; + send_fpacket<0x0095, 30>(s, fixed_95); - struct party *p = NULL; + PartyPair p; PartyName party_name; int send = 0; - if (ssd->status.party_id > 0 && (p = party_search(ssd->status.party_id)) != NULL) + if (ssd->status.party_id && (p = party_search(ssd->status.party_id))) { party_name = p->name; send = 1; @@ -3663,30 +3653,28 @@ void clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) if (send) { - WFIFOW(s, 0) = 0x195; - WFIFOL(s, 2) = account_id; - WFIFO_STRING(s, 6, party_name, 24); - WFIFO_STRING(s, 30, "", 24); - WFIFO_STRING(s, 54, "", 24); - WFIFO_STRING(s, 78, "", 24); // We send this value twice because the client expects it - WFIFOSET(s, clif_parse_func_table[0x195].len); - + Packet_Fixed<0x0195> fixed_195; + fixed_195.block_id = account_id; + fixed_195.party_name = party_name; + fixed_195.guild_name = ""_s; + fixed_195.guild_pos = ""_s; + fixed_195.guild_pos = ""_s; // We send this value twice because the client expects it + send_fpacket<0x0195, 102>(s, fixed_195); } - if (pc_isGM(sd) >= battle_config.hack_info_GM_level) + if (pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.hack_info_GM_level)))) { IP4Address ip = ssd->get_ip(); - WFIFOW(s, 0) = 0x20C; + Packet_Fixed<0x020c> fixed_20c; // Mask the IP using the char-server password if (battle_config.mask_ip_gms) ip = MD5_ip(ip); - WFIFOL(s, 2) = account_id; - WFIFOIP(s, 6) = ip; - WFIFOSET(s, clif_parse_func_table[0x20C].len); + fixed_20c.block_id = account_id; + fixed_20c.ip = ip; + send_fpacket<0x020c, 10>(s, fixed_20c); } - } break; case BL::NPC: @@ -3694,26 +3682,28 @@ void clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) NpcName name = bl->is_npc()->name; // [fate] elim hashed out/invisible names for the client auto it = std::find(name.begin(), name.end(), '#'); - WFIFO_STRING(s, 6, name.xislice_h(it), 24); - WFIFOSET(s, clif_parse_func_table[0x95].len); + fixed_95.char_name = stringish<CharName>(name.xislice_h(it)); + send_fpacket<0x0095, 30>(s, fixed_95); } break; case BL::MOB: { dumb_ptr<mob_data> md = bl->is_mob(); - nullpo_retv(md); + nullpo_retr(rv, md); - WFIFO_STRING(s, 6, md->name, 24); - WFIFOSET(s, clif_parse_func_table[0x95].len); + fixed_95.char_name = stringish<CharName>(md->name); + send_fpacket<0x0095, 30>(s, fixed_95); } break; default: if (battle_config.error_log) - PRINTF("clif_parse_GetCharNameRequest : bad type %d (%d)\n", + PRINTF("clif_parse_GetCharNameRequest : bad type %d (%d)\n"_fmt, bl->bl_type, account_id); break; } + + return rv; } /*========================================== @@ -3724,63 +3714,60 @@ void clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_GlobalMessage(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_GlobalMessage(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + AString repeat; + RecvResult rv = recv_packet_repeatonly<0x008c, 4, 1>(s, repeat); + if (rv != RecvResult::Complete) + return rv; - AString mbuf = clif_validate_chat(sd, ChatType::Global); + AString mbuf = clif_validate_chat(sd, ChatType::Global, repeat); if (!mbuf) { - clif_displaymessage(s, "Your message could not be sent."); - return; + clif_displaymessage(s, "Your message could not be sent."_s); + return rv; } - if (is_atcommand(s, sd, mbuf, 0)) - return; + if (is_atcommand(s, sd, mbuf, GmLevel())) + return rv; if (!magic_message(sd, mbuf)) { /* Don't send chat that results in an automatic ban. */ if (tmw_CheckChatSpam(sd, mbuf)) { - clif_displaymessage(s, "Your message could not be sent."); - return; + clif_displaymessage(s, "Your message could not be sent."_s); + return rv; } /* It's not a spell/magic message, so send the message to others. */ - size_t mbuf_size = mbuf.size() + 1; - uint8_t sendbuf[mbuf_size + 8]; - WBUFW(sendbuf, 0) = 0x8d; - WBUFW(sendbuf, 2) = mbuf_size + 8; /* Header(2) + length(2) + ID(4). */ - WBUFL(sendbuf, 4) = sd->bl_id; - WBUF_STRING(sendbuf, 8, mbuf, mbuf_size); - - clif_send(sendbuf, mbuf_size + 8, sd, SendWho::AREA_CHAT_WOC); + Packet_Head<0x008d> head_8d; + head_8d.block_id = sd->bl_id; + XString repeat_8d = mbuf; + Buffer sendbuf = create_vpacket<0x008d, 8, 1>(head_8d, repeat_8d); + + clif_send(sendbuf, sd, SendWho::AREA_CHAT_WOC); } /* Send the message back to the speaker. */ - size_t len = RFIFOW(s, 2); - RFIFO_WFIFO_CLONE(s, s, len); - WFIFOW(s, 0) = 0x8e; - WFIFOSET(s, len); + send_packet_repeatonly<0x008e, 4, 1>(s, repeat); + + return rv; } void clif_message(dumb_ptr<block_list> bl, XString msg) { size_t msg_len = msg.size() + 1; - uint8_t buf[512]; - if (msg_len + 16 > 512) return; nullpo_retv(bl); - WBUFW(buf, 0) = 0x8d; - WBUFW(buf, 2) = msg_len + 8; - WBUFL(buf, 4) = bl->bl_id; - WBUF_STRING(buf, 8, msg, msg_len); + Packet_Head<0x008d> head_8d; + head_8d.block_id = bl->bl_id; + Buffer buf = create_vpacket<0x008d, 8, 1>(head_8d, msg); - clif_send(buf, WBUFW(buf, 2), bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); } /*========================================== @@ -3788,16 +3775,17 @@ void clif_message(dumb_ptr<block_list> bl, XString msg) *------------------------------------------ */ static -void clif_parse_ChangeDir(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_ChangeDir(Session *s, dumb_ptr<map_session_data> sd) { - unsigned char buf[64]; + Packet_Fixed<0x009b> fixed; + RecvResult rv = recv_fpacket<0x009b, 5>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); - - // RFIFOW(fd, 2) and WBUFW(buf, 6) are always 0 + // RFIFOW(fd,2) and WBUFW(buf,6) are always 0 // TODO perhaps we could use that to remove this hack? DIR dir; - uint8_t client_dir = RFIFOB(s, 4); + uint8_t client_dir = fixed.client_dir; // the client uses a diffenent direction enum ... ugh switch (client_dir) { @@ -3810,21 +3798,22 @@ void clif_parse_ChangeDir(Session *s, dumb_ptr<map_session_data> sd) case 0 | 8: dir = DIR::E; break; // right case 1 | 8: dir = DIR::SE; break; default: - return; + return rv; } if (dir == sd->dir) - return; + return rv; pc_setdir(sd, dir); - WBUFW(buf, 0) = 0x9c; - WBUFL(buf, 2) = sd->bl_id; - WBUFW(buf, 6) = 0; - WBUFB(buf, 8) = client_dir; + Packet_Fixed<0x009c> fixed_9c; + fixed_9c.block_id = sd->bl_id; + fixed_9c.client_dir = client_dir; + Buffer buf = create_fpacket<0x009c, 9>(fixed_9c); - clif_send(buf, clif_parse_func_table[0x9c].len, sd, SendWho::AREA_WOS); + clif_send(buf, sd, SendWho::AREA_WOS); + return rv; } /*========================================== @@ -3832,23 +3821,27 @@ void clif_parse_ChangeDir(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_Emotion(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_Emotion(Session *s, dumb_ptr<map_session_data> sd) { - unsigned char buf[64]; - - nullpo_retv(sd); + Packet_Fixed<0x00bf> fixed; + RecvResult rv = recv_fpacket<0x00bf, 3>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, SkillID::NV_EMOTE) >= 1) { - uint8_t emote = RFIFOB(s, 2); - WBUFW(buf, 0) = 0xc0; - WBUFL(buf, 2) = sd->bl_id; - WBUFB(buf, 6) = emote; - clif_send(buf, clif_parse_func_table[0xc0].len, sd, SendWho::AREA); + uint8_t emote = fixed.emote; + Packet_Fixed<0x00c0> fixed_c0; + fixed_c0.block_id = sd->bl_id; + fixed_c0.type = emote; + Buffer buf = create_fpacket<0x00c0, 7>(fixed_c0); + clif_send(buf, sd, SendWho::AREA); } else clif_skill_fail(sd, SkillID::ONE, 0, 1); + + return rv; } /*========================================== @@ -3856,11 +3849,18 @@ void clif_parse_Emotion(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_HowManyConnections(Session *s, dumb_ptr<map_session_data>) +RecvResult clif_parse_HowManyConnections(Session *s, dumb_ptr<map_session_data>) { - WFIFOW(s, 0) = 0xc2; - WFIFOL(s, 2) = map_getusers(); - WFIFOSET(s, clif_parse_func_table[0xc2].len); + Packet_Fixed<0x00c1> fixed; + RecvResult rv = recv_fpacket<0x00c1, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + Packet_Fixed<0x00c2> fixed_c2; + fixed_c2.users = map_getusers(); + send_fpacket<0x00c2, 6>(s, fixed_c2); + + return rv; } /*========================================== @@ -3868,64 +3868,69 @@ void clif_parse_HowManyConnections(Session *s, dumb_ptr<map_session_data>) *------------------------------------------ */ static -void clif_parse_ActionRequest(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_ActionRequest(Session *s, dumb_ptr<map_session_data> sd) { - unsigned char buf[64]; - int action_type, target_id; + Packet_Fixed<0x0089> fixed; + RecvResult rv = recv_fpacket<0x0089, 7>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + DamageType action_type; + BlockId target_id; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } - if (sd->npc_id != 0 + if (sd->npc_id || bool(sd->opt1) || sd->state.storage_open) - return; + return rv; tick_t tick = gettick(); pc_stop_walking(sd, 0); pc_stopattack(sd); - target_id = RFIFOL(s, 2); - action_type = RFIFOB(s, 6); + target_id = fixed.target_id; + action_type = fixed.action; switch (action_type) { - case 0x00: // once attack - case 0x07: // continuous attack + case DamageType::NORMAL: + case DamageType::CONTINUOUS: if (bool(sd->status.option & Option::HIDE)) - return; + return rv; if (!battle_config.skill_delay_attack_enable) { if (tick < sd->canact_tick) { clif_skill_fail(sd, SkillID::ONE, 4, 0); - return; + return rv; } } if (sd->invincible_timer) pc_delinvincibletimer(sd); - if (sd->attacktarget > 0) // [Valaris] - sd->attacktarget = 0; - pc_attack(sd, target_id, action_type != 0); + sd->attacktarget = BlockId(); + pc_attack(sd, target_id, action_type != DamageType::NORMAL); break; - case 0x02: // sitdown + case DamageType::SIT: pc_stop_walking(sd, 1); pc_setsit(sd); clif_sitting(s, sd); break; - case 0x03: // standup + case DamageType::STAND: pc_setstand(sd); - WBUFW(buf, 0) = 0x8a; - WBUFL(buf, 2) = sd->bl_id; - WBUFB(buf, 26) = 3; - clif_send(buf, clif_parse_func_table[0x8a].len, sd, SendWho::AREA); + Packet_Fixed<0x008a> fixed_8a; + fixed_8a.src_id = sd->bl_id; + fixed_8a.damage_type = DamageType::STAND; + Buffer buf = create_fpacket<0x008a, 29>(fixed_8a); + clif_send(buf, sd, SendWho::AREA); break; } + + return rv; } /*========================================== @@ -3933,11 +3938,14 @@ void clif_parse_ActionRequest(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_Restart(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_Restart(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00b2> fixed; + RecvResult rv = recv_fpacket<0x00b2, 3>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - switch (RFIFOB(s, 2)) + switch (fixed.flag) { case 0x00: if (pc_isdead(sd)) @@ -3961,19 +3969,21 @@ void clif_parse_Restart(Session *s, dumb_ptr<map_session_data> sd) case 0x01: /* Rovert's Prevent logout option - Fixed [Valaris] */ if (!battle_config.prevent_logout - || gettick() >= sd->canlog_tick + std::chrono::seconds(10)) + || gettick() >= sd->canlog_tick + 10_s) { chrif_charselectreq(sd); } else { - WFIFOW(s, 0) = 0x18b; - WFIFOW(s, 2) = 1; + Packet_Fixed<0x018b> fixed_18b; + fixed_18b.okay = 1; - WFIFOSET(s, clif_parse_func_table[0x018b].len); + send_fpacket<0x018b, 4>(s, fixed_18b); } break; } + + return rv; } /*========================================== @@ -3987,29 +3997,33 @@ void clif_parse_Restart(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_Wis(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_Wis(Session *s, dumb_ptr<map_session_data> sd) { - dumb_ptr<map_session_data> dstsd = NULL; + Packet_Head<0x0096> head; + AString repeat; + RecvResult rv = recv_vpacket<0x0096, 28, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + dumb_ptr<map_session_data> dstsd = nullptr; - AString mbuf = clif_validate_chat(sd, ChatType::Whisper); + AString mbuf = clif_validate_chat(sd, ChatType::Whisper, repeat); if (!mbuf) { - clif_displaymessage(s, "Your message could not be sent."); - return; + clif_displaymessage(s, "Your message could not be sent."_s); + return rv; } - if (is_atcommand(s, sd, mbuf, 0)) + if (is_atcommand(s, sd, mbuf, GmLevel())) { - return; + return rv; } /* Don't send chat that results in an automatic ban. */ if (tmw_CheckChatSpam(sd, mbuf)) { - clif_displaymessage(s, "Your message could not be sent."); - return; + clif_displaymessage(s, "Your message could not be sent."_s); + return rv; } /* @@ -4018,7 +4032,7 @@ void clif_parse_Wis(Session *s, dumb_ptr<map_session_data> sd) * conflict (for instance, "Test" versus "test"), the char-server must * settle the discrepancy. */ - CharName tname = stringish<CharName>(RFIFO_STRING<24>(s, 4)); + CharName tname = head.target_name; if (!(dstsd = map_nick2sd(tname)) || dstsd->status_key.name != tname) intif_wis_message(sd, tname, mbuf); @@ -4027,7 +4041,7 @@ void clif_parse_Wis(Session *s, dumb_ptr<map_session_data> sd) /* Refuse messages addressed to self. */ if (dstsd->sess == s) { - ZString mes = "You cannot page yourself."; + ZString mes = "You cannot page yourself."_s; clif_wis_message(s, wisp_server_name, mes); } else @@ -4042,6 +4056,8 @@ void clif_parse_Wis(Session *s, dumb_ptr<map_session_data> sd) } } } + + return rv; } /*========================================== @@ -4049,37 +4065,41 @@ void clif_parse_Wis(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TakeItem(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TakeItem(Session *s, dumb_ptr<map_session_data> sd) { - dumb_ptr<flooritem_data> fitem; - int map_object_id; + Packet_Fixed<0x009f> fixed; + RecvResult rv = recv_fpacket<0x009f, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + dumb_ptr<flooritem_data> fitem; - map_object_id = RFIFOL(s, 2); + BlockId map_object_id = fixed.object_id; fitem = map_id_is_item(map_object_id); if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } - if (sd->npc_id != 0 + if (sd->npc_id || sd->opt1 != Opt1::ZERO) //会話禁止 - return; + return rv; - if (fitem == NULL || fitem->bl_m != sd->bl_m) - return; + if (fitem == nullptr || fitem->bl_m != sd->bl_m) + return rv; if (abs(sd->bl_x - fitem->bl_x) >= 2 || abs(sd->bl_y - fitem->bl_y) >= 2) - return; // too far away to pick up + return rv; // too far away to pick up if (sd->state.shroud_active && sd->state.shroud_disappears_on_pickup) magic_unshroud(sd); pc_takeitem(sd, fitem); + + return rv; } /*========================================== @@ -4087,33 +4107,38 @@ void clif_parse_TakeItem(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_DropItem(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_DropItem(Session *s, dumb_ptr<map_session_data> sd) { - int item_index, item_amount; - - nullpo_retv(sd); + Packet_Fixed<0x00a2> fixed; + RecvResult rv = recv_fpacket<0x00a2, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } if (sd->bl_m->flag.get(MapFlag::NO_PLAYER_DROPS)) { - clif_displaymessage(sd->sess, "Can't drop items here."); - return; + clif_displaymessage(sd->sess, "Can't drop items here."_s); + return rv; } - if (sd->npc_id != 0 + if (sd->npc_id || sd->opt1 != Opt1::ZERO) { - clif_displaymessage(sd->sess, "Can't drop items right now."); - return; + clif_displaymessage(sd->sess, "Can't drop items right now."_s); + return rv; } - item_index = RFIFOW(s, 2) - 2; - item_amount = RFIFOW(s, 4); + if (!fixed.ioff2.ok()) + return RecvResult::Error; + IOff0 item_index = fixed.ioff2.unshift(); + int item_amount = fixed.amount; pc_dropitem(sd, item_index, item_amount); + + return rv; } /*========================================== @@ -4121,23 +4146,30 @@ void clif_parse_DropItem(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_UseItem(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_UseItem(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00a7> fixed; + RecvResult rv = recv_fpacket<0x00a7, 8>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } - if (sd->npc_id != 0 + if (sd->npc_id || sd->opt1 != Opt1::ZERO) //会話禁止 - return; + return rv; if (sd->invincible_timer) pc_delinvincibletimer(sd); - pc_useitem(sd, RFIFOW(s, 2) - 2); + if (!fixed.ioff2.ok()) + return RecvResult::Error; + pc_useitem(sd, fixed.ioff2.unshift()); + + return rv; } /*========================================== @@ -4145,30 +4177,35 @@ void clif_parse_UseItem(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_EquipItem(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_EquipItem(Session *s, dumb_ptr<map_session_data> sd) { - int index; - - nullpo_retv(sd); + Packet_Fixed<0x00a9> fixed; + RecvResult rv = recv_fpacket<0x00a9, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } - index = RFIFOW(s, 2) - 2; - if (sd->npc_id != 0) - return; + if (!fixed.ioff2.ok()) + return RecvResult::Error; + IOff0 index = fixed.ioff2.unshift(); + if (sd->npc_id) + return rv; if (sd->inventory_data[index]) { - EPOS epos = EPOS(RFIFOW(s, 4)); + EPOS epos = fixed.epos_ignored; if (sd->inventory_data[index]->type == ItemType::ARROW) epos = EPOS::ARROW; // Note: the EPOS argument to pc_equipitem is actually ignored pc_equipitem(sd, index, epos); } + + return rv; } /*========================================== @@ -4176,23 +4213,28 @@ void clif_parse_EquipItem(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_UnequipItem(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_UnequipItem(Session *s, dumb_ptr<map_session_data> sd) { - int index; - - nullpo_retv(sd); + Packet_Fixed<0x00ab> fixed; + RecvResult rv = recv_fpacket<0x00ab, 4>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } - index = RFIFOW(s, 2) - 2; + if (!fixed.ioff2.ok()) + return RecvResult::Error; + IOff0 index = fixed.ioff2.unshift(); - if (sd->npc_id != 0 + if (sd->npc_id || sd->opt1 != Opt1::ZERO) - return; + return rv; pc_unequipitem(sd, index, CalcStatus::NOW); + + return rv; } /*========================================== @@ -4200,18 +4242,23 @@ void clif_parse_UnequipItem(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcClicked(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcClicked(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x0090> fixed; + RecvResult rv = recv_fpacket<0x0090, 7>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } - if (sd->npc_id != 0) - return; - npc_click(sd, RFIFOL(s, 2)); + if (sd->npc_id) + return rv; + npc_click(sd, fixed.block_id); + + return rv; } /*========================================== @@ -4219,9 +4266,16 @@ void clif_parse_NpcClicked(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcBuySellSelected(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcBuySellSelected(Session *s, dumb_ptr<map_session_data> sd) { - npc_buysellsel(sd, RFIFOL(s, 2), RFIFOB(s, 6)); + Packet_Fixed<0x00c5> fixed; + RecvResult rv = recv_fpacket<0x00c5, 7>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + npc_buysellsel(sd, fixed.block_id, fixed.type); + + return rv; } /*========================================== @@ -4229,17 +4283,20 @@ void clif_parse_NpcBuySellSelected(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcBuyListSend(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcBuyListSend(Session *s, dumb_ptr<map_session_data> sd) { - int n = (RFIFOW(s, 2) - 4) / 4; - // really an array of pairs of uint16_t - const uint16_t *item_list = static_cast<const uint16_t *>(RFIFOP(s, 4)); + std::vector<Packet_Repeat<0x00c8>> repeat; + RecvResult rv = recv_packet_repeatonly<0x00c8, 4, 4>(s, repeat); + if (rv != RecvResult::Complete) + return rv; - int fail = npc_buylist(sd, n, item_list); + int fail = npc_buylist(sd, repeat); - WFIFOW(s, 0) = 0xca; - WFIFOB(s, 2) = fail; - WFIFOSET(s, clif_parse_func_table[0xca].len); + Packet_Fixed<0x00ca> fixed_ca; + fixed_ca.fail = fail; + send_fpacket<0x00ca, 3>(s, fixed_ca); + + return rv; } /*========================================== @@ -4247,17 +4304,20 @@ void clif_parse_NpcBuyListSend(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcSellListSend(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcSellListSend(Session *s, dumb_ptr<map_session_data> sd) { - int n = (RFIFOW(s, 2) - 4) / 4; - // really an array of pairs of uint16_t - const uint16_t *item_list = static_cast<const uint16_t *>(RFIFOP(s, 4)); + std::vector<Packet_Repeat<0x00c9>> repeat; + RecvResult rv = recv_packet_repeatonly<0x00c9, 4, 4>(s, repeat); + if (rv != RecvResult::Complete) + return rv; + + int fail = npc_selllist(sd, repeat); - int fail = npc_selllist(sd, n, item_list); + Packet_Fixed<0x00cb> fixed_cb; + fixed_cb.fail = fail; + send_fpacket<0x00cb, 3>(s, fixed_cb); - WFIFOW(s, 0) = 0xcb; - WFIFOB(s, 2) = fail; - WFIFOSET(s, clif_parse_func_table[0xcb].len); + return rv; } /*========================================== @@ -4265,17 +4325,22 @@ void clif_parse_NpcSellListSend(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeRequest(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeRequest(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00e4> fixed; + RecvResult rv = recv_fpacket<0x00e4, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, SkillID::NV_TRADE) >= 1) { - trade_traderequest(sd, RFIFOL(sd->sess, 2)); + trade_traderequest(sd, fixed.block_id); } else clif_skill_fail(sd, SkillID::ONE, 0, 0); + + return rv; } /*========================================== @@ -4283,11 +4348,16 @@ void clif_parse_TradeRequest(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeAck(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeAck(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00e6> fixed; + RecvResult rv = recv_fpacket<0x00e6, 3>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - trade_tradeack(sd, RFIFOB(sd->sess, 2)); + trade_tradeack(sd, fixed.type); + + return rv; } /*========================================== @@ -4295,11 +4365,18 @@ void clif_parse_TradeAck(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeAddItem(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeAddItem(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00e8> fixed; + RecvResult rv = recv_fpacket<0x00e8, 8>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - trade_tradeadditem(sd, RFIFOW(sd->sess, 2), RFIFOL(sd->sess, 4)); + if (fixed.zeny_or_ioff2.index != 0 && !fixed.zeny_or_ioff2.ok()) + return RecvResult::Error; + trade_tradeadditem(sd, fixed.zeny_or_ioff2, fixed.amount); + + return rv; } /*========================================== @@ -4307,9 +4384,16 @@ void clif_parse_TradeAddItem(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeOk(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeOk(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x00eb> fixed; + RecvResult rv = recv_fpacket<0x00eb, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + trade_tradeok(sd); + + return rv; } /*========================================== @@ -4317,9 +4401,16 @@ void clif_parse_TradeOk(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeCansel(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeCansel(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x00ed> fixed; + RecvResult rv = recv_fpacket<0x00ed, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + trade_tradecancel(sd); + + return rv; } /*========================================== @@ -4327,9 +4418,16 @@ void clif_parse_TradeCansel(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeCommit(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeCommit(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x00ef> fixed; + RecvResult rv = recv_fpacket<0x00ef, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + trade_tradecommit(sd); + + return rv; } /*========================================== @@ -4337,9 +4435,16 @@ void clif_parse_TradeCommit(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_StopAttack(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_StopAttack(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x0118> fixed; + RecvResult rv = recv_fpacket<0x0118, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + pc_stopattack(sd); + + return rv; } /*========================================== @@ -4347,9 +4452,16 @@ void clif_parse_StopAttack(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_StatusUp(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_StatusUp(Session *s, dumb_ptr<map_session_data> sd) { - pc_statusup(sd, SP(RFIFOW(s, 2))); + Packet_Fixed<0x00bb> fixed; + RecvResult rv = recv_fpacket<0x00bb, 5>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + pc_statusup(sd, fixed.asp); + + return rv; } /*========================================== @@ -4357,9 +4469,16 @@ void clif_parse_StatusUp(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_SkillUp(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_SkillUp(Session *s, dumb_ptr<map_session_data> sd) { - pc_skillup(sd, SkillID(RFIFOW(s, 2))); + Packet_Fixed<0x0112> fixed; + RecvResult rv = recv_fpacket<0x0112, 4>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + pc_skillup(sd, fixed.skill_id); + + return rv; } /*========================================== @@ -4367,12 +4486,17 @@ void clif_parse_SkillUp(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcSelectMenu(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcSelectMenu(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00b8> fixed; + RecvResult rv = recv_fpacket<0x00b8, 7>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + sd->npc_menu = fixed.menu_entry; + map_scriptcont(sd, fixed.npc_id); - sd->npc_menu = RFIFOB(s, 6); - map_scriptcont(sd, RFIFOL(s, 2)); + return rv; } /*========================================== @@ -4380,9 +4504,16 @@ void clif_parse_NpcSelectMenu(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcNextClicked(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcNextClicked(Session *s, dumb_ptr<map_session_data> sd) { - map_scriptcont(sd, RFIFOL(s, 2)); + Packet_Fixed<0x00b9> fixed; + RecvResult rv = recv_fpacket<0x00b9, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + map_scriptcont(sd, fixed.npc_id); + + return rv; } /*========================================== @@ -4390,12 +4521,17 @@ void clif_parse_NpcNextClicked(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcAmountInput(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcAmountInput(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x0143> fixed; + RecvResult rv = recv_fpacket<0x0143, 10>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - sd->npc_amount = RFIFOL(s, 6); - map_scriptcont(sd, RFIFOL(s, 2)); + sd->npc_amount = fixed.input_int_value; + map_scriptcont(sd, fixed.block_id); + + return rv; } /*========================================== @@ -4405,22 +4541,19 @@ void clif_parse_NpcAmountInput(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcStringInput(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcStringInput(Session *s, dumb_ptr<map_session_data> sd) { - int len; - nullpo_retv(sd); + Packet_Head<0x01d5> head; + AString repeat; + RecvResult rv = recv_vpacket<0x01d5, 8, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + return rv; - len = RFIFOW(s, 2) - 8; + sd->npc_str = repeat; - /* - * If we check for equal to 0, too, we'll freeze clients that send (or - * claim to have sent) an "empty" message. - */ - if (len < 0) - return; - sd->npc_str = RFIFO_STRING(s, 8, len); + map_scriptcont(sd, head.block_id); - map_scriptcont(sd, RFIFOL(s, 4)); + return rv; } /*========================================== @@ -4428,9 +4561,16 @@ void clif_parse_NpcStringInput(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcCloseClicked(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcCloseClicked(Session *s, dumb_ptr<map_session_data> sd) { - map_scriptcont(sd, RFIFOL(s, 2)); + Packet_Fixed<0x0146> fixed; + RecvResult rv = recv_fpacket<0x0146, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + map_scriptcont(sd, fixed.block_id); + + return rv; } /*========================================== @@ -4438,21 +4578,26 @@ void clif_parse_NpcCloseClicked(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_MoveToKafra(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_MoveToKafra(Session *s, dumb_ptr<map_session_data> sd) { - int item_index, item_amount; + Packet_Fixed<0x00f3> fixed; + RecvResult rv = recv_fpacket<0x00f3, 8>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); - - item_index = RFIFOW(s, 2) - 2; - item_amount = RFIFOL(s, 4); + if (!fixed.ioff2.ok()) + return RecvResult::Error; + IOff0 item_index = fixed.ioff2.unshift(); + int item_amount = fixed.amount; - if ((sd->npc_id != 0 && !sd->npc_flags.storage) || sd->trade_partner != 0 + if ((sd->npc_id && !sd->npc_flags.storage) || sd->trade_partner || !sd->state.storage_open) - return; + return rv; if (sd->state.storage_open) storage_storageadd(sd, item_index, item_amount); + + return rv; } /*========================================== @@ -4460,21 +4605,26 @@ void clif_parse_MoveToKafra(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_MoveFromKafra(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_MoveFromKafra(Session *s, dumb_ptr<map_session_data> sd) { - int item_index, item_amount; - - nullpo_retv(sd); + Packet_Fixed<0x00f5> fixed; + RecvResult rv = recv_fpacket<0x00f5, 8>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - item_index = RFIFOW(s, 2) - 1; - item_amount = RFIFOL(s, 4); + if (!fixed.soff1.ok()) + return RecvResult::Error; + SOff0 item_index = fixed.soff1.unshift(); + int item_amount = fixed.amount; - if ((sd->npc_id != 0 && !sd->npc_flags.storage) || sd->trade_partner != 0 + if ((sd->npc_id && !sd->npc_flags.storage) || sd->trade_partner || !sd->state.storage_open) - return; + return rv; if (sd->state.storage_open) storage_storageget(sd, item_index, item_amount); + + return rv; } /*========================================== @@ -4482,12 +4632,17 @@ void clif_parse_MoveFromKafra(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_CloseKafra(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_CloseKafra(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00f7> fixed; + RecvResult rv = recv_fpacket<0x00f7, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (sd->state.storage_open) storage_storageclose(sd); + + return rv; } /*========================================== @@ -4498,16 +4653,23 @@ void clif_parse_CloseKafra(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_CreateParty(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_CreateParty(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x00f9> fixed; + RecvResult rv = recv_fpacket<0x00f9, 26>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, SkillID::NV_PARTY) >= 2) { - PartyName name = stringish<PartyName>(RFIFO_STRING<24>(s, 2)); + PartyName name = fixed.party_name; party_create(sd, name); } else clif_skill_fail(sd, SkillID::ONE, 0, 4); + + return rv; } /*========================================== @@ -4518,9 +4680,16 @@ void clif_parse_CreateParty(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_PartyInvite(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_PartyInvite(Session *s, dumb_ptr<map_session_data> sd) { - party_invite(sd, RFIFOL(s, 2)); + Packet_Fixed<0x00fc> fixed; + RecvResult rv = recv_fpacket<0x00fc, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + party_invite(sd, fixed.account_id); + + return rv; } /*========================================== @@ -4531,18 +4700,25 @@ void clif_parse_PartyInvite(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_ReplyPartyInvite(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_ReplyPartyInvite(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x00ff> fixed; + RecvResult rv = recv_fpacket<0x00ff, 10>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, SkillID::NV_PARTY) >= 1) { - party_reply_invite(sd, RFIFOL(s, 2), RFIFOL(s, 6)); + party_reply_invite(sd, fixed.account_id, fixed.flag); } else { - party_reply_invite(sd, RFIFOL(s, 2), 0); + party_reply_invite(sd, fixed.account_id, 0); clif_skill_fail(sd, SkillID::ONE, 0, 4); } + + return rv; } /*========================================== @@ -4550,9 +4726,16 @@ void clif_parse_ReplyPartyInvite(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_LeaveParty(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_LeaveParty(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x0100> fixed; + RecvResult rv = recv_fpacket<0x0100, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + party_leave(sd); + + return rv; } /*========================================== @@ -4560,11 +4743,18 @@ void clif_parse_LeaveParty(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_RemovePartyMember(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_RemovePartyMember(Session *s, dumb_ptr<map_session_data> sd) { - int account_id = RFIFOL(s, 2); - // unused RFIFO_STRING<24>(fd, 6); + Packet_Fixed<0x0103> fixed; + RecvResult rv = recv_fpacket<0x0103, 30>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + AccountId account_id = fixed.account_id; + // unused fixed.unusedchar_name; party_removemember(sd, account_id); + + return rv; } /*========================================== @@ -4572,9 +4762,16 @@ void clif_parse_RemovePartyMember(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_PartyChangeOption(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_PartyChangeOption(Session *s, dumb_ptr<map_session_data> sd) { - party_changeoption(sd, RFIFOW(s, 2), RFIFOW(s, 4)); + Packet_Fixed<0x0102> fixed; + RecvResult rv = recv_fpacket<0x0102, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + party_changeoption(sd, fixed.exp, fixed.item); + + return rv; } /*========================================== @@ -4586,582 +4783,604 @@ void clif_parse_PartyChangeOption(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_PartyMessage(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_PartyMessage(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + AString repeat; + RecvResult rv = recv_packet_repeatonly<0x0108, 4, 1>(s, repeat); + if (rv != RecvResult::Complete) + return rv; - AString mbuf = clif_validate_chat(sd, ChatType::Party); + AString mbuf = clif_validate_chat(sd, ChatType::Party, repeat); if (!mbuf) { - clif_displaymessage(s, "Your message could not be sent."); - return; + clif_displaymessage(s, "Your message could not be sent."_s); + return rv; } - if (is_atcommand(s, sd, mbuf, 0)) - return; + if (is_atcommand(s, sd, mbuf, GmLevel())) + return rv; /* Don't send chat that results in an automatic ban. */ if (tmw_CheckChatSpam(sd, mbuf)) { - clif_displaymessage(s, "Your message could not be sent."); - return; + clif_displaymessage(s, "Your message could not be sent."_s); + return rv; } party_send_message(sd, mbuf); + + return rv; } func_table clif_parse_func_table[0x0220] = { - {0, 10, NULL, }, // 0x0000 - {0, 0, NULL, }, // 0x0001 - {0, 0, NULL, }, // 0x0002 - {0, 0, NULL, }, // 0x0003 - {0, 0, NULL, }, // 0x0004 - {0, 0, NULL, }, // 0x0005 - {0, 0, NULL, }, // 0x0006 - {0, 0, NULL, }, // 0x0007 - {0, 0, NULL, }, // 0x0008 - {0, 0, NULL, }, // 0x0009 - {0, 0, NULL, }, // 0x000a - {0, 0, NULL, }, // 0x000b - {0, 0, NULL, }, // 0x000c - {0, 0, NULL, }, // 0x000d - {0, 0, NULL, }, // 0x000e - {0, 0, NULL, }, // 0x000f - {0, 0, NULL, }, // 0x0010 - {0, 0, NULL, }, // 0x0011 - {0, 0, NULL, }, // 0x0012 - {0, 0, NULL, }, // 0x0013 - {0, 0, NULL, }, // 0x0014 - {0, 0, NULL, }, // 0x0015 - {0, 0, NULL, }, // 0x0016 - {0, 0, NULL, }, // 0x0017 - {0, 0, NULL, }, // 0x0018 - {0, 0, NULL, }, // 0x0019 - {0, 0, NULL, }, // 0x001a - {0, 0, NULL, }, // 0x001b - {0, 0, NULL, }, // 0x001c - {0, 0, NULL, }, // 0x001d - {0, 0, NULL, }, // 0x001e - {0, 0, NULL, }, // 0x001f - {0, 0, NULL, }, // 0x0020 - {0, 0, NULL, }, // 0x0021 - {0, 0, NULL, }, // 0x0022 - {0, 0, NULL, }, // 0x0023 - {0, 0, NULL, }, // 0x0024 - {0, 0, NULL, }, // 0x0025 - {0, 0, NULL, }, // 0x0026 - {0, 0, NULL, }, // 0x0027 - {0, 0, NULL, }, // 0x0028 - {0, 0, NULL, }, // 0x0029 - {0, 0, NULL, }, // 0x002a - {0, 0, NULL, }, // 0x002b - {0, 0, NULL, }, // 0x002c - {0, 0, NULL, }, // 0x002d - {0, 0, NULL, }, // 0x002e - {0, 0, NULL, }, // 0x002f - {0, 0, NULL, }, // 0x0030 - {0, 0, NULL, }, // 0x0031 - {0, 0, NULL, }, // 0x0032 - {0, 0, NULL, }, // 0x0033 - {0, 0, NULL, }, // 0x0034 - {0, 0, NULL, }, // 0x0035 - {0, 0, NULL, }, // 0x0036 - {0, 0, NULL, }, // 0x0037 - {0, 0, NULL, }, // 0x0038 - {0, 0, NULL, }, // 0x0039 - {0, 0, NULL, }, // 0x003a - {0, 0, NULL, }, // 0x003b - {0, 0, NULL, }, // 0x003c - {0, 0, NULL, }, // 0x003d - {0, 0, NULL, }, // 0x003e - {0, 0, NULL, }, // 0x003f - {0, 0, NULL, }, // 0x0040 - {0, 0, NULL, }, // 0x0041 - {0, 0, NULL, }, // 0x0042 - {0, 0, NULL, }, // 0x0043 - {0, 0, NULL, }, // 0x0044 - {0, 0, NULL, }, // 0x0045 - {0, 0, NULL, }, // 0x0046 - {0, 0, NULL, }, // 0x0047 - {0, 0, NULL, }, // 0x0048 - {0, 0, NULL, }, // 0x0049 - {0, 0, NULL, }, // 0x004a - {0, 0, NULL, }, // 0x004b - {0, 0, NULL, }, // 0x004c - {0, 0, NULL, }, // 0x004d - {0, 0, NULL, }, // 0x004e - {0, 0, NULL, }, // 0x004f - {0, 0, NULL, }, // 0x0050 - {0, 0, NULL, }, // 0x0051 - {0, 0, NULL, }, // 0x0052 - {0, 0, NULL, }, // 0x0053 - {0, 0, NULL, }, // 0x0054 - {0, 0, NULL, }, // 0x0055 - {0, 0, NULL, }, // 0x0056 - {0, 0, NULL, }, // 0x0057 - {0, 0, NULL, }, // 0x0058 - {0, 0, NULL, }, // 0x0059 - {0, 0, NULL, }, // 0x005a - {0, 0, NULL, }, // 0x005b - {0, 0, NULL, }, // 0x005c - {0, 0, NULL, }, // 0x005d - {0, 0, NULL, }, // 0x005e - {0, 0, NULL, }, // 0x005f - {0, 0, NULL, }, // 0x0060 - {0, 0, NULL, }, // 0x0061 - {0, 0, NULL, }, // 0x0062 - {0, VAR,NULL, }, // 0x0063 - {0, 55, NULL, }, // 0x0064 - {0, 17, NULL, }, // 0x0065 - {0, 3, NULL, }, // 0x0066 - {0, 37, NULL, }, // 0x0067 - {0, 46, NULL, }, // 0x0068 - {0, VAR,NULL, }, // 0x0069 - {0, 23, NULL, }, // 0x006a - {0, VAR,NULL, }, // 0x006b - {0, 3, NULL, }, // 0x006c - {0, 108,NULL, }, // 0x006d - {0, 3, NULL, }, // 0x006e - {0, 2, NULL, }, // 0x006f - {0, 3, NULL, }, // 0x0070 - {0, 28, NULL, }, // 0x0071 + {0, 10, nullptr, }, // 0x0000 + {0, 0, nullptr, }, // 0x0001 + {0, 0, nullptr, }, // 0x0002 + {0, 0, nullptr, }, // 0x0003 + {0, 0, nullptr, }, // 0x0004 + {0, 0, nullptr, }, // 0x0005 + {0, 0, nullptr, }, // 0x0006 + {0, 0, nullptr, }, // 0x0007 + {0, 0, nullptr, }, // 0x0008 + {0, 0, nullptr, }, // 0x0009 + {0, 0, nullptr, }, // 0x000a + {0, 0, nullptr, }, // 0x000b + {0, 0, nullptr, }, // 0x000c + {0, 0, nullptr, }, // 0x000d + {0, 0, nullptr, }, // 0x000e + {0, 0, nullptr, }, // 0x000f + {0, 0, nullptr, }, // 0x0010 + {0, 0, nullptr, }, // 0x0011 + {0, 0, nullptr, }, // 0x0012 + {0, 0, nullptr, }, // 0x0013 + {0, 0, nullptr, }, // 0x0014 + {0, 0, nullptr, }, // 0x0015 + {0, 0, nullptr, }, // 0x0016 + {0, 0, nullptr, }, // 0x0017 + {0, 0, nullptr, }, // 0x0018 + {0, 0, nullptr, }, // 0x0019 + {0, 0, nullptr, }, // 0x001a + {0, 0, nullptr, }, // 0x001b + {0, 0, nullptr, }, // 0x001c + {0, 0, nullptr, }, // 0x001d + {0, 0, nullptr, }, // 0x001e + {0, 0, nullptr, }, // 0x001f + {0, 0, nullptr, }, // 0x0020 + {0, 0, nullptr, }, // 0x0021 + {0, 0, nullptr, }, // 0x0022 + {0, 0, nullptr, }, // 0x0023 + {0, 0, nullptr, }, // 0x0024 + {0, 0, nullptr, }, // 0x0025 + {0, 0, nullptr, }, // 0x0026 + {0, 0, nullptr, }, // 0x0027 + {0, 0, nullptr, }, // 0x0028 + {0, 0, nullptr, }, // 0x0029 + {0, 0, nullptr, }, // 0x002a + {0, 0, nullptr, }, // 0x002b + {0, 0, nullptr, }, // 0x002c + {0, 0, nullptr, }, // 0x002d + {0, 0, nullptr, }, // 0x002e + {0, 0, nullptr, }, // 0x002f + {0, 0, nullptr, }, // 0x0030 + {0, 0, nullptr, }, // 0x0031 + {0, 0, nullptr, }, // 0x0032 + {0, 0, nullptr, }, // 0x0033 + {0, 0, nullptr, }, // 0x0034 + {0, 0, nullptr, }, // 0x0035 + {0, 0, nullptr, }, // 0x0036 + {0, 0, nullptr, }, // 0x0037 + {0, 0, nullptr, }, // 0x0038 + {0, 0, nullptr, }, // 0x0039 + {0, 0, nullptr, }, // 0x003a + {0, 0, nullptr, }, // 0x003b + {0, 0, nullptr, }, // 0x003c + {0, 0, nullptr, }, // 0x003d + {0, 0, nullptr, }, // 0x003e + {0, 0, nullptr, }, // 0x003f + {0, 0, nullptr, }, // 0x0040 + {0, 0, nullptr, }, // 0x0041 + {0, 0, nullptr, }, // 0x0042 + {0, 0, nullptr, }, // 0x0043 + {0, 0, nullptr, }, // 0x0044 + {0, 0, nullptr, }, // 0x0045 + {0, 0, nullptr, }, // 0x0046 + {0, 0, nullptr, }, // 0x0047 + {0, 0, nullptr, }, // 0x0048 + {0, 0, nullptr, }, // 0x0049 + {0, 0, nullptr, }, // 0x004a + {0, 0, nullptr, }, // 0x004b + {0, 0, nullptr, }, // 0x004c + {0, 0, nullptr, }, // 0x004d + {0, 0, nullptr, }, // 0x004e + {0, 0, nullptr, }, // 0x004f + {0, 0, nullptr, }, // 0x0050 + {0, 0, nullptr, }, // 0x0051 + {0, 0, nullptr, }, // 0x0052 + {0, 0, nullptr, }, // 0x0053 + {0, 0, nullptr, }, // 0x0054 + {0, 0, nullptr, }, // 0x0055 + {0, 0, nullptr, }, // 0x0056 + {0, 0, nullptr, }, // 0x0057 + {0, 0, nullptr, }, // 0x0058 + {0, 0, nullptr, }, // 0x0059 + {0, 0, nullptr, }, // 0x005a + {0, 0, nullptr, }, // 0x005b + {0, 0, nullptr, }, // 0x005c + {0, 0, nullptr, }, // 0x005d + {0, 0, nullptr, }, // 0x005e + {0, 0, nullptr, }, // 0x005f + {0, 0, nullptr, }, // 0x0060 + {0, 0, nullptr, }, // 0x0061 + {0, 0, nullptr, }, // 0x0062 + {0, VAR,nullptr, }, // 0x0063 + {0, 55, nullptr, }, // 0x0064 + {0, 17, nullptr, }, // 0x0065 + {0, 3, nullptr, }, // 0x0066 + {0, 37, nullptr, }, // 0x0067 + {0, 46, nullptr, }, // 0x0068 + {0, VAR,nullptr, }, // 0x0069 + {0, 23, nullptr, }, // 0x006a + {0, VAR,nullptr, }, // 0x006b + {0, 3, nullptr, }, // 0x006c + {0, 108,nullptr, }, // 0x006d + {0, 3, nullptr, }, // 0x006e + {0, 2, nullptr, }, // 0x006f + {0, 3, nullptr, }, // 0x0070 + {0, 28, nullptr, }, // 0x0071 {0, 19, clif_parse_WantToConnection, }, // 0x0072 - {0, 11, NULL, }, // 0x0073 - {0, 3, NULL, }, // 0x0074 - {0, VAR,NULL, }, // 0x0075 - {0, 9, NULL, }, // 0x0076 - {0, 5, NULL, }, // 0x0077 - {0, 54, NULL, }, // 0x0078 - {0, 53, NULL, }, // 0x0079 - {0, 58, NULL, }, // 0x007a - {0, 60, NULL, }, // 0x007b - {0, 41, NULL, }, // 0x007c + {0, 11, nullptr, }, // 0x0073 + {0, 3, nullptr, }, // 0x0074 + {0, VAR,nullptr, }, // 0x0075 + {0, 9, nullptr, }, // 0x0076 + {0, 5, nullptr, }, // 0x0077 + {0, 54, nullptr, }, // 0x0078 + {0, 53, nullptr, }, // 0x0079 + {0, 58, nullptr, }, // 0x007a + {0, 60, nullptr, }, // 0x007b + {0, 41, nullptr, }, // 0x007c {-1, 2, clif_parse_LoadEndAck, }, // 0x007d {0, 6, clif_parse_TickSend, }, // 0x007e - {0, 6, NULL, }, // 0x007f - {0, 7, NULL, }, // 0x0080 - {0, 3, NULL, }, // 0x0081 - {0, 2, NULL, }, // 0x0082 - {0, 2, NULL, }, // 0x0083 - {0, 2, NULL, }, // 0x0084 + {0, 6, nullptr, }, // 0x007f + {0, 7, nullptr, }, // 0x0080 + {0, 3, nullptr, }, // 0x0081 + {0, 2, nullptr, }, // 0x0082 + {0, 2, nullptr, }, // 0x0083 + {0, 2, nullptr, }, // 0x0084 {-1, 5, clif_parse_WalkToXY, }, // 0x0085 Walk code limits this on it's own - {0, 16, NULL, }, // 0x0086 - {0, 12, NULL, }, // 0x0087 - {0, 10, NULL, }, // 0x0088 + {0, 16, nullptr, }, // 0x0086 + {0, 12, nullptr, }, // 0x0087 + {0, 10, nullptr, }, // 0x0088 {1000, 7, clif_parse_ActionRequest, }, // 0x0089 Special case - see below - {0, 29, NULL, }, // 0x008a - {0, 23, NULL, }, // 0x008b unknown... size 2 or 23? + {0, 29, nullptr, }, // 0x008a + {0, 23, nullptr, }, // 0x008b unknown... size 2 or 23? {300, VAR,clif_parse_GlobalMessage, }, // 0x008c - {0, VAR,NULL, }, // 0x008d - {0, VAR,NULL, }, // 0x008e - {0, 0, NULL, }, // 0x008f + {0, VAR,nullptr, }, // 0x008d + {0, VAR,nullptr, }, // 0x008e + {0, 0, nullptr, }, // 0x008f {500, 7, clif_parse_NpcClicked, }, // 0x0090 - {0, 22, NULL, }, // 0x0091 - {0, 28, NULL, }, // 0x0092 - {0, 2, NULL, }, // 0x0093 + {0, 22, nullptr, }, // 0x0091 + {0, 28, nullptr, }, // 0x0092 + {0, 2, nullptr, }, // 0x0093 {-1, 6, clif_parse_GetCharNameRequest, }, // 0x0094 - {0, 30, NULL, }, // 0x0095 + {0, 30, nullptr, }, // 0x0095 {300, VAR,clif_parse_Wis, }, // 0x0096 - {0, VAR,NULL, }, // 0x0097 - {0, 3, NULL, }, // 0x0098 - {300, VAR,NULL, }, // 0x0099 - {0, VAR,NULL, }, // 0x009a + {0, VAR,nullptr, }, // 0x0097 + {0, 3, nullptr, }, // 0x0098 + {300, VAR,nullptr, }, // 0x0099 + {0, VAR,nullptr, }, // 0x009a {-1, 5, clif_parse_ChangeDir, }, // 0x009b - {0, 9, NULL, }, // 0x009c - {0, 17, NULL, }, // 0x009d - {0, 17, NULL, }, // 0x009e + {0, 9, nullptr, }, // 0x009c + {0, 17, nullptr, }, // 0x009d + {0, 17, nullptr, }, // 0x009e {400, 6, clif_parse_TakeItem, }, // 0x009f - {0, 23, NULL, }, // 0x00a0 - {0, 6, NULL, }, // 0x00a1 + {0, 23, nullptr, }, // 0x00a0 + {0, 6, nullptr, }, // 0x00a1 {50, 6, clif_parse_DropItem, }, // 0x00a2 - {0, VAR,NULL, }, // 0x00a3 - {0, VAR,NULL, }, // 0x00a4 - {0, VAR,NULL, }, // 0x00a5 - {0, VAR,NULL, }, // 0x00a6 + {0, VAR,nullptr, }, // 0x00a3 + {0, VAR,nullptr, }, // 0x00a4 + {0, VAR,nullptr, }, // 0x00a5 + {0, VAR,nullptr, }, // 0x00a6 {0, 8, clif_parse_UseItem, }, // 0x00a7 - {0, 7, NULL, }, // 0x00a8 + {0, 7, nullptr, }, // 0x00a8 {-1, 6, clif_parse_EquipItem, }, // 0x00a9 Special case - outfit window (not implemented yet - needs to allow bursts) - {0, 7, NULL, }, // 0x00aa + {0, 7, nullptr, }, // 0x00aa {-1, 4, clif_parse_UnequipItem, }, // 0x00ab Special case - outfit window (not implemented yet - needs to allow bursts) - {0, 7, NULL, }, // 0x00ac - {0, 0, NULL, }, // 0x00ad - {0, VAR,NULL, }, // 0x00ae - {0, 6, NULL, }, // 0x00af - {0, 8, NULL, }, // 0x00b0 - {0, 8, NULL, }, // 0x00b1 + {0, 7, nullptr, }, // 0x00ac + {0, 0, nullptr, }, // 0x00ad + {0, VAR,nullptr, }, // 0x00ae + {0, 6, nullptr, }, // 0x00af + {0, 8, nullptr, }, // 0x00b0 + {0, 8, nullptr, }, // 0x00b1 {0, 3, clif_parse_Restart, }, // 0x00b2 - {0, 3, NULL, }, // 0x00b3 - {0, VAR,NULL, }, // 0x00b4 - {0, 6, NULL, }, // 0x00b5 - {0, 6, NULL, }, // 0x00b6 - {0, VAR,NULL, }, // 0x00b7 + {0, 3, nullptr, }, // 0x00b3 + {0, VAR,nullptr, }, // 0x00b4 + {0, 6, nullptr, }, // 0x00b5 + {0, 6, nullptr, }, // 0x00b6 + {0, VAR,nullptr, }, // 0x00b7 {0, 7, clif_parse_NpcSelectMenu, }, // 0x00b8 {-1, 6, clif_parse_NpcNextClicked, }, // 0x00b9 - {0, 2, NULL, }, // 0x00ba + {0, 2, nullptr, }, // 0x00ba {-1, 5, clif_parse_StatusUp, }, // 0x00bb People click this very quickly - {0, 6, NULL, }, // 0x00bc - {0, 44, NULL, }, // 0x00bd - {0, 5, NULL, }, // 0x00be + {0, 6, nullptr, }, // 0x00bc + {0, 44, nullptr, }, // 0x00bd + {0, 5, nullptr, }, // 0x00be {1000, 3, clif_parse_Emotion, }, // 0x00bf - {0, 7, NULL, }, // 0x00c0 + {0, 7, nullptr, }, // 0x00c0 {0, 2, clif_parse_HowManyConnections, }, // 0x00c1 - {0, 6, NULL, }, // 0x00c2 - {0, 8, NULL, }, // 0x00c3 - {0, 6, NULL, }, // 0x00c4 + {0, 6, nullptr, }, // 0x00c2 + {0, 8, nullptr, }, // 0x00c3 + {0, 6, nullptr, }, // 0x00c4 {0, 7, clif_parse_NpcBuySellSelected, }, // 0x00c5 - {0, VAR,NULL, }, // 0x00c6 - {0, VAR,NULL, }, // 0x00c7 + {0, VAR,nullptr, }, // 0x00c6 + {0, VAR,nullptr, }, // 0x00c7 {-1, VAR,clif_parse_NpcBuyListSend, }, // 0x00c8 {-1, VAR,clif_parse_NpcSellListSend, }, // 0x00c9 Selling multiple 1-slot items - {0, 3, NULL, }, // 0x00ca - {0, 3, NULL, }, // 0x00cb - {0, 6, NULL, }, // 0x00cc - {0, 6, NULL, }, // 0x00cd - {0, 2, NULL, }, // 0x00ce - {0, 27, NULL, }, // 0x00cf - {0, 3, NULL, }, // 0x00d0 - {0, 4, NULL, }, // 0x00d1 - {0, 4, NULL, }, // 0x00d2 - {0, 2, NULL, }, // 0x00d3 - {0, VAR,NULL, }, // 0x00d4 - {0, VAR,NULL, }, // 0x00d5 - {0, 3, NULL, }, // 0x00d6 - {0, VAR,NULL, }, // 0x00d7 - {0, 6, NULL, }, // 0x00d8 - {0, 14, NULL, }, // 0x00d9 - {0, 3, NULL, }, // 0x00da - {0, VAR,NULL, }, // 0x00db - {0, 28, NULL, }, // 0x00dc - {0, 29, NULL, }, // 0x00dd - {0, VAR,NULL, }, // 0x00de - {0, VAR,NULL, }, // 0x00df - {0, 30, NULL, }, // 0x00e0 - {0, 30, NULL, }, // 0x00e1 - {0, 26, NULL, }, // 0x00e2 - {0, 2, NULL, }, // 0x00e3 + {0, 3, nullptr, }, // 0x00ca + {0, 3, nullptr, }, // 0x00cb + {0, 6, nullptr, }, // 0x00cc + {0, 6, nullptr, }, // 0x00cd + {0, 2, nullptr, }, // 0x00ce + {0, 27, nullptr, }, // 0x00cf + {0, 3, nullptr, }, // 0x00d0 + {0, 4, nullptr, }, // 0x00d1 + {0, 4, nullptr, }, // 0x00d2 + {0, 2, nullptr, }, // 0x00d3 + {0, VAR,nullptr, }, // 0x00d4 + {0, VAR,nullptr, }, // 0x00d5 + {0, 3, nullptr, }, // 0x00d6 + {0, VAR,nullptr, }, // 0x00d7 + {0, 6, nullptr, }, // 0x00d8 + {0, 14, nullptr, }, // 0x00d9 + {0, 3, nullptr, }, // 0x00da + {0, VAR,nullptr, }, // 0x00db + {0, 28, nullptr, }, // 0x00dc + {0, 29, nullptr, }, // 0x00dd + {0, VAR,nullptr, }, // 0x00de + {0, VAR,nullptr, }, // 0x00df + {0, 30, nullptr, }, // 0x00e0 + {0, 30, nullptr, }, // 0x00e1 + {0, 26, nullptr, }, // 0x00e2 + {0, 2, nullptr, }, // 0x00e3 {2000, 6, clif_parse_TradeRequest, }, // 0x00e4 - {0, 26, NULL, }, // 0x00e5 + {0, 26, nullptr, }, // 0x00e5 {0, 3, clif_parse_TradeAck, }, // 0x00e6 - {0, 3, NULL, }, // 0x00e7 + {0, 3, nullptr, }, // 0x00e7 {0, 8, clif_parse_TradeAddItem, }, // 0x00e8 - {0, 19, NULL, }, // 0x00e9 - {0, 5, NULL, }, // 0x00ea + {0, 19, nullptr, }, // 0x00e9 + {0, 5, nullptr, }, // 0x00ea {0, 2, clif_parse_TradeOk, }, // 0x00eb - {0, 3, NULL, }, // 0x00ec + {0, 3, nullptr, }, // 0x00ec {0, 2, clif_parse_TradeCansel, }, // 0x00ed - {0, 2, NULL, }, // 0x00ee + {0, 2, nullptr, }, // 0x00ee {0, 2, clif_parse_TradeCommit, }, // 0x00ef - {0, 3, NULL, }, // 0x00f0 - {0, 2, NULL, }, // 0x00f1 - {0, 6, NULL, }, // 0x00f2 + {0, 3, nullptr, }, // 0x00f0 + {0, 2, nullptr, }, // 0x00f1 + {0, 6, nullptr, }, // 0x00f2 {-1, 8, clif_parse_MoveToKafra, }, // 0x00f3 - {0, 21, NULL, }, // 0x00f4 + {0, 21, nullptr, }, // 0x00f4 {-1, 8, clif_parse_MoveFromKafra, }, // 0x00f5 - {0, 8, NULL, }, // 0x00f6 + {0, 8, nullptr, }, // 0x00f6 {0, 2, clif_parse_CloseKafra, }, // 0x00f7 - {0, 2, NULL, }, // 0x00f8 + {0, 2, nullptr, }, // 0x00f8 {2000, 26, clif_parse_CreateParty, }, // 0x00f9 - {0, 3, NULL, }, // 0x00fa - {0, VAR,NULL, }, // 0x00fb + {0, 3, nullptr, }, // 0x00fa + {0, VAR,nullptr, }, // 0x00fb {2000, 6, clif_parse_PartyInvite, }, // 0x00fc - {0, 27, NULL, }, // 0x00fd - {0, 30, NULL, }, // 0x00fe + {0, 27, nullptr, }, // 0x00fd + {0, 30, nullptr, }, // 0x00fe {0, 10, clif_parse_ReplyPartyInvite, }, // 0x00ff {0, 2, clif_parse_LeaveParty, }, // 0x0100 - {0, 6, NULL, }, // 0x0101 + {0, 6, nullptr, }, // 0x0101 {0, 6, clif_parse_PartyChangeOption, }, // 0x0102 {0, 30, clif_parse_RemovePartyMember, }, // 0x0103 - {0, 79, NULL, }, // 0x0104 - {0, 31, NULL, }, // 0x0105 - {0, 10, NULL, }, // 0x0106 - {0, 10, NULL, }, // 0x0107 + {0, 79, nullptr, }, // 0x0104 + {0, 31, nullptr, }, // 0x0105 + {0, 10, nullptr, }, // 0x0106 + {0, 10, nullptr, }, // 0x0107 {300, VAR,clif_parse_PartyMessage, }, // 0x0108 - {0, VAR,NULL, }, // 0x0109 - {0, 4, NULL, }, // 0x010a - {0, 6, NULL, }, // 0x010b - {0, 6, NULL, }, // 0x010c - {0, 2, NULL, }, // 0x010d - {0, 11, NULL, }, // 0x010e - {0, VAR,NULL, }, // 0x010f - {0, 10, NULL, }, // 0x0110 - {0, 39, NULL, }, // 0x0111 + {0, VAR,nullptr, }, // 0x0109 + {0, 4, nullptr, }, // 0x010a + {0, 6, nullptr, }, // 0x010b + {0, 6, nullptr, }, // 0x010c + {0, 2, nullptr, }, // 0x010d + {0, 11, nullptr, }, // 0x010e + {0, VAR,nullptr, }, // 0x010f + {0, 10, nullptr, }, // 0x0110 + {0, 39, nullptr, }, // 0x0111 {-1, 4, clif_parse_SkillUp, }, // 0x0112 - {0, 10, NULL, }, // 0x0113 - {0, 31, NULL, }, // 0x0114 - {0, 35, NULL, }, // 0x0115 - {0, 10, NULL, }, // 0x0116 - {0, 18, NULL, }, // 0x0117 + {0, 10, nullptr, }, // 0x0113 + {0, 31, nullptr, }, // 0x0114 + {0, 35, nullptr, }, // 0x0115 + {0, 10, nullptr, }, // 0x0116 + {0, 18, nullptr, }, // 0x0117 {0, 2, clif_parse_StopAttack, }, // 0x0118 - {0, 13, NULL, }, // 0x0119 - {0, 15, NULL, }, // 0x011a - {0, 20, NULL, }, // 0x011b - {0, 68, NULL, }, // 0x011c - {0, 2, NULL, }, // 0x011d - {0, 3, NULL, }, // 0x011e - {0, 16, NULL, }, // 0x011f - {0, 6, NULL, }, // 0x0120 - {0, 14, NULL, }, // 0x0121 - {0, VAR,NULL, }, // 0x0122 - {0, VAR,NULL, }, // 0x0123 - {0, 21, NULL, }, // 0x0124 - {0, 8, NULL, }, // 0x0125 - {0, 8, NULL, }, // 0x0126 - {0, 8, NULL, }, // 0x0127 - {0, 8, NULL, }, // 0x0128 - {0, 8, NULL, }, // 0x0129 - {0, 2, NULL, }, // 0x012a - {0, 2, NULL, }, // 0x012b - {0, 3, NULL, }, // 0x012c - {0, 4, NULL, }, // 0x012d - {0, 2, NULL, }, // 0x012e - {0, VAR,NULL, }, // 0x012f - {0, 6, NULL, }, // 0x0130 - {0, 86, NULL, }, // 0x0131 - {0, 6, NULL, }, // 0x0132 - {0, VAR,NULL, }, // 0x0133 - {0, VAR,NULL, }, // 0x0134 - {0, 7, NULL, }, // 0x0135 - {0, VAR,NULL, }, // 0x0136 - {0, 6, NULL, }, // 0x0137 - {0, 3, NULL, }, // 0x0138 - {0, 16, NULL, }, // 0x0139 - {0, 4, NULL, }, // 0x013a - {0, 4, NULL, }, // 0x013b - {0, 4, NULL, }, // 0x013c - {0, 6, NULL, }, // 0x013d - {0, 24, NULL, }, // 0x013e - {0, 26, NULL, }, // 0x013f - {0, 22, NULL, }, // 0x0140 - {0, 14, NULL, }, // 0x0141 - {0, 6, NULL, }, // 0x0142 + {0, 13, nullptr, }, // 0x0119 + {0, 15, nullptr, }, // 0x011a + {0, 20, nullptr, }, // 0x011b + {0, 68, nullptr, }, // 0x011c + {0, 2, nullptr, }, // 0x011d + {0, 3, nullptr, }, // 0x011e + {0, 16, nullptr, }, // 0x011f + {0, 6, nullptr, }, // 0x0120 + {0, 14, nullptr, }, // 0x0121 + {0, VAR,nullptr, }, // 0x0122 + {0, VAR,nullptr, }, // 0x0123 + {0, 21, nullptr, }, // 0x0124 + {0, 8, nullptr, }, // 0x0125 + {0, 8, nullptr, }, // 0x0126 + {0, 8, nullptr, }, // 0x0127 + {0, 8, nullptr, }, // 0x0128 + {0, 8, nullptr, }, // 0x0129 + {0, 2, nullptr, }, // 0x012a + {0, 2, nullptr, }, // 0x012b + {0, 3, nullptr, }, // 0x012c + {0, 4, nullptr, }, // 0x012d + {0, 2, nullptr, }, // 0x012e + {0, VAR,nullptr, }, // 0x012f + {0, 6, nullptr, }, // 0x0130 + {0, 86, nullptr, }, // 0x0131 + {0, 6, nullptr, }, // 0x0132 + {0, VAR,nullptr, }, // 0x0133 + {0, VAR,nullptr, }, // 0x0134 + {0, 7, nullptr, }, // 0x0135 + {0, VAR,nullptr, }, // 0x0136 + {0, 6, nullptr, }, // 0x0137 + {0, 3, nullptr, }, // 0x0138 + {0, 16, nullptr, }, // 0x0139 + {0, 4, nullptr, }, // 0x013a + {0, 4, nullptr, }, // 0x013b + {0, 4, nullptr, }, // 0x013c + {0, 6, nullptr, }, // 0x013d + {0, 24, nullptr, }, // 0x013e + {0, 26, nullptr, }, // 0x013f + {0, 22, nullptr, }, // 0x0140 + {0, 14, nullptr, }, // 0x0141 + {0, 6, nullptr, }, // 0x0142 {300, 10, clif_parse_NpcAmountInput, }, // 0x0143 - {0, 23, NULL, }, // 0x0144 - {0, 19, NULL, }, // 0x0145 + {0, 23, nullptr, }, // 0x0144 + {0, 19, nullptr, }, // 0x0145 {300, 6, clif_parse_NpcCloseClicked, }, // 0x0146 - {0, 39, NULL, }, // 0x0147 - {0, 8, NULL, }, // 0x0148 - {0, 9, NULL, }, // 0x0149 - {0, 6, NULL, }, // 0x014a - {0, 27, NULL, }, // 0x014b - {0, VAR,NULL, }, // 0x014c - {0, 2, NULL, }, // 0x014d - {0, 6, NULL, }, // 0x014e - {0, 6, NULL, }, // 0x014f - {0, 110,NULL, }, // 0x0150 - {0, 6, NULL, }, // 0x0151 - {0, VAR,NULL, }, // 0x0152 - {0, VAR,NULL, }, // 0x0153 - {0, VAR,NULL, }, // 0x0154 - {0, VAR,NULL, }, // 0x0155 - {0, VAR,NULL, }, // 0x0156 - {0, 6, NULL, }, // 0x0157 - {0, VAR,NULL, }, // 0x0158 - {0, 54, NULL, }, // 0x0159 - {0, 66, NULL, }, // 0x015a - {0, 54, NULL, }, // 0x015b - {0, 90, NULL, }, // 0x015c - {0, 42, NULL, }, // 0x015d - {0, 6, NULL, }, // 0x015e - {0, 42, NULL, }, // 0x015f - {0, VAR,NULL, }, // 0x0160 - {0, VAR,NULL, }, // 0x0161 - {0, VAR,NULL, }, // 0x0162 - {0, VAR,NULL, }, // 0x0163 - {0, VAR,NULL, }, // 0x0164 - {0, 30, NULL, }, // 0x0165 - {0, VAR,NULL, }, // 0x0166 - {0, 3, NULL, }, // 0x0167 - {0, 14, NULL, }, // 0x0168 - {0, 3, NULL, }, // 0x0169 - {0, 30, NULL, }, // 0x016a - {0, 10, NULL, }, // 0x016b - {0, 43, NULL, }, // 0x016c - {0, 14, NULL, }, // 0x016d - {0, 186,NULL, }, // 0x016e - {0, 182,NULL, }, // 0x016f - {0, 14, NULL, }, // 0x0170 - {0, 30, NULL, }, // 0x0171 - {0, 10, NULL, }, // 0x0172 - {0, 3, NULL, }, // 0x0173 - {0, VAR,NULL, }, // 0x0174 - {0, 6, NULL, }, // 0x0175 - {0, 106,NULL, }, // 0x0176 - {0, VAR,NULL, }, // 0x0177 - {0, 4, NULL, }, // 0x0178 - {0, 5, NULL, }, // 0x0179 - {0, 4, NULL, }, // 0x017a - {0, VAR,NULL, }, // 0x017b - {0, 6, NULL, }, // 0x017c - {0, 7, NULL, }, // 0x017d - {0, VAR,NULL, }, // 0x017e - {0, VAR,NULL, }, // 0x017f - {0, 6, NULL, }, // 0x0180 - {0, 3, NULL, }, // 0x0181 - {0, 106,NULL, }, // 0x0182 - {0, 10, NULL, }, // 0x0183 - {0, 10, NULL, }, // 0x0184 - {0, 34, NULL, }, // 0x0185 - {0, 0, NULL, }, // 0x0186 - {0, 6, NULL, }, // 0x0187 - {0, 8, NULL, }, // 0x0188 - {0, 4, NULL, }, // 0x0189 + {0, 39, nullptr, }, // 0x0147 + {0, 8, nullptr, }, // 0x0148 + {0, 9, nullptr, }, // 0x0149 + {0, 6, nullptr, }, // 0x014a + {0, 27, nullptr, }, // 0x014b + {0, VAR,nullptr, }, // 0x014c + {0, 2, nullptr, }, // 0x014d + {0, 6, nullptr, }, // 0x014e + {0, 6, nullptr, }, // 0x014f + {0, 110,nullptr, }, // 0x0150 + {0, 6, nullptr, }, // 0x0151 + {0, VAR,nullptr, }, // 0x0152 + {0, VAR,nullptr, }, // 0x0153 + {0, VAR,nullptr, }, // 0x0154 + {0, VAR,nullptr, }, // 0x0155 + {0, VAR,nullptr, }, // 0x0156 + {0, 6, nullptr, }, // 0x0157 + {0, VAR,nullptr, }, // 0x0158 + {0, 54, nullptr, }, // 0x0159 + {0, 66, nullptr, }, // 0x015a + {0, 54, nullptr, }, // 0x015b + {0, 90, nullptr, }, // 0x015c + {0, 42, nullptr, }, // 0x015d + {0, 6, nullptr, }, // 0x015e + {0, 42, nullptr, }, // 0x015f + {0, VAR,nullptr, }, // 0x0160 + {0, VAR,nullptr, }, // 0x0161 + {0, VAR,nullptr, }, // 0x0162 + {0, VAR,nullptr, }, // 0x0163 + {0, VAR,nullptr, }, // 0x0164 + {0, 30, nullptr, }, // 0x0165 + {0, VAR,nullptr, }, // 0x0166 + {0, 3, nullptr, }, // 0x0167 + {0, 14, nullptr, }, // 0x0168 + {0, 3, nullptr, }, // 0x0169 + {0, 30, nullptr, }, // 0x016a + {0, 10, nullptr, }, // 0x016b + {0, 43, nullptr, }, // 0x016c + {0, 14, nullptr, }, // 0x016d + {0, 186,nullptr, }, // 0x016e + {0, 182,nullptr, }, // 0x016f + {0, 14, nullptr, }, // 0x0170 + {0, 30, nullptr, }, // 0x0171 + {0, 10, nullptr, }, // 0x0172 + {0, 3, nullptr, }, // 0x0173 + {0, VAR,nullptr, }, // 0x0174 + {0, 6, nullptr, }, // 0x0175 + {0, 106,nullptr, }, // 0x0176 + {0, VAR,nullptr, }, // 0x0177 + {0, 4, nullptr, }, // 0x0178 + {0, 5, nullptr, }, // 0x0179 + {0, 4, nullptr, }, // 0x017a + {0, VAR,nullptr, }, // 0x017b + {0, 6, nullptr, }, // 0x017c + {0, 7, nullptr, }, // 0x017d + {0, VAR,nullptr, }, // 0x017e + {0, VAR,nullptr, }, // 0x017f + {0, 6, nullptr, }, // 0x0180 + {0, 3, nullptr, }, // 0x0181 + {0, 106,nullptr, }, // 0x0182 + {0, 10, nullptr, }, // 0x0183 + {0, 10, nullptr, }, // 0x0184 + {0, 34, nullptr, }, // 0x0185 + {0, 0, nullptr, }, // 0x0186 + {0, 6, nullptr, }, // 0x0187 + {0, 8, nullptr, }, // 0x0188 + {0, 4, nullptr, }, // 0x0189 {0, 4, clif_parse_QuitGame, }, // 0x018a - {0, 4, NULL, }, // 0x018b - {0, 29, NULL, }, // 0x018c - {0, VAR,NULL, }, // 0x018d - {0, 10, NULL, }, // 0x018e - {0, 6, NULL, }, // 0x018f - {0, 90, NULL, }, // 0x0190 - {0, 86, NULL, }, // 0x0191 - {0, 24, NULL, }, // 0x0192 - {0, 6, NULL, }, // 0x0193 - {0, 30, NULL, }, // 0x0194 - {0, 102,NULL, }, // 0x0195 - {0, 9, NULL, }, // 0x0196 - {0, 4, NULL, }, // 0x0197 - {0, 8, NULL, }, // 0x0198 - {0, 4, NULL, }, // 0x0199 - {0, 14, NULL, }, // 0x019a - {0, 10, NULL, }, // 0x019b - {0, VAR,NULL, }, // 0x019c - {300, 6, NULL, }, // 0x019d - {0, 2, NULL, }, // 0x019e - {0, 6, NULL, }, // 0x019f - {0, 3, NULL, }, // 0x01a0 - {0, 3, NULL, }, // 0x01a1 - {0, 35, NULL, }, // 0x01a2 - {0, 5, NULL, }, // 0x01a3 - {0, 11, NULL, }, // 0x01a4 - {0, 26, NULL, }, // 0x01a5 - {0, VAR,NULL, }, // 0x01a6 - {0, 4, NULL, }, // 0x01a7 - {0, 4, NULL, }, // 0x01a8 - {0, 6, NULL, }, // 0x01a9 - {0, 10, NULL, }, // 0x01aa - {0, 12, NULL, }, // 0x01ab - {0, 6, NULL, }, // 0x01ac - {0, VAR,NULL, }, // 0x01ad - {0, 4, NULL, }, // 0x01ae - {0, 4, NULL, }, // 0x01af - {0, 11, NULL, }, // 0x01b0 - {0, 7, NULL, }, // 0x01b1 - {0, VAR,NULL, }, // 0x01b2 - {0, 67, NULL, }, // 0x01b3 - {0, 12, NULL, }, // 0x01b4 - {0, 18, NULL, }, // 0x01b5 - {0, 114,NULL, }, // 0x01b6 - {0, 6, NULL, }, // 0x01b7 - {0, 3, NULL, }, // 0x01b8 - {0, 6, NULL, }, // 0x01b9 - {0, 26, NULL, }, // 0x01ba - {0, 26, NULL, }, // 0x01bb - {0, 26, NULL, }, // 0x01bc - {0, 26, NULL, }, // 0x01bd - {0, 2, NULL, }, // 0x01be - {0, 3, NULL, }, // 0x01bf - {0, 2, NULL, }, // 0x01c0 - {0, 14, NULL, }, // 0x01c1 - {0, 10, NULL, }, // 0x01c2 - {0, VAR,NULL, }, // 0x01c3 - {0, 22, NULL, }, // 0x01c4 - {0, 22, NULL, }, // 0x01c5 - {0, 4, NULL, }, // 0x01c6 - {0, 2, NULL, }, // 0x01c7 - {0, 13, NULL, }, // 0x01c8 - {0, 97, NULL, }, // 0x01c9 - {0, 0, NULL, }, // 0x01ca - {0, 9, NULL, }, // 0x01cb - {0, 9, NULL, }, // 0x01cc - {0, 30, NULL, }, // 0x01cd - {0, 6, NULL, }, // 0x01ce - {0, 28, NULL, }, // 0x01cf - {0, 8, NULL, }, // 0x01d0 - {0, 14, NULL, }, // 0x01d1 - {0, 10, NULL, }, // 0x01d2 - {0, 35, NULL, }, // 0x01d3 - {0, 6, NULL, }, // 0x01d4 + {0, 4, nullptr, }, // 0x018b + {0, 29, nullptr, }, // 0x018c + {0, VAR,nullptr, }, // 0x018d + {0, 10, nullptr, }, // 0x018e + {0, 6, nullptr, }, // 0x018f + {0, 90, nullptr, }, // 0x0190 + {0, 86, nullptr, }, // 0x0191 + {0, 24, nullptr, }, // 0x0192 + {0, 6, nullptr, }, // 0x0193 + {0, 30, nullptr, }, // 0x0194 + {0, 102,nullptr, }, // 0x0195 + {0, 9, nullptr, }, // 0x0196 + {0, 4, nullptr, }, // 0x0197 + {0, 8, nullptr, }, // 0x0198 + {0, 4, nullptr, }, // 0x0199 + {0, 14, nullptr, }, // 0x019a + {0, 10, nullptr, }, // 0x019b + {0, VAR,nullptr, }, // 0x019c + {300, 6, nullptr, }, // 0x019d + {0, 2, nullptr, }, // 0x019e + {0, 6, nullptr, }, // 0x019f + {0, 3, nullptr, }, // 0x01a0 + {0, 3, nullptr, }, // 0x01a1 + {0, 35, nullptr, }, // 0x01a2 + {0, 5, nullptr, }, // 0x01a3 + {0, 11, nullptr, }, // 0x01a4 + {0, 26, nullptr, }, // 0x01a5 + {0, VAR,nullptr, }, // 0x01a6 + {0, 4, nullptr, }, // 0x01a7 + {0, 4, nullptr, }, // 0x01a8 + {0, 6, nullptr, }, // 0x01a9 + {0, 10, nullptr, }, // 0x01aa + {0, 12, nullptr, }, // 0x01ab + {0, 6, nullptr, }, // 0x01ac + {0, VAR,nullptr, }, // 0x01ad + {0, 4, nullptr, }, // 0x01ae + {0, 4, nullptr, }, // 0x01af + {0, 11, nullptr, }, // 0x01b0 + {0, 7, nullptr, }, // 0x01b1 + {0, VAR,nullptr, }, // 0x01b2 + {0, 67, nullptr, }, // 0x01b3 + {0, 12, nullptr, }, // 0x01b4 + {0, 18, nullptr, }, // 0x01b5 + {0, 114,nullptr, }, // 0x01b6 + {0, 6, nullptr, }, // 0x01b7 + {0, 3, nullptr, }, // 0x01b8 + {0, 6, nullptr, }, // 0x01b9 + {0, 26, nullptr, }, // 0x01ba + {0, 26, nullptr, }, // 0x01bb + {0, 26, nullptr, }, // 0x01bc + {0, 26, nullptr, }, // 0x01bd + {0, 2, nullptr, }, // 0x01be + {0, 3, nullptr, }, // 0x01bf + {0, 2, nullptr, }, // 0x01c0 + {0, 14, nullptr, }, // 0x01c1 + {0, 10, nullptr, }, // 0x01c2 + {0, VAR,nullptr, }, // 0x01c3 + {0, 22, nullptr, }, // 0x01c4 + {0, 22, nullptr, }, // 0x01c5 + {0, 4, nullptr, }, // 0x01c6 + {0, 2, nullptr, }, // 0x01c7 + {0, 13, nullptr, }, // 0x01c8 + {0, 97, nullptr, }, // 0x01c9 + {0, 0, nullptr, }, // 0x01ca + {0, 9, nullptr, }, // 0x01cb + {0, 9, nullptr, }, // 0x01cc + {0, 30, nullptr, }, // 0x01cd + {0, 6, nullptr, }, // 0x01ce + {0, 28, nullptr, }, // 0x01cf + {0, 8, nullptr, }, // 0x01d0 + {0, 14, nullptr, }, // 0x01d1 + {0, 10, nullptr, }, // 0x01d2 + {0, 35, nullptr, }, // 0x01d3 + {0, 6, nullptr, }, // 0x01d4 {300, VAR,clif_parse_NpcStringInput, }, // 0x01d5 - set to -1 - {0, 4, NULL, }, // 0x01d6 - {0, 11, NULL, }, // 0x01d7 - {0, 54, NULL, }, // 0x01d8 - {0, 53, NULL, }, // 0x01d9 - {0, 60, NULL, }, // 0x01da - {0, 2, NULL, }, // 0x01db - {0, VAR,NULL, }, // 0x01dc - {0, 47, NULL, }, // 0x01dd - {0, 33, NULL, }, // 0x01de - {0, 6, NULL, }, // 0x01df - {0, 30, NULL, }, // 0x01e0 - {0, 8, NULL, }, // 0x01e1 - {0, 34, NULL, }, // 0x01e2 - {0, 14, NULL, }, // 0x01e3 - {0, 2, NULL, }, // 0x01e4 - {0, 6, NULL, }, // 0x01e5 - {0, 26, NULL, }, // 0x01e6 - {0, 2, NULL, }, // 0x01e7 - {0, 28, NULL, }, // 0x01e8 - {0, 81, NULL, }, // 0x01e9 - {0, 6, NULL, }, // 0x01ea - {0, 10, NULL, }, // 0x01eb - {0, 26, NULL, }, // 0x01ec - {0, 2, NULL, }, // 0x01ed - {0, VAR,NULL, }, // 0x01ee - {0, VAR,NULL, }, // 0x01ef - {0, VAR,NULL, }, // 0x01f0 - {0, VAR,NULL, }, // 0x01f1 - {0, 20, NULL, }, // 0x01f2 - {0, 10, NULL, }, // 0x01f3 - {0, 32, NULL, }, // 0x01f4 - {0, 9, NULL, }, // 0x01f5 - {0, 34, NULL, }, // 0x01f6 - {0, 14, NULL, }, // 0x01f7 - {0, 2, NULL, }, // 0x01f8 - {0, 6, NULL, }, // 0x01f9 - {0, 48, NULL, }, // 0x01fa - {0, 56, NULL, }, // 0x01fb - {0, VAR,NULL, }, // 0x01fc - {0, 4, NULL, }, // 0x01fd - {0, 5, NULL, }, // 0x01fe - {0, 10, NULL, }, // 0x01ff - {0, 26, NULL, }, // 0x0200 - {0, VAR,NULL, }, // 0x0201 - {0, 26, NULL, }, // 0x0202 - {0, 10, NULL, }, // 0x0203 - {0, 18, NULL, }, // 0x0204 - {0, 26, NULL, }, // 0x0205 - {0, 11, NULL, }, // 0x0206 - {0, 34, NULL, }, // 0x0207 - {0, 14, NULL, }, // 0x0208 - {0, 36, NULL, }, // 0x0209 - {0, 10, NULL, }, // 0x020a - {0, 19, NULL, }, // 0x020b - {0, 10, NULL, }, // 0x020c - {0, VAR,NULL, }, // 0x020d - {0, 24, NULL, }, // 0x020e - {0, 0, NULL, }, // 0x020f - {0, 0, NULL, }, // 0x0210 - {0, 0, NULL, }, // 0x0211 - {0, 0, NULL, }, // 0x0212 - {0, 0, NULL, }, // 0x0213 - {0, 0, NULL, }, // 0x0214 - {0, 0, NULL, }, // 0x0215 - {0, 0, NULL, }, // 0x0216 - {0, 0, NULL, }, // 0x0217 - {0, 0, NULL, }, // 0x0218 - {0, 0, NULL, }, // 0x0219 - {0, 0, NULL, }, // 0x021a - {0, 0, NULL, }, // 0x021b - {0, 0, NULL, }, // 0x021c - {0, 0, NULL, }, // 0x021d - {0, 0, NULL, }, // 0x021e - {0, 0, NULL, }, // 0x021f + {0, 4, nullptr, }, // 0x01d6 + {0, 11, nullptr, }, // 0x01d7 + {0, 54, nullptr, }, // 0x01d8 + {0, 53, nullptr, }, // 0x01d9 + {0, 60, nullptr, }, // 0x01da + {0, 2, nullptr, }, // 0x01db + {0, VAR,nullptr, }, // 0x01dc + {0, 47, nullptr, }, // 0x01dd + {0, 33, nullptr, }, // 0x01de + {0, 6, nullptr, }, // 0x01df + {0, 30, nullptr, }, // 0x01e0 + {0, 8, nullptr, }, // 0x01e1 + {0, 34, nullptr, }, // 0x01e2 + {0, 14, nullptr, }, // 0x01e3 + {0, 2, nullptr, }, // 0x01e4 + {0, 6, nullptr, }, // 0x01e5 + {0, 26, nullptr, }, // 0x01e6 + {0, 2, nullptr, }, // 0x01e7 + {0, 28, nullptr, }, // 0x01e8 + {0, 81, nullptr, }, // 0x01e9 + {0, 6, nullptr, }, // 0x01ea + {0, 10, nullptr, }, // 0x01eb + {0, 26, nullptr, }, // 0x01ec + {0, 2, nullptr, }, // 0x01ed + {0, VAR,nullptr, }, // 0x01ee + {0, VAR,nullptr, }, // 0x01ef + {0, VAR,nullptr, }, // 0x01f0 + {0, VAR,nullptr, }, // 0x01f1 + {0, 20, nullptr, }, // 0x01f2 + {0, 10, nullptr, }, // 0x01f3 + {0, 32, nullptr, }, // 0x01f4 + {0, 9, nullptr, }, // 0x01f5 + {0, 34, nullptr, }, // 0x01f6 + {0, 14, nullptr, }, // 0x01f7 + {0, 2, nullptr, }, // 0x01f8 + {0, 6, nullptr, }, // 0x01f9 + {0, 48, nullptr, }, // 0x01fa + {0, 56, nullptr, }, // 0x01fb + {0, VAR,nullptr, }, // 0x01fc + {0, 4, nullptr, }, // 0x01fd + {0, 5, nullptr, }, // 0x01fe + {0, 10, nullptr, }, // 0x01ff + {0, 26, nullptr, }, // 0x0200 + {0, VAR,nullptr, }, // 0x0201 + {0, 26, nullptr, }, // 0x0202 + {0, 10, nullptr, }, // 0x0203 + {0, 18, nullptr, }, // 0x0204 + {0, 26, nullptr, }, // 0x0205 + {0, 11, nullptr, }, // 0x0206 + {0, 34, nullptr, }, // 0x0207 + {0, 14, nullptr, }, // 0x0208 + {0, 36, nullptr, }, // 0x0209 + {0, 10, nullptr, }, // 0x020a + {0, 19, nullptr, }, // 0x020b + {0, 10, nullptr, }, // 0x020c + {0, VAR,nullptr, }, // 0x020d + {0, 24, nullptr, }, // 0x020e + {0, 0, nullptr, }, // 0x020f + {0, 0, nullptr, }, // 0x0210 + {0, 0, nullptr, }, // 0x0211 + {0, 0, nullptr, }, // 0x0212 + {0, 0, nullptr, }, // 0x0213 + {0, 0, nullptr, }, // 0x0214 + {0, 0, nullptr, }, // 0x0215 + {0, 0, nullptr, }, // 0x0216 + {0, 0, nullptr, }, // 0x0217 + {0, 0, nullptr, }, // 0x0218 + {0, 0, nullptr, }, // 0x0219 + {0, 0, nullptr, }, // 0x021a + {0, 0, nullptr, }, // 0x021b + {0, 0, nullptr, }, // 0x021c + {0, 0, nullptr, }, // 0x021d + {0, 0, nullptr, }, // 0x021e + {0, 0, nullptr, }, // 0x021f }; // Checks for packet flooding static -int clif_check_packet_flood(Session *s, int cmd) +uint16_t clif_check_packet_flood(Session *s, int cmd) { + uint16_t len = clif_parse_func_table[cmd].len_unused; + if (len == VAR) + { + Little16 netlen; + if (!packet_fetch(s, 2, reinterpret_cast<Byte *>(&netlen), 2)) + { + return 0; + } + if (!network_to_native(&len, netlen)) + { + s->set_eof(); + return 0; + } + } + if (packet_avail(s) < len) + return 0; + dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())); tick_t tick = gettick(); @@ -5182,30 +5401,28 @@ int clif_check_packet_flood(Session *s, int cmd) // Default rate is 100ms interval_t rate = clif_parse_func_table[cmd].rate; if (rate == interval_t::zero()) - rate = std::chrono::milliseconds(100); + rate = 100_ms; // ActionRequest - attacks are allowed a faster rate than sit/stand if (cmd == 0x89) { - int action_type = RFIFOB(s, 6); - if (action_type == 0x00 || action_type == 0x07) - rate = std::chrono::milliseconds(20); + DamageType damage_type; + Byte action_type; + if (!packet_fetch(s, 6, &action_type, 1)) + return 0; + if (!network_to_native(&damage_type, action_type)) + { + s->set_eof(); + return 0; + } + if (damage_type == DamageType::NORMAL || damage_type == DamageType::CONTINUOUS) + rate = 20_ms; else - rate = std::chrono::seconds(1); + rate = 1_s; } -// Restore this code when mana1.0 is released -#if 0 - // ChangeDir - only apply limit if not walking - if (cmd == 0x9b) - { - // .29 clients spam this packet when walking into a blocked tile - if (RFIFOB(fd, 4) == sd->dir || sd->walktimer != -1) - return 0; - - rate = 500; - } -#endif + // Restore this code when mana1.0 is released + // nope, nuh-uh // They are flooding if (tick < sd->flood_rates[cmd] + rate) @@ -5223,16 +5440,16 @@ int clif_check_packet_flood(Session *s, int cmd) if (sd->packet_flood_in >= battle_config.packet_spam_flood) { - PRINTF("packet flood detected from %s [0x%x]\n", sd->status_key.name, cmd); + PRINTF("packet flood detected from %s [0x%x]\n"_fmt, sd->status_key.name, cmd); if (battle_config.packet_spam_kick) { s->set_eof(); - return 1; + return len; } sd->packet_flood_in = 0; } - return 1; + return len; } sd->flood_rates[cmd] = tick; @@ -5240,9 +5457,9 @@ int clif_check_packet_flood(Session *s, int cmd) } inline -void WARN_MALFORMED_MSG(dumb_ptr<map_session_data> sd, const char *msg) +void WARN_MALFORMED_MSG(dumb_ptr<map_session_data> sd, ZString msg) { - PRINTF("clif_validate_chat(): %s (ID %d) sent a malformed message: %s.\n", + PRINTF("clif_validate_chat(): %s (ID %d) sent a malformed message: %s.\n"_fmt, sd->status_key.name, sd->status_key.account_id, msg); } /** @@ -5256,7 +5473,7 @@ void WARN_MALFORMED_MSG(dumb_ptr<map_session_data> sd, const char *msg) * @return a dynamically allocated copy of the message, or empty string upon failure */ static -AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type) +AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type, XString buf) { nullpo_retr(AString(), sd); /* @@ -5267,54 +5484,8 @@ AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type) return AString(); Session *s = sd->sess; - size_t msg_len = RFIFOW(s, 2) - 4; size_t name_len = sd->status_key.name.to__actual().size(); - /* - * At least one character is required in all instances. - * Notes for length checks: - * - * For all types, header (2) + length (2) is considered empty. - * For type 1, the message must be longer than the maximum name length (24) - * to be valid. - * For type 2, the message must be longer than the sender's name length - * plus the length of the separator (" : "). - */ - size_t min_len = - (type == ChatType::Whisper) ? 24 - : (type == ChatType::Global) ? name_len + 3 - : 0; - - /* The player just sent the header (2) and length (2) words. */ - if (!msg_len) - { - WARN_MALFORMED_MSG(sd, "no message sent"); - return AString(); - } - - /* The client sent (or claims to have sent) an empty message. */ - if (msg_len == min_len) - { - WARN_MALFORMED_MSG(sd, "empty message"); - return AString(); - } - - /* The protocol specifies that the target must be 24 bytes long. */ - if (type == ChatType::Whisper && msg_len < min_len) - { - /* Disallow malformed messages. */ - clif_setwaitclose(s); - WARN_MALFORMED_MSG(sd, "illegal target name"); - return AString(); - } - - size_t pstart = 4; - size_t buf_len = msg_len; - if (type == ChatType::Whisper) - { - pstart += 24; - buf_len -= 24; - } - AString pbuf = RFIFO_STRING(s, pstart, buf_len); + XString pbuf = buf; /* * The client attempted to exceed the maximum message length. @@ -5323,20 +5494,21 @@ AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type) * is truncated. But the previous behavior was to drop the message, so * we'll do that, too. */ - if (buf_len >= battle_config.chat_maxline) + // TODO this cuts global chat short by (name_length + 3) + if (buf.size() >= battle_config.chat_maxline) { - WARN_MALFORMED_MSG(sd, "exceeded maximum message length"); + WARN_MALFORMED_MSG(sd, "exceeded maximum message length"_s); return AString(); } if (type == ChatType::Global) { XString p = pbuf; - if (!(p.startswith(sd->status_key.name.to__actual()) && p.xslice_t(name_len).startswith(" : "))) + if (!(p.startswith(sd->status_key.name.to__actual()) && p.xslice_t(name_len).startswith(" : "_s))) { /* Disallow malformed/spoofed messages. */ clif_setwaitclose(s); - WARN_MALFORMED_MSG(sd, "spoofed name/invalid format"); + WARN_MALFORMED_MSG(sd, "spoofed name/invalid format"_s); return AString(); } /* Step beyond the separator. */ @@ -5354,19 +5526,39 @@ AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type) static void clif_parse(Session *s) { - int packet_len = 0, cmd = 0; + // old code: + // no while loop (can hang if more than one packet) + // handles 0x7530 and 0x7532 specially, also 0x0072 + // checks packet length table + // checks rate limiter + // dispatches to actual function, unchecked + // interstitial code: + // introduces while loop + // checks rate limiter + // dispatches to actual function + // if incomplete, unchecks rate limiter + // if error, close socket + // future code: + // hoists while loop + // treats all packets as variable-length, except a hard-coded list + // reads packet of that length unconditionally into a buffer + // does rate-limit check (hoisted?) + // dispatches to actual function + // if error, close socket + dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())); if (!sd || (sd && !sd->state.auth)) { - if (RFIFOREST(s) < 2) - { // too small a packet disconnect - s->set_eof(); - } - if (RFIFOW(s, 0) != 0x72 && RFIFOW(s, 0) != 0x7530) + uint16_t packet_id; + if (!packet_peek_id(s, &packet_id)) + return; + + if (packet_id != 0x0072 && packet_id != 0x7530) { // first packet must be auth or finger s->set_eof(); + return; } } @@ -5375,100 +5567,89 @@ void clif_parse(Session *s) s->set_eof(); return; } - - if (RFIFOREST(s) < 2) - return; // Too small (no packet number) - - cmd = RFIFOW(s, 0); - - // 管理用パケット処理 - if (cmd >= 30000) + if (sd && sd->state.auth == 1 && sd->state.waitingdisconnect == 1) { - switch (cmd) - { - case 0x7530: // Athena情報所得 - WFIFOW(s, 0) = 0x7531; - WFIFO_STRUCT(s, 2, CURRENT_MAP_SERVER_VERSION); - WFIFOSET(s, 10); - RFIFOSKIP(s, 2); - break; - case 0x7532: // 接続の切断 - s->set_eof(); - break; - } + packet_discard(s, packet_avail(s)); return; } - else if (cmd >= 0x200) - return; - // パケット長を計算 - packet_len = clif_parse_func_table[cmd].len; - if (packet_len == VAR) + uint16_t packet_id; + RecvResult rv = RecvResult::Complete; + while (rv == RecvResult::Complete && packet_peek_id(s, &packet_id)) { - if (RFIFOREST(s) < 4) + switch (packet_id) { - return; // Runt packet (variable length without a length sent) + case 0x7530: + { + Packet_Fixed<0x7530> fixed; + rv = recv_fpacket<0x7530, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x7531> fixed_31; + fixed_31.version = CURRENT_MAP_SERVER_VERSION; + send_fpacket<0x7531, 10>(s, fixed_31); + break; + } + case 0x7532: + { + Packet_Fixed<0x7532> fixed; + rv = recv_fpacket<0x7532, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + s->set_eof(); + break; + } } - packet_len = RFIFOW(s, 2); - if (packet_len < 4 || packet_len > 32768) + if (packet_id < 0x0220) { - s->set_eof(); - return; // Runt packet (variable out of bounds) + if (uint16_t len = clif_check_packet_flood(s, packet_id)) + { + // Packet flood: skip packet + packet_discard(s, len); + rv = RecvResult::Complete; + } + else + { + clif_func func = clif_parse_func_table[packet_id].func; + if (!func) + goto unknown_packet; + rv = func(s, sd); + } } + else + goto unknown_packet; } - if (RFIFOREST(s) < packet_len) - { - return; // Runt packet (sent legnth is too small) - } - - if (sd && sd->state.auth == 1 && sd->state.waitingdisconnect == 1) - { // 切断待ちの場合パケットを処理しない - - } - else if (clif_parse_func_table[cmd].func) - { - if (clif_check_packet_flood(s, cmd)) - { - // Flood triggered. Skip packet. - RFIFOSKIP(sd->sess, packet_len); - return; - } + if (rv == RecvResult::Error) + s->set_eof(); + return; - clif_parse_func_table[cmd].func(s, sd); - } - else +unknown_packet: { - // 不明なパケット if (battle_config.error_log) { if (s) - PRINTF("\nclif_parse: session #%d, packet 0x%x, lenght %d\n", - s, cmd, packet_len); -#ifdef DUMP_UNKNOWN_PACKET + PRINTF("\nclif_parse: session #%d, packet 0x%x, lenght %zu\n"_fmt, + s, packet_id, packet_avail(s)); { - int i; - ZString packet_txt = "save/packet.txt"; - PRINTF("---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F"); - for (i = 0; i < packet_len; i++) - { - if ((i & 15) == 0) - PRINTF("\n%04X ", i); - PRINTF("%02X ", RFIFOB(s, i)); - } + ZString packet_txt = "save/packet.txt"_s; if (sd && sd->state.auth) { - PRINTF("\nAccount ID %d, character ID %d, player name %s.\n", + PRINTF("Unknown packet: Account ID %d, character ID %d, player name %s.\n"_fmt, sd->status_key.account_id, sd->status_key.char_id, sd->status_key.name); } else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified) - PRINTF("\nAccount ID %d.\n", sd->bl_id); + PRINTF("Unkonwn packet (unauthenticated): Account ID %d.\n"_fmt, sd->bl_id); + else + PRINTF("Unknown packet (unknown)\n"_fmt); io::AppendFile fp(packet_txt); if (!fp.is_open()) { - PRINTF("clif.c: cant write [%s] !!! data is lost !!!\n", + PRINTF("clif.c: cant write [%s] !!! data is lost !!!\n"_fmt, packet_txt); return; } @@ -5479,34 +5660,29 @@ void clif_parse(Session *s) if (sd && sd->state.auth) { FPRINTF(fp, - "%s\nPlayer with account ID %d (character ID %d, player name %s) sent wrong packet:\n", + "%s\nPlayer with account ID %d (character ID %d, player name %s) sent wrong packet:\n"_fmt, now, sd->status_key.account_id, sd->status_key.char_id, sd->status_key.name); } else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified) FPRINTF(fp, - "%s\nPlayer with account ID %d sent wrong packet:\n", + "%s\nUnauthenticated player with account ID %d sent wrong packet:\n"_fmt, now, sd->bl_id); + else + FPRINTF(fp, + "%s\nUnknown connection sent wrong packet:\n"_fmt, + now); - FPRINTF(fp, - "\t---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F"); - for (i = 0; i < packet_len; i++) - { - if ((i & 15) == 0) - FPRINTF(fp, "\n\t%04X ", i); - FPRINTF(fp, "%02X ", RFIFOB(s, i)); - } - FPRINTF(fp, "\n\n"); + packet_dump(fp, s); } } -#endif } } - RFIFOSKIP(s, packet_len); } void do_init_clif(void) { - make_listen_port(map_port, SessionParsers{func_parse: clif_parse, func_delete: clif_delete}); + make_listen_port(map_port, SessionParsers{.func_parse= clif_parse, .func_delete= clif_delete}); } +} // namespace tmwa diff --git a/src/map/clif.hpp b/src/map/clif.hpp index 1fdd67c..adb4889 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_CLIF_HPP -#define TMWA_MAP_CLIF_HPP +#pragma once // clif.hpp - Network interface to the client. // // Copyright © ????-2004 Athena Dev Teams @@ -21,22 +20,29 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "clif.t.hpp" +#include "clif.t.hpp" -# include <functional> +#include <functional> -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "../mmo/ip.hpp" -# include "../mmo/timer.t.hpp" +#include "../generic/fwd.hpp" -# include "battle.t.hpp" -# include "map.hpp" -# include "pc.t.hpp" -# include "skill.t.hpp" +#include "../net/timer.t.hpp" +#include "../mmo/fwd.hpp" +#include "../mmo/mmo.hpp" + +#include "battle.t.hpp" +#include "map.t.hpp" +#include "pc.t.hpp" +#include "skill.t.hpp" + + +namespace tmwa +{ void clif_setip(IP4Address); void clif_setport(int); @@ -47,16 +53,16 @@ void clif_setwaitclose(Session *); int clif_authok(dumb_ptr<map_session_data>); int clif_authfail_fd(Session *, int); -int clif_charselectok(int); +int clif_charselectok(BlockId); int clif_dropflooritem(dumb_ptr<flooritem_data>); int clif_clearflooritem(dumb_ptr<flooritem_data>, Session *); int clif_clearchar(dumb_ptr<block_list>, BeingRemoveWhy); // area or fd int clif_clearchar_delay(tick_t, dumb_ptr<block_list>, BeingRemoveWhy); -void clif_clearchar_id(int, BeingRemoveWhy, Session *); +void clif_clearchar_id(BlockId, BeingRemoveWhy, Session *); int clif_spawnpc(dumb_ptr<map_session_data>); //area int clif_spawnnpc(dumb_ptr<npc_data>); // area int clif_spawn_fake_npc_for_player(dumb_ptr<map_session_data> sd, - int fake_npc_id); + BlockId fake_npc_id); int clif_spawnmob(dumb_ptr<mob_data>); // area int clif_walkok(dumb_ptr<map_session_data>); // self int clif_movechar(dumb_ptr<map_session_data>); // area @@ -66,18 +72,18 @@ void clif_changemapserver(dumb_ptr<map_session_data>, MapName, int, int, IP4Addr void clif_fixpos(dumb_ptr<block_list>); // area int clif_fixmobpos(dumb_ptr<mob_data> md); int clif_fixpcpos(dumb_ptr<map_session_data> sd); -int clif_npcbuysell(dumb_ptr<map_session_data>, int); //self +int clif_npcbuysell(dumb_ptr<map_session_data>, BlockId); //self int clif_buylist(dumb_ptr<map_session_data>, dumb_ptr<npc_data_shop>); //self int clif_selllist(dumb_ptr<map_session_data>); //self -void clif_scriptmes(dumb_ptr<map_session_data>, int, XString); //self -void clif_scriptnext(dumb_ptr<map_session_data>, int); //self -void clif_scriptclose(dumb_ptr<map_session_data>, int); //self -void clif_scriptmenu(dumb_ptr<map_session_data>, int, XString); //self -void clif_scriptinput(dumb_ptr<map_session_data>, int); //self -void clif_scriptinputstr(dumb_ptr<map_session_data> sd, int npcid); // self -void clif_viewpoint(dumb_ptr<map_session_data>, int, int, int, int, int, int); //self -int clif_additem(dumb_ptr<map_session_data>, int, int, PickupFail); //self -void clif_delitem(dumb_ptr<map_session_data>, int, int); //self +void clif_scriptmes(dumb_ptr<map_session_data>, BlockId, XString); //self +void clif_scriptnext(dumb_ptr<map_session_data>, BlockId); //self +void clif_scriptclose(dumb_ptr<map_session_data>, BlockId); //self +void clif_scriptmenu(dumb_ptr<map_session_data>, BlockId, XString); //self +void clif_scriptinput(dumb_ptr<map_session_data>, BlockId); //self +void clif_scriptinputstr(dumb_ptr<map_session_data> sd, BlockId npcid); // self + +int clif_additem(dumb_ptr<map_session_data>, IOff0, int, PickupFail); //self +void clif_delitem(dumb_ptr<map_session_data>, IOff0, int); //self int clif_updatestatus(dumb_ptr<map_session_data>, SP); //self int clif_damage(dumb_ptr<block_list>, dumb_ptr<block_list>, tick_t, interval_t, interval_t, @@ -89,14 +95,14 @@ int clif_takeitem(dumb_ptr<block_list> src, dumb_ptr<block_list> dst) } int clif_changelook(dumb_ptr<block_list>, LOOK, int); // area void clif_changelook_accessories(dumb_ptr<block_list> bl, dumb_ptr<map_session_data> dst); // area or target; list gloves, boots etc. -int clif_arrowequip(dumb_ptr<map_session_data> sd, int val); //self +int clif_arrowequip(dumb_ptr<map_session_data> sd, IOff0 val); //self int clif_arrow_fail(dumb_ptr<map_session_data> sd, int type); //self int clif_statusupack(dumb_ptr<map_session_data>, SP, int, int); // self -int clif_equipitemack(dumb_ptr<map_session_data>, int, EPOS, int); // self -int clif_unequipitemack(dumb_ptr<map_session_data>, int, EPOS, int); // self +int clif_equipitemack(dumb_ptr<map_session_data>, IOff0, EPOS, int); // self +int clif_unequipitemack(dumb_ptr<map_session_data>, IOff0, EPOS, int); // self int clif_misceffect(dumb_ptr<block_list>, int); // area int clif_changeoption(dumb_ptr<block_list>); // area -int clif_useitemack(dumb_ptr<map_session_data>, int, int, int); // self +int clif_useitemack(dumb_ptr<map_session_data>, IOff0, int, int); // self void clif_emotion(dumb_ptr<block_list> bl, int type); void clif_sitting(Session *, dumb_ptr<map_session_data> sd); @@ -105,22 +111,22 @@ void clif_sitting(Session *, dumb_ptr<map_session_data> sd); void clif_traderequest(dumb_ptr<map_session_data> sd, CharName name); void clif_tradestart(dumb_ptr<map_session_data> sd, int type); void clif_tradeadditem(dumb_ptr<map_session_data> sd, - dumb_ptr<map_session_data> tsd, int index, int amount); -int clif_tradeitemok(dumb_ptr<map_session_data> sd, int index, int amount, + dumb_ptr<map_session_data> tsd, IOff2 index2, int amount); +int clif_tradeitemok(dumb_ptr<map_session_data> sd, IOff2 index, int amount, int fail); int clif_tradedeal_lock(dumb_ptr<map_session_data> sd, int fail); int clif_tradecancelled(dumb_ptr<map_session_data> sd); int clif_tradecompleted(dumb_ptr<map_session_data> sd, int fail); // storage -int clif_storageitemlist(dumb_ptr<map_session_data> sd, struct storage *stor); +int clif_storageitemlist(dumb_ptr<map_session_data> sd, Storage *stor); int clif_storageequiplist(dumb_ptr<map_session_data> sd, - struct storage *stor); + Storage *stor); int clif_updatestorageamount(dumb_ptr<map_session_data> sd, - struct storage *stor); -int clif_storageitemadded(dumb_ptr<map_session_data> sd, struct storage *stor, - int index, int amount); -int clif_storageitemremoved(dumb_ptr<map_session_data> sd, int index, + Storage *stor); +int clif_storageitemadded(dumb_ptr<map_session_data> sd, Storage *stor, + SOff0 index, int amount); +int clif_storageitemremoved(dumb_ptr<map_session_data> sd, SOff0 index, int amount); int clif_storageclose(dumb_ptr<map_session_data> sd); @@ -157,17 +163,17 @@ int clif_movetoattack(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> bl); // party int clif_party_created(dumb_ptr<map_session_data> sd, int flag); -int clif_party_info(struct party *p, Session *s); +int clif_party_info(PartyPair p, Session *s); void clif_party_invite(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd); void clif_party_inviteack(dumb_ptr<map_session_data> sd, CharName nick, int flag); -void clif_party_option(struct party *p, dumb_ptr<map_session_data> sd, +void clif_party_option(PartyPair p, dumb_ptr<map_session_data> sd, int flag); -void clif_party_leaved(struct party *p, dumb_ptr<map_session_data> sd, - int account_id, CharName name, int flag); -void clif_party_message(struct party *p, int account_id, XString mes); -int clif_party_xy(struct party *p, dumb_ptr<map_session_data> sd); -int clif_party_hp(struct party *p, dumb_ptr<map_session_data> sd); +void clif_party_leaved(PartyPair p, dumb_ptr<map_session_data> sd, + AccountId account_id, CharName name, int flag); +void clif_party_message(PartyPair p, AccountId account_id, XString mes); +int clif_party_xy(PartyPair p, dumb_ptr<map_session_data> sd); +int clif_party_hp(PartyPair p, dumb_ptr<map_session_data> sd); // atcommand void clif_displaymessage(Session *s, XString mes); @@ -183,5 +189,4 @@ int clif_GM_kick(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd, int clif_foreachclient(std::function<void(dumb_ptr<map_session_data>)>); void do_init_clif(void); - -#endif // TMWA_MAP_CLIF_HPP +} // namespace tmwa diff --git a/src/map/clif.t.hpp b/src/map/clif.t.hpp index 5cb06ad..1789ee8 100644 --- a/src/map/clif.t.hpp +++ b/src/map/clif.t.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_CLIF_T_HPP -#define TMWA_MAP_CLIF_T_HPP +#pragma once // clif.t.hpp - Network interface to the client. // // Copyright © ????-2004 Athena Dev Teams @@ -21,9 +20,99 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdint> +#include <cstdint> + +#include "../ints/little.hpp" + +#include "../compat/iter.hpp" + +#include "../generic/enum.hpp" + +#include "../mmo/consts.hpp" +#include "../mmo/enums.hpp" + + +namespace tmwa +{ +namespace e +{ +// [Fate] status.option properties. These are persistent status changes. +// IDs that are not listed are not used in the code (to the best of my knowledge) +enum class Option : uint16_t +{ + ZERO = 0x0000, + + // [Fate] This is the GM `@hide' flag + HIDE = 0x0040, + // [Fate] Complete invisibility to other clients + INVISIBILITY = 0x1000, + + // ? + REAL_ANY_HIDE = HIDE, +}; +enum class Opt1 : uint16_t +{ + ZERO = 0, + _stone1 = 1, + _freeze = 2, + _stan = 3, + _sleep = 4, + _stone6 = 6, +}; +enum class Opt2 : uint16_t +{ + ZERO = 0x0000, + _poison = 0x0001, + _curse = 0x0002, + _silence = 0x0004, + BLIND = 0x0010, + _speedpotion0 = 0x0020, + _signumcrucis = 0x0040, + _atkpot = 0x0080, + _heal = 0x0100, + _slowpoison = 0x0200, +}; +enum class Opt3 : uint16_t +{ + ZERO = 0x0000, + _concentration = 0x0001, + _overthrust = 0x0002, + _energycoat = 0x0004, + _explosionspirits = 0x0008, + _steelbody = 0x0010, + _berserk = 0x0080, + + _marionette = 0x0400, + _assumptio = 0x0800, +}; + +ENUM_BITWISE_OPERATORS(Option) +ENUM_BITWISE_OPERATORS(Opt2) +ENUM_BITWISE_OPERATORS(Opt3) +} +using e::Option; +using e::Opt1; +using e::Opt2; +using e::Opt3; + + +enum class ItemType : uint8_t +{ + USE = 0, // in eA, healing only + _1 = 1, // unused + _2 = 2, // in eA, other usable items + JUNK = 3, // "useless" items (e.g. quests) + WEAPON = 4, // all weapons + ARMOR = 5, // all other equipment + _6 = 6, // in eA, card + _7 = 7, // in eA, pet egg + _8 = 8, // in eA, pet equipment + _9 = 9, // unused + ARROW = 10, // ammo + _11 = 11, // in eA, delayed use (special script) +}; enum class BeingRemoveWhy : uint8_t { @@ -40,4 +129,589 @@ enum class BeingRemoveWhy : uint8_t NEGATIVE1 = 0xff, }; -#endif // TMWA_MAP_CLIF_T_HPP +enum class PickupFail : uint8_t +{ + OKAY = 0, + BAD_ITEM = 1, + TOO_HEAVY = 2, + TOO_FAR = 3, + INV_FULL = 4, + STACK_FULL = 5, + DROP_STEAL = 6, +}; + +// this is used for both input and output +// different values are valid in 0x0089 vs 0x008a +enum class DamageType : uint8_t +{ + NORMAL = 0x00, + TAKEITEM = 0x01, + SIT = 0x02, + STAND = 0x03, + RETURNED = 0x04, + CONTINUOUS = 0x07, + DOUBLED = 0x08, + CRITICAL = 0x0a, + FLEE2 = 0x0b, +}; + +enum class LOOK : uint8_t +{ + BASE = 0, + HAIR = 1, + WEAPON = 2, + HEAD_BOTTOM = 3, + HEAD_TOP = 4, + HEAD_MID = 5, + HAIR_COLOR = 6, + CLOTHES_COLOR = 7, + SHIELD = 8, + SHOES = 9, + GLOVES = 10, + CAPE = 11, + MISC1 = 12, + MISC2 = 13, + + COUNT, +}; + +// Note: there is also a typedef by this name in <dirent.h> +// but we should be fine since we never include it. +// (in the long term we should still rename this though) +enum class DIR : uint8_t +{ + S = 0, + SW = 1, + W = 2, + NW = 3, + N = 4, + NE = 5, + E = 6, + SE = 7, + + COUNT, +}; + +constexpr +earray<int, DIR, DIR::COUNT> dirx //= +{{ + 0, -1, -1, -1, 0, 1, 1, 1, +}}, diry //= +{{ + 1, 1, 0, -1, -1, -1, 0, 1, +}}; + +constexpr +bool dir_is_diagonal(DIR d) +{ + return static_cast<uint8_t>(d) & 1; +} + + +enum class SP : uint16_t +{ + // sent to client + SPEED = 0, + + // when used as "no stat" + ZERO = 0, + + // sent to client + BASEEXP = 1, + // sent to client + JOBEXP = 2, +#if 0 + KARMA = 3, +#endif + + // sent to client + HP = 5, + // sent to client + MAXHP = 6, + // sent to client + SP = 7, + // sent to client + MAXSP = 8, + // sent to client + STATUSPOINT = 9, + + // sent to client + BASELEVEL = 11, + // sent to client + SKILLPOINT = 12, + // sent to client + STR = 13, + // sent to client + AGI = 14, + // sent to client + VIT = 15, + // sent to client + INT = 16, + // sent to client + DEX = 17, + // sent to client + LUK = 18, + CLASS = 19, + // sent to client + ZENY = 20, + SEX = 21, + // sent to client + NEXTBASEEXP = 22, + // sent to client + NEXTJOBEXP = 23, + // sent to client + WEIGHT = 24, + // sent to client + MAXWEIGHT = 25, + + // sent to client + USTR = 32, + // sent to client + UAGI = 33, + // sent to client + UVIT = 34, + // sent to client + UINT = 35, + // sent to client + UDEX = 36, + // sent to client + ULUK = 37, + + // sent to client + ATK1 = 41, + // sent to client + ATK2 = 42, + // sent to client + MATK1 = 43, + // sent to client + MATK2 = 44, + // sent to client + DEF1 = 45, + // sent to client + DEF2 = 46, + // sent to client + MDEF1 = 47, + // sent to client + MDEF2 = 48, + // sent to client + HIT = 49, + // sent to client + FLEE1 = 50, + // sent to client + FLEE2 = 51, + // sent to client + CRITICAL = 52, + // sent to client + ASPD = 53, + + // sent to client + JOBLEVEL = 55, + +#if 0 + PARTNER = 57, + CART = 58, + FAME = 59, + UNBREAKABLE = 60, +#endif + + DEAF = 70, + + // sent to client + GM = 500, + + // sent to client + ATTACKRANGE = 1000, +#if 0 + ATKELE = 1001, +#endif +#if 0 + DEFELE = 1002, +#endif +#if 0 + CASTRATE = 1003, +#endif + MAXHPRATE = 1004, +#if 0 + MAXSPRATE = 1005, +#endif +#if 0 + SPRATE = 1006, +#endif + +#if 0 + ADDEFF = 1012, +#endif +#if 0 + RESEFF = 1013, +#endif + BASE_ATK = 1014, + ASPD_RATE = 1015, + HP_RECOV_RATE = 1016, +#if 0 + SP_RECOV_RATE = 1017, +#endif +#if 0 + SPEED_RATE = 1018, +#endif + CRITICAL_DEF = 1019, +#if 0 + NEAR_ATK_DEF = 1020, +#endif +#if 0 + LONG_ATK_DEF = 1021, +#endif +#if 0 + DOUBLE_RATE = 1022, +#endif + DOUBLE_ADD_RATE = 1023, +#if 0 + MATK = 1024, +#endif +#if 0 + MATK_RATE = 1025, +#endif +#if 0 + IGNORE_DEF_ELE = 1026, +#endif +#if 0 + IGNORE_DEF_RACE = 1027, +#endif +#if 0 + ATK_RATE = 1028, +#endif + SPEED_ADDRATE = 1029, +#if 0 + ASPD_ADDRATE = 1030, +#endif +#if 0 + MAGIC_ATK_DEF = 1031, +#endif +#if 0 + MISC_ATK_DEF = 1032, +#endif +#if 0 + IGNORE_MDEF_ELE = 1033, +#endif +#if 0 + IGNORE_MDEF_RACE = 1034, +#endif + +#if 0 + PERFECT_HIT_RATE = 1038, +#endif +#if 0 + PERFECT_HIT_ADD_RATE = 1039, +#endif +#if 0 + CRITICAL_RATE = 1040, +#endif +#if 0 + GET_ZENY_NUM = 1041, +#endif +#if 0 + ADD_GET_ZENY_NUM = 1042, +#endif + +#if 0 + ADD_MONSTER_DROP_ITEM = 1047, +#endif +#if 0 + DEF_RATIO_ATK_ELE = 1048, +#endif +#if 0 + DEF_RATIO_ATK_RACE = 1049, +#endif +#if 0 + ADD_SPEED = 1050, +#endif +#if 0 + HIT_RATE = 1051, +#endif +#if 0 + FLEE_RATE = 1052, +#endif +#if 0 + FLEE2_RATE = 1053, +#endif + DEF_RATE = 1054, + DEF2_RATE = 1055, +#if 0 + MDEF_RATE = 1056, +#endif +#if 0 + MDEF2_RATE = 1057, +#endif +#if 0 + SPLASH_RANGE = 1058, +#endif +#if 0 + SPLASH_ADD_RANGE = 1059, +#endif + + HP_DRAIN_RATE = 1061, +#if 0 + SP_DRAIN_RATE = 1062, +#endif +#if 0 + SHORT_WEAPON_DAMAGE_RETURN = 1063, +#endif +#if 0 + LONG_WEAPON_DAMAGE_RETURN = 1064, +#endif + +#if 0 + ADDEFF2 = 1067, +#endif + BREAK_WEAPON_RATE = 1068, + BREAK_ARMOR_RATE = 1069, + ADD_STEAL_RATE = 1070, + MAGIC_DAMAGE_RETURN = 1071, +#if 0 + RANDOM_ATTACK_INCREASE = 1072, +#endif +}; + +constexpr +SP attr_to_sp(ATTR attr) +{ + return static_cast<SP>(static_cast<uint16_t>(attr) + static_cast<uint16_t>(SP::STR)); +} + +constexpr +ATTR sp_to_attr(SP sp) +{ + return static_cast<ATTR>(static_cast<uint16_t>(sp) - static_cast<uint16_t>(SP::STR)); +} + +constexpr +SP attr_to_usp(ATTR attr) +{ + return static_cast<SP>(static_cast<uint16_t>(attr) + static_cast<uint16_t>(SP::USTR)); +} + +constexpr +ATTR usp_to_attr(SP sp) +{ + return static_cast<ATTR>(static_cast<uint16_t>(sp) - static_cast<uint16_t>(SP::USTR)); +} + +constexpr +SP sp_to_usp(SP sp) +{ + return attr_to_usp(sp_to_attr(sp)); +} + +constexpr +SP usp_to_sp(SP sp) +{ + return attr_to_sp(usp_to_attr(sp)); +} + + +// xxxx xxxx xxyy yyyy yyyy dddd +struct NetPosition1 +{ + Byte data[3]; +}; + +struct Position1 +{ + uint16_t x, y; + DIR dir; +}; + +inline +bool native_to_network(NetPosition1 *network, Position1 native) +{ + uint16_t x = native.x; + uint16_t y = native.y; + uint8_t d = static_cast<uint8_t>(native.dir); + + uint8_t *p = reinterpret_cast<uint8_t *>(network); + p[0] = x >> 2; + p[1] = (x << 6) | ((y >> 4) & 0x3f); + p[2] = y << 4 | d; + + return x < 1024 && y < 1024 && d < 16; +} + +inline +bool network_to_native(Position1 *native, NetPosition1 network) +{ + const uint8_t *p = reinterpret_cast<const uint8_t *>(&network); + native->x = (p[0] & (0x3ff >> 2)) << 2 | p[1] >> (8 - 2); + native->y = (p[1] & (0x3ff >> 4)) << 4 | p[2] >> (8 - 4); + uint8_t d = p[2] & 0x0f; + native->dir = static_cast<DIR>(d); + return d < 8; +} + +// x0xx xxxx xxy0 yyyy yyyy x1xx xxxx xxy1 yyyy yyyy +struct NetPosition2 +{ + Byte data[5]; +}; + +struct Position2 +{ + uint16_t x0, y0; + uint16_t x1, y1; +}; + +inline +bool native_to_network(NetPosition2 *network, Position2 native) +{ + uint16_t x0 = native.x0; + uint16_t y0 = native.y0; + uint16_t x1 = native.x1; + uint16_t y1 = native.y1; + + uint8_t *p = reinterpret_cast<uint8_t *>(network); + p[0] = x0 >> 2; + p[1] = (x0 << 6) | ((y0 >> 4) & 0x3f); + p[2] = (y0 << 4) | ((x1 >> 6) & 0x0f); + p[3] = (x1 << 2) | ((y1 >> 8) & 0x03); + p[4] = y1; + + return x0 < 1024 && y0 < 1024 && x1 < 1024 && y1 < 1024; +} + +inline +bool network_to_native(Position2 *native, NetPosition2 network) +{ + const uint8_t *p = reinterpret_cast<const uint8_t *>(&network); + native->x0 = (p[0] & (0x3ff >> 2)) << 2 | p[1] >> (8 - 2); + native->y0 = (p[1] & (0x3ff >> 4)) << 4 | p[2] >> (8 - 4); + native->x1 = (p[2] & (0x3ff >> 6)) << 6 | p[3] >> (8 - 6); + native->y1 = (p[3] & (0x3ff >> 8)) << 8 | p[4] >> (8 - 8); + return true; +} + +struct IOff2; +struct SOff1; + +struct IOff0 +{ + uint16_t index; + + bool ok() const + { return get0() < MAX_INVENTORY; } + uint16_t get0() const + { return index; } + static IOff0 from(uint16_t i) + { return IOff0{i}; } + static IteratorPair<ValueIterator<IOff0>> iter() + { return {IOff0::from(0), IOff0::from(MAX_INVENTORY)}; } + friend uint16_t convert_for_printf(IOff0 i0) { return i0.index; } + + IOff0& operator ++() { ++index; return *this; } + friend bool operator == (IOff0 l, IOff0 r) { return l.index == r.index; } + friend bool operator != (IOff0 l, IOff0 r) { return !(l == r); } + IOff2 shift() const; + + IOff0() : index(0) {} +private: + explicit IOff0(uint16_t i) : index(i) {} +}; + +struct SOff0 +{ + uint16_t index; + + bool ok() const + { return get0() < MAX_STORAGE; } + uint16_t get0() const + { return index; } + static SOff0 from(uint16_t i) + { return SOff0{i}; } + static IteratorPair<ValueIterator<SOff0>> iter() + { return {SOff0::from(0), SOff0::from(MAX_STORAGE)}; } + friend uint16_t convert_for_printf(SOff0 s0) { return s0.index; } + + SOff0& operator ++() { ++index; return *this; } + friend bool operator == (SOff0 l, SOff0 r) { return l.index == r.index; } + friend bool operator != (SOff0 l, SOff0 r) { return !(l == r); } + SOff1 shift() const; + + SOff0() : index(0) {} +private: + explicit SOff0(uint16_t i) : index(i) {} +}; + +struct IOff2 +{ + uint16_t index; + + bool ok() const + { return get2() < MAX_INVENTORY; } + uint16_t get2() const + { return index - 2; } + static IOff2 from(uint16_t i) + { return IOff2{static_cast<uint16_t>(i + 2)}; } + static IteratorPair<ValueIterator<IOff2>> iter() + { return {IOff2::from(0), IOff2::from(MAX_INVENTORY)}; } + + IOff2& operator ++() { ++index; return *this; } + friend bool operator == (IOff2 l, IOff2 r) { return l.index == r.index; } + friend bool operator != (IOff2 l, IOff2 r) { return !(l == r); } + IOff0 unshift() const + { return IOff0::from(get2()); } + + IOff2() : index(0) {} +private: + explicit IOff2(uint16_t i) : index(i) {} +}; + +struct SOff1 +{ + uint16_t index; + + bool ok() const + { return get1() < MAX_STORAGE; } + uint16_t get1() const + { return index - 1; } + static SOff1 from(uint16_t i) + { return SOff1{static_cast<uint16_t>(i + 1)}; } + static IteratorPair<ValueIterator<SOff1>> iter() + { return {SOff1::from(0), SOff1::from(MAX_STORAGE)}; } + + SOff1& operator ++() { ++index; return *this; } + friend bool operator == (SOff1 l, SOff1 r) { return l.index == r.index; } + friend bool operator != (SOff1 l, SOff1 r) { return !(l == r); } + SOff0 unshift() const + { return SOff0::from(get1()); } + + SOff1() : index(0) {} +private: + explicit SOff1(uint16_t i) : index(i) {} +}; + +inline IOff2 IOff0::shift() const +{ return IOff2::from(get0()); } +inline SOff1 SOff0::shift() const +{ return SOff1::from(get0()); } + +inline +bool native_to_network(Little16 *network, IOff2 native) +{ + return native_to_network(network, native.index); +} + +inline +bool network_to_native(IOff2 *native, Little16 network) +{ + return network_to_native(&native->index, network); +} + +inline +bool native_to_network(Little16 *network, SOff1 native) +{ + return native_to_network(network, native.index); +} + +inline +bool network_to_native(SOff1 *native, Little16 network) +{ + return network_to_native(&native->index, network); +} +} // namespace tmwa diff --git a/src/map/fwd.hpp b/src/map/fwd.hpp new file mode 100644 index 0000000..fe66b15 --- /dev/null +++ b/src/map/fwd.hpp @@ -0,0 +1,57 @@ +#pragma once +// map/fwd.hpp - list of type names for map server +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +// meh, add more when I feel like it +class BlockId; +struct block_list; +struct map_session_data; +struct npc_data; +struct mob_data; +struct flooritem_data; +struct invocation; +struct map_local; +class npc_data_script; +class npc_data_shop; +class npc_data_warp; +class npc_data_message; +struct NpcEvent; + +struct item_data; + +// magic +struct fun_t; +struct op_t; +struct expr_t; +struct val_t; +struct location_t; +struct area_t; +struct spell_t; +struct invocation; +struct teleport_anchor_t; +struct env_t; +struct magic_conf_t; +struct component_t; +struct effect_set_t; +} // namespace tmwa diff --git a/src/map/grfio.cpp b/src/map/grfio.cpp index c3d1e40..4a1656b 100644 --- a/src/map/grfio.cpp +++ b/src/map/grfio.cpp @@ -20,28 +20,29 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <sys/stat.h> - #include <fcntl.h> #include <unistd.h> #include <cassert> -#include <cstdio> -#include <cstring> #include <map> #include "../strings/mstring.hpp" #include "../strings/rstring.hpp" #include "../strings/astring.hpp" +#include "../strings/zstring.hpp" #include "../io/cxxstdio.hpp" #include "../io/read.hpp" #include "../mmo/extract.hpp" +#include "../mmo/mmo.hpp" #include "../poison.hpp" + +namespace tmwa +{ static std::map<MapName, RString> resnametable; @@ -50,7 +51,7 @@ bool load_resnametable(ZString filename) io::ReadFile in(filename); if (!in.is_open()) { - FPRINTF(stderr, "Missing %s\n", filename); + FPRINTF(stderr, "Missing %s\n"_fmt, filename); return false; } @@ -63,7 +64,7 @@ bool load_resnametable(ZString filename) if (!extract(line, record<'#'>(&key, &value))) { - PRINTF("Bad resnametable line: %s\n", line); + PRINTF("Bad resnametable line: %s\n"_fmt, line); rv = false; continue; } @@ -85,7 +86,7 @@ std::vector<uint8_t> grfio_reads(MapName rname) { MString lfname_; // TODO ... instead of here - lfname_ += "data/"; + lfname_ += "data/"_s; lfname_ += grfio_resnametable(rname); AString lfname = AString(lfname_); @@ -93,7 +94,7 @@ std::vector<uint8_t> grfio_reads(MapName rname) int fd = open(lfname.c_str(), O_RDONLY); if (fd == -1) { - FPRINTF(stderr, "Resource %s (file %s) not found\n", + FPRINTF(stderr, "Resource %s (file %s) not found\n"_fmt, rname, lfname); return {}; } @@ -105,3 +106,4 @@ std::vector<uint8_t> grfio_reads(MapName rname) close(fd); return buffer; } +} // namespace tmwa diff --git a/src/map/grfio.hpp b/src/map/grfio.hpp index 9b6d5e2..d2ab058 100644 --- a/src/map/grfio.hpp +++ b/src/map/grfio.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_GRFIO_HPP -#define TMWA_MAP_GRFIO_HPP +#pragma once // grfio.hpp - Don't read GRF files, just name-map .wlk files. // // Copyright © ????-2004 Athena Dev Teams @@ -21,19 +20,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdint> +#include <cstdint> -# include <vector> +#include <vector> -# include "../mmo/mmo.hpp" +#include "../strings/fwd.hpp" +#include "../mmo/fwd.hpp" + + +namespace tmwa +{ bool load_resnametable(ZString filename); /// Load a resource into memory, subject to data/resnametable.txt. /// Normally, resourcename is xxx-y.gat and the file is xxx-y.wlk. /// Currently there is exactly one .wlk per .gat, but multiples are fine. std::vector<uint8_t> grfio_reads(MapName resourcename); - -#endif // TMWA_MAP_GRFIO_HPP +} // namespace tmwa diff --git a/src/map/intif.cpp b/src/map/intif.cpp index 2cae2ad..314db24 100644 --- a/src/map/intif.cpp +++ b/src/map/intif.cpp @@ -20,18 +20,21 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <cstdlib> -#include <cstring> - #include "../compat/nullpo.hpp" #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" +#include "../strings/literal.hpp" #include "../io/cxxstdio.hpp" -#include "../mmo/socket.hpp" +#include "../net/packets.hpp" +#include "../net/socket.hpp" + +#include "../mmo/mmo.hpp" + +#include "../proto2/char-map.hpp" #include "battle.hpp" #include "chrif.hpp" @@ -43,32 +46,19 @@ #include "../poison.hpp" -static -const int packet_len_table[] = -{ - -1, -1, 27, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 7, 0, 0, 0, 0, 0, 0, -1, 11, 0, 0, 0, 0, 0, 0, - 35, -1, 11, 15, 34, 29, 7, -1, 0, 0, 0, 0, 0, 0, 0, 0, - 10, -1, 15, 0, 79, 19, 7, -1, 0, -1, -1, -1, 14, 67, 186, -1, - 9, 9, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 11, -1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - +namespace tmwa +{ //----------------------------------------------------------------- // inter serverへの送信 // Message for all GMs on all map servers void intif_GMmessage(XString mes) { - WFIFOW(char_session, 0) = 0x3000; - size_t len = mes.size() + 1; - WFIFOW(char_session, 2) = 4 + len; - WFIFO_STRING(char_session, 4, mes, len); - WFIFOSET(char_session, WFIFOW(char_session, 2)); + if (!char_session) + return; + + send_packet_repeatonly<0x3000, 4, 1>(char_session, mes); } // The transmission of Wisp/Page to inter-server (player not found on this server) @@ -76,65 +66,69 @@ void intif_wis_message(dumb_ptr<map_session_data> sd, CharName nick, ZString mes { nullpo_retv(sd); - size_t mes_len = mes.size() + 1; - WFIFOW(char_session, 0) = 0x3001; - WFIFOW(char_session, 2) = mes_len + 52; - WFIFO_STRING(char_session, 4, sd->status_key.name.to__actual(), 24); - WFIFO_STRING(char_session, 28, nick.to__actual(), 24); - WFIFO_STRING(char_session, 52, mes, mes_len); - WFIFOSET(char_session, WFIFOW(char_session, 2)); + if (!char_session) + return; + + Packet_Head<0x3001> head_01; + head_01.from_char_name = sd->status_key.name; + head_01.to_char_name = nick; + send_vpacket<0x3001, 52, 1>(char_session, head_01, mes); if (battle_config.etc_log) - PRINTF("intif_wis_message from %s to %s)\n", + PRINTF("intif_wis_message from %s to %s)\n"_fmt, sd->status_key.name, nick); } // The reply of Wisp/page static -void intif_wis_replay(int id, int flag) +void intif_wis_replay(CharId id, int flag) { - WFIFOW(char_session, 0) = 0x3002; - WFIFOL(char_session, 2) = id; - WFIFOB(char_session, 6) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - WFIFOSET(char_session, 7); + if (!char_session) + return; + + Packet_Fixed<0x3002> fixed_02; + fixed_02.char_id = id; + fixed_02.flag = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + send_fpacket<0x3002, 7>(char_session, fixed_02); if (battle_config.etc_log) - PRINTF("intif_wis_replay: id: %d, flag:%d\n", id, flag); + PRINTF("intif_wis_replay: id: %d, flag:%d\n"_fmt, id, flag); } // The transmission of GM only Wisp/Page from server to inter-server -void intif_wis_message_to_gm(CharName Wisp_name, int min_gm_level, ZString mes) +void intif_wis_message_to_gm(CharName Wisp_name, GmLevel min_gm_level, ZString mes) { - size_t mes_len = mes.size() + 1; - WFIFOW(char_session, 0) = 0x3003; - WFIFOW(char_session, 2) = mes_len + 30; - WFIFO_STRING(char_session, 4, Wisp_name.to__actual(), 24); - WFIFOW(char_session, 28) = min_gm_level; - WFIFO_STRING(char_session, 30, mes, mes_len); - WFIFOSET(char_session, WFIFOW(char_session, 2)); + if (!char_session) + return; + + Packet_Head<0x3003> head_03; + head_03.char_name = Wisp_name; + head_03.min_gm_level = min_gm_level; + send_vpacket<0x3003, 30, 1>(char_session, head_03, mes); if (battle_config.etc_log) - PRINTF("intif_wis_message_to_gm: from: '%s', min level: %d, message: '%s'.\n", + PRINTF("intif_wis_message_to_gm: from: '%s', min level: %d, message: '%s'.\n"_fmt, Wisp_name, min_gm_level, mes); } // アカウント変数送信 void intif_saveaccountreg(dumb_ptr<map_session_data> sd) { - int j, p; - nullpo_retv(sd); + if (!char_session) + return; + assert (sd->status.account_reg_num < ACCOUNT_REG_NUM); - WFIFOW(char_session, 0) = 0x3004; - WFIFOL(char_session, 4) = sd->bl_id; - for (j = 0, p = 8; j < sd->status.account_reg_num; j++, p += 36) + Packet_Head<0x3004> head_04; + head_04.account_id = block_to_account(sd->bl_id); + std::vector<Packet_Repeat<0x3004>> repeat_04(sd->status.account_reg_num); + for (size_t j = 0; j < sd->status.account_reg_num; j++) { - WFIFO_STRING(char_session, p, sd->status.account_reg[j].str, 32); - WFIFOL(char_session, p + 32) = sd->status.account_reg[j].value; + repeat_04[j].name = sd->status.account_reg[j].str; + repeat_04[j].value = sd->status.account_reg[j].value; } - WFIFOW(char_session, 2) = p; - WFIFOSET(char_session, p); + send_vpacket<0x3004, 8, 36>(char_session, head_04, repeat_04); } // アカウント変数要求 @@ -142,28 +136,36 @@ void intif_request_accountreg(dumb_ptr<map_session_data> sd) { nullpo_retv(sd); - WFIFOW(char_session, 0) = 0x3005; - WFIFOL(char_session, 2) = sd->bl_id; - WFIFOSET(char_session, 6); + if (!char_session) + return; + + Packet_Fixed<0x3005> fixed_05; + fixed_05.account_id = block_to_account(sd->bl_id); + send_fpacket<0x3005, 6>(char_session, fixed_05); } // 倉庫データ要求 -void intif_request_storage(int account_id) +void intif_request_storage(AccountId account_id) { - WFIFOW(char_session, 0) = 0x3010; - WFIFOL(char_session, 2) = account_id; - WFIFOSET(char_session, 6); + if (!char_session) + return; + + Packet_Fixed<0x3010> fixed_10; + fixed_10.account_id = account_id; + send_fpacket<0x3010, 6>(char_session, fixed_10); } // 倉庫データ送信 -void intif_send_storage(struct storage *stor) +void intif_send_storage(Storage *stor) { nullpo_retv(stor); - WFIFOW(char_session, 0) = 0x3011; - WFIFOW(char_session, 2) = sizeof(struct storage) + 8; - WFIFOL(char_session, 4) = stor->account_id; - WFIFO_STRUCT(char_session, 8, *stor); - WFIFOSET(char_session, WFIFOW(char_session, 2)); + if (!char_session) + return; + + Packet_Payload<0x3011> payload_11; + payload_11.account_id = stor->account_id; + payload_11.storage = *stor; + send_ppacket<0x3011>(char_session, payload_11); } // パーティ作成要求 @@ -171,95 +173,116 @@ void intif_create_party(dumb_ptr<map_session_data> sd, PartyName name) { nullpo_retv(sd); - WFIFOW(char_session, 0) = 0x3020; - WFIFOL(char_session, 2) = sd->status_key.account_id; - WFIFO_STRING(char_session, 6, name, 24); - WFIFO_STRING(char_session, 30, sd->status_key.name.to__actual(), 24); - WFIFO_STRING(char_session, 54, sd->bl_m->name_, 16); - WFIFOW(char_session, 70) = sd->status.base_level; - WFIFOSET(char_session, 72); + if (!char_session) + return; + + Packet_Fixed<0x3020> fixed_20; + fixed_20.account_id = sd->status_key.account_id; + fixed_20.party_name = name; + fixed_20.char_name = sd->status_key.name; + fixed_20.map_name = sd->bl_m->name_; + fixed_20.level = sd->status.base_level; + send_fpacket<0x3020, 72>(char_session, fixed_20); } // パーティ情報要求 -void intif_request_partyinfo(int party_id) +void intif_request_partyinfo(PartyId party_id) { - WFIFOW(char_session, 0) = 0x3021; - WFIFOL(char_session, 2) = party_id; - WFIFOSET(char_session, 6); + if (!char_session) + return; + + Packet_Fixed<0x3021> fixed_21; + fixed_21.party_id = party_id; + send_fpacket<0x3021, 6>(char_session, fixed_21); } // パーティ追加要求 -void intif_party_addmember(int party_id, int account_id) +void intif_party_addmember(PartyId party_id, AccountId account_id) { + if (!char_session) + return; + dumb_ptr<map_session_data> sd; - sd = map_id2sd(account_id); - if (sd != NULL) + sd = map_id2sd(account_to_block(account_id)); + if (sd != nullptr) { - WFIFOW(char_session, 0) = 0x3022; - WFIFOL(char_session, 2) = party_id; - WFIFOL(char_session, 6) = account_id; - WFIFO_STRING(char_session, 10, sd->status_key.name.to__actual(), 24); - WFIFO_STRING(char_session, 34, sd->bl_m->name_, 16); - WFIFOW(char_session, 50) = sd->status.base_level; - WFIFOSET(char_session, 52); + Packet_Fixed<0x3022> fixed_22; + fixed_22.party_id = party_id; + fixed_22.account_id = account_id; + fixed_22.char_name = sd->status_key.name; + fixed_22.map_name = sd->bl_m->name_; + fixed_22.level = sd->status.base_level; + send_fpacket<0x3022, 52>(char_session, fixed_22); } } // パーティ設定変更 -void intif_party_changeoption(int party_id, int account_id, int exp, int item) -{ - WFIFOW(char_session, 0) = 0x3023; - WFIFOL(char_session, 2) = party_id; - WFIFOL(char_session, 6) = account_id; - WFIFOW(char_session, 10) = exp; - WFIFOW(char_session, 12) = item; - WFIFOSET(char_session, 14); +void intif_party_changeoption(PartyId party_id, AccountId account_id, int exp, int item) +{ + if (!char_session) + return; + + Packet_Fixed<0x3023> fixed_23; + fixed_23.party_id = party_id; + fixed_23.account_id = account_id; + fixed_23.exp = exp; + fixed_23.item = item; + send_fpacket<0x3023, 14>(char_session, fixed_23); } // パーティ脱退要求 -void intif_party_leave(int party_id, int account_id) +void intif_party_leave(PartyId party_id, AccountId account_id) { - WFIFOW(char_session, 0) = 0x3024; - WFIFOL(char_session, 2) = party_id; - WFIFOL(char_session, 6) = account_id; - WFIFOSET(char_session, 10); + if (!char_session) + return; + + Packet_Fixed<0x3024> fixed_24; + fixed_24.party_id = party_id; + fixed_24.account_id = account_id; + send_fpacket<0x3024, 10>(char_session, fixed_24); } // パーティ移動要求 void intif_party_changemap(dumb_ptr<map_session_data> sd, int online) { - if (sd != NULL) + if (!char_session) + return; + + if (sd != nullptr) { - WFIFOW(char_session, 0) = 0x3025; - WFIFOL(char_session, 2) = sd->status.party_id; - WFIFOL(char_session, 6) = sd->status_key.account_id; - WFIFO_STRING(char_session, 10, sd->bl_m->name_, 16); - WFIFOB(char_session, 26) = online; - WFIFOW(char_session, 27) = sd->status.base_level; - WFIFOSET(char_session, 29); + Packet_Fixed<0x3025> fixed_25; + fixed_25.party_id = sd->status.party_id; + fixed_25.account_id = sd->status_key.account_id; + fixed_25.map_name = sd->bl_m->name_; + fixed_25.online = online; + fixed_25.level = sd->status.base_level; + send_fpacket<0x3025, 29>(char_session, fixed_25); } } // パーティ会話送信 -void intif_party_message(int party_id, int account_id, XString mes) -{ - size_t len = mes.size() + 1; - WFIFOW(char_session, 0) = 0x3027; - WFIFOW(char_session, 2) = len + 12; - WFIFOL(char_session, 4) = party_id; - WFIFOL(char_session, 8) = account_id; - WFIFO_STRING(char_session, 12, mes, len); - WFIFOSET(char_session, len + 12); +void intif_party_message(PartyId party_id, AccountId account_id, XString mes) +{ + if (!char_session) + return; + + Packet_Head<0x3027> head_27; + head_27.party_id = party_id; + head_27.account_id = account_id; + send_vpacket<0x3027, 12, 1>(char_session, head_27, mes); } // パーティ競合チェック要求 -void intif_party_checkconflict(int party_id, int account_id, CharName nick) +void intif_party_checkconflict(PartyId party_id, AccountId account_id, CharName nick) { - WFIFOW(char_session, 0) = 0x3028; - WFIFOL(char_session, 2) = party_id; - WFIFOL(char_session, 6) = account_id; - WFIFO_STRING(char_session, 10, nick.to__actual(), 24); - WFIFOSET(char_session, 34); + if (!char_session) + return; + + Packet_Fixed<0x3028> fixed_28; + fixed_28.party_id = party_id; + fixed_28.account_id = account_id; + fixed_28.char_name = nick; + send_fpacket<0x3028, 34>(char_session, fixed_28); } //----------------------------------------------------------------- @@ -267,55 +290,52 @@ void intif_party_checkconflict(int party_id, int account_id, CharName nick) // Wisp/Page reception static -int intif_parse_WisMessage(Session *s) +int intif_parse_WisMessage(Session *, const Packet_Head<0x3801>& head, AString& buf) { // rewritten by [Yor] dumb_ptr<map_session_data> sd; - CharName from = stringish<CharName>(RFIFO_STRING<24>(s, 8)); - CharName to = stringish<CharName>(RFIFO_STRING<24>(s, 32)); - - size_t len = RFIFOW(s, 2) - 56; - AString buf = RFIFO_STRING(s, 56, len); + CharName from = head.src_char_name; + CharName to = head.dst_char_name; if (battle_config.etc_log) { - PRINTF("intif_parse_wismessage: id: %d, from: %s, to: %s\n", - RFIFOL(s, 4), - from, - to); + PRINTF("intif_parse_wismessage: id: %d, from: %s, to: %s\n"_fmt, + head.whisper_id, + from, + to); } sd = map_nick2sd(to); // Searching destination player - if (sd != NULL && sd->status_key.name == to) + if (sd != nullptr && sd->status_key.name == to) { // exactly same name (inter-server have checked the name before) { // if source player not found in ignore list { clif_wis_message(sd->sess, from, buf); - intif_wis_replay(RFIFOL(s, 4), 0); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + intif_wis_replay(head.whisper_id, 0); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target } } } else - intif_wis_replay(RFIFOL(s, 4), 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + intif_wis_replay(head.whisper_id, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target return 0; } // Wisp/page transmission result reception static -int intif_parse_WisEnd(Session *s) +int intif_parse_WisEnd(Session *, const Packet_Fixed<0x3802>& fixed) { dumb_ptr<map_session_data> sd; - CharName name = stringish<CharName>(RFIFO_STRING<24>(s, 2)); - uint8_t flag = RFIFOB(s, 26); + CharName name = fixed.sender_char_name; + uint8_t flag = fixed.flag; if (battle_config.etc_log) // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - PRINTF("intif_parse_wisend: player: %s, flag: %d\n", + PRINTF("intif_parse_wisend: player: %s, flag: %d\n"_fmt, name, flag); sd = map_nick2sd(name); - if (sd != NULL) + if (sd != nullptr) clif_wis_end(sd->sess, flag); return 0; @@ -323,19 +343,11 @@ int intif_parse_WisEnd(Session *s) // Received wisp message from map-server via char-server for ALL gm static -void mapif_parse_WisToGM(Session *s) +void mapif_parse_WisToGM(Session *, const Packet_Head<0x3803>& head, AString& message) { // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B - int min_gm_level, len; - - if (RFIFOW(s, 2) - 30 <= 0) - return; - - len = RFIFOW(s, 2) - 30; - - min_gm_level = RFIFOW(s, 28); - CharName Wisp_name = stringish<CharName>(RFIFO_STRING<24>(s, 4)); - AString message = RFIFO_STRING(s, 30, len); + GmLevel min_gm_level = head.min_gm_level; + CharName Wisp_name = head.char_name; // information is sended to all online GM for (io::FD i : iter_fds()) { @@ -345,7 +357,7 @@ void mapif_parse_WisToGM(Session *s) dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get())); if (pl_sd && pl_sd->state.auth) { - if (pc_isGM(pl_sd) >= min_gm_level) + if (pc_isGM(pl_sd).satisfies(min_gm_level)) clif_wis_message(s2, Wisp_name, message); } } @@ -353,65 +365,57 @@ void mapif_parse_WisToGM(Session *s) // アカウント変数通知 static -int intif_parse_AccountReg(Session *s) +int intif_parse_AccountReg(Session *, const Packet_Head<0x3804>& head, const std::vector<Packet_Repeat<0x3804>>& repeat) { - int j, p; - dumb_ptr<map_session_data> sd = map_id2sd(RFIFOL(s, 4)); - if (sd == NULL) + dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(head.account_id)); + if (sd == nullptr) return 1; - for (p = 8, j = 0; p < RFIFOW(s, 2) && j < ACCOUNT_REG_NUM; - p += 36, j++) + + size_t jlim = std::min(ACCOUNT_REG_NUM, repeat.size()); + for (size_t j = 0; j < jlim; j++) { - sd->status.account_reg[j].str = stringish<VarName>(RFIFO_STRING<32>(s, p)); - sd->status.account_reg[j].value = RFIFOL(s, p + 32); + sd->status.account_reg[j].str = repeat[j].name; + sd->status.account_reg[j].value = repeat[j].value; } - sd->status.account_reg_num = j; -// PRINTF("intif: accountreg\n"); + sd->status.account_reg_num = jlim; return 0; } // 倉庫データ受信 static -int intif_parse_LoadStorage(Session *s) +int intif_parse_LoadStorage(Session *, const Packet_Payload<0x3810>& payload) { - struct storage *stor; + Storage *stor; dumb_ptr<map_session_data> sd; - sd = map_id2sd(RFIFOL(s, 4)); - if (sd == NULL) + sd = map_id2sd(account_to_block(payload.account_id)); + if (sd == nullptr) { if (battle_config.error_log) - PRINTF("intif_parse_LoadStorage: user not found %d\n", - RFIFOL(s, 4)); + PRINTF("intif_parse_LoadStorage: user not found %d\n"_fmt, + payload.account_id); return 1; } - stor = account2storage(RFIFOL(s, 4)); + stor = account2storage(payload.account_id); if (stor->storage_status == 1) { // Already open.. lets ignore this update if (battle_config.error_log) - PRINTF("intif_parse_LoadStorage: storage received for a client already open (User %d:%d)\n", - sd->status_key.account_id, sd->status_key.char_id); + PRINTF("intif_parse_LoadStorage: storage received for a client already open (User %d:%d)\n"_fmt, + sd->status_key.account_id, sd->status_key.char_id); return 1; } if (stor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex] if (battle_config.error_log) - PRINTF("intif_parse_LoadStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", - sd->status_key.account_id, sd->status_key.char_id); + PRINTF("intif_parse_LoadStorage: received storage for an already modified non-saved storage! (User %d:%d)\n"_fmt, + sd->status_key.account_id, sd->status_key.char_id); return 1; } - if (RFIFOW(s, 2) - 8 != sizeof(struct storage)) - { - if (battle_config.error_log) - PRINTF("intif_parse_LoadStorage: data size error %d %zu\n", - RFIFOW(s, 2) - 8, sizeof(struct storage)); - return 1; - } if (battle_config.save_log) - PRINTF("intif_openstorage: %d\n", RFIFOL(s, 4)); - RFIFO_STRUCT(s, 8, *stor); + PRINTF("intif_openstorage: %d\n"_fmt, payload.account_id); + *stor = payload.storage; stor->dirty = 0; stor->storage_status = 1; sd->state.storage_open = 1; @@ -424,199 +428,273 @@ int intif_parse_LoadStorage(Session *s) // 倉庫データ送信成功 static -void intif_parse_SaveStorage(Session *s) +void intif_parse_SaveStorage(Session *, const Packet_Fixed<0x3811>& fixed) { if (battle_config.save_log) - PRINTF("intif_savestorage: done %d %d\n", RFIFOL(s, 2), - RFIFOB(s, 6)); - storage_storage_saved(RFIFOL(s, 2)); + PRINTF("intif_savestorage: done %d %d\n"_fmt, fixed.account_id, + fixed.unknown); + storage_storage_saved(fixed.account_id); } // パーティ作成可否 static -void intif_parse_PartyCreated(Session *s) +void intif_parse_PartyCreated(Session *, const Packet_Fixed<0x3820>& fixed) { if (battle_config.etc_log) - PRINTF("intif: party created\n"); - int account_id = RFIFOL(s, 2); - int fail = RFIFOB(s, 6); - int party_id = RFIFOL(s, 7); - PartyName name = stringish<PartyName>(RFIFO_STRING<24>(s, 11)); + PRINTF("intif: party created\n"_fmt); + AccountId account_id = fixed.account_id; + int fail = fixed.error; + PartyId party_id = fixed.party_id; + PartyName name = fixed.party_name; party_created(account_id, fail, party_id, name); } // パーティ情報 static -void intif_parse_PartyInfo(Session *s) +void intif_parse_PartyInfo(Session *, const Packet_Head<0x3821>& head, bool has_opt, const Packet_Option<0x3821>& option) { - if (RFIFOW(s, 2) == 8) + if (!has_opt) { if (battle_config.error_log) - PRINTF("intif: party noinfo %d\n", RFIFOL(s, 4)); - party_recv_noinfo(RFIFOL(s, 4)); + PRINTF("intif: party noinfo %d\n"_fmt, head.party_id); + party_recv_noinfo(head.party_id); return; } -// PRINTF("intif: party info %d\n",RFIFOL(fd,4)); - if (RFIFOW(s, 2) != sizeof(struct party) + 4) - { - if (battle_config.error_log) - PRINTF("intif: party info : data size error %d %d %zu\n", - RFIFOL(s, 4), RFIFOW(s, 2), - sizeof(struct party) + 4); - } - party p {}; - RFIFO_STRUCT(s, 4, p); - party_recv_info(&p); + PartyId pi = head.party_id; + PartyMost pm = option.party_most; + PartyPair pp; + pp.party_id = pi; + pp.party_most = ± + party_recv_info(pp); } // パーティ追加通知 static -void intif_parse_PartyMemberAdded(Session *s) +void intif_parse_PartyMemberAdded(Session *, const Packet_Fixed<0x3822>& fixed) { if (battle_config.etc_log) - PRINTF("intif: party member added %d %d %d\n", RFIFOL(s, 2), - RFIFOL(s, 6), RFIFOB(s, 10)); - party_member_added(RFIFOL(s, 2), RFIFOL(s, 6), RFIFOB(s, 10)); + PRINTF("intif: party member added %d %d %d\n"_fmt, fixed.party_id, + fixed.account_id, fixed.flag); + party_member_added(fixed.party_id, fixed.account_id, fixed.flag); } // パーティ設定変更通知 static -void intif_parse_PartyOptionChanged(Session *s) +void intif_parse_PartyOptionChanged(Session *, const Packet_Fixed<0x3823>& fixed) { - party_optionchanged(RFIFOL(s, 2), RFIFOL(s, 6), RFIFOW(s, 10), - RFIFOW(s, 12), RFIFOB(s, 14)); + party_optionchanged(fixed.party_id, fixed.account_id, fixed.exp, + fixed.item, fixed.flag); } // パーティ脱退通知 static -void intif_parse_PartyMemberLeaved(Session *s) +void intif_parse_PartyMemberLeaved(Session *, const Packet_Fixed<0x3824>& fixed) { - int party_id = RFIFOL(s, 2); - int account_id = RFIFOL(s, 6); - CharName name = stringish<CharName>(RFIFO_STRING<24>(s, 10)); + PartyId party_id = fixed.party_id; + AccountId account_id = fixed.account_id; + CharName name = fixed.char_name; if (battle_config.etc_log) - PRINTF("intif: party member leaved %d %d %s\n", + PRINTF("intif: party member leaved %d %d %s\n"_fmt, party_id, account_id, name); party_member_leaved(party_id, account_id, name); } // パーティ解散通知 static -void intif_parse_PartyBroken(Session *s) +void intif_parse_PartyBroken(Session *, const Packet_Fixed<0x3826>& fixed) { - party_broken(RFIFOL(s, 2)); + party_broken(fixed.party_id); } // パーティ移動通知 static -void intif_parse_PartyMove(Session *s) +void intif_parse_PartyMove(Session *, const Packet_Fixed<0x3825>& fixed) { - int party_id = RFIFOL(s, 2); - int account_id = RFIFOL(s, 6); - MapName map = stringish<MapName>(RFIFO_STRING<16>(s, 10)); - uint8_t online = RFIFOB(s, 26); - uint16_t lv = RFIFOW(s, 27); + PartyId party_id = fixed.party_id; + AccountId account_id = fixed.account_id; + MapName map = fixed.map_name; + uint8_t online = fixed.online; + uint16_t lv = fixed.level; party_recv_movemap(party_id, account_id, map, online, lv); } // パーティメッセージ static -void intif_parse_PartyMessage(Session *s) +void intif_parse_PartyMessage(Session *, const Packet_Head<0x3827>& head, AString& buf) { - size_t len = RFIFOW(s, 2) - 12; - AString buf = RFIFO_STRING(s, 12, len); - party_recv_message(RFIFOL(s, 4), RFIFOL(s, 8), buf); + party_recv_message(head.party_id, head.account_id, buf); } //----------------------------------------------------------------- // inter serverからの通信 // エラーがあれば0(false)を返すこと // パケットが処理できれば1,パケット長が足りなければ2を返すこと -int intif_parse(Session *s) -{ - int packet_len; - int cmd = RFIFOW(s, 0); - // パケットのID確認 - if (cmd < 0x3800 - || cmd >= - 0x3800 + (sizeof(packet_len_table) / sizeof(packet_len_table[0])) - || packet_len_table[cmd - 0x3800] == 0) - { - return 0; - } - // パケットの長さ確認 - packet_len = packet_len_table[cmd - 0x3800]; - if (packet_len == -1) - { - if (RFIFOREST(s) < 4) - return 2; - packet_len = RFIFOW(s, 2); - } -// if(battle_config.etc_log) -// PRINTF("intif_parse %d %x %d %d\n",fd,cmd,packet_len,RFIFOREST(fd)); - if (RFIFOREST(s) < packet_len) - { - return 2; - } - // 処理分岐 - switch (cmd) +RecvResult intif_parse(Session *s, uint16_t packet_id) +{ + RecvResult rv; + + switch (packet_id) { case 0x3800: { - AString mes = RFIFO_STRING(s, 4, packet_len - 4); - clif_GMmessage(NULL, mes, 0); - } + AString mes; + rv = recv_packet_repeatonly<0x3800, 4, 1>(s, mes); + if (rv != RecvResult::Complete) + return rv; + + clif_GMmessage(nullptr, mes, 0); break; + } case 0x3801: - intif_parse_WisMessage(s); + { + Packet_Head<0x3801> head; + AString repeat; + rv = recv_vpacket<0x3801, 56, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_WisMessage(s, head, repeat); break; + } case 0x3802: - intif_parse_WisEnd(s); + { + Packet_Fixed<0x3802> fixed; + rv = recv_fpacket<0x3802, 27>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_WisEnd(s, fixed); break; + } case 0x3803: - mapif_parse_WisToGM(s); + { + Packet_Head<0x3803> head; + AString repeat; + rv = recv_vpacket<0x3803, 30, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + return rv; + + mapif_parse_WisToGM(s, head, repeat); break; + } case 0x3804: - intif_parse_AccountReg(s); + { + Packet_Head<0x3804> head; + std::vector<Packet_Repeat<0x3804>> repeat; + rv = recv_vpacket<0x3804, 8, 36>(s, head, repeat); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_AccountReg(s, head, repeat); break; + } case 0x3810: - intif_parse_LoadStorage(s); + { + Packet_Payload<0x3810> payload; + rv = recv_ppacket<0x3810>(s, payload); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_LoadStorage(s, payload); break; + } case 0x3811: - intif_parse_SaveStorage(s); + { + Packet_Fixed<0x3811> fixed; + rv = recv_fpacket<0x3811, 7>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_SaveStorage(s, fixed); break; + } case 0x3820: - intif_parse_PartyCreated(s); + { + Packet_Fixed<0x3820> fixed; + rv = recv_fpacket<0x3820, 35>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_PartyCreated(s, fixed); break; + } case 0x3821: - intif_parse_PartyInfo(s); + { + Packet_Head<0x3821> head; + bool has_opt; + Packet_Option<0x3821> option; + rv = recv_opacket<0x3821, 8, sizeof(NetPacket_Option<0x3821>)>(s, head, &has_opt, option); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_PartyInfo(s, head, has_opt, option); break; + } case 0x3822: - intif_parse_PartyMemberAdded(s); + { + Packet_Fixed<0x3822> fixed; + rv = recv_fpacket<0x3822, 11>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_PartyMemberAdded(s, fixed); break; + } case 0x3823: - intif_parse_PartyOptionChanged(s); + { + Packet_Fixed<0x3823> fixed; + rv = recv_fpacket<0x3823, 15>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_PartyOptionChanged(s, fixed); break; + } case 0x3824: - intif_parse_PartyMemberLeaved(s); + { + Packet_Fixed<0x3824> fixed; + rv = recv_fpacket<0x3824, 34>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_PartyMemberLeaved(s, fixed); break; + } case 0x3825: - intif_parse_PartyMove(s); + { + Packet_Fixed<0x3825> fixed; + rv = recv_fpacket<0x3825, 29>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_PartyMove(s, fixed); break; + } case 0x3826: - intif_parse_PartyBroken(s); + { + Packet_Fixed<0x3826> fixed; + rv = recv_fpacket<0x3826, 7>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_PartyBroken(s, fixed); break; + } case 0x3827: - intif_parse_PartyMessage(s); + { + Packet_Head<0x3827> head; + AString repeat; + rv = recv_vpacket<0x3827, 12, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_PartyMessage(s, head, repeat); break; + } default: - if (battle_config.error_log) - PRINTF("intif_parse : unknown packet %d %x\n", s, - RFIFOW(s, 0)); - return 0; + return RecvResult::Error; } - // パケット読み飛ばし - RFIFOSKIP(s, packet_len); - return 1; + return rv; } +} // namespace tmwa diff --git a/src/map/intif.hpp b/src/map/intif.hpp index 80de797..5be61a9 100644 --- a/src/map/intif.hpp +++ b/src/map/intif.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_INTIF_HPP -#define TMWA_MAP_INTIF_HPP +#pragma once // intif.hpp - Network interface to the internal server. // // Copyright © ????-2004 Athena Dev Teams @@ -21,33 +20,39 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "map.hpp" +#include "../generic/fwd.hpp" -int intif_parse(Session *); +#include "../net/fwd.hpp" + +#include "../mmo/fwd.hpp" + + +namespace tmwa +{ +RecvResult intif_parse(Session *, uint16_t packet_id); void intif_GMmessage(XString mes); void intif_wis_message(dumb_ptr<map_session_data> sd, CharName nick, ZString mes); -void intif_wis_message_to_gm(CharName Wisp_name, int min_gm_level, ZString mes); +void intif_wis_message_to_gm(CharName Wisp_name, GmLevel min_gm_level, ZString mes); void intif_saveaccountreg(dumb_ptr<map_session_data> sd); void intif_request_accountreg(dumb_ptr<map_session_data> sd); -void intif_request_storage(int account_id); -void intif_send_storage(struct storage *stor); +void intif_request_storage(AccountId account_id); +void intif_send_storage(Storage *stor); void intif_create_party(dumb_ptr<map_session_data> sd, PartyName name); -void intif_request_partyinfo(int party_id); -void intif_party_addmember(int party_id, int account_id); -void intif_party_changeoption(int party_id, int account_id, int exp, +void intif_request_partyinfo(PartyId party_id); +void intif_party_addmember(PartyId party_id, AccountId account_id); +void intif_party_changeoption(PartyId party_id, AccountId account_id, int exp, int item); -void intif_party_leave(int party_id, int accound_id); +void intif_party_leave(PartyId party_id, AccountId accound_id); void intif_party_changemap(dumb_ptr<map_session_data> sd, int online); -void intif_party_message(int party_id, int account_id, XString mes); -void intif_party_checkconflict(int party_id, int account_id, CharName nick); - -#endif // TMWA_MAP_INTIF_HPP +void intif_party_message(PartyId party_id, AccountId account_id, XString mes); +void intif_party_checkconflict(PartyId party_id, AccountId account_id, CharName nick); +} // namespace tmwa diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp index 4ebb52c..edc9982 100644 --- a/src/map/itemdb.cpp +++ b/src/map/itemdb.cpp @@ -20,29 +20,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <cstdlib> -#include <cstring> - -#include "../compat/nullpo.hpp" +#include <algorithm> #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" #include "../generic/db.hpp" -#include "../generic/random.hpp" #include "../io/cxxstdio.hpp" #include "../io/read.hpp" #include "../mmo/config_parse.hpp" #include "../mmo/extract.hpp" -#include "../mmo/socket.hpp" #include "../poison.hpp" + +namespace tmwa +{ static -Map<int, struct item_data> item_db; +Map<ItemNameId, struct item_data> item_db; // Function declarations @@ -67,7 +65,7 @@ struct item_data *itemdb_searchname(XString str_) ItemName str = stringish<ItemName>(str_); if (XString(str) != str_) return nullptr; - struct item_data *item = NULL; + struct item_data *item = nullptr; for (auto& pair : item_db) itemdb_searchname_sub(&pair.second, str, &item); return item; @@ -77,7 +75,7 @@ struct item_data *itemdb_searchname(XString str_) * DBの存在確認 *------------------------------------------ */ -struct item_data *itemdb_exists(int nameid) +struct item_data *itemdb_exists(ItemNameId nameid) { return item_db.search(nameid); } @@ -86,7 +84,7 @@ struct item_data *itemdb_exists(int nameid) * DBの検索 *------------------------------------------ */ -struct item_data *itemdb_search(int nameid) +struct item_data *itemdb_search(ItemNameId nameid) { struct item_data *id = item_db.search(nameid); if (id) @@ -101,22 +99,7 @@ struct item_data *itemdb_search(int nameid) id->sex = SEX::NEUTRAL; id->elv = 0; - if (nameid > 500 && nameid < 600) - id->type = ItemType::USE; - else if (nameid > 600 && nameid < 700) - id->type = ItemType::_2; - else if ((nameid > 700 && nameid < 1100) || - (nameid > 7000 && nameid < 8000)) - id->type = ItemType::JUNK; - else if (nameid >= 1750 && nameid < 1771) - id->type = ItemType::ARROW; - else if (nameid > 1100 && nameid < 2000) - id->type = ItemType::WEAPON; - else if ((nameid > 2100 && nameid < 3000) || - (nameid > 5000 && nameid < 6000)) - id->type = ItemType::ARMOR; - else if (nameid > 4000 && nameid < 5000) - id->type = ItemType::_6; + id->type = ItemType::JUNK; return id; } @@ -125,7 +108,7 @@ struct item_data *itemdb_search(int nameid) * *------------------------------------------ */ -int itemdb_isequip(int nameid) +int itemdb_isequip(ItemNameId nameid) { ItemType type = itemdb_type(nameid); return !(type == ItemType::USE @@ -155,7 +138,7 @@ int itemdb_isequip2(struct item_data *data) * *------------------------------------------ */ -int itemdb_isequip3(int nameid) +int itemdb_isequip3(ItemNameId nameid) { ItemType type = itemdb_type(nameid); return (type == ItemType::WEAPON @@ -174,7 +157,7 @@ bool itemdb_readdb(ZString filename) if (!in.is_open()) { - PRINTF("can't read %s\n", filename); + PRINTF("can't read %s\n"_fmt, filename); return false; } @@ -220,7 +203,7 @@ bool itemdb_readdb(ZString filename) ) ) { - PRINTF("%s:%d: error: bad item line: %s\n", + PRINTF("%s:%d: error: bad item line: %s\n"_fmt, filename, lines, line); rv = false; continue; @@ -242,8 +225,8 @@ bool itemdb_readdb(ZString filename) id->value_sell = id->value_buy / 2; } - id->use_script = NULL; - id->equip_script = NULL; + id->use_script = nullptr; + id->equip_script = nullptr; if (!tail_part) continue; @@ -254,7 +237,7 @@ bool itemdb_readdb(ZString filename) continue; id->equip_script = parse_script(tail_part, lines, true); } - PRINTF("read %s done (count=%d)\n", filename, ln); + PRINTF("read %s done (count=%d)\n"_fmt, filename, ln); } return rv; @@ -281,3 +264,4 @@ void do_final_itemdb(void) itemdb_final(&pair.second); item_db.clear(); } +} // namespace tmwa diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp index 16802da..25b4dad 100644 --- a/src/map/itemdb.hpp +++ b/src/map/itemdb.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_ITEMDB_HPP -#define TMWA_MAP_ITEMDB_HPP +#pragma once // itemdb.hpp - Item definitions. // // Copyright © ????-2004 Athena Dev Teams @@ -21,16 +20,20 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../mmo/mmo.hpp" +#include "../mmo/ids.hpp" +#include "../mmo/mmo.hpp" -# include "map.t.hpp" -# include "script.hpp" +#include "map.t.hpp" +#include "script.hpp" + +namespace tmwa +{ struct item_data { - int nameid; + ItemNameId nameid; ItemName name, jname; int value_buy; int value_sell; @@ -58,47 +61,47 @@ struct random_item_data inline struct item_data *itemdb_searchname(ItemName) = delete; struct item_data *itemdb_searchname(XString name); -struct item_data *itemdb_search(int nameid); -struct item_data *itemdb_exists(int nameid); +// TODO this function should die +struct item_data *itemdb_search(ItemNameId nameid); +struct item_data *itemdb_exists(ItemNameId nameid); inline -ItemType itemdb_type(int n) +ItemType itemdb_type(ItemNameId n) { return itemdb_search(n)->type; } inline -ItemLook itemdb_look(int n) +ItemLook itemdb_look(ItemNameId n) { return itemdb_search(n)->look; } inline -int itemdb_weight(int n) +int itemdb_weight(ItemNameId n) { return itemdb_search(n)->weight; } inline -const ScriptBuffer *itemdb_equipscript(int n) +const ScriptBuffer *itemdb_equipscript(ItemNameId n) { return itemdb_search(n)->equip_script.get(); } inline -int itemdb_wlv(int n) +int itemdb_wlv(ItemNameId n) { return itemdb_search(n)->wlv; } inline -int itemdb_value_sell(int n) +int itemdb_value_sell(ItemNameId n) { return itemdb_search(n)->value_sell; } -int itemdb_isequip(int); +int itemdb_isequip(ItemNameId); int itemdb_isequip2(struct item_data *); -int itemdb_isequip3(int); +int itemdb_isequip3(ItemNameId); void itemdb_reload(void); void do_final_itemdb(void); bool itemdb_readdb(ZString filename); - -#endif // TMWA_MAP_ITEMDB_HPP +} // namespace tmwa diff --git a/src/map/magic-expr-eval.cpp b/src/map/magic-expr-eval.cpp index 36b69f5..0283b8d 100644 --- a/src/map/magic-expr-eval.cpp +++ b/src/map/magic-expr-eval.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/map/magic-expr-eval.hpp b/src/map/magic-expr-eval.hpp index 9b9f5f8..a291fcd 100644 --- a/src/map/magic-expr-eval.hpp +++ b/src/map/magic-expr-eval.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MAGIC_EXPR_EVAL_HPP -#define TMWA_MAP_MAGIC_EXPR_EVAL_HPP +#pragma once // magic-expr-eval.hpp - Utilities for evaluating magic. // // Copyright © 2004-2011 The Mana World Development Team @@ -20,47 +19,40 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../range/slice.hpp" +#include "../strings/zstring.hpp" -# include "../strings/zstring.hpp" +#include "magic-interpreter.t.hpp" -# include "magic-interpreter.hpp" -/* Helper definitions for dealing with functions and operations */ +namespace tmwa +{ +// TODO kill this like I killed VAR +#define ARGINT(x) args[x].v.v_int +#define ARGDIR(x) args[x].v.v_dir +#define ARGSTR(x) ZString(args[x].v.v_string) +#define ARGENTITY(x) args[x].v.v_entity +#define ARGLOCATION(x) args[x].v.v_location +#define ARGAREA(x) args[x].v.v_area +#define ARGSPELL(x) args[x].v.v_spell +#define ARGINVOCATION(x) args[x].v.v_invocation -int magic_signature_check(ZString opname, ZString funname, ZString signature, - Slice<val_t> args, int line, int column); +#define RESULTINT result->v.v_int +#define RESULTDIR result->v.v_dir +#define RESULTSTR result->v.v_string +#define RESULTENTITY result->v.v_entity +#define RESULTLOCATION result->v.v_location +#define RESULTAREA result->v.v_area +#define RESULTSPELL result->v.v_spell +#define RESULTINVOCATION result->v.v_invocation -void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height, - area_t& area); +#define ARG_TYPE(x) args[x].ty +#define ENTITY_TYPE(x) ARGENTITY(x)->bl_type -# define ARGINT(x) args[x].v.v_int -# define ARGDIR(x) args[x].v.v_dir -# define ARGSTR(x) ZString(args[x].v.v_string) -# define ARGENTITY(x) args[x].v.v_entity -# define ARGLOCATION(x) args[x].v.v_location -# define ARGAREA(x) args[x].v.v_area -# define ARGSPELL(x) args[x].v.v_spell -# define ARGINVOCATION(x) args[x].v.v_invocation +#define ARGPC(x) (ARGENTITY(x)->is_player()) +#define ARGNPC(x) (ARGENTITY(x)->is_npc()) +#define ARGMOB(x) (ARGENTITY(x)->is_mob()) -# define RESULTINT result->v.v_int -# define RESULTDIR result->v.v_dir -# define RESULTSTR result->v.v_string -# define RESULTENTITY result->v.v_entity -# define RESULTLOCATION result->v.v_location -# define RESULTAREA result->v.v_area -# define RESULTSPELL result->v.v_spell -# define RESULTINVOCATION result->v.v_invocation - -# define ARG_TYPE(x) args[x].ty -# define ENTITY_TYPE(x) ARGENTITY(x)->bl_type - -# define ARGPC(x) (ARGENTITY(x)->is_player()) -# define ARGNPC(x) (ARGENTITY(x)->is_npc()) -# define ARGMOB(x) (ARGENTITY(x)->is_mob()) - -# define ARG_MAY_BE_AREA(x) (ARG_TYPE(x) == TYPE::AREA || ARG_TYPE(x) == TYPE::LOCATION) - -#endif // TMWA_MAP_MAGIC_EXPR_EVAL_HPP +#define ARG_MAY_BE_AREA(x) (ARG_TYPE(x) == TYPE::AREA || ARG_TYPE(x) == TYPE::LOCATION) +} // namespace tmwa diff --git a/src/map/magic-expr.cpp b/src/map/magic-expr.cpp index 42ff3a7..dfb65c5 100644 --- a/src/map/magic-expr.cpp +++ b/src/map/magic-expr.cpp @@ -1,6 +1,4 @@ -#include "magic-expr-eval.hpp" #include "magic-expr.hpp" -#include "magic-interpreter-aux.hpp" // magic-expr.cpp - Pure functions for the old magic backend. // // Copyright © 2004-2011 The Mana World Development Team @@ -22,26 +20,39 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include <cassert> -#include <cmath> -#include "../compat/alg.hpp" +#include <algorithm> #include "../strings/mstring.hpp" #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/vstring.hpp" +#include "../strings/literal.hpp" +#include "../generic/dumb_ptr.hpp" #include "../generic/random.hpp" #include "../io/cxxstdio.hpp" #include "battle.hpp" +#include "itemdb.hpp" +#include "magic-expr-eval.hpp" +#include "magic-interpreter.hpp" +#include "magic-interpreter-base.hpp" #include "npc.hpp" #include "pc.hpp" -#include "itemdb.hpp" #include "../poison.hpp" + +namespace tmwa +{ +template<class T> +bool CHECK_TYPE(T *v, TYPE t) +{ + return v->ty == t; +} + static void free_area(dumb_ptr<area_t> area) { @@ -125,38 +136,38 @@ AString show_entity(dumb_ptr<block_list> entity) case BL::MOB: return entity->is_mob()->name; case BL::ITEM: - assert (0 && "There is no way this code did what it was supposed to do!"); + assert (0 && "There is no way this code did what it was supposed to do!"_s); /* Sorry about this one... */ - // WTF? item_data is a struct item, not a struct item_data + // WTF? item_data is a Item, not a struct item_data // return ((struct item_data *) (&entity->is_item()->item_data))->name; abort(); case BL::SPELL: - return {"%invocation(ERROR:this-should-not-be-an-entity)"}; + return "%invocation(ERROR:this-should-not-be-an-entity)"_s; default: - return {"%unknown-entity"}; + return "%unknown-entity"_s; } } static void stringify(val_t *v, int within_op) { - static earray<ZString, DIR, DIR::COUNT> dirs //= + static earray<LString, DIR, DIR::COUNT> dirs //= {{ - {"south"}, {"south-west"}, - {"west"}, {"north-west"}, - {"north"}, {"north-east"}, - {"east"}, {"south-east"}, + "south"_s, "south-west"_s, + "west"_s, "north-west"_s, + "north"_s, "north-east"_s, + "east"_s, "south-east"_s, }}; AString buf; switch (v->ty) { case TYPE::UNDEF: - buf = "UNDEF"; + buf = "UNDEF"_s; break; case TYPE::INT: - buf = STRPRINTF("%i", v->v.v_int); + buf = STRPRINTF("%i"_fmt, v->v.v_int); break; case TYPE::STRING: @@ -171,14 +182,14 @@ void stringify(val_t *v, int within_op) break; case TYPE::LOCATION: - buf = STRPRINTF("<\"%s\", %d, %d>", + buf = STRPRINTF("<\"%s\", %d, %d>"_fmt, v->v.v_location.m->name_, v->v.v_location.x, v->v.v_location.y); break; case TYPE::AREA: - buf = "%area"; + buf = "%area"_s; free_area(v->v.v_area); break; @@ -190,13 +201,13 @@ void stringify(val_t *v, int within_op) { dumb_ptr<invocation> invocation_ = within_op ? v->v.v_invocation - : map_id2bl(v->v.v_int)->is_spell(); + : map_id2bl(wrap<BlockId>(static_cast<uint32_t>(v->v.v_int)))->is_spell(); buf = invocation_->spell->name; } break; default: - FPRINTF(stderr, "[magic] INTERNAL ERROR: Cannot stringify %d\n", + FPRINTF(stderr, "[magic] INTERNAL ERROR: Cannot stringify %d\n"_fmt, v->ty); return; } @@ -294,8 +305,8 @@ int fun_add(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) make_area(&args[0]); make_area(&args[1]); RESULTAREA = area_union(ARGAREA(0), ARGAREA(1)); - ARGAREA(0) = NULL; - ARGAREA(1) = NULL; + ARGAREA(0) = nullptr; + ARGAREA(1) = nullptr; result->ty = TYPE::AREA; } else @@ -504,14 +515,14 @@ int fun_bitshr(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) static int fun_max(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { - RESULTINT = max(ARGINT(0), ARGINT(1)); + RESULTINT = std::max(ARGINT(0), ARGINT(1)); return 0; } static int fun_min(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { - RESULTINT = min(ARGINT(0), ARGINT(1)); + RESULTINT = std::min(ARGINT(0), ARGINT(1)); return 0; } @@ -590,7 +601,7 @@ void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height, default: FPRINTF(stderr, - "Error: Trying to compute area of NE/SE/NW/SW-facing bar"); + "Error: Trying to compute area of NE/SE/NW/SW-facing bar"_fmt); *x = tx; *y = ty; *width = *height = 1; @@ -619,7 +630,7 @@ int magic_location_in_area(map_local *m, int x, int y, dumb_ptr<area_t> area) && (x < ax + awidth) && (y < ay + aheight)); } default: - FPRINTF(stderr, "INTERNAL ERROR: Invalid area\n"); + FPRINTF(stderr, "INTERNAL ERROR: Invalid area\n"_fmt); return 0; } } @@ -639,7 +650,7 @@ int fun_skill(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) if (ENTITY_TYPE(0) != BL::PC // don't convert to enum until after the range check || ARGINT(1) < 0 - || ARGINT(1) >= uint16_t(MAX_SKILL)) + || ARGINT(1) >= static_cast<uint16_t>(MAX_SKILL)) { RESULTINT = 0; } @@ -725,7 +736,7 @@ int fun_mob_id(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ENTITY_TYPE(0) != BL::MOB) return 1; - RESULTINT = ARGMOB(0)->mob_class; + RESULTINT = unwrap<Species>(ARGMOB(0)->mob_class); return 0; } @@ -783,18 +794,18 @@ int fun_random_dir(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) static int fun_hash_entity(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { - RESULTINT = ARGENTITY(0)->bl_id; + RESULTINT = unwrap<BlockId>(ARGENTITY(0)->bl_id); return 0; } -int // ret -1: not a string, ret 1: no such item, ret 0: OK -magic_find_item(Slice<val_t> args, int index, struct item *item_, int *stackable) +// ret -1: not a string, ret 1: no such item, ret 0: OK +int magic_find_item(Slice<val_t> args, int index, Item *item_, int *stackable) { struct item_data *item_data; int must_add_sequentially; if (ARG_TYPE(index) == TYPE::INT) - item_data = itemdb_exists(ARGINT(index)); + item_data = itemdb_exists(wrap<ItemNameId>(static_cast<uint16_t>(ARGINT(index)))); else if (ARG_TYPE(index) == TYPE::STRING) item_data = itemdb_searchname(ARGSTR(index)); else @@ -813,7 +824,7 @@ magic_find_item(Slice<val_t> args, int index, struct item *item_, int *stackable if (stackable) *stackable = !must_add_sequentially; - *item_ = item(); + *item_ = Item(); item_->nameid = item_data->nameid; return 0; @@ -822,9 +833,9 @@ magic_find_item(Slice<val_t> args, int index, struct item *item_, int *stackable static int fun_count_item(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { - dumb_ptr<map_session_data> chr = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; + dumb_ptr<map_session_data> chr = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : nullptr; int stackable; - struct item item; + Item item; GET_ARG_ITEM(1, item, stackable); @@ -838,9 +849,9 @@ int fun_count_item(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) static int fun_is_equipped(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { - dumb_ptr<map_session_data> chr = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; + dumb_ptr<map_session_data> chr = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : nullptr; int stackable; - struct item item; + Item item; bool retval = false; GET_ARG_ITEM(1, item, stackable); @@ -850,8 +861,8 @@ int fun_is_equipped(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) for (EQUIP i : EQUIPs) { - int idx = chr->equip_index_maybe[i]; - if (idx >= 0 && chr->status.inventory[idx].nameid == item.nameid) + IOff0 idx = chr->equip_index_maybe[i]; + if (idx.ok() && chr->status.inventory[idx].nameid == item.nameid) { retval = true; break; @@ -927,7 +938,7 @@ int fun_npc(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { NpcName name = stringish<NpcName>(ARGSTR(0)); RESULTENTITY = npc_name2id(name); - return RESULTENTITY == NULL; + return RESULTENTITY == nullptr; } static @@ -935,7 +946,7 @@ int fun_pc(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { CharName name = stringish<CharName>(ARGSTR(0)); RESULTENTITY = map_nick2sd(name); - return RESULTENTITY == NULL; + return RESULTENTITY == nullptr; } static @@ -944,7 +955,7 @@ int fun_distance(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) if (ARGLOCATION(0).m != ARGLOCATION(1).m) RESULTINT = 0x7fffffff; else - RESULTINT = max(abs(ARGLOCATION(0).x - ARGLOCATION(1).x), + RESULTINT = std::max(abs(ARGLOCATION(0).x - ARGLOCATION(1).x), abs(ARGLOCATION(0).y - ARGLOCATION(1).y)); return 0; } @@ -1034,7 +1045,7 @@ void magic_random_location(location_t *dest, dumb_ptr<area_t> area) } default: - FPRINTF(stderr, "Unknown area type %d\n", + FPRINTF(stderr, "Unknown area type %d\n"_fmt, area->ty); } } @@ -1133,7 +1144,7 @@ int fun_is_exterior(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) static int fun_contains_string(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { - RESULTINT = NULL != strstr(ARGSTR(0).c_str(), ARGSTR(1).c_str()); + RESULTINT = nullptr != strstr(ARGSTR(0).c_str(), ARGSTR(1).c_str()); return 0; } @@ -1142,7 +1153,7 @@ int fun_strstr(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { const char *offset = strstr(ARGSTR(0).c_str(), ARGSTR(1).c_str()); RESULTINT = offset - ARGSTR(0).c_str(); - return offset == NULL; + return offset == nullptr; } static @@ -1273,7 +1284,7 @@ int fun_dir_towards(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) static int fun_extract_healer_xp(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { - dumb_ptr<map_session_data> sd = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; + dumb_ptr<map_session_data> sd = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : nullptr; if (!sd) RESULTINT = 0; @@ -1282,89 +1293,89 @@ int fun_extract_healer_xp(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) return 0; } -#define MAGIC_FUNCTION(name, args, ret, impl) {{name}, {{name}, {args}, ret, impl}} -#define MAGIC_FUNCTION1(name, args, ret) MAGIC_FUNCTION(#name, args, ret, fun_##name) -static +#define MAGIC_FUNCTION(name, args, ret, impl) {name, {name, args, ret, impl}} +#define MAGIC_FUNCTION1(name, args, ret) MAGIC_FUNCTION(#name##_s, args, ret, fun_##name) +static // should be LString, but no heterogenous lookup yet std::map<ZString, fun_t> functions = { - MAGIC_FUNCTION("+", "..", '.', fun_add), - MAGIC_FUNCTION("-", "ii", 'i', fun_sub), - MAGIC_FUNCTION("*", "ii", 'i', fun_mul), - MAGIC_FUNCTION("/", "ii", 'i', fun_div), - MAGIC_FUNCTION("%", "ii", 'i', fun_mod), - MAGIC_FUNCTION("||", "ii", 'i', fun_or), - MAGIC_FUNCTION("&&", "ii", 'i', fun_and), - MAGIC_FUNCTION("<", "..", 'i', fun_lt), - MAGIC_FUNCTION(">", "..", 'i', fun_gt), - MAGIC_FUNCTION("<=", "..", 'i', fun_lte), - MAGIC_FUNCTION(">=", "..", 'i', fun_gte), - MAGIC_FUNCTION("==", "..", 'i', fun_eq), - MAGIC_FUNCTION("!=", "..", 'i', fun_ne), - MAGIC_FUNCTION("|", "..", 'i', fun_bitor), - MAGIC_FUNCTION("&", "ii", 'i', fun_bitand), - MAGIC_FUNCTION("^", "ii", 'i', fun_bitxor), - MAGIC_FUNCTION("<<", "ii", 'i', fun_bitshl), - MAGIC_FUNCTION(">>", "ii", 'i', fun_bitshr), - MAGIC_FUNCTION1(not, "i", 'i'), - MAGIC_FUNCTION1(neg, "i", 'i'), - MAGIC_FUNCTION1(max, "ii", 'i'), - MAGIC_FUNCTION1(min, "ii", 'i'), - MAGIC_FUNCTION1(is_in, "la", 'i'), - MAGIC_FUNCTION1(if_then_else, "i__", '_'), - MAGIC_FUNCTION1(skill, "ei", 'i'), - MAGIC_FUNCTION("str", "e", 'i', fun_get_str), - MAGIC_FUNCTION("agi", "e", 'i', fun_get_agi), - MAGIC_FUNCTION("vit", "e", 'i', fun_get_vit), - MAGIC_FUNCTION("dex", "e", 'i', fun_get_dex), - MAGIC_FUNCTION("luk", "e", 'i', fun_get_luk), - MAGIC_FUNCTION("int", "e", 'i', fun_get_int), - MAGIC_FUNCTION("level", "e", 'i', fun_get_lv), - MAGIC_FUNCTION("mdef", "e", 'i', fun_get_mdef), - MAGIC_FUNCTION("def", "e", 'i', fun_get_def), - MAGIC_FUNCTION("hp", "e", 'i', fun_get_hp), - MAGIC_FUNCTION("max_hp", "e", 'i', fun_get_max_hp), - MAGIC_FUNCTION("sp", "e", 'i', fun_get_sp), - MAGIC_FUNCTION("max_sp", "e", 'i', fun_get_max_sp), - MAGIC_FUNCTION("dir", "e", 'd', fun_get_dir), - MAGIC_FUNCTION1(name_of, ".", 's'), - MAGIC_FUNCTION1(mob_id, "e", 'i'), - MAGIC_FUNCTION1(location, "e", 'l'), - MAGIC_FUNCTION1(random, "i", 'i'), - MAGIC_FUNCTION1(random_dir, "i", 'd'), - MAGIC_FUNCTION1(hash_entity, "e", 'i'), - MAGIC_FUNCTION1(is_married, "e", 'i'), - MAGIC_FUNCTION1(partner, "e", 'e'), - MAGIC_FUNCTION1(awayfrom, "ldi", 'l'), - MAGIC_FUNCTION1(failed, "_", 'i'), - MAGIC_FUNCTION1(pc, "s", 'e'), - MAGIC_FUNCTION1(npc, "s", 'e'), - MAGIC_FUNCTION1(distance, "ll", 'i'), - MAGIC_FUNCTION1(rdistance, "ll", 'i'), - MAGIC_FUNCTION1(anchor, "s", 'a'), - MAGIC_FUNCTION("random_location", "a", 'l', fun_pick_location), - MAGIC_FUNCTION("script_int", "es", 'i', fun_read_script_int), - MAGIC_FUNCTION("script_str", "es", 's', fun_read_script_str), - MAGIC_FUNCTION1(rbox, "li", 'a'), - MAGIC_FUNCTION1(count_item, "e.", 'i'), - MAGIC_FUNCTION1(line_of_sight, "ll", 'i'), - MAGIC_FUNCTION1(running_status_update, "ei", 'i'), - MAGIC_FUNCTION1(status_option, "ei", 'i'), - MAGIC_FUNCTION1(element, "e", 'i'), - MAGIC_FUNCTION1(element_level, "e", 'i'), - MAGIC_FUNCTION1(his_shroud, "e", 'i'), - MAGIC_FUNCTION1(is_equipped, "e.", 'i'), - MAGIC_FUNCTION1(is_exterior, "l", 'i'), - MAGIC_FUNCTION1(contains_string, "ss", 'i'), - MAGIC_FUNCTION1(strstr, "ss", 'i'), - MAGIC_FUNCTION1(strlen, "s", 'i'), - MAGIC_FUNCTION1(substr, "sii", 's'), - MAGIC_FUNCTION1(sqrt, "i", 'i'), - MAGIC_FUNCTION1(map_level, "l", 'i'), - MAGIC_FUNCTION1(map_nr, "l", 'i'), - MAGIC_FUNCTION1(dir_towards, "lli", 'd'), - MAGIC_FUNCTION1(is_dead, "e", 'i'), - MAGIC_FUNCTION1(is_pc, "e", 'i'), - MAGIC_FUNCTION("extract_healer_experience", "ei", 'i', fun_extract_healer_xp), + MAGIC_FUNCTION("+"_s, ".."_s, '.', fun_add), + MAGIC_FUNCTION("-"_s, "ii"_s, 'i', fun_sub), + MAGIC_FUNCTION("*"_s, "ii"_s, 'i', fun_mul), + MAGIC_FUNCTION("/"_s, "ii"_s, 'i', fun_div), + MAGIC_FUNCTION("%"_s, "ii"_s, 'i', fun_mod), + MAGIC_FUNCTION("||"_s, "ii"_s, 'i', fun_or), + MAGIC_FUNCTION("&&"_s, "ii"_s, 'i', fun_and), + MAGIC_FUNCTION("<"_s, ".."_s, 'i', fun_lt), + MAGIC_FUNCTION(">"_s, ".."_s, 'i', fun_gt), + MAGIC_FUNCTION("<="_s, ".."_s, 'i', fun_lte), + MAGIC_FUNCTION(">="_s, ".."_s, 'i', fun_gte), + MAGIC_FUNCTION("=="_s, ".."_s, 'i', fun_eq), + MAGIC_FUNCTION("!="_s, ".."_s, 'i', fun_ne), + MAGIC_FUNCTION("|"_s, ".."_s, 'i', fun_bitor), + MAGIC_FUNCTION("&"_s, "ii"_s, 'i', fun_bitand), + MAGIC_FUNCTION("^"_s, "ii"_s, 'i', fun_bitxor), + MAGIC_FUNCTION("<<"_s, "ii"_s, 'i', fun_bitshl), + MAGIC_FUNCTION(">>"_s, "ii"_s, 'i', fun_bitshr), + MAGIC_FUNCTION1(not, "i"_s, 'i'), + MAGIC_FUNCTION1(neg, "i"_s, 'i'), + MAGIC_FUNCTION1(max, "ii"_s, 'i'), + MAGIC_FUNCTION1(min, "ii"_s, 'i'), + MAGIC_FUNCTION1(is_in, "la"_s, 'i'), + MAGIC_FUNCTION1(if_then_else, "i__"_s, '_'), + MAGIC_FUNCTION1(skill, "ei"_s, 'i'), + MAGIC_FUNCTION("str"_s, "e"_s, 'i', fun_get_str), + MAGIC_FUNCTION("agi"_s, "e"_s, 'i', fun_get_agi), + MAGIC_FUNCTION("vit"_s, "e"_s, 'i', fun_get_vit), + MAGIC_FUNCTION("dex"_s, "e"_s, 'i', fun_get_dex), + MAGIC_FUNCTION("luk"_s, "e"_s, 'i', fun_get_luk), + MAGIC_FUNCTION("int"_s, "e"_s, 'i', fun_get_int), + MAGIC_FUNCTION("level"_s, "e"_s, 'i', fun_get_lv), + MAGIC_FUNCTION("mdef"_s, "e"_s, 'i', fun_get_mdef), + MAGIC_FUNCTION("def"_s, "e"_s, 'i', fun_get_def), + MAGIC_FUNCTION("hp"_s, "e"_s, 'i', fun_get_hp), + MAGIC_FUNCTION("max_hp"_s, "e"_s, 'i', fun_get_max_hp), + MAGIC_FUNCTION("sp"_s, "e"_s, 'i', fun_get_sp), + MAGIC_FUNCTION("max_sp"_s, "e"_s, 'i', fun_get_max_sp), + MAGIC_FUNCTION("dir"_s, "e"_s, 'd', fun_get_dir), + MAGIC_FUNCTION1(name_of, "."_s, 's'), + MAGIC_FUNCTION1(mob_id, "e"_s, 'i'), + MAGIC_FUNCTION1(location, "e"_s, 'l'), + MAGIC_FUNCTION1(random, "i"_s, 'i'), + MAGIC_FUNCTION1(random_dir, "i"_s, 'd'), + MAGIC_FUNCTION1(hash_entity, "e"_s, 'i'), + MAGIC_FUNCTION1(is_married, "e"_s, 'i'), + MAGIC_FUNCTION1(partner, "e"_s, 'e'), + MAGIC_FUNCTION1(awayfrom, "ldi"_s, 'l'), + MAGIC_FUNCTION1(failed, "_"_s, 'i'), + MAGIC_FUNCTION1(pc, "s"_s, 'e'), + MAGIC_FUNCTION1(npc, "s"_s, 'e'), + MAGIC_FUNCTION1(distance, "ll"_s, 'i'), + MAGIC_FUNCTION1(rdistance, "ll"_s, 'i'), + MAGIC_FUNCTION1(anchor, "s"_s, 'a'), + MAGIC_FUNCTION("random_location"_s, "a"_s, 'l', fun_pick_location), + MAGIC_FUNCTION("script_int"_s, "es"_s, 'i', fun_read_script_int), + MAGIC_FUNCTION("script_str"_s, "es"_s, 's', fun_read_script_str), + MAGIC_FUNCTION1(rbox, "li"_s, 'a'), + MAGIC_FUNCTION1(count_item, "e."_s, 'i'), + MAGIC_FUNCTION1(line_of_sight, "ll"_s, 'i'), + MAGIC_FUNCTION1(running_status_update, "ei"_s, 'i'), + MAGIC_FUNCTION1(status_option, "ei"_s, 'i'), + MAGIC_FUNCTION1(element, "e"_s, 'i'), + MAGIC_FUNCTION1(element_level, "e"_s, 'i'), + MAGIC_FUNCTION1(his_shroud, "e"_s, 'i'), + MAGIC_FUNCTION1(is_equipped, "e."_s, 'i'), + MAGIC_FUNCTION1(is_exterior, "l"_s, 'i'), + MAGIC_FUNCTION1(contains_string, "ss"_s, 'i'), + MAGIC_FUNCTION1(strstr, "ss"_s, 'i'), + MAGIC_FUNCTION1(strlen, "s"_s, 'i'), + MAGIC_FUNCTION1(substr, "sii"_s, 's'), + MAGIC_FUNCTION1(sqrt, "i"_s, 'i'), + MAGIC_FUNCTION1(map_level, "l"_s, 'i'), + MAGIC_FUNCTION1(map_nr, "l"_s, 'i'), + MAGIC_FUNCTION1(dir_towards, "lli"_s, 'd'), + MAGIC_FUNCTION1(is_dead, "e"_s, 'i'), + MAGIC_FUNCTION1(is_pc, "e"_s, 'i'), + MAGIC_FUNCTION("extract_healer_experience"_s, "ei"_s, 'i', fun_extract_healer_xp), }; fun_t *magic_get_fun(ZString name) @@ -1420,7 +1431,7 @@ dumb_ptr<area_t> eval_area(dumb_ptr<env_t> env, e_area_t& expr_) if (eval_location(env, &area->a.a_loc, &expr->a.a_loc)) { area.delete_(); - return NULL; + return nullptr; } else return area; @@ -1443,7 +1454,7 @@ dumb_ptr<area_t> eval_area(dumb_ptr<env_t> env, e_area_t& expr_) free_area(area->a.a_union[i]); } area.delete_(); - return NULL; + return nullptr; } area->size = area->a.a_union[0]->size + area->a.a_union[1]->size; return area; @@ -1473,7 +1484,7 @@ dumb_ptr<area_t> eval_area(dumb_ptr<env_t> env, e_area_t& expr_) area.delete_(); magic_clear_var(&width); magic_clear_var(&height); - return NULL; + return nullptr; } } @@ -1507,15 +1518,15 @@ dumb_ptr<area_t> eval_area(dumb_ptr<env_t> env, e_area_t& expr_) magic_clear_var(&width); magic_clear_var(&depth); magic_clear_var(&dir); - return NULL; + return nullptr; } } default: - FPRINTF(stderr, "INTERNAL ERROR: Unknown area type %d\n", + FPRINTF(stderr, "INTERNAL ERROR: Unknown area type %d\n"_fmt, area->ty); area.delete_(); - return NULL; + return nullptr; } } @@ -1559,13 +1570,13 @@ int magic_signature_check(ZString opname, ZString funname, ZString signature, if (ty == TYPE::ENTITY) { /* Dereference entities in preparation for calling function */ - arg->v.v_entity = map_id2bl(arg->v.v_int); + arg->v.v_entity = map_id2bl(wrap<BlockId>(static_cast<uint32_t>(arg->v.v_int))); if (!arg->v.v_entity) ty = arg->ty = TYPE::FAIL; } else if (ty == TYPE::INVOCATION) { - arg->v.v_invocation = map_id2bl(arg->v.v_int)->is_spell(); + arg->v.v_invocation = map_id2bl(wrap<BlockId>(static_cast<uint32_t>(arg->v.v_int)))->is_spell(); if (!arg->v.v_entity) ty = arg->ty = TYPE::FAIL; } @@ -1573,8 +1584,8 @@ int magic_signature_check(ZString opname, ZString funname, ZString signature, if (!ty_key) { FPRINTF(stderr, - "[magic-eval]: L%d:%d: Too many arguments (%zu) to %s `%s'\n", - line, column, args.size(), opname, funname); + "[magic-eval]: L%d:%d: Too many arguments (%zu) to %s `%s'\n"_fmt, + line, column, args.size(), opname, funname); return 1; } @@ -1587,8 +1598,8 @@ int magic_signature_check(ZString opname, ZString funname, ZString signature, if (ty == TYPE::UNDEF) { FPRINTF(stderr, - "[magic-eval]: L%d:%d: Argument #%d to %s `%s' undefined\n", - line, column, i + 1, opname, funname); + "[magic-eval]: L%d:%d: Argument #%d to %s `%s' undefined\n"_fmt, + line, column, i + 1, opname, funname); return 1; } @@ -1619,9 +1630,9 @@ int magic_signature_check(ZString opname, ZString funname, ZString signature, { /* Coercion failed? */ if (ty != TYPE::FAIL) FPRINTF(stderr, - "[magic-eval]: L%d:%d: Argument #%d to %s `%s' of incorrect type (%d)\n", - line, column, i + 1, opname, funname, - ty); + "[magic-eval]: L%d:%d: Argument #%d to %s `%s' of incorrect type (%d)\n"_fmt, + line, column, i + 1, opname, funname, + ty); return 1; } } @@ -1660,7 +1671,7 @@ void magic_eval(dumb_ptr<env_t> env, val_t *dest, dumb_ptr<expr_t> expr) for (i = 0; i < args_nr; ++i) magic_eval(env, &arguments[i], expr->e.e_funapp.args[i]); - if (magic_signature_check("function", f->name, f->signature, Slice<val_t>(arguments, args_nr), + if (magic_signature_check("function"_s, f->name, f->signature, Slice<val_t>(arguments, args_nr), expr->e.e_funapp.line_nr, expr->e.e_funapp.column) || f->fun(env, dest, Slice<val_t>(arguments, args_nr))) dest->ty = TYPE::FAIL; @@ -1674,7 +1685,7 @@ void magic_eval(dumb_ptr<env_t> env, val_t *dest, dumb_ptr<expr_t> expr) if (dest->ty == TYPE::ENTITY) { if (dest->v.v_entity) - dest->v.v_int = dest->v.v_entity->bl_id; + dest->v.v_int = static_cast<int32_t>(unwrap<BlockId>(dest->v.v_entity->bl_id)); else dest->ty = TYPE::FAIL; } @@ -1700,7 +1711,7 @@ void magic_eval(dumb_ptr<env_t> env, val_t *dest, dumb_ptr<expr_t> expr) if (v.ty == TYPE::INVOCATION) { - dumb_ptr<invocation> t = map_id2bl(v.v.v_int)->is_spell(); + dumb_ptr<invocation> t = map_id2bl(wrap<BlockId>(static_cast<uint32_t>(v.v.v_int)))->is_spell(); if (!t) dest->ty = TYPE::UNDEF; @@ -1713,8 +1724,8 @@ void magic_eval(dumb_ptr<env_t> env, val_t *dest, dumb_ptr<expr_t> expr) else { FPRINTF(stderr, - "[magic] Attempt to access field %s on non-spell\n", - env->base_env->varv[id].name); + "[magic] Attempt to access field %s on non-spell\n"_fmt, + env->base_env->varv[id].name); dest->ty = TYPE::FAIL; } break; @@ -1722,8 +1733,8 @@ void magic_eval(dumb_ptr<env_t> env, val_t *dest, dumb_ptr<expr_t> expr) default: FPRINTF(stderr, - "[magic] INTERNAL ERROR: Unknown expression type %d\n", - expr->ty); + "[magic] INTERNAL ERROR: Unknown expression type %d\n"_fmt, + expr->ty); break; } } @@ -1747,7 +1758,7 @@ AString magic_eval_str(dumb_ptr<env_t> env, dumb_ptr<expr_t> expr) magic_eval(env, &result, expr); if (result.ty == TYPE::FAIL || result.ty == TYPE::UNDEF) - return {"?"}; + return "?"_s; stringify(&result, 0); @@ -1760,3 +1771,4 @@ dumb_ptr<expr_t> magic_new_expr(EXPR ty) expr->ty = ty; return expr; } +} // namespace tmwa diff --git a/src/map/magic-expr.hpp b/src/map/magic-expr.hpp index 58f6596..e582a66 100644 --- a/src/map/magic-expr.hpp +++ b/src/map/magic-expr.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MAGIC_EXPR_HPP -#define TMWA_MAP_MAGIC_EXPR_HPP +#pragma once // magic-expr.hpp - Pure functions for the old magic backend. // // Copyright © 2004-2011 The Mana World Development Team @@ -20,15 +19,22 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "magic-interpreter.hpp" +#include "../generic/fwd.hpp" -# include "../range/slice.hpp" +#include "../range/fwd.hpp" -# include "../strings/fwd.hpp" -# include "../strings/zstring.hpp" +#include "../strings/zstring.hpp" +#include "../strings/literal.hpp" +#include "../mmo/fwd.hpp" + +#include "magic-interpreter.t.hpp" + + +namespace tmwa +{ /* * Argument types: * i : int @@ -44,34 +50,20 @@ */ struct fun_t { - ZString name; - ZString signature; + LString name; + LString signature; char ret_ty; int (*fun)(dumb_ptr<env_t> env, val_t *result, Slice<val_t> arga); }; -struct op_t -{ - ZString name; - ZString signature; - int (*op)(dumb_ptr<env_t> env, Slice<val_t> arga); -}; - /** * Retrieves a function by name * @param name The name to look up - * @return A function of that name, or NULL. + * @return A function of that name, or nullptr. */ fun_t *magic_get_fun(ZString name); /** - * Retrieves an operation by name - * @param name The name to look up - * @return An operation of that name, or NULL, and a function index - */ -op_t *magic_get_op(ZString name); - -/** * Evaluates an expression and stores the result in `dest' */ void magic_eval(dumb_ptr<env_t> env, val_t *dest, dumb_ptr<expr_t> expr); @@ -95,9 +87,9 @@ void magic_copy_var(val_t *dest, val_t *src); void magic_random_location(location_t *dest, dumb_ptr<area_t> area); // ret -1: not a string, ret 1: no such item, ret 0: OK -int magic_find_item(Slice<val_t> args, int index, struct item *item, int *stackable); +int magic_find_item(Slice<val_t> args, int index, Item *item, int *stackable); -# define GET_ARG_ITEM(index, dest, stackable) \ +#define GET_ARG_ITEM(index, dest, stackable) \ switch (magic_find_item(args, index, &dest, &stackable)) \ { \ case -1: return 1; \ @@ -107,4 +99,11 @@ int magic_find_item(Slice<val_t> args, int index, struct item *item, int *stacka int magic_location_in_area(map_local *m, int x, int y, dumb_ptr<area_t> area); -#endif // TMWA_MAP_MAGIC_EXPR_HPP +/* Helper definitions for dealing with functions and operations */ + +int magic_signature_check(ZString opname, ZString funname, ZString signature, + Slice<val_t> args, int line, int column); + +void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height, + area_t& area); +} // namespace tmwa diff --git a/src/map/magic-interpreter-base.cpp b/src/map/magic-interpreter-base.cpp index d86f595..768a7df 100644 --- a/src/map/magic-interpreter-base.cpp +++ b/src/map/magic-interpreter-base.cpp @@ -19,22 +19,25 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include "magic-interpreter-aux.hpp" -#include "magic-interpreter.hpp" +#include <algorithm> #include "../strings/astring.hpp" #include "../strings/xstring.hpp" #include "../io/cxxstdio.hpp" -#include "../mmo/timer.hpp" +#include "../net/timer.hpp" +#include "magic.hpp" #include "magic-expr.hpp" - +#include "magic-interpreter.hpp" #include "pc.hpp" #include "../poison.hpp" + +namespace tmwa +{ static void set_int_p(val_t *v, int i, TYPE t) { @@ -43,8 +46,8 @@ void set_int_p(val_t *v, int i, TYPE t) } #warning "This code should die" -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-macros" +DIAG_PUSH(); +DIAG_I(unused_macros); #define set_int(v, i) set_int_p(v, i, TYPE::INT) #define set_dir(v, i) set_int_p(v, i, TYPE::DIR) @@ -58,14 +61,14 @@ static void set_entity(val_t *v, dumb_ptr<block_list> e) { v->ty = TYPE::ENTITY; - v->v.v_int = e->bl_id; + v->v.v_int = static_cast<int32_t>(unwrap<BlockId>(e->bl_id)); } static void set_invocation(val_t *v, dumb_ptr<invocation> i) { v->ty = TYPE::INVOCATION; - v->v.v_int = i->bl_id; + v->v.v_int = static_cast<int32_t>(unwrap<BlockId>(i->bl_id)); } static @@ -82,10 +85,10 @@ void set_spell SETTER(dumb_ptr<spell_t>, TYPE::SPELL, v_spell) #define set_env_invocation(v, x) setenv(set_invocation, v, x) #define set_env_spell(v, x) setenv(set_spell, v, x) -#pragma GCC diagnostic pop +DIAG_POP(); magic_conf_t magic_conf; /* Global magic conf */ -env_t magic_default_env = { &magic_conf, NULL }; +env_t magic_default_env = { &magic_conf, nullptr }; AString magic_find_invocation(XString spellname) { @@ -102,7 +105,7 @@ dumb_ptr<spell_t> magic_find_spell(XString invocation) if (it != magic_conf.spells_by_invocation.end()) return it->second; - return NULL; + return nullptr; } /* -------------------------------------------------------------------------------- */ @@ -125,7 +128,7 @@ dumb_ptr<teleport_anchor_t> magic_find_anchor(XString name) if (it != magic_conf.anchors_by_invocation.end()) return it->second; - return NULL; + return nullptr; } /* -------------------------------------------------------------------------------- */ @@ -187,8 +190,8 @@ dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell, break; default: - FPRINTF(stderr, "Unexpected spellarg type %d\n", - spell->spellarg_ty); + FPRINTF(stderr, "Unexpected spellarg type %d\n"_fmt, + spell->spellarg_ty); } set_env_entity(VAR_CASTER, caster); @@ -201,22 +204,22 @@ dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell, static void free_components(dumb_ptr<component_t> *component_holder) { - if (*component_holder == NULL) + if (*component_holder == nullptr) return; free_components(&(*component_holder)->next); (*component_holder).delete_(); - *component_holder = NULL; + *component_holder = nullptr; } -void magic_add_component(dumb_ptr<component_t> *component_holder, int id, int count) +void magic_add_component(dumb_ptr<component_t> *component_holder, ItemNameId id, int count) { if (count <= 0) return; - if (*component_holder == NULL) + if (*component_holder == nullptr) { auto component = dumb_ptr<component_t>::make(); - component->next = NULL; + component->next = nullptr; component->item_id = id; component->count = count; *component_holder = component; @@ -238,7 +241,7 @@ void magic_add_component(dumb_ptr<component_t> *component_holder, int id, int co static void copy_components(dumb_ptr<component_t> *component_holder, dumb_ptr<component_t> component) { - if (component == NULL) + if (component == nullptr) return; magic_add_component(component_holder, component->item_id, component->count); @@ -296,7 +299,7 @@ int spellguard_can_satisfy(spellguard_check_t *check, dumb_ptr<map_session_data> interval_t casttime = check->casttime; if (env->VAR(VAR_MIN_CASTTIME).ty == TYPE::INT) - casttime = max(casttime, static_cast<interval_t>(env->VAR(VAR_MIN_CASTTIME).v.v_int)); + casttime = std::max(casttime, static_cast<interval_t>(env->VAR(VAR_MIN_CASTTIME).v.v_int)); caster->cast_tick = tick + casttime; /* Make sure not to cast too frequently */ @@ -314,14 +317,14 @@ effect_set_t *spellguard_check_sub(spellguard_check_t *check, dumb_ptr<env_t> env, int *near_miss) { - if (guard == NULL) - return NULL; + if (guard == nullptr) + return nullptr; switch (guard->ty) { case SPELLGUARD::CONDITION: if (!magic_eval_int(env, guard->s.s_condition)) - return NULL; + return nullptr; break; case SPELLGUARD::COMPONENTS: @@ -337,8 +340,8 @@ effect_set_t *spellguard_check_sub(spellguard_check_t *check, spellguard_check_t altcheck = *check; effect_set_t *retval; - altcheck.components = NULL; - altcheck.catalysts = NULL; + altcheck.components = nullptr; + altcheck.catalysts = nullptr; copy_components(&altcheck.catalysts, check->catalysts); copy_components(&altcheck.components, check->components); @@ -367,12 +370,12 @@ effect_set_t *spellguard_check_sub(spellguard_check_t *check, if (spellguard_can_satisfy(check, caster, env, near_miss)) return &guard->s.s_effect; else - return NULL; + return nullptr; default: - FPRINTF(stderr, "Unexpected spellguard type %d\n", + FPRINTF(stderr, "Unexpected spellguard type %d\n"_fmt, guard->ty); - return NULL; + return nullptr; } return spellguard_check_sub(check, guard->next, caster, env, near_miss); @@ -385,8 +388,8 @@ effect_set_t *check_spellguard(dumb_ptr<spellguard_t> guard, { spellguard_check_t check; effect_set_t *retval; - check.catalysts = NULL; - check.components = NULL; + check.catalysts = nullptr; + check.components = nullptr; check.mana = 0; check.casttime = interval_t::zero(); @@ -449,7 +452,7 @@ dumb_ptr<invocation> spell_instantiate(effect_set_t *effect_set, dumb_ptr<env_t> retval->env = env; - retval->caster = env->VAR(VAR_CASTER).v.v_int; + retval->caster = wrap<BlockId>(static_cast<uint32_t>(env->VAR(VAR_CASTER).v.v_int)); retval->spell = env->VAR(VAR_SPELL).v.v_spell; retval->stack_size = 0; retval->current_effect = effect_set->effect; @@ -478,12 +481,12 @@ dumb_ptr<invocation> spell_clone_effect(dumb_ptr<invocation> base) // since this is the only call site, it is expanded here //*retval = *base; - retval->next_invocation = NULL; + retval->next_invocation = nullptr; retval->flags = INVOCATION_FLAG::ZERO; dumb_ptr<env_t> env = retval->env = clone_env(base->env); retval->spell = base->spell; retval->caster = base->caster; - retval->subject = 0; + retval->subject = BlockId(); // retval->timer = 0; retval->stack_size = 0; // retval->stack = undef; @@ -491,12 +494,12 @@ dumb_ptr<invocation> spell_clone_effect(dumb_ptr<invocation> base) // huh? retval->current_effect = base->trigger_effect; retval->trigger_effect = base->trigger_effect; - retval->end_effect = NULL; - // retval->status_change_refs = NULL; + retval->end_effect = nullptr; + // retval->status_change_refs = nullptr; - retval->bl_id = 0; - retval->bl_prev = NULL; - retval->bl_next = NULL; + retval->bl_id = BlockId(); + retval->bl_prev = nullptr; + retval->bl_next = nullptr; retval->bl_m = base->bl_m; retval->bl_x = base->bl_x; retval->bl_y = base->bl_y; @@ -517,10 +520,10 @@ void spell_bind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invocat if (bool(invocation->flags & INVOCATION_FLAG::BOUND) || invocation->subject || invocation->next_invocation) { - int *i = NULL; + int *i = nullptr; FPRINTF(stderr, - "[magic] INTERNAL ERROR: Attempt to re-bind spell invocation `%s'\n", - invocation->spell->name); + "[magic] INTERNAL ERROR: Attempt to re-bind spell invocation `%s'\n"_fmt, + invocation->spell->name); *i = 1; return; } @@ -545,8 +548,8 @@ int spell_unbind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invoca *seeker = invocation_->next_invocation; invocation_->flags &= ~INVOCATION_FLAG::BOUND; - invocation_->next_invocation = NULL; - invocation_->subject = 0; + invocation_->next_invocation = nullptr; + invocation_->subject = BlockId(); return 0; } @@ -555,3 +558,4 @@ int spell_unbind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invoca return 1; } +} // namespace tmwa diff --git a/src/map/magic-interpreter-base.hpp b/src/map/magic-interpreter-base.hpp index 9b1e08a..57dde85 100644 --- a/src/map/magic-interpreter-base.hpp +++ b/src/map/magic-interpreter-base.hpp @@ -1,8 +1,8 @@ -#ifndef TMWA_MAP_MAGIC_INTERPRETER_BASE_HPP -#define TMWA_MAP_MAGIC_INTERPRETER_BASE_HPP -// magic-interpreter-base.hpp - dummy header to make Make dependencies work. +#pragma once +// magic-interpreter-base.hpp - Core of the old magic system. // -// Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> +// Copyright © 2004-2011 The Mana World Development Team +// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> // // This file is part of The Mana World (Athena server) // @@ -19,6 +19,69 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -#endif // TMWA_MAP_MAGIC_INTERPRETER_BASE_HPP +#include "../strings/fwd.hpp" + +#include "../generic/fwd.hpp" + +#include "../mmo/fwd.hpp" + + +namespace tmwa +{ +extern magic_conf_t magic_conf; /* Global magic conf */ +extern env_t magic_default_env; /* Fake default environment */ + +/** + * Adds a component selection to a component holder (which may initially be nullptr) + */ +void magic_add_component(dumb_ptr<component_t> *component_holder, ItemNameId id, int count); + +/** + * Identifies the invocation used to trigger a spell + * + * Returns empty string if not found + */ +AString magic_find_invocation(XString spellname); + +/** + * Identifies the invocation used to denote a teleport location + * + * Returns empty string if not found + */ +AString magic_find_anchor_invocation(XString teleport_location); + +dumb_ptr<teleport_anchor_t> magic_find_anchor(XString name); + +dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell, + dumb_ptr<map_session_data> caster, int spellpower, XString param); + +void magic_free_env(dumb_ptr<env_t> env); + +/** + * near_miss is set to nonzero iff the spell only failed due to ephemereal issues (spell delay in effect, out of mana, out of components) + */ +effect_set_t *spell_trigger(dumb_ptr<spell_t> spell, + dumb_ptr<map_session_data> caster, + dumb_ptr<env_t> env, int *near_miss); + +dumb_ptr<invocation> spell_instantiate(effect_set_t *effect, dumb_ptr<env_t> env); + +/** + * Bind a spell to a subject (this is a no-op for `local' spells). + */ +void spell_bind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invocation); + +// 1 on failure +int spell_unbind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invocation); + +/** + * Clones a spell to run the at_effect field + */ +dumb_ptr<invocation> spell_clone_effect(dumb_ptr<invocation> source); + +dumb_ptr<spell_t> magic_find_spell(XString invocation); + +void spell_update_location(dumb_ptr<invocation> invocation); +} // namespace tmwa diff --git a/src/map/magic-interpreter.cpp b/src/map/magic-interpreter.cpp index 4680971..87ac23e 100644 --- a/src/map/magic-interpreter.cpp +++ b/src/map/magic-interpreter.cpp @@ -1,5 +1,5 @@ #include "magic-interpreter.hpp" -// magic-interpreter.hpp - Old magic. +// magic-interpreter.cpp - Old magic. // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> // @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/map/magic-interpreter.hpp b/src/map/magic-interpreter.hpp index 7d529ee..c9b6c97 100644 --- a/src/map/magic-interpreter.hpp +++ b/src/map/magic-interpreter.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MAGIC_INTERPRETER_HPP -#define TMWA_MAP_MAGIC_INTERPRETER_HPP +#pragma once // magic-interpreter.hpp - Old magic. // // Copyright © 2004-2011 The Mana World Development Team @@ -20,29 +19,31 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "magic-interpreter.t.hpp" +#include "magic-interpreter.t.hpp" -# include <cassert> +#include <cassert> -# include "../strings/fwd.hpp" -# include "../strings/rstring.hpp" +#include <memory> -# include "magic.hpp" -# include "map.hpp" -# include "script.hpp" -# include "skill.t.hpp" +#include "../strings/fwd.hpp" +#include "../strings/rstring.hpp" -struct fun_t; -struct op_t; -struct expr_t; -struct val_t; -struct location_t; -struct area_t; -struct spell_t; -struct invocation; +#include "../generic/fwd.hpp" +#include "../net/timer.t.hpp" + +#include "../mmo/ids.hpp" +#include "../mmo/utils.hpp" + +#include "map.hpp" +#include "script.hpp" +#include "skill.t.hpp" + + +namespace tmwa +{ struct location_t { map_local *m; @@ -103,7 +104,7 @@ struct val_t /* Expressions */ /* ----------- */ -# define MAX_ARGS 7 /* Max. # of args used in builtin primitive functions */ +#define MAX_ARGS 7 /* Max. # of args used in builtin primitive functions */ struct e_location_t { @@ -223,7 +224,7 @@ struct effect_t struct component_t { dumb_ptr<component_t> next; - int item_id; + ItemNameId item_id; int count; }; @@ -309,17 +310,15 @@ struct magic_conf_t /* Execution environment */ // these are not an enum they're a nasty intern hack -# define VAR_MIN_CASTTIME 0 -# define VAR_OBSCURE_CHANCE 1 -# define VAR_CASTER 2 -# define VAR_SPELLPOWER 3 -# define VAR_SPELL 4 -# define VAR_INVOCATION 5 -# define VAR_TARGET 6 -# define VAR_SCRIPTTARGET 7 -# define VAR_LOCATION 8 - -struct magic_config; +#define VAR_MIN_CASTTIME 0 +#define VAR_OBSCURE_CHANCE 1 +#define VAR_CASTER 2 +#define VAR_SPELLPOWER 3 +#define VAR_SPELL 4 +#define VAR_INVOCATION 5 +#define VAR_TARGET 6 +#define VAR_SCRIPTTARGET 7 +#define VAR_LOCATION 8 struct env_t { @@ -337,7 +336,7 @@ struct env_t }; -# define MAX_STACK_SIZE 32 +#define MAX_STACK_SIZE 32 struct cont_activation_record_t { @@ -349,7 +348,7 @@ struct cont_activation_record_t int id; TYPE ty; dumb_ptr<effect_t> body; - dumb_ptr<std::vector<int>> entities_vp; + dumb_ptr<std::vector<BlockId>> entities_vp; int index; } c_foreach; struct @@ -377,7 +376,7 @@ struct cont_activation_record_t struct status_change_ref_t { StatusChange sc_type; - int bl_id; + BlockId bl_id; }; struct invocation : block_list @@ -387,8 +386,8 @@ struct invocation : block_list dumb_ptr<env_t> env; dumb_ptr<spell_t> spell; - int caster; /* this is the person who originally invoked the spell */ - int subject; /* when this person dies, the spell dies with it */ + BlockId caster; /* this is the person who originally invoked the spell */ + BlockId subject; /* when this person dies, the spell dies with it */ Timer timer; /* spell timer, if any */ @@ -397,56 +396,18 @@ struct invocation : block_list int script_pos; /* Script position; if nonzero, resume the script we were running. */ dumb_ptr<effect_t> current_effect; - dumb_ptr<effect_t> trigger_effect; /* If non-NULL, this is used to spawn a cloned effect based on the same environment */ - dumb_ptr<effect_t> end_effect; /* If non-NULL, this is executed when the spell terminates naturally, e.g. when all status changes have run out or all delays are over. */ + dumb_ptr<effect_t> trigger_effect; /* If non-nullptr, this is used to spawn a cloned effect based on the same environment */ + dumb_ptr<effect_t> end_effect; /* If non-nullptr, this is executed when the spell terminates naturally, e.g. when all status changes have run out or all delays are over. */ /* Status change references: for status change updates, keep track of whom we updated where */ std::vector<status_change_ref_t> status_change_refv; }; +// inlines for map.hpp inline dumb_ptr<invocation> block_list::as_spell() { return dumb_ptr<invocation>(static_cast<invocation *>(this)); } inline dumb_ptr<invocation> block_list::is_spell() { return bl_type == BL::SPELL ? as_spell() : nullptr; } -extern magic_conf_t magic_conf; /* Global magic conf */ -extern env_t magic_default_env; /* Fake default environment */ - -/** - * Adds a component selection to a component holder (which may initially be NULL) - */ -void magic_add_component(dumb_ptr<component_t> *component_holder, int id, int count); - -dumb_ptr<teleport_anchor_t> magic_find_anchor(XString name); - -dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell, - dumb_ptr<map_session_data> caster, int spellpower, XString param); - -void magic_free_env(dumb_ptr<env_t> env); - -/** - * near_miss is set to nonzero iff the spell only failed due to ephemereal issues (spell delay in effect, out of mana, out of components) - */ -effect_set_t *spell_trigger(dumb_ptr<spell_t> spell, - dumb_ptr<map_session_data> caster, - dumb_ptr<env_t> env, int *near_miss); - -dumb_ptr<invocation> spell_instantiate(effect_set_t *effect, dumb_ptr<env_t> env); - -/** - * Bind a spell to a subject (this is a no-op for `local' spells). - */ -void spell_bind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invocation); - -// 1 on failure -int spell_unbind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invocation); - -/** - * Clones a spell to run the at_effect field - */ -dumb_ptr<invocation> spell_clone_effect(dumb_ptr<invocation> source); - -dumb_ptr<spell_t> magic_find_spell(XString invocation); - /* The following is used only by the parser: */ struct args_rec_t { @@ -465,7 +426,4 @@ struct proc_t , body() {} }; - -void spell_update_location(dumb_ptr<invocation> invocation); - -#endif // TMWA_MAP_MAGIC_INTERPRETER_HPP +} // namespace tmwa diff --git a/src/map/magic-interpreter.py b/src/map/magic-interpreter.py index 8170f27..f6fa4c9 100644 --- a/src/map/magic-interpreter.py +++ b/src/map/magic-interpreter.py @@ -2,7 +2,7 @@ class area_t(object): ''' print an area_t ''' __slots__ = ('_value') - name = 'area_t' + name = 'tmwa::area_t' enabled = True def __init__(self, value): @@ -31,7 +31,7 @@ class val_t(object): ''' print a val_t ''' __slots__ = ('_value') - name = 'val_t' + name = 'tmwa::val_t' enabled = True def __init__(self, value): @@ -69,7 +69,7 @@ class e_area_t(object): ''' print an e_area_t ''' __slots__ = ('_value') - name = 'e_area_t' + name = 'tmwa::e_area_t' enabled = True def __init__(self, value): @@ -97,7 +97,7 @@ class expr_t(object): ''' print an expr_t ''' __slots__ = ('_value') - name = 'expr_t' + name = 'tmwa::expr_t' enabled = True def __init__(self, value): @@ -129,7 +129,7 @@ class effect_t(object): ''' print an effect_t ''' __slots__ = ('_value') - name = 'effect_t' + name = 'tmwa::effect_t' enabled = True def __init__(self, value): @@ -166,7 +166,7 @@ class spellguard_t(object): ''' print a spellguard_t ''' __slots__ = ('_value') - name = 'spellguard_t' + name = 'tmwa::spellguard_t' enabled = True def __init__(self, value): @@ -201,7 +201,7 @@ class cont_activation_record_t(object): ''' print a cont_activation_record_t ''' __slots__ = ('_value') - name = 'cont_activation_record_t' + name = 'tmwa::cont_activation_record_t' enabled = True def __init__(self, value): diff --git a/src/map/magic-interpreter.t.hpp b/src/map/magic-interpreter.t.hpp index 9310a7b..6c7ff81 100644 --- a/src/map/magic-interpreter.t.hpp +++ b/src/map/magic-interpreter.t.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MAGIC_INTERPRETER_T_HPP -#define TMWA_MAP_MAGIC_INTERPRETER_T_HPP +#pragma once // magic-interpreter.t.hpp - Old magic. // // Copyright © 2004-2011 The Mana World Development Team @@ -20,10 +19,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../generic/enum.hpp" +#include "../generic/enum.hpp" + +namespace tmwa +{ enum class SPELLARG : uint8_t { NONE, @@ -47,38 +49,6 @@ enum class TYPE : uint8_t NEGATIVE_1 = 255, }; -// Note: there is also a typedef by this name in <dirent.h> -// but we should be fine since we never include it. -// (in the long term we should still rename this though) -enum class DIR : uint8_t -{ - S = 0, - SW = 1, - W = 2, - NW = 3, - N = 4, - NE = 5, - E = 6, - SE = 7, - - COUNT, -}; - -constexpr -earray<int, DIR, DIR::COUNT> dirx //= -{{ - 0, -1, -1, -1, 0, 1, 1, 1, -}}, diry //= -{{ - 1, 1, 0, -1, -1, -1, 0, 1, -}}; - -constexpr -bool dir_is_diagonal(DIR d) -{ - return static_cast<uint8_t>(d) & 1; -} - enum class AREA : uint8_t { LOCATION, @@ -176,5 +146,4 @@ enum class INVOCATION_FLAG : uint8_t ENUM_BITWISE_OPERATORS(INVOCATION_FLAG) } using e::INVOCATION_FLAG; - -#endif // TMWA_MAP_MAGIC_INTERPRETER_T_HPP +} // namespace tmwa diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp index ba99409..9aca511 100644 --- a/src/map/magic-stmt.cpp +++ b/src/map/magic-stmt.cpp @@ -30,15 +30,15 @@ #include "../io/cxxstdio.hpp" -#include "../mmo/timer.hpp" +#include "../net/timer.hpp" +#include "battle.hpp" +#include "clif.hpp" +#include "magic.hpp" #include "magic-expr.hpp" #include "magic-expr-eval.hpp" #include "magic-interpreter.hpp" -#include "magic-interpreter-aux.hpp" - -#include "battle.hpp" -#include "clif.hpp" +#include "magic-interpreter-base.hpp" #include "mob.hpp" #include "npc.hpp" #include "pc.hpp" @@ -46,8 +46,11 @@ #include "../poison.hpp" + +namespace tmwa +{ /* used for local spell effects */ -constexpr int INVISIBLE_NPC = 127; +constexpr Species INVISIBLE_NPC = wrap<Species>(127); //#define DEBUG @@ -58,19 +61,19 @@ void print_val(val_t *v) switch (v->ty) { case TYPE::UNDEF: - FPRINTF(stderr, "UNDEF"); + FPRINTF(stderr, "UNDEF"_fmt); break; case TYPE::INT: - FPRINTF(stderr, "%d", v->v.v_int); + FPRINTF(stderr, "%d"_fmt, v->v.v_int); break; case TYPE::DIR: - FPRINTF(stderr, "dir%d", v->v.v_int); + FPRINTF(stderr, "dir%d"_fmt, v->v.v_int); break; case TYPE::STRING: - FPRINTF(stderr, "`%s'", v->v.v_string); + FPRINTF(stderr, "`%s'"_fmt, v->v.v_string); break; default: - FPRINTF(stderr, "ty%d", v->ty); + FPRINTF(stderr, "ty%d"_fmt, v->ty); break; } } @@ -84,11 +87,11 @@ void dump_env(env_t *env) val_t *v = &env->vars[i]; val_t *bv = &env->base_env->vars[i]; - FPRINTF(stderr, "%02x %30s ", i, env->base_env->var_name[i]); + FPRINTF(stderr, "%02x %30s "_fmt, i, env->base_env->var_name[i]); print_val(v); - FPRINTF(stderr, "\t("); + FPRINTF(stderr, "\t("_fmt); print_val(bv); - FPRINTF(stderr, ")\n"); + FPRINTF(stderr, ")\n"_fmt); } } #endif @@ -108,7 +111,7 @@ void clear_activation_record(cont_activation_record_t *ar) } static -void invocation_timer_callback(TimerData *, tick_t, int id) +void invocation_timer_callback(TimerData *, tick_t, BlockId id) { dumb_ptr<invocation> invocation = map_id_is_spell(id); @@ -153,7 +156,7 @@ void spell_free_invocation(dumb_ptr<invocation> invocation_) static void char_set_weapon_icon(dumb_ptr<map_session_data> subject, int count, - StatusChange icon, int look) + StatusChange icon, ItemNameId look) { const StatusChange old_icon = subject->attack_spell_icon_override; @@ -166,7 +169,7 @@ void char_set_weapon_icon(dumb_ptr<map_session_data> subject, int count, clif_fixpcpos(subject); if (count) { - clif_changelook(subject, LOOK::WEAPON, look); + clif_changelook(subject, LOOK::WEAPON, unwrap<ItemNameId>(look)); if (icon != StatusChange::ZERO) clif_status_change(subject, icon, 1); } @@ -202,7 +205,7 @@ void magic_stop_completely(dumb_ptr<map_session_data> c) { // Zap all status change references to spells for (StatusChange i : erange(StatusChange(), StatusChange::MAX_STATUSCHANGE)) - c->sc_data[i].spell_invocation = 0; + c->sc_data[i].spell_invocation = BlockId(); while (c->active_spells) spell_free_invocation(c->active_spells); @@ -212,8 +215,8 @@ void magic_stop_completely(dumb_ptr<map_session_data> c) dumb_ptr<invocation> attack_spell = map_id_is_spell(c->attack_spell_override); if (attack_spell) spell_free_invocation(attack_spell); - c->attack_spell_override = 0; - char_set_weapon_icon(c, 0, StatusChange::ZERO, 0); + c->attack_spell_override = BlockId(); + char_set_weapon_icon(c, 0, StatusChange::ZERO, ItemNameId()); char_set_attack_info(c, interval_t::zero(), 0); } } @@ -228,7 +231,7 @@ void try_to_finish_invocation(dumb_ptr<invocation> invocation) { clear_stack(invocation); invocation->current_effect = invocation->end_effect; - invocation->end_effect = NULL; + invocation->end_effect = nullptr; spell_execute(invocation); } else @@ -237,19 +240,19 @@ void try_to_finish_invocation(dumb_ptr<invocation> invocation) } static -int trigger_spell(int subject, int spell) +BlockId trigger_spell(BlockId subject, BlockId spell) { dumb_ptr<invocation> invocation_ = map_id_is_spell(spell); if (!invocation_) - return 0; + return BlockId(); invocation_ = spell_clone_effect(invocation_); spell_bind(map_id_is_player(subject), invocation_); magic_clear_var(&invocation_->env->varu[VAR_CASTER]); invocation_->env->varu[VAR_CASTER].ty = TYPE::ENTITY; - invocation_->env->varu[VAR_CASTER].v.v_int = subject; + invocation_->env->varu[VAR_CASTER].v.v_int = static_cast<int32_t>(unwrap<BlockId>(subject)); return invocation_->bl_id; } @@ -265,7 +268,7 @@ void char_update(dumb_ptr<map_session_data> character) } static -void timer_callback_effect(TimerData *, tick_t, int id, int data) +void timer_callback_effect(TimerData *, tick_t, BlockId id, int data) { dumb_ptr<block_list> target = map_id2bl(id); if (target) @@ -286,12 +289,12 @@ void magic_unshroud(dumb_ptr<map_session_data> other_char) other_char->state.shroud_active = 0; // Now warp the caster out of and back into here to refresh everyone's display char_update(other_char); - clif_displaymessage(other_char->sess, "Your shroud has been dispelled!"); + clif_displaymessage(other_char->sess, "Your shroud has been dispelled!"_s); // entity_effect(other_char, MAGIC_EFFECT_REVEAL); } static -void timer_callback_effect_npc_delete(TimerData *, tick_t, int npc_id) +void timer_callback_effect_npc_delete(TimerData *, tick_t, BlockId npc_id) { dumb_ptr<npc_data> effect_npc = map_id_is_npc(npc_id); npc_free(effect_npc); @@ -302,10 +305,10 @@ dumb_ptr<npc_data> local_spell_effect(map_local *m, int x, int y, int effect, interval_t tdelay) { /* 1 minute should be enough for all interesting spell effects, I hope */ - std::chrono::seconds delay = std::chrono::seconds(30); + std::chrono::seconds delay = 30_s; dumb_ptr<npc_data> effect_npc = npc_spawn_text(m, x, y, - INVISIBLE_NPC, NpcName(), "?"); - int effect_npc_id = effect_npc->bl_id; + INVISIBLE_NPC, NpcName(), "?"_s); + BlockId effect_npc_id = effect_npc->bl_id; entity_effect(effect_npc, effect, tdelay); Timer(gettick() + delay, @@ -341,7 +344,7 @@ static int op_instaheal(dumb_ptr<env_t> env, Slice<val_t> args) { dumb_ptr<block_list> caster = (env->VAR(VAR_CASTER).ty == TYPE::ENTITY) - ? map_id2bl(env->VAR(VAR_CASTER).v.v_int) : NULL; + ? map_id2bl(wrap<BlockId>(static_cast<uint32_t>(env->VAR(VAR_CASTER).v.v_int))) : nullptr; dumb_ptr<block_list> subject = ARGENTITY(0); if (!caster) caster = subject; @@ -350,8 +353,8 @@ int op_instaheal(dumb_ptr<env_t> env, Slice<val_t> args) { dumb_ptr<map_session_data> caster_pc = caster->is_player(); dumb_ptr<map_session_data> subject_pc = subject->is_player(); - MAP_LOG_PC(caster_pc, "SPELLHEAL-INSTA PC%d FOR %d", - subject_pc->status_key.char_id, ARGINT(1)); + MAP_LOG_PC(caster_pc, "SPELLHEAL-INSTA PC%d FOR %d"_fmt, + subject_pc->status_key.char_id, ARGINT(1)); } battle_heal(caster, subject, ARGINT(1), ARGINT(2), 0); @@ -430,7 +433,7 @@ int op_message(dumb_ptr<env_t>, Slice<val_t> args) } static -void timer_callback_kill_npc(TimerData *, tick_t, int npc_id) +void timer_callback_kill_npc(TimerData *, tick_t, BlockId npc_id) { dumb_ptr<npc_data> npc = map_id_is_npc(npc_id); if (npc) @@ -445,7 +448,7 @@ int op_messenger_npc(dumb_ptr<env_t>, Slice<val_t> args) NpcName npcname = stringish<NpcName>(ARGSTR(2)); npc = npc_spawn_text(loc->m, loc->x, loc->y, - ARGINT(1), npcname, ARGSTR(3)); + wrap<Species>(static_cast<uint16_t>(ARGINT(1))), npcname, ARGSTR(3)); Timer(gettick() + static_cast<interval_t>(ARGINT(4)), std::bind(timer_callback_kill_npc, ph::_1, ph::_2, @@ -537,7 +540,7 @@ int op_banish(dumb_ptr<env_t>, Slice<val_t> args) } static -void record_status_change(dumb_ptr<invocation> invocation_, int bl_id, +void record_status_change(dumb_ptr<invocation> invocation_, BlockId bl_id, StatusChange sc_id) { status_change_ref_t cr {}; @@ -551,8 +554,8 @@ static int op_status_change(dumb_ptr<env_t> env, Slice<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); - int invocation_id = env->VAR(VAR_INVOCATION).ty == TYPE::INVOCATION - ? env->VAR(VAR_INVOCATION).v.v_int : 0; + BlockId invocation_id = env->VAR(VAR_INVOCATION).ty == TYPE::INVOCATION + ? wrap<BlockId>(static_cast<uint32_t>(env->VAR(VAR_INVOCATION).v.v_int)) : BlockId(); dumb_ptr<invocation> invocation_ = map_id_is_spell(invocation_id); assert (!ARGINT(3)); @@ -563,7 +566,7 @@ int op_status_change(dumb_ptr<env_t> env, Slice<val_t> args) static_cast<interval_t>(ARGINT(6)), invocation_id); if (invocation_ && subject->bl_type == BL::PC) - record_status_change(invocation_, subject->bl_id, StatusChange(ARGINT(1))); + record_status_change(invocation_, subject->bl_id, static_cast<StatusChange>(ARGINT(1))); return 0; } @@ -587,7 +590,7 @@ int op_override_attack(dumb_ptr<env_t> env, Slice<val_t> args) interval_t attack_delay = static_cast<interval_t>(ARGINT(2)); int attack_range = ARGINT(3); StatusChange icon = StatusChange(ARGINT(4)); - int look = ARGINT(5); + ItemNameId look = wrap<ItemNameId>(static_cast<uint16_t>(ARGINT(5))); int stopattack = ARGINT(6); dumb_ptr<map_session_data> subject; @@ -604,7 +607,7 @@ int op_override_attack(dumb_ptr<env_t> env, Slice<val_t> args) } subject->attack_spell_override = - trigger_spell(subject->bl_id, env->VAR(VAR_INVOCATION).v.v_int); + trigger_spell(subject->bl_id, wrap<BlockId>(static_cast<uint32_t>(env->VAR(VAR_INVOCATION).v.v_int))); subject->attack_spell_charges = charges; if (subject->attack_spell_override) @@ -623,7 +626,7 @@ int op_override_attack(dumb_ptr<env_t> env, Slice<val_t> args) static int op_create_item(dumb_ptr<env_t>, Slice<val_t> args) { - struct item item; + Item item; dumb_ptr<block_list> entity = ARGENTITY(0); dumb_ptr<map_session_data> subject; int stackable; @@ -698,13 +701,13 @@ int op_spawn(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<area_t> area = ARGAREA(0); dumb_ptr<block_list> owner_e = ARGENTITY(1); - int monster_id = ARGINT(2); + Species monster_id = wrap<Species>(ARGINT(2)); MonsterAttitude monster_attitude = static_cast<MonsterAttitude>(ARGINT(3)); int monster_count = ARGINT(4); interval_t monster_lifetime = static_cast<interval_t>(ARGINT(5)); int i; - dumb_ptr<map_session_data> owner = NULL; + dumb_ptr<map_session_data> owner = nullptr; if (monster_attitude == MonsterAttitude::SERVANT && owner_e->bl_type == BL::PC) owner = owner_e->is_player(); @@ -714,7 +717,7 @@ int op_spawn(dumb_ptr<env_t>, Slice<val_t> args) location_t loc; magic_random_location(&loc, area); - int mob_id; + BlockId mob_id; dumb_ptr<mob_data> mob; mob_id = mob_once_spawn(owner, loc.m->name_, loc.x, loc.y, JAPANESE_NAME, // Is that needed? @@ -724,7 +727,7 @@ int op_spawn(dumb_ptr<env_t>, Slice<val_t> args) if (mob) { - mob->mode = mob_db[monster_id].mode; + mob->mode = get_mob_db(monster_id).mode; switch (monster_attitude) { @@ -770,18 +773,18 @@ int op_spawn(dumb_ptr<env_t>, Slice<val_t> args) } static -const char *get_invocation_name(dumb_ptr<env_t> env) +ZString get_invocation_name(dumb_ptr<env_t> env) { dumb_ptr<invocation> invocation_; if (env->VAR(VAR_INVOCATION).ty != TYPE::INVOCATION) - return "?"; - invocation_ = map_id_is_spell(env->VAR(VAR_INVOCATION).v.v_int); + return "?"_s; + invocation_ = map_id_is_spell(wrap<BlockId>(static_cast<uint32_t>(env->VAR(VAR_INVOCATION).v.v_int))); if (invocation_) - return invocation_->spell->name.c_str(); + return invocation_->spell->name; else - return "??"; + return "??"_s; } static @@ -824,9 +827,9 @@ int op_injure(dumb_ptr<env_t> env, Slice<val_t> args) { dumb_ptr<mob_data> mob = target->is_mob(); - MAP_LOG_PC(caster_pc, "SPELLDMG MOB%d %d FOR %d BY %s", - mob->bl_id, mob->mob_class, damage_caused, - get_invocation_name(env)); + MAP_LOG_PC(caster_pc, "SPELLDMG MOB%d %d FOR %d BY %s"_fmt, + mob->bl_id, mob->mob_class, damage_caused, + get_invocation_name(env)); } } battle_damage(caster, target, damage_caused, mp_damage); @@ -847,7 +850,7 @@ int op_emote(dumb_ptr<env_t>, Slice<val_t> args) static int op_set_script_variable(dumb_ptr<env_t>, Slice<val_t> args) { - dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; + dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : nullptr; VarName varname = stringish<VarName>(ARGSTR(1)); int array_index = 0; @@ -862,7 +865,7 @@ int op_set_script_variable(dumb_ptr<env_t>, Slice<val_t> args) static int op_set_script_str(dumb_ptr<env_t>, Slice<val_t> args) { - dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; + dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : nullptr; VarName varname = stringish<VarName>(ARGSTR(1)); int array_index = 0; @@ -877,7 +880,7 @@ int op_set_script_str(dumb_ptr<env_t>, Slice<val_t> args) static int op_set_hair_colour(dumb_ptr<env_t>, Slice<val_t> args) { - dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; + dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : nullptr; if (!c) return 1; @@ -890,7 +893,7 @@ int op_set_hair_colour(dumb_ptr<env_t>, Slice<val_t> args) static int op_set_hair_style(dumb_ptr<env_t>, Slice<val_t> args) { - dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; + dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : nullptr; if (!c) return 1; @@ -903,25 +906,29 @@ int op_set_hair_style(dumb_ptr<env_t>, Slice<val_t> args) static int op_drop_item_for (dumb_ptr<env_t>, Slice<val_t> args) { - struct item item; + Item item; int stackable; location_t *loc = &ARGLOCATION(0); int count = ARGINT(2); interval_t interval = static_cast<interval_t>(ARGINT(3)); - dumb_ptr<map_session_data> c = ((args.size() > 4) && (ENTITY_TYPE(4) == BL::PC)) ? ARGPC(4) : NULL; + dumb_ptr<map_session_data> c = ((args.size() > 4) && (ENTITY_TYPE(4) == BL::PC)) ? ARGPC(4) : nullptr; interval_t delay = (args.size() > 5) ? static_cast<interval_t>(ARGINT(5)) : interval_t::zero(); interval_t delaytime[3] = { delay, delay, delay }; - dumb_ptr<map_session_data> owners[3] = { c, NULL, NULL }; + dumb_ptr<map_session_data> owners[3] = { c, nullptr, nullptr }; GET_ARG_ITEM(1, item, stackable); if (stackable) + { map_addflooritem_any(&item, count, loc->m, loc->x, loc->y, owners, delaytime, interval, 0); + } else + { while (count-- > 0) map_addflooritem_any(&item, 1, loc->m, loc->x, loc->y, owners, delaytime, interval, 0); + } return 0; } @@ -929,7 +936,7 @@ int op_drop_item_for (dumb_ptr<env_t>, Slice<val_t> args) static int op_gain_exp(dumb_ptr<env_t>, Slice<val_t> args) { - dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; + dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : nullptr; if (!c) return 1; @@ -940,35 +947,35 @@ int op_gain_exp(dumb_ptr<env_t>, Slice<val_t> args) } #define MAGIC_OPERATION(name, args, impl) {{name}, {{name}, {args}, impl}} -#define MAGIC_OPERATION1(name, args) MAGIC_OPERATION(#name, args, op_##name) +#define MAGIC_OPERATION1(name, args) MAGIC_OPERATION(#name##_s, args, op_##name) static std::map<ZString, op_t> operations = { - MAGIC_OPERATION1(sfx, ".ii"), - MAGIC_OPERATION1(instaheal, "eii"), - MAGIC_OPERATION1(itemheal, "eii"), - MAGIC_OPERATION1(shroud, "ei"), - MAGIC_OPERATION("unshroud", "e", op_reveal), - MAGIC_OPERATION1(message, "es"), - MAGIC_OPERATION1(messenger_npc, "lissi"), - MAGIC_OPERATION1(move, "ed"), - MAGIC_OPERATION1(warp, "el"), - MAGIC_OPERATION1(banish, "e"), - MAGIC_OPERATION1(status_change, "eiiiiii"), - MAGIC_OPERATION1(stop_status_change, "ei"), - MAGIC_OPERATION1(override_attack, "eiiiiii"), - MAGIC_OPERATION1(create_item, "e.i"), - MAGIC_OPERATION1(aggravate, "eie"), - MAGIC_OPERATION1(spawn, "aeiiii"), - MAGIC_OPERATION1(injure, "eeii"), - MAGIC_OPERATION1(emote, "ei"), - MAGIC_OPERATION1(set_script_variable, "esi"), - MAGIC_OPERATION1(set_script_str, "ess"), - MAGIC_OPERATION1(set_hair_colour, "ei"), - MAGIC_OPERATION1(set_hair_style, "ei"), - MAGIC_OPERATION("drop_item", "l.ii", op_drop_item_for), - MAGIC_OPERATION1(drop_item_for, "l.iiei"), - MAGIC_OPERATION("gain_experience", "eiii", op_gain_exp), + MAGIC_OPERATION1(sfx, ".ii"_s), + MAGIC_OPERATION1(instaheal, "eii"_s), + MAGIC_OPERATION1(itemheal, "eii"_s), + MAGIC_OPERATION1(shroud, "ei"_s), + MAGIC_OPERATION("unshroud"_s, "e"_s, op_reveal), + MAGIC_OPERATION1(message, "es"_s), + MAGIC_OPERATION1(messenger_npc, "lissi"_s), + MAGIC_OPERATION1(move, "ed"_s), + MAGIC_OPERATION1(warp, "el"_s), + MAGIC_OPERATION1(banish, "e"_s), + MAGIC_OPERATION1(status_change, "eiiiiii"_s), + MAGIC_OPERATION1(stop_status_change, "ei"_s), + MAGIC_OPERATION1(override_attack, "eiiiiii"_s), + MAGIC_OPERATION1(create_item, "e.i"_s), + MAGIC_OPERATION1(aggravate, "eie"_s), + MAGIC_OPERATION1(spawn, "aeiiii"_s), + MAGIC_OPERATION1(injure, "eeii"_s), + MAGIC_OPERATION1(emote, "ei"_s), + MAGIC_OPERATION1(set_script_variable, "esi"_s), + MAGIC_OPERATION1(set_script_str, "ess"_s), + MAGIC_OPERATION1(set_hair_colour, "ei"_s), + MAGIC_OPERATION1(set_hair_style, "ei"_s), + MAGIC_OPERATION("drop_item"_s, "l.ii"_s, op_drop_item_for), + MAGIC_OPERATION1(drop_item_for, "l.iiei"_s), + MAGIC_OPERATION("gain_experience"_s, "eiii"_s, op_gain_exp), }; op_t *magic_get_op(ZString name) @@ -979,7 +986,7 @@ op_t *magic_get_op(ZString name) return &it->second; } -void spell_effect_report_termination(int invocation_id, int bl_id, +void spell_effect_report_termination(BlockId invocation_id, BlockId bl_id, StatusChange sc_id, int) { dumb_ptr<invocation> invocation_ = map_id_is_spell(invocation_id); @@ -1004,8 +1011,8 @@ void spell_effect_report_termination(int invocation_id, int bl_id, dumb_ptr<block_list> entity = map_id2bl(bl_id); if (entity->bl_type == BL::PC) FPRINTF(stderr, - "[magic] INTERNAL ERROR: spell-effect-report-termination: tried to terminate on unexpected bl %d, sc %d\n", - bl_id, sc_id); + "[magic] INTERNAL ERROR: spell-effect-report-termination: tried to terminate on unexpected bl %d, sc %d\n"_fmt, + bl_id, sc_id); return; } @@ -1015,7 +1022,7 @@ static dumb_ptr<effect_t> return_to_stack(dumb_ptr<invocation> invocation_) { if (!invocation_->stack_size) - return NULL; + return nullptr; else { cont_activation_record_t *ar = @@ -1042,7 +1049,7 @@ dumb_ptr<effect_t> return_to_stack(dumb_ptr<invocation> invocation_) case CONT_STACK::FOREACH: { - int entity_id; + BlockId entity_id; val_t *var = &invocation_->env->varu[ar->c.c_foreach.id]; do @@ -1065,7 +1072,7 @@ dumb_ptr<effect_t> return_to_stack(dumb_ptr<invocation> invocation_) magic_clear_var(var); var->ty = ar->c.c_foreach.ty; - var->v.v_int = entity_id; + var->v.v_int = static_cast<int32_t>(unwrap<BlockId>(entity_id)); return ar->c.c_foreach.body; } @@ -1089,9 +1096,9 @@ dumb_ptr<effect_t> return_to_stack(dumb_ptr<invocation> invocation_) default: FPRINTF(stderr, - "[magic] INTERNAL ERROR: While executing spell `%s': stack corruption\n", - invocation_->spell->name); - return NULL; + "[magic] INTERNAL ERROR: While executing spell `%s': stack corruption\n"_fmt, + invocation_->spell->name); + return nullptr; } } } @@ -1105,10 +1112,10 @@ cont_activation_record_t *add_stack_entry(dumb_ptr<invocation> invocation_, if (invocation_->stack_size >= MAX_STACK_SIZE) { FPRINTF(stderr, - "[magic] Execution stack size exceeded in spell `%s'; truncating effect\n", - invocation_->spell->name); + "[magic] Execution stack size exceeded in spell `%s'; truncating effect\n"_fmt, + invocation_->spell->name); invocation_->stack_size--; - return NULL; + return nullptr; } ar->ty = ty; @@ -1118,7 +1125,7 @@ cont_activation_record_t *add_stack_entry(dumb_ptr<invocation> invocation_, static void find_entities_in_area_c(dumb_ptr<block_list> target, - std::vector<int> *entities_vp, + std::vector<BlockId> *entities_vp, FOREACH_FILTER filter) { switch (target->bl_type) @@ -1180,7 +1187,7 @@ void find_entities_in_area_c(dumb_ptr<block_list> target, static void find_entities_in_area(area_t& area_, - std::vector<int> *entities_vp, + std::vector<BlockId> *entities_vp, FOREACH_FILTER filter) { area_t *area = &area_; // temporary hack to "keep diff small". Heh. @@ -1221,8 +1228,8 @@ dumb_ptr<effect_t> run_foreach(dumb_ptr<invocation> invocation, { magic_clear_var(&area); FPRINTF(stderr, - "[magic] Error in spell `%s': FOREACH loop over non-area\n", - invocation->spell->name.c_str()); + "[magic] Error in spell `%s': FOREACH loop over non-area\n"_fmt, + invocation->spell->name); return return_location; } else @@ -1233,7 +1240,7 @@ dumb_ptr<effect_t> run_foreach(dumb_ptr<invocation> invocation, if (!ar) return return_location; - std::vector<int> entities_v; + std::vector<BlockId> entities_v; find_entities_in_area(*area.v.v_area, &entities_v, filter); entities_v.shrink_to_fit(); @@ -1271,8 +1278,8 @@ dumb_ptr<effect_t> run_for (dumb_ptr<invocation> invocation, magic_clear_var(&start); magic_clear_var(&stop); FPRINTF(stderr, - "[magic] Error in spell `%s': FOR loop start or stop point is not an integer\n", - invocation->spell->name); + "[magic] Error in spell `%s': FOR loop start or stop point is not an integer\n"_fmt, + invocation->spell->name); return return_location; } @@ -1319,9 +1326,9 @@ void print_cfg(int i, effect_t *e) { int j; for (j = 0; j < i; j++) - PRINTF(" "); + PRINTF(" "_fmt); - PRINTF("%p: ", e); + PRINTF("%p: "_fmt, e); if (!e) { @@ -1354,11 +1361,11 @@ void print_cfg(int i, effect_t *e) case EFFECT::IF: puts("IF"); for (j = 0; j < i; j++) - PRINTF(" "); + PRINTF(" "_fmt); puts("THEN"); print_cfg(i + 1, e->e.e_if.true_branch); for (j = 0; j < i; j++) - PRINTF(" "); + PRINTF(" "_fmt); puts("ELSE"); print_cfg(i + 1, e->e.e_if.false_branch); break; @@ -1391,12 +1398,12 @@ void print_cfg(int i, effect_t *e) static interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) { - const int invocation_id = invocation_->bl_id; + const BlockId invocation_id = invocation_->bl_id; #define REFRESH_INVOCATION invocation_ = map_id_is_spell(invocation_id); if (!invocation_) return interval_t::zero(); #ifdef DEBUG - FPRINTF(stderr, "Resuming execution: invocation of `%s'\n", - invocation_->spell->name); + FPRINTF(stderr, "Resuming execution: invocation of `%s'\n"_fmt, + invocation_->spell->name); print_cfg(1, invocation_->current_effect); #endif while (invocation_->current_effect) @@ -1406,7 +1413,7 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) int i; #ifdef DEBUG - FPRINTF(stderr, "Next step of type %d\n", e->ty); + FPRINTF(stderr, "Next step of type %d\n"_fmt, e->ty); dump_env(invocation_->env); #endif @@ -1417,11 +1424,11 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) case EFFECT::ABORT: invocation_->flags |= INVOCATION_FLAG::ABORTED; - invocation_->end_effect = NULL; + invocation_->end_effect = nullptr; FALLTHROUGH; case EFFECT::END: clear_stack(invocation_); - next = NULL; + next = nullptr; break; case EFFECT::ASSIGN: @@ -1464,14 +1471,14 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) ZString caster_name = (caster ? caster->status_key.name : CharName()).to__actual(); argrec_t arg[3] = { - {"@target", env->VAR(VAR_TARGET).ty == TYPE::ENTITY ? 0 : env->VAR(VAR_TARGET).v.v_int}, - {"@caster", invocation_->caster}, - {"@caster_name$", caster_name}, + {"@target"_s, env->VAR(VAR_TARGET).ty == TYPE::ENTITY ? 0 : env->VAR(VAR_TARGET).v.v_int}, + {"@caster"_s, static_cast<int32_t>(unwrap<BlockId>(invocation_->caster))}, + {"@caster_name$"_s, caster_name}, }; - int message_recipient = - env->VAR(VAR_SCRIPTTARGET).ty == - TYPE::ENTITY ? env->VAR(VAR_SCRIPTTARGET). - v.v_int : invocation_->caster; + BlockId message_recipient = + env->VAR(VAR_SCRIPTTARGET).ty == TYPE::ENTITY + ? wrap<BlockId>(static_cast<uint32_t>(env->VAR(VAR_SCRIPTTARGET).v.v_int)) + : invocation_->caster; dumb_ptr<map_session_data> recipient = map_id_is_player(message_recipient); if (recipient->npc_id @@ -1516,7 +1523,7 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) for (i = 0; i < e->e.e_op.args_nr; i++) magic_eval(invocation_->env, &args[i], e->e.e_op.args[i]); - if (!magic_signature_check("effect", op->name, op->signature, + if (!magic_signature_check("effect"_s, op->name, op->signature, Slice<val_t>(args, e->e.e_op.args_nr), e->e.e_op.line_nr, e->e.e_op.column)) @@ -1535,8 +1542,8 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) default: FPRINTF(stderr, - "[magic] INTERNAL ERROR: Unknown effect %d\n", - e->ty); + "[magic] INTERNAL ERROR: Unknown effect %d\n"_fmt, + e->ty); } if (!next) @@ -1583,7 +1590,7 @@ void spell_execute_script(dumb_ptr<invocation> invocation) * running the same spell twice! */ } -int spell_attack(int caster_id, int target_id) +int spell_attack(BlockId caster_id, BlockId target_id) { dumb_ptr<map_session_data> caster = map_id_is_player(caster_id); dumb_ptr<invocation> invocation_; @@ -1601,7 +1608,7 @@ int spell_attack(int caster_id, int target_id) { magic_clear_var(&invocation_->env->varu[VAR_TARGET]); invocation_->env->varu[VAR_TARGET].ty = TYPE::ENTITY; - invocation_->env->varu[VAR_TARGET].v.v_int = target_id; + invocation_->env->varu[VAR_TARGET].v.v_int = static_cast<int32_t>(unwrap<BlockId>(target_id)); invocation_->current_effect = invocation_->trigger_effect; invocation_->flags &= ~INVOCATION_FLAG::ABORTED; @@ -1622,8 +1629,8 @@ int spell_attack(int caster_id, int target_id) } else if (!invocation_ || caster->attack_spell_charges <= 0) { - caster->attack_spell_override = 0; - char_set_weapon_icon(caster, 0, StatusChange::ZERO, 0); + caster->attack_spell_override = BlockId(); + char_set_weapon_icon(caster, 0, StatusChange::ZERO, ItemNameId()); char_set_attack_info(caster, interval_t::zero(), 0); if (stop_attack) @@ -1635,3 +1642,4 @@ int spell_attack(int caster_id, int target_id) return 1; } +} // namespace tmwa diff --git a/src/map/magic-stmt.hpp b/src/map/magic-stmt.hpp index 838854f..729562e 100644 --- a/src/map/magic-stmt.hpp +++ b/src/map/magic-stmt.hpp @@ -1,8 +1,8 @@ -#ifndef TMWA_MAP_MAGIC_STMT_HPP -#define TMWA_MAP_MAGIC_STMT_HPP -// magic-stmt.hpp - dummy header to make Make dependencies work. +#pragma once +// magic-stmt.hpp - Imperative commands for the magic backend. // -// Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> +// Copyright © 2004-2011 The Mana World Development Team +// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> // // This file is part of The Mana World (Athena server) // @@ -19,6 +19,73 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -#endif // TMWA_MAP_MAGIC_STMT_HPP +#include "../range/fwd.hpp" + +#include "../strings/zstring.hpp" + +#include "../generic/fwd.hpp" + +#include "skill.t.hpp" + + +namespace tmwa +{ +struct op_t +{ + ZString name; + ZString signature; + int (*op)(dumb_ptr<env_t> env, Slice<val_t> arga); +}; + +/** + * Retrieves an operation by name + * @param name The name to look up + * @return An operation of that name, or nullptr, and a function index + */ +op_t *magic_get_op(ZString name); + +/** + * Removes the shroud from a character + * + * \param character The character to remove the shroud from + */ +void magic_unshroud(dumb_ptr<map_session_data> character); + +/** + * Notifies a running spell that a status_change timer triggered by the spell has expired + * + * \param invocation The invocation to notify + * \param bl_id ID of the PC for whom this happened + * \param sc_id ID of the status change entry that finished + * \param supplanted Whether the status_change finished normally (0) or was supplanted by a new status_change (1) + */ +void spell_effect_report_termination(BlockId invocation, BlockId bl_id, + StatusChange sc_id, int supplanted); + +/** + * Execute a spell invocation and sets up timers to finish + */ +void spell_execute(dumb_ptr<invocation> invocation); + +/** + * Continue an NPC script embedded in a spell + */ +void spell_execute_script(dumb_ptr<invocation> invocation); + +/** + * Stops all magic bound to the specified character + * + */ +void magic_stop_completely(dumb_ptr<map_session_data> c); + +/** + * Attacks with a magical spell charged to the character + * + * Returns 0 if there is no charged spell or the spell is depleted. + */ +int spell_attack(BlockId caster, BlockId target); + +void spell_free_invocation(dumb_ptr<invocation> invocation); +} // namespace tmwa diff --git a/src/map/magic-v2.cpp b/src/map/magic-v2.cpp index 41d29cd..a671dea 100644 --- a/src/map/magic-v2.cpp +++ b/src/map/magic-v2.cpp @@ -18,17 +18,33 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include <cstddef> + +#include <algorithm> +#include <map> #include <set> -#include "../sexpr/parser.hpp" +#include "../strings/rstring.hpp" +#include "../strings/literal.hpp" + +#include "../generic/dumb_ptr.hpp" + +#include "../io/cxxstdio.hpp" +#include "../io/line.hpp" -#include "../mmo/dumb_ptr.hpp" +#include "../sexpr/parser.hpp" #include "itemdb.hpp" #include "magic-expr.hpp" +#include "magic-interpreter.hpp" +#include "magic-interpreter-base.hpp" +#include "magic-stmt.hpp" #include "../poison.hpp" + +namespace tmwa +{ namespace magic_v2 { static @@ -61,8 +77,8 @@ namespace magic_v2 if (zid != id) { FPRINTF(stderr, - "[magic-conf] INTERNAL ERROR: Builtin special var %s interned to %d, not %d as it should be!\n", - name, zid, id); + "[magic-conf] INTERNAL ERROR: Builtin special var %s interned to %d, not %d as it should be!\n"_fmt, + name, zid, id); } return zid == id; } @@ -72,15 +88,15 @@ namespace magic_v2 { bool ok = true; - ok &= INTERN_ASSERT("min_casttime", VAR_MIN_CASTTIME); - ok &= INTERN_ASSERT("obscure_chance", VAR_OBSCURE_CHANCE); - ok &= INTERN_ASSERT("caster", VAR_CASTER); - ok &= INTERN_ASSERT("spellpower", VAR_SPELLPOWER); - ok &= INTERN_ASSERT("self_spell", VAR_SPELL); - ok &= INTERN_ASSERT("self_invocation", VAR_INVOCATION); - ok &= INTERN_ASSERT("target", VAR_TARGET); - ok &= INTERN_ASSERT("script_target", VAR_SCRIPTTARGET); - ok &= INTERN_ASSERT("location", VAR_LOCATION); + ok &= INTERN_ASSERT("min_casttime"_s, VAR_MIN_CASTTIME); + ok &= INTERN_ASSERT("obscure_chance"_s, VAR_OBSCURE_CHANCE); + ok &= INTERN_ASSERT("caster"_s, VAR_CASTER); + ok &= INTERN_ASSERT("spellpower"_s, VAR_SPELLPOWER); + ok &= INTERN_ASSERT("self_spell"_s, VAR_SPELL); + ok &= INTERN_ASSERT("self_invocation"_s, VAR_INVOCATION); + ok &= INTERN_ASSERT("target"_s, VAR_TARGET); + ok &= INTERN_ASSERT("script_target"_s, VAR_SCRIPTTARGET); + ok &= INTERN_ASSERT("location"_s, VAR_LOCATION); return ok; } @@ -91,7 +107,7 @@ namespace magic_v2 { if (!const_defm.insert({name, *val}).second) { - span.error(STRPRINTF("Redefinition of constant '%s'", name)); + span.error(STRPRINTF("Redefinition of constant '%s'"_fmt, name)); return false; } return true; @@ -103,7 +119,7 @@ namespace magic_v2 if (it != const_defm.end()) return &it->second; - return NULL; + return nullptr; } static dumb_ptr<effect_t> new_effect(EFFECT ty) @@ -184,14 +200,14 @@ namespace magic_v2 auto pair1 = magic_conf.spells_by_name.insert({spell->name, spell}); if (!pair1.second) { - span.error(STRPRINTF("Attempt to redefine spell '%s'", spell->name)); + span.error(STRPRINTF("Attempt to redefine spell '%s'"_fmt, spell->name)); return false; } auto pair2 = magic_conf.spells_by_invocation.insert({spell->invocation, spell}); if (!pair2.second) { - span.error(STRPRINTF("Attempt to redefine spell invocation '%s'", spell->invocation)); + span.error(STRPRINTF("Attempt to redefine spell invocation '%s'"_fmt, spell->invocation)); magic_conf.spells_by_name.erase(pair1.first); return false; } @@ -203,14 +219,14 @@ namespace magic_v2 auto pair1 = magic_conf.anchors_by_name.insert({anchor->name, anchor}); if (!pair1.second) { - span.error(STRPRINTF("Attempt to redefine teleport anchor '%s'", anchor->name)); + span.error(STRPRINTF("Attempt to redefine teleport anchor '%s'"_fmt, anchor->name)); return false; } auto pair2 = magic_conf.anchors_by_invocation.insert({anchor->name, anchor}); if (!pair2.second) { - span.error(STRPRINTF("Attempt to redefine anchor invocation '%s'", anchor->invocation)); + span.error(STRPRINTF("Attempt to redefine anchor invocation '%s'"_fmt, anchor->invocation)); magic_conf.anchors_by_name.erase(pair1.first); return false; } @@ -223,7 +239,7 @@ namespace magic_v2 RString name = proc->name; if (!procs.insert({name, std::move(*proc)}).second) { - span.error("procedure already exists"); + span.error("procedure already exists"_s); return false; } return true; @@ -234,7 +250,7 @@ namespace magic_v2 auto pi = procs.find(name); if (pi == procs.end()) { - span.error(STRPRINTF("Unknown procedure '%s'", name)); + span.error(STRPRINTF("Unknown procedure '%s'"_fmt, name)); return false; } @@ -242,7 +258,7 @@ namespace magic_v2 if (p->argv.size() != argvp->size()) { - span.error(STRPRINTF("Procedure %s/%zu invoked with %zu parameters", + span.error(STRPRINTF("Procedure %s/%zu invoked with %zu parameters"_fmt, name, p->argv.size(), argvp->size())); return false; } @@ -259,13 +275,13 @@ namespace magic_v2 op_t *op = magic_get_op(name); if (!op) { - span.error(STRPRINTF("Unknown operation '%s'", name)); + span.error(STRPRINTF("Unknown operation '%s'"_fmt, name)); return false; } if (op->signature.size() != argv.size()) { - span.error(STRPRINTF("Incorrect number of arguments to operation '%s': Expected %zu, found %zu", - name, op->signature.size(), argv.size())); + span.error(STRPRINTF("Incorrect number of arguments to operation '%s': Expected %zu, found %zu"_fmt, + name, op->signature.size(), argv.size())); return false; } @@ -295,13 +311,13 @@ namespace magic_v2 fun_t *fun = magic_get_fun(name); if (!fun) { - span.error(STRPRINTF("Unknown function '%s'", name)); + span.error(STRPRINTF("Unknown function '%s'"_fmt, name)); return false; } if (fun->signature.size() != argv.size()) { - span.error(STRPRINTF("Incorrect number of arguments to function '%s': Expected %zu, found %zu", - name, fun->signature.size(), argv.size())); + span.error(STRPRINTF("Incorrect number of arguments to function '%s': Expected %zu, found %zu"_fmt, + name, fun->signature.size(), argv.size())); return false; } expr = magic_new_expr(EXPR::FUNAPP); @@ -362,20 +378,20 @@ namespace magic_v2 return false; if (s._list[0]._type != sexpr::TOKEN) return false; - return s._list[0]._str == "DISABLED"; + return s._list[0]._str == "DISABLED"_s; } static bool parse_loc(const SExpr& s, e_location_t& loc) { if (s._type != sexpr::LIST) - return fail(s, "loc not list"); + return fail(s, "loc not list"_s); if (s._list.size() != 4) - return fail(s, "loc not 3 args"); + return fail(s, "loc not 3 args"_s); if (s._list[0]._type != sexpr::TOKEN) - return fail(s._list[0], "loc cmd not tok"); - if (s._list[0]._str != "@") - return fail(s._list[0], "loc cmd not cmd"); + return fail(s._list[0], "loc cmd not tok"_s); + if (s._list[0]._str != "@"_s) + return fail(s._list[0], "loc cmd not cmd"_s); return parse_expression(s._list[1], loc.m) && parse_expression(s._list[2], loc.x) && parse_expression(s._list[3], loc.y); @@ -392,7 +408,7 @@ namespace magic_v2 val.ty = TYPE::INT; val.v.v_int = x._int; if (val.v.v_int != x._int) - return fail(x, "integer too large"); + return fail(x, "integer too large"_s); out = magic_new_expr(EXPR::VAL); out->e.e_val = val; @@ -410,9 +426,11 @@ namespace magic_v2 } case sexpr::TOKEN: { - ZString dirs[8] = { - ZString("S"), ZString("SW"), ZString("W"), ZString("NW"), ZString("N"), ZString("NE"), ZString("E"), ZString("SE"), - }; + earray<LString, DIR, DIR::COUNT> dirs //= + {{ + "S"_s, "SW"_s, "W"_s, "NW"_s, + "N"_s, "NE"_s, "E"_s, "SE"_s, + }}; auto begin = std::begin(dirs); auto end = std::end(dirs); auto it = std::find(begin, end, x._str); @@ -444,13 +462,13 @@ namespace magic_v2 break; case sexpr::LIST: if (x._list.empty()) - return fail(x, "empty list"); + return fail(x, "empty list"_s); { if (x._list[0]._type != sexpr::TOKEN) - return fail(x._list[0], "op not token"); + return fail(x._list[0], "op not token"_s); ZString op = x._list[0]._str; // area - if (op == "@") + if (op == "@"_s) { e_location_t loc; if (!parse_loc(x, loc)) @@ -460,7 +478,7 @@ namespace magic_v2 out->e.e_area.a.a_loc = loc; return true; } - if (op == "@+") + if (op == "@+"_s) { e_location_t loc; dumb_ptr<expr_t> width; @@ -478,7 +496,7 @@ namespace magic_v2 out->e.e_area.a.a_rect.height = height; return true; } - if (op == "TOWARDS") + if (op == "TOWARDS"_s) { e_location_t loc; dumb_ptr<expr_t> dir; @@ -500,33 +518,33 @@ namespace magic_v2 out->e.e_area.a.a_bar.depth = depth; return true; } - if (op == ".") + if (op == "."_s) { if (x._list.size() != 3) - return fail(x, ". not 2"); + return fail(x, ". not 2"_s); dumb_ptr<expr_t> expr; if (!parse_expression(x._list[1], expr)) return false; if (x._list[2]._type != sexpr::TOKEN) - return fail(x._list[2], ".elem not name"); + return fail(x._list[2], ".elem not name"_s); ZString elem = x._list[2]._str; out = dot_expr(expr, intern_id(elem)); return true; } - static + static // TODO LString std::set<ZString> ops = { - "<", ">", "<=", ">=", "==", "!=", - "+", "-", "*", "%", "/", - "&", "^", "|", "<<", ">>", - "&&", "||", + "<"_s, ">"_s, "<="_s, ">="_s, "=="_s, "!="_s, + "+"_s, "-"_s, "*"_s, "%"_s, "/"_s, + "&"_s, "^"_s, "|"_s, "<<"_s, ">>"_s, + "&&"_s, "||"_s, }; // TODO implement unary operators if (ops.count(op)) { // operators are n-ary and left-associative if (x._list.size() < 3) - return fail(x, "operator not at least 2 args"); + return fail(x, "operator not at least 2 args"_s); auto begin = x._list.begin() + 1; auto end = x._list.end(); if (!parse_expression(*begin, out)) @@ -557,7 +575,7 @@ namespace magic_v2 } static - bool parse_item(const SExpr& s, int& id, int& count) + bool parse_item(const SExpr& s, ItemNameId& id, int& count) { if (s._type == sexpr::STRING) { @@ -565,23 +583,23 @@ namespace magic_v2 item_data *item = itemdb_searchname(s._str); if (!item) - return fail(s, "no such item"); + return fail(s, "no such item"_s); id = item->nameid; return true; } if (s._type != sexpr::LIST) - return fail(s, "item not string or list"); + return fail(s, "item not string or list"_s); if (s._list.size() != 2) - return fail(s, "item list is not pair"); + return fail(s, "item list is not pair"_s); if (s._list[0]._type != sexpr::INT) - return fail(s._list[0], "item pair first not int"); + return fail(s._list[0], "item pair first not int"_s); count = s._list[0]._int; if (s._list[1]._type != sexpr::STRING) - return fail(s._list[1], "item pair second not name"); + return fail(s._list[1], "item pair second not name"_s); item_data *item = itemdb_searchname(s._list[1]._str); if (!item) - return fail(s, "no such item"); + return fail(s, "no such item"_s); id = item->nameid; return true; } @@ -590,18 +608,18 @@ namespace magic_v2 bool parse_spellguard(const SExpr& s, dumb_ptr<spellguard_t>& out) { if (s._type != sexpr::LIST) - return fail(s, "not list"); + return fail(s, "not list"_s); if (s._list.empty()) - return fail(s, "empty list"); + return fail(s, "empty list"_s); if (s._list[0]._type != sexpr::TOKEN) - return fail(s._list[0], "not token"); + return fail(s._list[0], "not token"_s); ZString cmd = s._list[0]._str; - if (cmd == "OR") + if (cmd == "OR"_s) { auto begin = s._list.begin() + 1; auto end = s._list.end(); if (begin == end) - return fail(s, "missing arguments"); + return fail(s, "missing arguments"_s); if (!parse_spellguard(*begin, out)) return false; ++begin; @@ -617,14 +635,14 @@ namespace magic_v2 } return true; } - if (cmd == "GUARD") + if (cmd == "GUARD"_s) { auto begin = s._list.begin() + 1; auto end = s._list.end(); while (is_comment(end[-1])) --end; if (begin == end) - return fail(s, "missing arguments"); + return fail(s, "missing arguments"_s); if (!parse_spellguard(end[-1], out)) return false; --end; @@ -639,10 +657,10 @@ namespace magic_v2 } return true; } - if (cmd == "REQUIRE") + if (cmd == "REQUIRE"_s) { if (s._list.size() != 2) - return fail(s, "not one argument"); + return fail(s, "not one argument"_s); dumb_ptr<expr_t> condition; if (!parse_expression(s._list[1], condition)) return false; @@ -650,10 +668,10 @@ namespace magic_v2 out->s.s_condition = condition; return true; } - if (cmd == "MANA") + if (cmd == "MANA"_s) { if (s._list.size() != 2) - return fail(s, "not one argument"); + return fail(s, "not one argument"_s); dumb_ptr<expr_t> mana; if (!parse_expression(s._list[1], mana)) return false; @@ -661,10 +679,10 @@ namespace magic_v2 out->s.s_mana = mana; return true; } - if (cmd == "CASTTIME") + if (cmd == "CASTTIME"_s) { if (s._list.size() != 2) - return fail(s, "not one argument"); + return fail(s, "not one argument"_s); dumb_ptr<expr_t> casttime; if (!parse_expression(s._list[1], casttime)) return false; @@ -672,12 +690,13 @@ namespace magic_v2 out->s.s_casttime = casttime; return true; } - if (cmd == "CATALYSTS") + if (cmd == "CATALYSTS"_s) { dumb_ptr<component_t> items = nullptr; for (auto it = s._list.begin() + 1, end = s._list.end(); it != end; ++it) { - int id, count; + ItemNameId id; + int count; if (!parse_item(*it, id, count)) return false; magic_add_component(&items, id, count); @@ -686,12 +705,13 @@ namespace magic_v2 out->s.s_catalysts = items; return true; } - if (cmd == "COMPONENTS") + if (cmd == "COMPONENTS"_s) { dumb_ptr<component_t> items = nullptr; for (auto it = s._list.begin() + 1, end = s._list.end(); it != end; ++it) { - int id, count; + ItemNameId id; + int count; if (!parse_item(*it, id, count)) return false; magic_add_component(&items, id, count); @@ -700,7 +720,7 @@ namespace magic_v2 out->s.s_components = items; return true; } - return fail(s._list[0], "unknown guard"); + return fail(s._list[0], "unknown guard"_s); } static @@ -727,25 +747,25 @@ namespace magic_v2 bool parse_effect(const SExpr& s, dumb_ptr<effect_t>& out) { if (s._type != sexpr::LIST) - return fail(s, "not list"); + return fail(s, "not list"_s); if (s._list.empty()) - return fail(s, "empty list"); + return fail(s, "empty list"_s); if (s._list[0]._type != sexpr::TOKEN) - return fail(s._list[0], "not token"); + return fail(s._list[0], "not token"_s); ZString cmd = s._list[0]._str; - if (cmd == "BLOCK") + if (cmd == "BLOCK"_s) { return build_effect_list(s._list.begin() + 1, s._list.end(), out); } - if (cmd == "SET") + if (cmd == "SET"_s) { if (s._list.size() != 3) - return fail(s, "not 2 args"); + return fail(s, "not 2 args"_s); if (s._list[1]._type != sexpr::TOKEN) - return fail(s._list[1], "not token"); + return fail(s._list[1], "not token"_s); ZString name = s._list[1]._str; if (find_constant(name)) - return fail(s._list[1], "assigning to constant"); + return fail(s._list[1], "assigning to constant"_s); dumb_ptr<expr_t> expr; if (!parse_expression(s._list[2], expr)) return false; @@ -755,72 +775,72 @@ namespace magic_v2 out->e.e_assign.expr = expr; return true; } - if (cmd == "SCRIPT") + if (cmd == "SCRIPT"_s) { if (s._list.size() != 2) - return fail(s, "not 1 arg"); + return fail(s, "not 1 arg"_s); if (s._list[1]._type != sexpr::STRING) - return fail(s._list[1], "not string"); + return fail(s._list[1], "not string"_s); ZString body = s._list[1]._str; std::unique_ptr<const ScriptBuffer> script = parse_script(body, s._list[1]._span.begin.line, true); if (!script) - return fail(s._list[1], "script does not compile"); + return fail(s._list[1], "script does not compile"_s); out = new_effect(EFFECT::SCRIPT); out->e.e_script = dumb_ptr<const ScriptBuffer>(script.release()); return true; } - if (cmd == "SKIP") + if (cmd == "SKIP"_s) { if (s._list.size() != 1) - return fail(s, "not 0 arg"); + return fail(s, "not 0 arg"_s); out = new_effect(EFFECT::SKIP); return true; } - if (cmd == "ABORT") + if (cmd == "ABORT"_s) { if (s._list.size() != 1) - return fail(s, "not 0 arg"); + return fail(s, "not 0 arg"_s); out = new_effect(EFFECT::ABORT); return true; } - if (cmd == "END") + if (cmd == "END"_s) { if (s._list.size() != 1) - return fail(s, "not 0 arg"); + return fail(s, "not 0 arg"_s); out = new_effect(EFFECT::END); return true; } - if (cmd == "BREAK") + if (cmd == "BREAK"_s) { if (s._list.size() != 1) - return fail(s, "not 0 arg"); + return fail(s, "not 0 arg"_s); out = new_effect(EFFECT::BREAK); return true; } - if (cmd == "FOREACH") + if (cmd == "FOREACH"_s) { if (s._list.size() != 5) - return fail(s, "not 4 arg"); + return fail(s, "not 4 arg"_s); if (s._list[1]._type != sexpr::TOKEN) - return fail(s._list[1], "foreach type not token"); + return fail(s._list[1], "foreach type not token"_s); ZString type = s._list[1]._str; FOREACH_FILTER filter; - if (type == "PC") + if (type == "PC"_s) filter = FOREACH_FILTER::PC; - else if (type == "MOB") + else if (type == "MOB"_s) filter = FOREACH_FILTER::MOB; - else if (type == "ENTITY") + else if (type == "ENTITY"_s) filter = FOREACH_FILTER::ENTITY; - else if (type == "SPELL") + else if (type == "SPELL"_s) filter = FOREACH_FILTER::SPELL; - else if (type == "TARGET") + else if (type == "TARGET"_s) filter = FOREACH_FILTER::TARGET; - else if (type == "NPC") + else if (type == "NPC"_s) filter = FOREACH_FILTER::NPC; else - return fail(s._list[1], "unknown foreach filter"); + return fail(s._list[1], "unknown foreach filter"_s); if (s._list[2]._type != sexpr::TOKEN) - return fail(s._list[2], "foreach var not token"); + return fail(s._list[2], "foreach var not token"_s); ZString var = s._list[2]._str; dumb_ptr<expr_t> area; dumb_ptr<effect_t> effect; @@ -835,12 +855,12 @@ namespace magic_v2 out->e.e_foreach.filter = filter; return true; } - if (cmd == "FOR") + if (cmd == "FOR"_s) { if (s._list.size() != 5) - return fail(s, "not 4 arg"); + return fail(s, "not 4 arg"_s); if (s._list[1]._type != sexpr::TOKEN) - return fail(s._list[1], "for var not token"); + return fail(s._list[1], "for var not token"_s); ZString var = s._list[1]._str; dumb_ptr<expr_t> low; dumb_ptr<expr_t> high; @@ -858,10 +878,10 @@ namespace magic_v2 out->e.e_for.body = effect; return true; } - if (cmd == "IF") + if (cmd == "IF"_s) { if (s._list.size() != 3 && s._list.size() != 4) - return fail(s, "not 2 or 3 args"); + return fail(s, "not 2 or 3 args"_s); dumb_ptr<expr_t> cond; dumb_ptr<effect_t> if_true; dumb_ptr<effect_t> if_false; @@ -882,10 +902,10 @@ namespace magic_v2 out->e.e_if.false_branch = if_false; return true; } - if (cmd == "WAIT") + if (cmd == "WAIT"_s) { if (s._list.size() != 2) - return fail(s, "not 1 arg"); + return fail(s, "not 1 arg"_s); dumb_ptr<expr_t> expr; if (!parse_expression(s._list[1], expr)) return false; @@ -893,12 +913,12 @@ namespace magic_v2 out->e.e_sleep = expr; return true; } - if (cmd == "CALL") + if (cmd == "CALL"_s) { if (s._list.size() < 2) - return fail(s, "call what?"); + return fail(s, "call what?"_s); if (s._list[1]._type != sexpr::TOKEN) - return fail(s._list[1], "call token please"); + return fail(s._list[1], "call token please"_s); ZString func = s._list[1]._str; auto argvp = dumb_ptr<std::vector<dumb_ptr<expr_t>>>::make(); for (auto it = s._list.begin() + 2, end = s._list.end(); it != end; ++it) @@ -925,16 +945,16 @@ namespace magic_v2 bool parse_spellbody(const SExpr& s, dumb_ptr<spellguard_t>& out) { if (s._type != sexpr::LIST) - return fail(s, "not list"); + return fail(s, "not list"_s); if (s._list.empty()) - return fail(s, "empty list"); + return fail(s, "empty list"_s); if (s._list[0]._type != sexpr::TOKEN) - return fail(s._list[0], "not token"); + return fail(s._list[0], "not token"_s); ZString cmd = s._list[0]._str; - if (cmd == "=>") + if (cmd == "=>"_s) { if (s._list.size() != 3) - return fail(s, "list does not have exactly 2 arguments"); + return fail(s, "list does not have exactly 2 arguments"_s); dumb_ptr<spellguard_t> guard; if (!parse_spellguard(s._list[1], guard)) return false; @@ -944,10 +964,10 @@ namespace magic_v2 out = spellguard_implication(guard, body); return true; } - if (cmd == "|") + if (cmd == "|"_s) { if (s._list.size() == 1) - return fail(s, "spellbody choice empty"); + return fail(s, "spellbody choice empty"_s); auto begin = s._list.begin() + 1; auto end = s._list.end(); if (!parse_spellbody(*begin, out)) @@ -965,7 +985,7 @@ namespace magic_v2 } return true; } - if (cmd == "EFFECT") + if (cmd == "EFFECT"_s) { auto begin = s._list.begin() + 1; auto end = s._list.end(); @@ -978,7 +998,7 @@ namespace magic_v2 --end; if (end[-1]._type == sexpr::LIST && !end[-1]._list.empty() && end[-1]._list[0]._type == sexpr::TOKEN - && end[-1]._list[0]._str == "ATEND") + && end[-1]._list[0]._str == "ATEND"_s) { auto atb = end[-1]._list.begin() + 1; auto ate = end[-1]._list.end(); @@ -995,7 +1015,7 @@ namespace magic_v2 } if (end[-1]._type == sexpr::LIST && !end[-1]._list.empty() && end[-1]._list[0]._type == sexpr::TOKEN - && end[-1]._list[0]._str == "ATTRIGGER") + && end[-1]._list[0]._str == "ATTRIGGER"_s) { auto atb = end[-1]._list.begin() + 1; auto ate = end[-1]._list.end(); @@ -1015,20 +1035,20 @@ namespace magic_v2 out->s.s_effect.at_end = atend; return true; } - return fail(s._list[0], "unknown spellbody"); + return fail(s._list[0], "unknown spellbody"_s); } static bool parse_top_set(const std::vector<SExpr>& in) { if (in.size() != 3) - return fail(in[0], "not 2 arguments"); + return fail(in[0], "not 2 arguments"_s); ZString name = in[1]._str; dumb_ptr<expr_t> expr; if (!parse_expression(in[2], expr)) return false; if (find_constant(name)) - return fail(in[1], "assign constant"); + return fail(in[1], "assign constant"_s); size_t var_id = intern_id(name); magic_eval(dumb_ptr<env_t>(&magic_default_env), &magic_conf.varv[var_id].val, expr); return true; @@ -1037,9 +1057,9 @@ namespace magic_v2 bool parse_const(io::LineSpan span, const std::vector<SExpr>& in) { if (in.size() != 3) - return fail(in[0], "not 2 arguments"); + return fail(in[0], "not 2 arguments"_s); if (in[1]._type != sexpr::TOKEN) - return fail(in[1], "not token"); + return fail(in[1], "not token"_s); ZString name = in[1]._str; dumb_ptr<expr_t> expr; if (!parse_expression(in[2], expr)) @@ -1052,13 +1072,13 @@ namespace magic_v2 bool parse_anchor(io::LineSpan span, const std::vector<SExpr>& in) { if (in.size() != 4) - return fail(in[0], "not 3 arguments"); + return fail(in[0], "not 3 arguments"_s); auto anchor = dumb_ptr<teleport_anchor_t>::make(); if (in[1]._type != sexpr::TOKEN) - return fail(in[1], "not token"); + return fail(in[1], "not token"_s); anchor->name = in[1]._str; if (in[2]._type != sexpr::STRING) - return fail(in[2], "not string"); + return fail(in[2], "not string"_s); anchor->invocation = in[2]._str; dumb_ptr<expr_t> expr; if (!parse_expression(in[3], expr)) @@ -1070,17 +1090,17 @@ namespace magic_v2 bool parse_proc(io::LineSpan span, const std::vector<SExpr>& in) { if (in.size() < 4) - return fail(in[0], "not at least 3 arguments"); + return fail(in[0], "not at least 3 arguments"_s); auto proc = dumb_ptr<proc_t>::make(); if (in[1]._type != sexpr::TOKEN) - return fail(in[1], "name not token"); + return fail(in[1], "name not token"_s); proc->name = in[1]._str; if (in[2]._type != sexpr::LIST) - return fail(in[2], "args not list"); + return fail(in[2], "args not list"_s); for (const SExpr& arg : in[2]._list) { if (arg._type != sexpr::TOKEN) - return fail(arg, "arg not token"); + return fail(arg, "arg not token"_s); proc->argv.push_back(intern_id(arg._str)); } if (!build_effect_list(in.begin() + 3, in.end(), proc->body)) @@ -1091,37 +1111,37 @@ namespace magic_v2 bool parse_spell(io::LineSpan span, const std::vector<SExpr>& in) { if (in.size() < 6) - return fail(in[0], "not at least 5 arguments"); + return fail(in[0], "not at least 5 arguments"_s); if (in[1]._type != sexpr::LIST) - return fail(in[1], "flags not list"); + return fail(in[1], "flags not list"_s); auto spell = dumb_ptr<spell_t>::make(); for (const SExpr& s : in[1]._list) { if (s._type != sexpr::TOKEN) - return fail(s, "flag not token"); + return fail(s, "flag not token"_s); SPELL_FLAG flag = SPELL_FLAG::ZERO; - if (s._str == "LOCAL") + if (s._str == "LOCAL"_s) flag = SPELL_FLAG::LOCAL; - else if (s._str == "NONMAGIC") + else if (s._str == "NONMAGIC"_s) flag = SPELL_FLAG::NONMAGIC; - else if (s._str == "SILENT") + else if (s._str == "SILENT"_s) flag = SPELL_FLAG::SILENT; else - return fail(s, "unknown flag"); + return fail(s, "unknown flag"_s); if (bool(spell->flags & flag)) - return fail(s, "duplicate flag"); + return fail(s, "duplicate flag"_s); spell->flags |= flag; } if (in[2]._type != sexpr::TOKEN) - return fail(in[2], "name not token"); + return fail(in[2], "name not token"_s); spell->name = in[2]._str; if (in[3]._type != sexpr::STRING) - return fail(in[3], "invoc not string"); + return fail(in[3], "invoc not string"_s); spell->invocation = in[3]._str; if (in[4]._type != sexpr::LIST) - return fail(in[4], "spellarg not list"); + return fail(in[4], "spellarg not list"_s); if (in[4]._list.size() == 0) { spell->spellarg_ty = SPELLARG::NONE; @@ -1129,18 +1149,18 @@ namespace magic_v2 else { if (in[4]._list.size() != 2) - return fail(in[4], "spellarg not empty list or pair"); + return fail(in[4], "spellarg not empty list or pair"_s); if (in[4]._list[0]._type != sexpr::TOKEN) - return fail(in[4]._list[0], "spellarg type not token"); + return fail(in[4]._list[0], "spellarg type not token"_s); if (in[4]._list[1]._type != sexpr::TOKEN) - return fail(in[4]._list[1], "spellarg name not token"); + return fail(in[4]._list[1], "spellarg name not token"_s); ZString ty = in[4]._list[0]._str; - if (ty == "PC") + if (ty == "PC"_s) spell->spellarg_ty = SPELLARG::PC; - else if (ty == "STRING") + else if (ty == "STRING"_s) spell->spellarg_ty = SPELLARG::STRING; else - return fail(in[4]._list[0], "unknown spellarg type"); + return fail(in[4]._list[0], "unknown spellarg type"_s); ZString an = in[4]._list[1]._str; spell->arg = intern_id(an); } @@ -1148,19 +1168,19 @@ namespace magic_v2 for (;; ++it) { if (it == in.end()) - return fail(it[-1], "end of list scanning LET defs"); + return fail(it[-1], "end of list scanning LET defs"_s); if (is_comment(*it)) continue; if (it->_type != sexpr::LIST || it->_list.empty()) break; - if (it->_list[0]._type != sexpr::TOKEN || it->_list[0]._str != "LET") + if (it->_list[0]._type != sexpr::TOKEN || it->_list[0]._str != "LET"_s) break; if (it->_list[1]._type != sexpr::TOKEN) - return fail(it->_list[1], "let name not token"); + return fail(it->_list[1], "let name not token"_s); ZString name = it->_list[1]._str; if (find_constant(name)) - return fail(it->_list[1], "constant exists"); + return fail(it->_list[1], "constant exists"_s); dumb_ptr<expr_t> expr; if (!parse_expression(it->_list[2], expr)) return false; @@ -1170,7 +1190,7 @@ namespace magic_v2 spell->letdefv.push_back(let); } if (it + 1 != in.end()) - return fail(*it, "expected only one body entry besides LET"); + return fail(*it, "expected only one body entry besides LET"_s); // formally, 'guard' only refers to the first argument of '=>' // but internally, spellbodies use the same thing @@ -1186,23 +1206,23 @@ namespace magic_v2 { if (vs.empty()) { - span.error("Empty list at top"); + span.error("Empty list at top"_s); return false; } if (vs[0]._type != sexpr::TOKEN) - return fail(vs[0], "top not token"); + return fail(vs[0], "top not token"_s); ZString cmd = vs[0]._str; - if (cmd == "CONST") + if (cmd == "CONST"_s) return parse_const(span, vs); - if (cmd == "PROCEDURE") + if (cmd == "PROCEDURE"_s) return parse_proc(span, vs); - if (cmd == "SET") + if (cmd == "SET"_s) return parse_top_set(vs); - if (cmd == "SPELL") + if (cmd == "SPELL"_s) return parse_spell(span, vs); - if (cmd == "TELEPORT-ANCHOR") + if (cmd == "TELEPORT-ANCHOR"_s) return parse_anchor(span, vs); - return fail(vs[0], "Unknown top-level command"); + return fail(vs[0], "Unknown top-level command"_s); } static @@ -1214,14 +1234,14 @@ namespace magic_v2 if (is_comment(s)) continue; if (s._type != sexpr::LIST) - return fail(s, "top-level entity not a list or comment"); + return fail(s, "top-level entity not a list or comment"_s); if (!parse_top(s._span, s._list)) return false; } // handle low-level errors if (in.peek() != sexpr::TOK_EOF) { - in.span().error("parser gave up before end of file"); + in.span().error("parser gave up before end of file"_s); return false; } return true; @@ -1239,7 +1259,8 @@ bool load_magic_file_v2(ZString filename) bool rv = magic_v2::loop(in); if (!rv) { - in.span().error(STRPRINTF("next token: %s '%s'", sexpr::token_name(in.peek()), in.val_string())); + in.span().error(STRPRINTF("next token: %s '%s'"_fmt, sexpr::token_name(in.peek()), in.val_string())); } return rv; } +} // namespace tmwa diff --git a/src/map/magic-v2.hpp b/src/map/magic-v2.hpp index 888e183..07d467e 100644 --- a/src/map/magic-v2.hpp +++ b/src/map/magic-v2.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MAGIC_V2_HPP -#define TMWA_MAP_MAGIC_V2_HPP +#pragma once // magic-v2.hpp - second generation magic parser // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,12 +18,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/zstring.hpp" +#include "../strings/zstring.hpp" + +namespace tmwa +{ bool magic_init0(); // must be called after itemdb initialization bool load_magic_file_v2(ZString filename); - -#endif // TMWA_MAP_MAGIC_V2_HPP +} // namespace tmwa diff --git a/src/map/magic.cpp b/src/map/magic.cpp index 9896b26..b899a5e 100644 --- a/src/map/magic.cpp +++ b/src/map/magic.cpp @@ -1,3 +1,4 @@ +#include "magic.hpp" // magic.cpp - Entry to the magic system. // // Copyright © 2004-2011 The Mana World Development Team @@ -18,23 +19,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <cstring> +#include <algorithm> +#include <utility> #include "../strings/xstring.hpp" -#include "../io/cxxstdio.hpp" - -#include "magic-interpreter.hpp" +#include "../generic/dumb_ptr.hpp" -#include "pc.hpp" +#include "../io/cxxstdio.hpp" #include "magic-expr.hpp" +#include "magic-interpreter.hpp" #include "magic-interpreter-base.hpp" #include "magic-stmt.hpp" -#include "magic.hpp" +#include "map.hpp" +#include "pc.hpp" #include "../poison.hpp" + +namespace tmwa +{ #undef DEBUG /// Return a pair of strings, {spellname, parameter} @@ -95,15 +100,15 @@ int magic_message(dumb_ptr<map_session_data> caster, XString source_invocation) if (bool(spell->flags & SPELL_FLAG::NONMAGIC) || (power >= 1)) effects = spell_trigger(spell, caster, env, &near_miss); else - effects = NULL; + effects = nullptr; #ifdef DEBUG - FPRINTF(stderr, "Found spell `%s', triggered = %d\n", spell_, - effects != NULL); + FPRINTF(stderr, "Found spell `%s', triggered = %d\n"_fmt, spell_, + effects != nullptr); #endif - MAP_LOG_PC(caster, "CAST %s %s", - spell->name, effects ? "SUCCESS" : "FAILURE"); + MAP_LOG_PC(caster, "CAST %s %s"_fmt, + spell->name, effects ? "SUCCESS"_s : "FAILURE"_s); if (effects) { @@ -122,3 +127,4 @@ int magic_message(dumb_ptr<map_session_data> caster, XString source_invocation) return 0; /* Not a spell */ } +} // namespace tmwa diff --git a/src/map/magic.hpp b/src/map/magic.hpp index a5a966c..e06e913 100644 --- a/src/map/magic.hpp +++ b/src/map/magic.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MAGIC_HPP -#define TMWA_MAP_MAGIC_HPP +#pragma once // magic.hpp - Entry to the magic system. // // Copyright © 2004-2011 The Mana World Development Team @@ -20,17 +19,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "../mmo/dumb_ptr.hpp" +#include "../generic/fwd.hpp" -# include "map.hpp" -# include "skill.t.hpp" +#include "map.t.hpp" +#include "skill.t.hpp" -struct invocation; /* Spell invocation */ +namespace tmwa +{ /** * Try to cast magic. * @@ -43,62 +43,4 @@ struct invocation; /* Spell invocation */ * message should not be repeated. */ int magic_message(dumb_ptr<map_session_data> caster, XString source_invocation); - -/** - * Removes the shroud from a character - * - * \param character The character to remove the shroud from - */ -void magic_unshroud(dumb_ptr<map_session_data> character); - -/** - * Notifies a running spell that a status_change timer triggered by the spell has expired - * - * \param invocation The invocation to notify - * \param bl_id ID of the PC for whom this happened - * \param sc_id ID of the status change entry that finished - * \param supplanted Whether the status_change finished normally (0) or was supplanted by a new status_change (1) - */ -void spell_effect_report_termination(int invocation, int bl_id, - StatusChange sc_id, int supplanted); - -/** - * Identifies the invocation used to trigger a spell - * - * Returns empty string if not found - */ -AString magic_find_invocation(XString spellname); - -/** - * Identifies the invocation used to denote a teleport location - * - * Returns empty string if not found - */ -AString magic_find_anchor_invocation(XString teleport_location); - -/** - * Execute a spell invocation and sets up timers to finish - */ -void spell_execute(dumb_ptr<invocation> invocation); - -/** - * Continue an NPC script embedded in a spell - */ -void spell_execute_script(dumb_ptr<invocation> invocation); - -/** - * Stops all magic bound to the specified character - * - */ -void magic_stop_completely(dumb_ptr<map_session_data> c); - -/** - * Attacks with a magical spell charged to the character - * - * Returns 0 if there is no charged spell or the spell is depleted. - */ -int spell_attack(int caster, int target); - -void spell_free_invocation(dumb_ptr<invocation> invocation); - -#endif // TMWA_MAP_MAGIC_HPP +} // namespace tmwa diff --git a/src/map/main.cpp b/src/map/main.cpp index 2db1408..8e8e9d5 100644 --- a/src/map/main.cpp +++ b/src/map/main.cpp @@ -1,4 +1,3 @@ -#include "map.hpp" // map/main.cpp - dummy file to make Make dependencies work // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -18,4 +17,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include "map.hpp" + #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/map/map.cpp b/src/map/map.cpp index b49b225..033f299 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -29,15 +29,17 @@ #include <cassert> #include <cstdlib> -#include <cstring> #include "../compat/nullpo.hpp" #include "../compat/fun.hpp" +#include "../ints/udl.hpp" + #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" #include "../strings/vstring.hpp" +#include "../strings/literal.hpp" #include "../generic/db.hpp" #include "../generic/random2.hpp" @@ -47,11 +49,13 @@ #include "../io/tty.hpp" #include "../io/write.hpp" +#include "../net/socket.hpp" +#include "../net/timer.hpp" + #include "../mmo/config_parse.hpp" #include "../mmo/core.hpp" #include "../mmo/extract.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" +#include "../mmo/utils.hpp" #include "../mmo/version.hpp" #include "atcommand.hpp" @@ -60,8 +64,8 @@ #include "clif.hpp" #include "grfio.hpp" #include "itemdb.hpp" -#include "magic.hpp" -#include "magic-interpreter.hpp" +#include "magic-interpreter.hpp" // for is_spell inline body +#include "magic-stmt.hpp" #include "magic-v2.hpp" #include "mob.hpp" #include "npc.hpp" @@ -74,7 +78,10 @@ #include "../poison.hpp" -DMap<int, dumb_ptr<block_list>> id_db; + +namespace tmwa +{ +DMap<BlockId, dumb_ptr<block_list>> id_db; UPMap<MapName, map_abstract> maps_db; @@ -88,21 +95,21 @@ struct charid2nick }; static -Map<int, struct charid2nick> charid_db; +Map<CharId, struct charid2nick> charid_db; static int users = 0; static -Array<dumb_ptr<block_list>, MAX_FLOORITEM> object; +Array<dumb_ptr<block_list>, unwrap<BlockId>(MAX_FLOORITEM)> object; static -int first_free_object_id = 0, last_object_id = 0; +BlockId first_free_object_id = BlockId(); interval_t autosave_time = DEFAULT_AUTOSAVE_INTERVAL; int save_settings = 0xFFFF; -AString motd_txt = "conf/motd.txt"; +AString motd_txt = "conf/motd.txt"_s; -CharName wisp_server_name = stringish<CharName>("Server"); // can be modified in char-server configuration file +CharName wisp_server_name = stringish<CharName>("Server"_s); // can be modified in char-server configuration file static void map_delmap(MapName mapname); @@ -112,6 +119,10 @@ void SessionDeleter::operator()(SessionData *sd) really_delete1 static_cast<map_session_data *>(sd); } +VString<49> convert_for_printf(NpcEvent ev) +{ + return STRNPRINTF(50, "%s::%s"_fmt, ev.npc, ev.label); +} bool extract(XString str, NpcEvent *ev) { XString mid; @@ -181,12 +192,12 @@ struct block_list bl_head; */ int map_addblock(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_prev) { if (battle_config.error_log) - PRINTF("map_addblock error : bl->bl_prev!=NULL\n"); + PRINTF("map_addblock error : bl->bl_prev!=nullptr\n"_fmt); return 0; } @@ -226,7 +237,7 @@ int map_addblock(dumb_ptr<block_list> bl) */ int map_delblock(dumb_ptr<block_list> bl) { - nullpo_ret(bl); + nullpo_retz(bl); // 既にblocklistから抜けている if (!bl->bl_prev) @@ -235,7 +246,7 @@ int map_delblock(dumb_ptr<block_list> bl) { // prevがNULLでnextがNULLでないのは有ってはならない if (battle_config.error_log) - PRINTF("map_delblock error : bl->bl_next!=NULL\n"); + PRINTF("map_delblock error : bl->bl_next!=nullptr\n"_fmt); } return 0; } @@ -261,8 +272,8 @@ int map_delblock(dumb_ptr<block_list> bl) { bl->bl_prev->bl_next = bl->bl_next; } - bl->bl_next = NULL; - bl->bl_prev = NULL; + bl->bl_next = nullptr; + bl->bl_prev = nullptr; return 0; } @@ -274,7 +285,7 @@ int map_delblock(dumb_ptr<block_list> bl) int map_count_oncell(map_local *m, int x, int y) { int bx, by; - dumb_ptr<block_list> bl = NULL; + dumb_ptr<block_list> bl = nullptr; int count = 0; if (x < 0 || y < 0 || (x >= m->xs) || (y >= m->ys)) @@ -533,29 +544,27 @@ void map_foreachincell(std::function<void(dumb_ptr<block_list>)> func, * bl->bl_idもこの中で設定して問題無い? *------------------------------------------ */ -int map_addobject(dumb_ptr<block_list> bl) +BlockId map_addobject(dumb_ptr<block_list> bl) { - int i; + BlockId i; if (!bl) { - PRINTF("map_addobject nullpo?\n"); - return 0; + PRINTF("map_addobject nullpo?\n"_fmt); + return BlockId(); } - if (first_free_object_id < 2 || first_free_object_id >= MAX_FLOORITEM) - first_free_object_id = 2; - for (i = first_free_object_id; i < MAX_FLOORITEM; i++) - if (!object[i]) + if (first_free_object_id < wrap<BlockId>(2) || first_free_object_id == MAX_FLOORITEM) + first_free_object_id = wrap<BlockId>(2); + for (i = first_free_object_id; i < MAX_FLOORITEM; i = next(i)) + if (!object[i._value]) break; - if (i >= MAX_FLOORITEM) + if (i == MAX_FLOORITEM) { if (battle_config.error_log) - PRINTF("no free object id\n"); - return 0; + PRINTF("no free object id\n"_fmt); + return BlockId(); } first_free_object_id = i; - if (last_object_id < i) - last_object_id = i; - object[i] = bl; + object[i._value] = bl; id_db.put(i, bl); return i; } @@ -565,32 +574,26 @@ int map_addobject(dumb_ptr<block_list> bl) * map_delobjectのfreeしないバージョン *------------------------------------------ */ -int map_delobjectnofree(int id, BL type) +void map_delobjectnofree(BlockId id, BL type) { assert (id < MAX_FLOORITEM); - if (!object[id]) - return 0; + if (!object[id._value]) + return; - if (object[id]->bl_type != type) + if (object[id._value]->bl_type != type) { - FPRINTF(stderr, "Incorrect type: expected %d, got %d\n", + FPRINTF(stderr, "Incorrect type: expected %d, got %d\n"_fmt, type, - object[id]->bl_type); + object[id._value]->bl_type); abort(); } - map_delblock(object[id]); + map_delblock(object[id._value]); id_db.put(id, dumb_ptr<block_list>()); -// map_freeblock(object[id]); - object[id] = nullptr; + object[id._value] = nullptr; - if (first_free_object_id > id) + if (id < first_free_object_id) first_free_object_id = id; - - while (last_object_id > 2 && object[last_object_id] == NULL) - last_object_id--; - - return 0; } /*========================================== @@ -601,21 +604,19 @@ int map_delobjectnofree(int id, BL type) * addとの対称性が無いのが気になる *------------------------------------------ */ -int map_delobject(int id, BL type) +void map_delobject(BlockId id, BL type) { assert (id < MAX_FLOORITEM); - dumb_ptr<block_list> obj = object[id]; + dumb_ptr<block_list> obj = object[id._value]; - if (obj == NULL) - return 0; + if (obj == nullptr) + return; map_delobjectnofree(id, type); if (obj->bl_type == BL::PC) // [Fate] Not sure where else to put this... I'm not sure where delobject for PCs is called from pc_cleanup(obj->is_player()); MapBlockLock::freeblock(obj); - - return 0; } /*========================================== @@ -626,24 +627,28 @@ int map_delobject(int id, BL type) void map_foreachobject(std::function<void(dumb_ptr<block_list>)> func, BL type) { - assert (last_object_id < MAX_FLOORITEM); std::vector<dumb_ptr<block_list>> bl_list; - for (int i = 2; i <= last_object_id; i++) + for (BlockId i = wrap<BlockId>(2); i < MAX_FLOORITEM; i = next(i)) { - if (!object[i]) + if (!object[i._value]) continue; { - if (type != BL::NUL && object[i]->bl_type != type) + if (type != BL::NUL && object[i._value]->bl_type != type) continue; - bl_list.push_back(object[i]); + bl_list.push_back(object[i._value]); } } MapBlockLock lock; for (dumb_ptr<block_list> bl : bl_list) + { + // TODO figure out if the second branch can happen + // bl_prev is non-null for all that are on a map (see bl_head) + // bl_next is only meaningful for objects that are on a map if (bl->bl_prev || bl->bl_next) func(bl); + } } /*========================================== @@ -656,15 +661,15 @@ void map_foreachobject(std::function<void(dumb_ptr<block_list>)> func, * map.h内で#defineしてある *------------------------------------------ */ -void map_clearflooritem_timer(TimerData *tid, tick_t, int id) +void map_clearflooritem_timer(TimerData *tid, tick_t, BlockId id) { assert (id < MAX_FLOORITEM); - dumb_ptr<block_list> obj = object[id]; + dumb_ptr<block_list> obj = object[id._value]; assert (obj && obj->bl_type == BL::ITEM); dumb_ptr<flooritem_data> fitem = obj->is_item(); if (!tid) fitem->cleartimer.cancel(); - clif_clearflooritem(fitem, 0); + clif_clearflooritem(fitem, nullptr); map_delobject(fitem->bl_id, BL::ITEM); } @@ -678,7 +683,7 @@ std::pair<uint16_t, uint16_t> map_randfreecell(map_local *m, if (!bool(read_gatp(m, x + dx, y + dy) & MapCell::UNWALKABLE)) return {static_cast<uint16_t>(x + dx), static_cast<uint16_t>(y + dy)}; } - return {static_cast<uint16_t>(0), static_cast<uint16_t>(0)}; + return {0_u16, 0_u16}; } /// Return a randomly selected passable cell within a given range. @@ -695,36 +700,36 @@ std::pair<uint16_t, uint16_t> map_searchrandfreecell(map_local *m, int x, int y, * item_dataはamount以外をcopyする *------------------------------------------ */ -int map_addflooritem_any(struct item *item_data, int amount, +BlockId map_addflooritem_any(Item *item_data, int amount, map_local *m, int x, int y, dumb_ptr<map_session_data> *owners, interval_t *owner_protection, interval_t lifetime, int dispersal) { - dumb_ptr<flooritem_data> fitem = NULL; + dumb_ptr<flooritem_data> fitem = nullptr; - nullpo_ret(item_data); + nullpo_retr(BlockId(), item_data); auto xy = map_searchrandfreecell(m, x, y, dispersal); if (xy.first == 0 && xy.second == 0) - return 0; + return BlockId(); fitem.new_(); fitem->bl_type = BL::ITEM; - fitem->bl_prev = fitem->bl_next = NULL; + fitem->bl_prev = fitem->bl_next = nullptr; fitem->bl_m = m; fitem->bl_x = xy.first; fitem->bl_y = xy.second; - fitem->first_get_id = 0; + fitem->first_get_id = BlockId(); fitem->first_get_tick = tick_t(); - fitem->second_get_id = 0; + fitem->second_get_id = BlockId(); fitem->second_get_tick = tick_t(); - fitem->third_get_id = 0; + fitem->third_get_id = BlockId(); fitem->third_get_tick = tick_t(); fitem->bl_id = map_addobject(fitem); - if (fitem->bl_id == 0) + if (!fitem->bl_id) { fitem.delete_(); - return 0; + return BlockId(); } tick_t tick = gettick(); @@ -760,7 +765,7 @@ int map_addflooritem_any(struct item *item_data, int amount, return fitem->bl_id; } -int map_addflooritem(struct item *item_data, int amount, +BlockId map_addflooritem(Item *item_data, int amount, map_local *m, int x, int y, dumb_ptr<map_session_data> first_sd, dumb_ptr<map_session_data> second_sd, @@ -784,10 +789,10 @@ int map_addflooritem(struct item *item_data, int amount, * charid_dbへ追加(返信待ちがあれば返信) *------------------------------------------ */ -void map_addchariddb(int charid, CharName name) +void map_addchariddb(CharId charid, CharName name) { struct charid2nick *p = charid_db.search(charid); - if (p == NULL) + if (p == nullptr) p = charid_db.init(charid); p->nick = name; @@ -840,7 +845,7 @@ void map_quit(dumb_ptr<map_session_data> sd) if (sd->trade_partner) // 取引を中断する trade_tradecancel(sd); - if (sd->party_invite > 0) // パーティ勧誘を拒否する + if (sd->party_invite) // パーティ勧誘を拒否する party_reply_invite(sd, sd->party_invite_account, 0); party_send_logout(sd); // パーティのログアウトメッセージ送信 @@ -883,7 +888,7 @@ void map_quit(dumb_ptr<map_session_data> sd) * id番号のPCを探す。居なければNULL *------------------------------------------ */ -dumb_ptr<map_session_data> map_id2sd(int id) +dumb_ptr<map_session_data> map_id2sd(BlockId id) { // This is bogus. // However, there might be differences for de-auth'ed accounts. @@ -899,7 +904,7 @@ dumb_ptr<map_session_data> map_id2sd(int id) bl=numdb_search(id_db,id); if (bl && bl->bl_type==BL::PC) return (struct map_session_data*)bl; - return NULL; + return nullptr; */ for (io::FD i : iter_fds()) { @@ -914,18 +919,18 @@ dumb_ptr<map_session_data> map_id2sd(int id) } } - return NULL; + return nullptr; } /*========================================== * char_id番号の名前を探す *------------------------------------------ */ -CharName map_charid2nick(int id) +CharName map_charid2nick(CharId id) { struct charid2nick *p = charid_db.search(id); - if (p == NULL) + if (p == nullptr) return CharName(); if (p->req_id != 0) return CharName(); @@ -947,7 +952,7 @@ dumb_ptr<map_session_data> map_get_session(io::FD i) return dumb_ptr<map_session_data>(d); } - return NULL; + return nullptr; } static @@ -960,7 +965,7 @@ dumb_ptr<map_session_data> map_get_session_forward(int start) return d; } - return NULL; + return nullptr; } static @@ -973,7 +978,7 @@ dumb_ptr<map_session_data> map_get_session_backward(int start) return d; } - return NULL; + return nullptr; } dumb_ptr<map_session_data> map_get_first_session(void) @@ -999,7 +1004,7 @@ dumb_ptr<map_session_data> map_get_prev_session(dumb_ptr<map_session_data> d) /*========================================== * Search session data from a nick name * (without sensitive case if necessary) - * return map_session_data pointer or NULL + * return map_session_data pointer or nullptr *------------------------------------------ */ dumb_ptr<map_session_data> map_nick2sd(CharName nick) @@ -1018,7 +1023,7 @@ dumb_ptr<map_session_data> map_nick2sd(CharName nick) } } } - return NULL; + return nullptr; } /*========================================== @@ -1026,11 +1031,11 @@ dumb_ptr<map_session_data> map_nick2sd(CharName nick) * 一時objectの場合は配列を引くのみ *------------------------------------------ */ -dumb_ptr<block_list> map_id2bl(int id) +dumb_ptr<block_list> map_id2bl(BlockId id) { - dumb_ptr<block_list> bl = NULL; - if (id < sizeof(object) / sizeof(object[0])) - bl = object[id]; + dumb_ptr<block_list> bl = nullptr; + if (id < MAX_FLOORITEM) + bl = object[id._value]; else bl = id_db.get(id); @@ -1047,12 +1052,12 @@ int map_addnpc(map_local *m, dumb_ptr<npc_data> nd) if (!m) return -1; for (i = 0; i < m->npc_num && i < MAX_NPC_PER_MAP; i++) - if (m->npc[i] == NULL) + if (m->npc[i] == nullptr) break; if (i == MAX_NPC_PER_MAP) { if (battle_config.error_log) - PRINTF("too many NPCs in one map %s\n", m->name_); + PRINTF("too many NPCs in one map %s\n"_fmt, m->name_); return -1; } if (i == m->npc_num) @@ -1060,7 +1065,7 @@ int map_addnpc(map_local *m, dumb_ptr<npc_data> nd) m->npc_num++; } - nullpo_ret(nd); + nullpo_retz(nd); m->npc[i] = nd; nd->n = i; @@ -1081,7 +1086,7 @@ void map_removenpc(void) map_local *m = static_cast<map_local *>(mitp.second.get()); for (int i = 0; i < m->npc_num && i < MAX_NPC_PER_MAP; i++) { - if (m->npc[i] != NULL) + if (m->npc[i] != nullptr) { clif_clearchar(m->npc[i], BeingRemoveWhy::QUIT); map_delblock(m->npc[i]); @@ -1096,7 +1101,7 @@ void map_removenpc(void) } } } - PRINTF("%d NPCs removed.\n", n); + PRINTF("%d NPCs removed.\n"_fmt, n); } /*========================================== @@ -1106,7 +1111,7 @@ void map_removenpc(void) map_local *map_mapname2mapid(MapName name) { map_abstract *md = maps_db.get(name); - if (md == NULL || md->gat == NULL) + if (md == nullptr || md->gat == nullptr) return nullptr; return static_cast<map_local *>(md); } @@ -1118,7 +1123,7 @@ map_local *map_mapname2mapid(MapName name) int map_mapname2ipport(MapName name, IP4Address *ip, int *port) { map_abstract *md = maps_db.get(name); - if (md == NULL || md->gat) + if (md == nullptr || md->gat) return -1; map_remote *mdos = static_cast<map_remote *>(md); *ip = mdos->ip; @@ -1227,12 +1232,12 @@ void map_setcell(map_local *m, int x, int y, MapCell t) int map_setipport(MapName name, IP4Address ip, int port) { map_abstract *md = maps_db.get(name); - if (md == NULL) + if (md == nullptr) { // not exist -> add new data auto mdos = make_unique<map_remote>(); mdos->name_ = name; - mdos->gat = NULL; + mdos->gat = nullptr; mdos->ip = ip; mdos->port = port; maps_db.put(mdos->name_, std::move(mdos)); @@ -1244,7 +1249,7 @@ int map_setipport(MapName name, IP4Address ip, int port) // local -> check data if (ip != clif_getip() || port != clif_getport()) { - PRINTF("from char server : %s -> %s:%d\n", + PRINTF("from char server : %s -> %s:%d\n"_fmt, name, ip, port); return 1; } @@ -1275,7 +1280,7 @@ bool map_readmap(map_local *m, size_t num, MapName fn) int xs = m->xs = gat_v[0] | gat_v[1] << 8; int ys = m->ys = gat_v[2] | gat_v[3] << 8; - PRINTF("\rLoading Maps [%zu/%zu]: %-30s (%i, %i)", + PRINTF("\rLoading Maps [%zu/%zu]: %-30s (%i, %i)"_fmt, num, maps_db.size(), fn, xs, ys); fflush(stdout); @@ -1328,10 +1333,10 @@ bool map_readallmap(void) } } - PRINTF("\rMaps Loaded: %-65zu\n", maps_db.size()); + PRINTF("\rMaps Loaded: %-65zu\n"_fmt, maps_db.size()); if (maps_removed) { - PRINTF("Cowardly refusing to keep going after removing %d maps.\n", + PRINTF("Cowardly refusing to keep going after removing %d maps.\n"_fmt, maps_removed); return false; } @@ -1346,7 +1351,7 @@ bool map_readallmap(void) static void map_addmap(MapName mapname) { - if (mapname == "clear") + if (mapname == "clear"_s) { maps_db.clear(); return; @@ -1366,7 +1371,7 @@ void map_addmap(MapName mapname) */ void map_delmap(MapName mapname) { - if (mapname == "all") + if (mapname == "all"_s) { maps_db.clear(); return; @@ -1389,13 +1394,13 @@ void map_close_logfile(void) { if (map_logfile) { - AString filename = STRPRINTF("%s.%ld", map_logfile_name, map_logfile_index); + AString filename = STRPRINTF("%s.%ld"_fmt, map_logfile_name, map_logfile_index); const char *args[] = { "gzip", "-f", filename.c_str(), - NULL + nullptr }; char **argv = const_cast<char **>(args); @@ -1406,7 +1411,7 @@ void map_close_logfile(void) execvp("gzip", argv); _exit(1); } - wait(NULL); + wait(nullptr); } } @@ -1416,7 +1421,7 @@ void map_start_logfile(long index) map_logfile_index = index; AString filename_buf = STRPRINTF( - "%s.%ld", + "%s.%ld"_fmt, map_logfile_name, map_logfile_index); map_logfile = make_unique<io::AppendFile>(filename_buf); @@ -1433,11 +1438,11 @@ void map_set_logfile(AString filename) struct timeval tv; map_logfile_name = std::move(filename); - gettimeofday(&tv, NULL); + gettimeofday(&tv, nullptr); map_start_logfile(tv.tv_sec >> LOGFILE_SECONDS_PER_CHUNK_SHIFT); - MAP_LOG("log-start v5"); + MAP_LOG("log-start v5"_fmt); } void map_log(XString line) @@ -1464,12 +1469,12 @@ void map_log(XString line) static bool map_config_read(ZString cfgName) { - struct hostent *h = NULL; + struct hostent *h = nullptr; io::ReadFile in(cfgName); if (!in.is_open()) { - PRINTF("Map configuration file not found at: %s\n", cfgName); + PRINTF("Map configuration file not found at: %s\n"_fmt, cfgName); return false; } @@ -1483,25 +1488,25 @@ bool map_config_read(ZString cfgName) ZString w2; if (!config_split(line, &w1, &w2)) { - PRINTF("Bad config line: %s\n", line); + PRINTF("Bad config line: %s\n"_fmt, line); rv = false; continue; } - if (w1 == "userid") + if (w1 == "userid"_s) { AccountName name = stringish<AccountName>(w2); chrif_setuserid(name); } - else if (w1 == "passwd") + else if (w1 == "passwd"_s) { AccountPass pass = stringish<AccountPass>(w2); chrif_setpasswd(pass); } - else if (w1 == "char_ip") + else if (w1 == "char_ip"_s) { h = gethostbyname(w2.c_str()); IP4Address w2ip; - if (h != NULL) + if (h != nullptr) { w2ip = IP4Address({ static_cast<uint8_t>(h->h_addr[0]), @@ -1509,25 +1514,25 @@ bool map_config_read(ZString cfgName) static_cast<uint8_t>(h->h_addr[2]), static_cast<uint8_t>(h->h_addr[3]), }); - PRINTF("Character server IP address : %s -> %s\n", + PRINTF("Character server IP address : %s -> %s\n"_fmt, w2, w2ip); } else { - PRINTF("Bad IP value: %s\n", line); + PRINTF("Bad IP value: %s\n"_fmt, line); return false; } chrif_setip(w2ip); } - else if (w1 == "char_port") + else if (w1 == "char_port"_s) { chrif_setport(atoi(w2.c_str())); } - else if (w1 == "map_ip") + else if (w1 == "map_ip"_s) { h = gethostbyname(w2.c_str()); IP4Address w2ip; - if (h != NULL) + if (h != nullptr) { w2ip = IP4Address({ static_cast<uint8_t>(h->h_addr[0]), @@ -1535,61 +1540,61 @@ bool map_config_read(ZString cfgName) static_cast<uint8_t>(h->h_addr[2]), static_cast<uint8_t>(h->h_addr[3]), }); - PRINTF("Map server IP address : %s -> %s\n", + PRINTF("Map server IP address : %s -> %s\n"_fmt, w2, w2ip); } else { - PRINTF("Bad IP value: %s\n", line); + PRINTF("Bad IP value: %s\n"_fmt, line); return false; } clif_setip(w2ip); } - else if (w1 == "map_port") + else if (w1 == "map_port"_s) { clif_setport(atoi(w2.c_str())); } - else if (w1 == "map") + else if (w1 == "map"_s) { MapName name = VString<15>(w2); map_addmap(name); } - else if (w1 == "delmap") + else if (w1 == "delmap"_s) { MapName name = VString<15>(w2); map_delmap(name); } - else if (w1 == "npc") + else if (w1 == "npc"_s) { npc_addsrcfile(w2); } - else if (w1 == "delnpc") + else if (w1 == "delnpc"_s) { npc_delsrcfile(w2); } - else if (w1 == "autosave_time") + else if (w1 == "autosave_time"_s) { autosave_time = std::chrono::seconds(atoi(w2.c_str())); if (autosave_time <= interval_t::zero()) autosave_time = DEFAULT_AUTOSAVE_INTERVAL; } - else if (w1 == "motd_txt") + else if (w1 == "motd_txt"_s) { motd_txt = w2; } - else if (w1 == "mapreg_txt") + else if (w1 == "mapreg_txt"_s) { mapreg_txt = w2; } - else if (w1 == "gm_log") + else if (w1 == "gm_log"_s) { gm_log = std::move(w2); } - else if (w1 == "log_file") + else if (w1 == "log_file"_s) { map_set_logfile(w2); } - else if (w1 == "import") + else if (w1 == "import"_s) { rv &= map_config_read(w2); } @@ -1656,7 +1661,7 @@ void term_func(void) map_close_logfile(); } -int compare_item(struct item *a, struct item *b) +int compare_item(Item *a, Item *b) { return (a->nameid == b->nameid); } @@ -1664,29 +1669,29 @@ int compare_item(struct item *a, struct item *b) static bool map_confs(XString key, ZString value) { - if (key == "map_conf") + if (key == "map_conf"_s) return map_config_read(value); - if (key == "battle_conf") + if (key == "battle_conf"_s) return battle_config_read(value); - if (key == "atcommand_conf") + if (key == "atcommand_conf"_s) return atcommand_config_read(value); - if (key == "item_db") + if (key == "item_db"_s) return itemdb_readdb(value); - if (key == "mob_db") + if (key == "mob_db"_s) return mob_readdb(value); - if (key == "mob_skill_db") + if (key == "mob_skill_db"_s) return mob_readskilldb(value); - if (key == "skill_db") + if (key == "skill_db"_s) return skill_readdb(value); - if (key == "magic_conf") + if (key == "magic_conf"_s) return load_magic_file_v2(value); - if (key == "resnametable") + if (key == "resnametable"_s) return load_resnametable(value); - if (key == "const_db") + if (key == "const_db"_s) return read_constdb(value); - PRINTF("unknown map conf key: %s\n", AString(key)); + PRINTF("unknown map conf key: %s\n"_fmt, AString(key)); return false; } @@ -1705,22 +1710,22 @@ int do_init(Slice<ZString> argv) ZString argvi = argv.pop_front(); if (argvi.startswith('-')) { - if (argvi == "--help") + if (argvi == "--help"_s) { - PRINTF("Usage: %s [--help] [--version] [--write_atcommand_config outfile] [files...]\n", + PRINTF("Usage: %s [--help] [--version] [--write_atcommand_config outfile] [files...]\n"_fmt, argv0); exit(0); } - else if (argvi == "--version") + else if (argvi == "--version"_s) { - PRINTF("%s\n", CURRENT_VERSION_STRING); + PRINTF("%s\n"_fmt, CURRENT_VERSION_STRING); exit(0); } - else if (argvi == "--write-atcommand-config") + else if (argvi == "--write-atcommand-config"_s) { if (!argv) { - PRINTF("Missing argument\n"); + PRINTF("Missing argument\n"_fmt); exit(1); } ZString filename = argv.pop_front(); @@ -1729,7 +1734,7 @@ int do_init(Slice<ZString> argv) } else { - FPRINTF(stderr, "Unknown argument: %s\n", argvi); + FPRINTF(stderr, "Unknown argument: %s\n"_fmt, argvi); runflag = false; } } @@ -1741,7 +1746,7 @@ int do_init(Slice<ZString> argv) } if (!loaded_config_yet) - runflag &= load_config_file("conf/tmwa-map.conf", map_confs); + runflag &= load_config_file("conf/tmwa-map.conf"_s, map_confs); battle_config_check(); runflag &= map_readallmap(); @@ -1758,15 +1763,15 @@ int do_init(Slice<ZString> argv) npc_event_do_oninit(); // npcのOnInitイベント実行 if (battle_config.pk_mode == 1) - PRINTF("The server is running in " SGR_BOLD SGR_RED "PK Mode" SGR_RESET "\n"); + PRINTF("The server is running in " SGR_BOLD SGR_RED "PK Mode" SGR_RESET "\n"_fmt); - PRINTF("The map-server is " SGR_BOLD SGR_GREEN "ready" SGR_RESET " (Server is listening on the port %d).\n\n", + PRINTF("The map-server is " SGR_BOLD SGR_GREEN "ready" SGR_RESET " (Server is listening on the port %d).\n\n"_fmt, clif_getport()); return 0; } -int map_scriptcont(dumb_ptr<map_session_data> sd, int id) +int map_scriptcont(dumb_ptr<map_session_data> sd, BlockId id) { dumb_ptr<block_list> bl = map_id2bl(id); @@ -1784,3 +1789,4 @@ int map_scriptcont(dumb_ptr<map_session_data> sd, int id) return 0; } +} // namespace tmwa diff --git a/src/map/map.hpp b/src/map/map.hpp index 0cec5e8..0e4815c 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MAP_HPP -#define TMWA_MAP_MAP_HPP +#pragma once // map.hpp - Core of the map server. // // Copyright © ????-2004 Athena Dev Teams @@ -21,48 +20,53 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "map.t.hpp" +#include "map.t.hpp" -# include <netinet/in.h> +#include <chrono> +#include <functional> +#include <list> -# include <functional> -# include <list> +#include "../ints/udl.hpp" -# include "../strings/fwd.hpp" -# include "../strings/rstring.hpp" -# include "../strings/astring.hpp" -# include "../strings/vstring.hpp" +#include "../strings/fwd.hpp" +#include "../strings/rstring.hpp" +#include "../strings/astring.hpp" +#include "../strings/vstring.hpp" -# include "../generic/db.hpp" -# include "../generic/matrix.hpp" +#include "../generic/db.hpp" +#include "../generic/dumb_ptr.hpp" +#include "../generic/matrix.hpp" -# include "../io/cxxstdio.hpp" +#include "../net/socket.hpp" +#include "../net/timer.t.hpp" -# include "../mmo/socket.hpp" -# include "../mmo/timer.t.hpp" +#include "../mmo/utils.hpp" -# include "battle.t.hpp" -# include "magic-interpreter.t.hpp" -# include "mapflag.hpp" -# include "mob.t.hpp" -# include "script.hpp" // change to script.t.hpp -# include "skill.t.hpp" +#include "battle.t.hpp" +#include "clif.t.hpp" +#include "mapflag.hpp" +#include "mob.t.hpp" +#include "script.hpp" // change to script.t.hpp +#include "skill.t.hpp" + +namespace tmwa +{ constexpr int MAX_NPC_PER_MAP = 512; constexpr int BLOCK_SIZE = 8; -# define AREA_SIZE battle_config.area_size -constexpr std::chrono::seconds LIFETIME_FLOORITEM = std::chrono::minutes(1); +#define AREA_SIZE battle_config.area_size +constexpr std::chrono::seconds LIFETIME_FLOORITEM = 1_min; constexpr int MAX_SKILL_LEVEL = 100; constexpr int MAX_EVENTTIMER = 32; -constexpr interval_t NATURAL_HEAL_INTERVAL = std::chrono::milliseconds(500); -constexpr int MAX_FLOORITEM = 500000; +constexpr interval_t NATURAL_HEAL_INTERVAL = 500_ms; +constexpr BlockId MAX_FLOORITEM = wrap<BlockId>(500000_u32); constexpr int MAX_LEVEL = 255; constexpr int MAX_WALKPATH = 48; constexpr int MAX_DROP_PER_MAP = 48; -constexpr interval_t DEFAULT_AUTOSAVE_INTERVAL = std::chrono::minutes(1); +constexpr interval_t DEFAULT_AUTOSAVE_INTERVAL = 1_min; // formerly VString<49>, as name::label struct NpcEvent @@ -89,24 +93,14 @@ struct NpcEvent return l.npc < r.npc || (l.npc == r.npc && l.label < r.label); } - friend VString<49> convert_for_printf(NpcEvent ev) - { - return STRNPRINTF(50, "%s::%s", ev.npc, ev.label); - } + friend VString<49> convert_for_printf(NpcEvent ev); }; bool extract(XString str, NpcEvent *ev); -struct map_session_data; -struct npc_data; -struct mob_data; -struct flooritem_data; -struct invocation; -struct map_local; - struct block_list { dumb_ptr<block_list> bl_next, bl_prev; - int bl_id; + BlockId bl_id; map_local *bl_m; short bl_x, bl_y; BL bl_type; @@ -141,14 +135,9 @@ struct status_change { Timer timer; int val1; - int spell_invocation; /* [Fate] If triggered by a spell, record here */ + BlockId spell_invocation; /* [Fate] If triggered by a spell, record here */ }; -struct invocation; - -struct npc_data; -struct item_data; - struct quick_regeneration { // [Fate] int amount; // Amount of HP/SP left to regenerate @@ -190,13 +179,14 @@ struct map_session_data : block_list, SessionData unsigned unbreakable_armor:1; unsigned deaf:1; } special_state; - int char_id, login_id1, login_id2; + CharId char_id_; + int login_id1, login_id2; SEX sex; unsigned char tmw_version; // tmw client version CharKey status_key; CharData status; - Array<struct item_data *, MAX_INVENTORY> inventory_data; - earray<short, EQUIP, EQUIP::COUNT> equip_index_maybe; + GenericArray<struct item_data *, InventoryIndexing<IOff0, MAX_INVENTORY>> inventory_data; + earray<IOff0, EQUIP, EQUIP::COUNT> equip_index_maybe; int weight, max_weight; MapName mapname_; Session *sess; // use this, you idiots! @@ -206,10 +196,9 @@ struct map_session_data : block_list, SessionData Opt2 opt2; Opt3 opt3; DIR dir, head_dir; - tick_t client_tick, server_tick; struct walkpath_data walkpath; Timer walktimer; - int npc_id, areanpc_id, npc_shopid; + BlockId npc_id, areanpc_id, npc_shopid; // this is important int npc_pos; int npc_menu; @@ -226,20 +215,20 @@ struct map_session_data : block_list, SessionData } npc_flags; Timer attacktimer; - int attacktarget; + BlockId attacktarget; ATK attacktarget_lv; tick_t attackabletime; // used by @hugo and @linus - int followtarget; + BlockId followtarget; tick_t cast_tick; // [Fate] Next tick at which spellcasting is allowed dumb_ptr<invocation> active_spells; // [Fate] Singly-linked list of active spells linked to this PC - int attack_spell_override; // [Fate] When an attack spell is active for this player, they trigger it + BlockId attack_spell_override; // [Fate] When an attack spell is active for this player, they trigger it // like a weapon. Check pc_attack_timer() for details. // Weapon equipment slot (slot 4) item override StatusChange attack_spell_icon_override; - short attack_spell_look_override; // Weapon `look' (attack animation) override + ItemNameId attack_spell_look_override; // Weapon `look' (attack animation) override short attack_spell_charges; // [Fate] Remaining number of charges for the attack spell interval_t attack_spell_delay; // [Fate] ms delay after spell attack short attack_spell_range; // [Fate] spell range @@ -296,16 +285,18 @@ struct map_session_data : block_list, SessionData earray<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; short sc_count; - int trade_partner; - Array<int, TRADE_MAX> deal_item_index; + AccountId trade_partner; + Array<IOff2, TRADE_MAX> deal_item_index; Array<int, TRADE_MAX> deal_item_amount; int deal_zeny; short deal_locked; - int party_sended, party_invite, party_invite_account; + int party_sended; + PartyId party_invite; + AccountId party_invite_account; int party_hp, party_x, party_y; - int partyspy; // [Syrus22] + PartyId partyspy; // [Syrus22] int catch_target_class; @@ -349,18 +340,15 @@ struct npc_label_list }; struct npc_item_list { - int nameid, value; + ItemNameId nameid; + int value; }; -class npc_data_script; -class npc_data_shop; -class npc_data_warp; -class npc_data_message; struct npc_data : block_list { NpcSubtype npc_subtype; short n; - short npc_class; + Species npc_class; DIR dir; interval_t speed; NpcName name; @@ -446,7 +434,7 @@ constexpr int MOB_XP_BONUS_SHIFT = 10; struct mob_data : block_list { short n; - short mob_class; + Species mob_class; DIR dir; MobMode mode; struct @@ -472,7 +460,7 @@ struct mob_data : block_list Timer timer; short to_x, to_y; int hp; - int target_id, attacked_id; + BlockId target_id, attacked_id; ATK target_lv; struct walkpath_data walkpath; tick_t next_walktime; @@ -482,12 +470,12 @@ struct mob_data : block_list short move_fail_count; struct DmgLogEntry { - int id; + BlockId id; int dmg; }; // logically a map ... std::vector<DmgLogEntry> dmglogv; - std::vector<struct item> lootitemv; + std::vector<Item> lootitemv; earray<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; short sc_count; @@ -499,14 +487,15 @@ struct mob_data : block_list Timer deletetimer; Timer skilltimer; - int skilltarget; + BlockId skilltarget; short skillx, skilly; SkillID skillid; short skilllv; struct mob_skill *skillidx; std::unique_ptr<tick_t[]> skilldelayup; // [MAX_MOBSKILL]; LevelElement def_ele; - int master_id, master_dist; + BlockId master_id; + int master_dist; int exclusion_src, exclusion_party; NpcEvent npc_event; // [Fate] mob-specific stats @@ -522,7 +511,7 @@ struct BlockLists struct map_abstract { MapName name_; - // gat is NULL for map_remote and non-NULL or map_local + // gat is nullptr for map_remote and non-nullptr or map_local std::unique_ptr<MapCell[]> gat; virtual ~map_abstract() {} @@ -537,8 +526,8 @@ struct map_local : map_abstract int npc_num; int users; MapFlags flag; - struct point save; - struct point resave; + Point save; + Point resave; Array<dumb_ptr<npc_data>, MAX_NPC_PER_MAP> npc; }; @@ -560,9 +549,9 @@ struct flooritem_data : block_list { short subx, suby; Timer cleartimer; - int first_get_id, second_get_id, third_get_id; + BlockId first_get_id, second_get_id, third_get_id; tick_t first_get_tick, second_get_tick, third_get_tick; - struct item item_data; + Item item_data; }; extern interval_t autosave_time; @@ -607,9 +596,9 @@ void map_foreachinmovearea(std::function<void(dumb_ptr<block_list>)>, //block関連に追加 int map_count_oncell(map_local *m, int x, int y); // 一時的object関連 -int map_addobject(dumb_ptr<block_list>); -int map_delobject(int, BL type); -int map_delobjectnofree(int id, BL type); +BlockId map_addobject(dumb_ptr<block_list>); +void map_delobject(BlockId, BL type); +void map_delobjectnofree(BlockId id, BL type); void map_foreachobject(std::function<void(dumb_ptr<block_list>)>, BL); // @@ -618,64 +607,64 @@ void map_quit(dumb_ptr<map_session_data>); int map_addnpc(map_local *, dumb_ptr<npc_data>); void map_log(XString line); -# define MAP_LOG(format, ...) \ +#define MAP_LOG(format, ...) \ map_log(STRPRINTF(format, ## __VA_ARGS__)) -# define MAP_LOG_PC(sd, fmt, ...) \ +#define MAP_LOG_PC(sd, fmt, ...) \ MAP_LOG("PC%d %s:%d,%d " fmt, \ - sd->status_key.char_id, (sd->bl_m ? sd->bl_m->name_ : stringish<MapName>("undefined.gat")), sd->bl_x, sd->bl_y, ## __VA_ARGS__) + sd->status_key.char_id, (sd->bl_m ? sd->bl_m->name_ : stringish<MapName>("undefined.gat"_s)), sd->bl_x, sd->bl_y, ## __VA_ARGS__) // 床アイテム関連 -void map_clearflooritem_timer(TimerData *, tick_t, int); +void map_clearflooritem_timer(TimerData *, tick_t, BlockId); inline -void map_clearflooritem(int id) +void map_clearflooritem(BlockId id) { map_clearflooritem_timer(nullptr, tick_t(), id); } -int map_addflooritem_any(struct item *, int amount, +BlockId map_addflooritem_any(Item *, int amount, map_local *m, int x, int y, dumb_ptr<map_session_data> *owners, interval_t *owner_protection, interval_t lifetime, int dispersal); -int map_addflooritem(struct item *, int, +BlockId map_addflooritem(Item *, int, map_local *, int, int, dumb_ptr<map_session_data>, dumb_ptr<map_session_data>, dumb_ptr<map_session_data>); // キャラid=>キャラ名 変換関連 extern -DMap<int, dumb_ptr<block_list>> id_db; -void map_addchariddb(int charid, CharName name); -CharName map_charid2nick(int); +DMap<BlockId, dumb_ptr<block_list>> id_db; +void map_addchariddb(CharId charid, CharName name); +CharName map_charid2nick(CharId); -dumb_ptr<map_session_data> map_id2sd(int); -dumb_ptr<block_list> map_id2bl(int); +dumb_ptr<map_session_data> map_id2sd(BlockId); +dumb_ptr<block_list> map_id2bl(BlockId); inline -dumb_ptr<map_session_data> map_id_is_player(int id) +dumb_ptr<map_session_data> map_id_is_player(BlockId id) { dumb_ptr<block_list> bl = map_id2bl(id); return bl ? bl->is_player() : nullptr; } inline -dumb_ptr<npc_data> map_id_is_npc(int id) +dumb_ptr<npc_data> map_id_is_npc(BlockId id) { dumb_ptr<block_list> bl = map_id2bl(id); return bl ? bl->is_npc() : nullptr; } inline -dumb_ptr<mob_data> map_id_is_mob(int id) +dumb_ptr<mob_data> map_id_is_mob(BlockId id) { dumb_ptr<block_list> bl = map_id2bl(id); return bl ? bl->is_mob() : nullptr; } inline -dumb_ptr<flooritem_data> map_id_is_item(int id) +dumb_ptr<flooritem_data> map_id_is_item(BlockId id) { dumb_ptr<block_list> bl = map_id2bl(id); return bl ? bl->is_item() : nullptr; } inline -dumb_ptr<invocation> map_id_is_spell(int id) +dumb_ptr<invocation> map_id_is_spell(BlockId id) { dumb_ptr<block_list> bl = map_id2bl(id); return bl ? bl->is_spell() : nullptr; @@ -688,9 +677,9 @@ int map_setipport(MapName name, IP4Address ip, int port); void map_addiddb(dumb_ptr<block_list>); void map_deliddb(dumb_ptr<block_list> bl); void map_addnickdb(dumb_ptr<map_session_data>); -int map_scriptcont(dumb_ptr<map_session_data> sd, int id); /* Continues a script either on a spell or on an NPC */ +int map_scriptcont(dumb_ptr<map_session_data> sd, BlockId id); /* Continues a script either on a spell or on an NPC */ dumb_ptr<map_session_data> map_nick2sd(CharName); -int compare_item(struct item *a, struct item *b); +int compare_item(Item *a, Item *b); dumb_ptr<map_session_data> map_get_first_session(void); dumb_ptr<map_session_data> map_get_last_session(void); @@ -733,5 +722,4 @@ inline dumb_ptr<npc_data_script> npc_data::is_script() { return npc_subtype == N inline dumb_ptr<npc_data_shop> npc_data::is_shop() { return npc_subtype == NpcSubtype::SHOP ? as_shop() : nullptr ; } inline dumb_ptr<npc_data_warp> npc_data::is_warp() { return npc_subtype == NpcSubtype::WARP ? as_warp() : nullptr ; } inline dumb_ptr<npc_data_message> npc_data::is_message() { return npc_subtype == NpcSubtype::MESSAGE ? as_message() : nullptr ; } - -#endif // TMWA_MAP_MAP_HPP +} // namespace tmwa diff --git a/src/map/map.t.hpp b/src/map/map.t.hpp index b73cbdd..b475f9b 100644 --- a/src/map/map.t.hpp +++ b/src/map/map.t.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MAP_T_HPP -#define TMWA_MAP_MAP_T_HPP +#pragma once // map.t.hpp - Core of the map server. // // Copyright © ????-2004 Athena Dev Teams @@ -21,73 +20,20 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/vstring.hpp" +#include <cstdint> -# include "../mmo/mmo.hpp" +#include "../strings/vstring.hpp" -namespace e -{ -// [Fate] status.option properties. These are persistent status changes. -// IDs that are not listed are not used in the code (to the best of my knowledge) -enum class Option : uint16_t -{ - ZERO = 0x0000, +#include "../generic/enum.hpp" - // [Fate] This is the GM `@hide' flag - HIDE = 0x0040, - // [Fate] Complete invisibility to other clients - INVISIBILITY = 0x1000, +#include "../mmo/ids.hpp" +#include "../mmo/mmo.hpp" - // ? - REAL_ANY_HIDE = HIDE, -}; -enum class Opt1 : uint16_t -{ - ZERO = 0, - _stone1 = 1, - _freeze = 2, - _stan = 3, - _sleep = 4, - _stone6 = 6, -}; -enum class Opt2 : uint16_t -{ - ZERO = 0x0000, - _poison = 0x0001, - _curse = 0x0002, - _silence = 0x0004, - BLIND = 0x0010, - _speedpotion0 = 0x0020, - _signumcrucis = 0x0040, - _atkpot = 0x0080, - _heal = 0x0100, - _slowpoison = 0x0200, -}; -enum class Opt3 : uint16_t -{ - ZERO = 0x0000, - _concentration = 0x0001, - _overthrust = 0x0002, - _energycoat = 0x0004, - _explosionspirits = 0x0008, - _steelbody = 0x0010, - _berserk = 0x0080, - - _marionette = 0x0400, - _assumptio = 0x0800, -}; - -ENUM_BITWISE_OPERATORS(Option) -ENUM_BITWISE_OPERATORS(Opt2) -ENUM_BITWISE_OPERATORS(Opt3) -} -using e::Option; -using e::Opt1; -using e::Opt2; -using e::Opt3; +namespace tmwa +{ enum class BL : uint8_t { NUL, @@ -103,6 +49,8 @@ enum class NpcSubtype : uint8_t SHOP, SCRIPT, MESSAGE, + + COUNT, }; enum class mob_stat @@ -146,325 +94,6 @@ enum class ATK DEF, }; -enum class SP : uint16_t -{ - // sent to client - SPEED = 0, - - // when used as "no stat" - ZERO = 0, - - // sent to client - BASEEXP = 1, - // sent to client - JOBEXP = 2, -# if 0 - KARMA = 3, -# endif - - // sent to client - HP = 5, - // sent to client - MAXHP = 6, - // sent to client - SP = 7, - // sent to client - MAXSP = 8, - // sent to client - STATUSPOINT = 9, - - // sent to client - BASELEVEL = 11, - // sent to client - SKILLPOINT = 12, - // sent to client - STR = 13, - // sent to client - AGI = 14, - // sent to client - VIT = 15, - // sent to client - INT = 16, - // sent to client - DEX = 17, - // sent to client - LUK = 18, - CLASS = 19, - // sent to client - ZENY = 20, - SEX = 21, - // sent to client - NEXTBASEEXP = 22, - // sent to client - NEXTJOBEXP = 23, - // sent to client - WEIGHT = 24, - // sent to client - MAXWEIGHT = 25, - - // sent to client - USTR = 32, - // sent to client - UAGI = 33, - // sent to client - UVIT = 34, - // sent to client - UINT = 35, - // sent to client - UDEX = 36, - // sent to client - ULUK = 37, - - // sent to client - ATK1 = 41, - // sent to client - ATK2 = 42, - // sent to client - MATK1 = 43, - // sent to client - MATK2 = 44, - // sent to client - DEF1 = 45, - // sent to client - DEF2 = 46, - // sent to client - MDEF1 = 47, - // sent to client - MDEF2 = 48, - // sent to client - HIT = 49, - // sent to client - FLEE1 = 50, - // sent to client - FLEE2 = 51, - // sent to client - CRITICAL = 52, - // sent to client - ASPD = 53, - - // sent to client - JOBLEVEL = 55, - -# if 0 - PARTNER = 57, - CART = 58, - FAME = 59, - UNBREAKABLE = 60, -# endif - - DEAF = 70, - - // sent to client - GM = 500, - - // sent to client - ATTACKRANGE = 1000, -# if 0 - ATKELE = 1001, -# endif -# if 0 - DEFELE = 1002, -# endif -# if 0 - CASTRATE = 1003, -# endif - MAXHPRATE = 1004, -# if 0 - MAXSPRATE = 1005, -# endif -# if 0 - SPRATE = 1006, -# endif - -# if 0 - ADDEFF = 1012, -# endif -# if 0 - RESEFF = 1013, -# endif - BASE_ATK = 1014, - ASPD_RATE = 1015, - HP_RECOV_RATE = 1016, -# if 0 - SP_RECOV_RATE = 1017, -# endif -# if 0 - SPEED_RATE = 1018, -# endif - CRITICAL_DEF = 1019, -# if 0 - NEAR_ATK_DEF = 1020, -# endif -# if 0 - LONG_ATK_DEF = 1021, -# endif -# if 0 - DOUBLE_RATE = 1022, -# endif - DOUBLE_ADD_RATE = 1023, -# if 0 - MATK = 1024, -# endif -# if 0 - MATK_RATE = 1025, -# endif -# if 0 - IGNORE_DEF_ELE = 1026, -# endif -# if 0 - IGNORE_DEF_RACE = 1027, -# endif -# if 0 - ATK_RATE = 1028, -# endif - SPEED_ADDRATE = 1029, -# if 0 - ASPD_ADDRATE = 1030, -# endif -# if 0 - MAGIC_ATK_DEF = 1031, -# endif -# if 0 - MISC_ATK_DEF = 1032, -# endif -# if 0 - IGNORE_MDEF_ELE = 1033, -# endif -# if 0 - IGNORE_MDEF_RACE = 1034, -# endif - -# if 0 - PERFECT_HIT_RATE = 1038, -# endif -# if 0 - PERFECT_HIT_ADD_RATE = 1039, -# endif -# if 0 - CRITICAL_RATE = 1040, -# endif -# if 0 - GET_ZENY_NUM = 1041, -# endif -# if 0 - ADD_GET_ZENY_NUM = 1042, -# endif - -# if 0 - ADD_MONSTER_DROP_ITEM = 1047, -# endif -# if 0 - DEF_RATIO_ATK_ELE = 1048, -# endif -# if 0 - DEF_RATIO_ATK_RACE = 1049, -# endif -# if 0 - ADD_SPEED = 1050, -# endif -# if 0 - HIT_RATE = 1051, -# endif -# if 0 - FLEE_RATE = 1052, -# endif -# if 0 - FLEE2_RATE = 1053, -# endif - DEF_RATE = 1054, - DEF2_RATE = 1055, -# if 0 - MDEF_RATE = 1056, -# endif -# if 0 - MDEF2_RATE = 1057, -# endif -# if 0 - SPLASH_RANGE = 1058, -# endif -# if 0 - SPLASH_ADD_RANGE = 1059, -# endif - - HP_DRAIN_RATE = 1061, -# if 0 - SP_DRAIN_RATE = 1062, -# endif -# if 0 - SHORT_WEAPON_DAMAGE_RETURN = 1063, -# endif -# if 0 - LONG_WEAPON_DAMAGE_RETURN = 1064, -# endif - -# if 0 - ADDEFF2 = 1067, -# endif - BREAK_WEAPON_RATE = 1068, - BREAK_ARMOR_RATE = 1069, - ADD_STEAL_RATE = 1070, - MAGIC_DAMAGE_RETURN = 1071, -# if 0 - RANDOM_ATTACK_INCREASE = 1072, -# endif -}; - -constexpr -SP attr_to_sp(ATTR attr) -{ - return SP(uint16_t(attr) + uint16_t(SP::STR)); -} - -constexpr -ATTR sp_to_attr(SP sp) -{ - return ATTR(uint16_t(sp) - uint16_t(SP::STR)); -} - -constexpr -SP attr_to_usp(ATTR attr) -{ - return SP(uint16_t(attr) + uint16_t(SP::USTR)); -} - -constexpr -ATTR usp_to_attr(SP sp) -{ - return ATTR(uint16_t(sp) - uint16_t(SP::USTR)); -} - -constexpr -SP sp_to_usp(SP sp) -{ - return attr_to_usp(sp_to_attr(sp)); -} - -constexpr -SP usp_to_sp(SP sp) -{ - return attr_to_sp(usp_to_attr(sp)); -} - - -enum class LOOK : uint8_t -{ - BASE = 0, - HAIR = 1, - WEAPON = 2, - HEAD_BOTTOM = 3, - HEAD_TOP = 4, - HEAD_MID = 5, - HAIR_COLOR = 6, - CLOTHES_COLOR = 7, - SHIELD = 8, - SHOES = 9, - GLOVES = 10, - CAPE = 11, - MISC1 = 12, - MISC2 = 13, - - COUNT, -}; enum class EQUIP { @@ -514,22 +143,6 @@ EQUIP EQUIPs_noarrow[] = EQUIP::WEAPON, }; -enum class ItemType : uint8_t -{ - USE = 0, // in eA, healing only - _1 = 1, // unused - _2 = 2, // in eA, other usable items - JUNK = 3, // "useless" items (e.g. quests) - WEAPON = 4, // all weapons - ARMOR = 5, // all other equipment - _6 = 6, // in eA, card - _7 = 7, // in eA, pet egg - _8 = 8, // in eA, pet equipment - _9 = 9, // unused - ARROW = 10, // ammo - _11 = 11, // in eA, delayed use (special script) -}; - namespace e { enum class MobMode : uint16_t @@ -583,4 +196,8 @@ struct NpcName : VString<23> {}; struct ScriptLabel : VString<23> {}; struct ItemName : VString<23> {}; -#endif // TMWA_MAP_MAP_T_HPP +inline +BlockId account_to_block(AccountId a) { return wrap<BlockId>(unwrap<AccountId>(a)); } +inline +AccountId block_to_account(BlockId b) { return wrap<AccountId>(unwrap<BlockId>(b)); } +} // namespace tmwa diff --git a/src/map/mapflag.cpp b/src/map/mapflag.cpp index 51af30a..f9cf8f6 100644 --- a/src/map/mapflag.cpp +++ b/src/map/mapflag.cpp @@ -20,6 +20,9 @@ #include "../poison.hpp" + +namespace tmwa +{ // because bitfields, that's why bool MapFlags::get(MapFlag mf) const @@ -40,41 +43,41 @@ bool extract<MapFlag, void, void>(XString str, MapFlag *mf) { const struct { - ZString str; + LString str; MapFlag id; } flags[] = { - //{ZString("alias"), MapFlag::ALIAS}, - //{ZString("nomemo"), MapFlag::NOMEMO}, - {ZString("noteleport"), MapFlag::NOTELEPORT}, - {ZString("noreturn"), MapFlag::NORETURN}, - {ZString("monster_noteleport"), MapFlag::MONSTER_NOTELEPORT}, - {ZString("nosave"), MapFlag::NOSAVE}, - //{ZString("nobranch"), MapFlag::NOBRANCH}, - {ZString("nopenalty"), MapFlag::NOPENALTY}, - {ZString("pvp"), MapFlag::PVP}, - {ZString("pvp_noparty"), MapFlag::PVP_NOPARTY}, - //{ZString("pvp_noguild"), MapFlag::PVP_NOGUILD}, - //{ZString("pvp_nightmaredrop"), MapFlag::PVP_NIGHTMAREDROP}, - {ZString("pvp_nocalcrank"), MapFlag::PVP_NOCALCRANK}, - //{ZString("gvg"), MapFlag::GVG}, - //{ZString("gvg_noparty"), MapFlag::GVG_NOPARTY}, - //{ZString("nozenypenalty"), MapFlag::NOZENYPENALTY}, - //{ZString("notrade"), MapFlag::NOTRADE}, - //{ZString("noskill"), MapFlag::NOSKILL}, - {ZString("nowarp"), MapFlag::NOWARP}, - {ZString("nowarpto"), MapFlag::NOWARPTO}, - {ZString("nopvp"), MapFlag::NOPVP}, - //{ZString("noicewall"), MapFlag::NOICEWALL}, - {ZString("snow"), MapFlag::SNOW}, - {ZString("fog"), MapFlag::FOG}, - {ZString("sakura"), MapFlag::SAKURA}, - {ZString("leaves"), MapFlag::LEAVES}, - {ZString("rain"), MapFlag::RAIN}, - {ZString("no_player_drops"), MapFlag::NO_PLAYER_DROPS}, - {ZString("town"), MapFlag::TOWN}, - {ZString("outside"), MapFlag::OUTSIDE}, - {ZString("resave"), MapFlag::RESAVE}, + //{"alias"_s, MapFlag::ALIAS}, + //{"nomemo"_s, MapFlag::NOMEMO}, + {"noteleport"_s, MapFlag::NOTELEPORT}, + {"noreturn"_s, MapFlag::NORETURN}, + {"monster_noteleport"_s, MapFlag::MONSTER_NOTELEPORT}, + {"nosave"_s, MapFlag::NOSAVE}, + //{"nobranch"_s, MapFlag::NOBRANCH}, + {"nopenalty"_s, MapFlag::NOPENALTY}, + {"pvp"_s, MapFlag::PVP}, + {"pvp_noparty"_s, MapFlag::PVP_NOPARTY}, + //{"pvp_noguild"_s, MapFlag::PVP_NOGUILD}, + //{"pvp_nightmaredrop"_s, MapFlag::PVP_NIGHTMAREDROP}, + {"pvp_nocalcrank"_s, MapFlag::PVP_NOCALCRANK}, + //{"gvg"_s, MapFlag::GVG}, + //{"gvg_noparty"_s, MapFlag::GVG_NOPARTY}, + //{"nozenypenalty"_s, MapFlag::NOZENYPENALTY}, + //{"notrade"_s, MapFlag::NOTRADE}, + //{"noskill"_s, MapFlag::NOSKILL}, + {"nowarp"_s, MapFlag::NOWARP}, + {"nowarpto"_s, MapFlag::NOWARPTO}, + {"nopvp"_s, MapFlag::NOPVP}, + //{"noicewall"_s, MapFlag::NOICEWALL}, + {"snow"_s, MapFlag::SNOW}, + {"fog"_s, MapFlag::FOG}, + {"sakura"_s, MapFlag::SAKURA}, + {"leaves"_s, MapFlag::LEAVES}, + {"rain"_s, MapFlag::RAIN}, + {"no_player_drops"_s, MapFlag::NO_PLAYER_DROPS}, + {"town"_s, MapFlag::TOWN}, + {"outside"_s, MapFlag::OUTSIDE}, + {"resave"_s, MapFlag::RESAVE}, }; for (auto& pair : flags) if (str == pair.str) @@ -89,3 +92,4 @@ MapFlag map_flag_from_int(int shift) { return static_cast<MapFlag>(1 << shift); } +} // namespace tmwa diff --git a/src/map/mapflag.hpp b/src/map/mapflag.hpp index e3a55f5..197d250 100644 --- a/src/map/mapflag.hpp +++ b/src/map/mapflag.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MAPFLAG_HPP -#define TMWA_MAP_MAPFLAG_HPP +#pragma once // mapflag.hpp - booleans that apply to an entire map // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,12 +18,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../mmo/extract.hpp" // TODO remove this (requires specializing the *other* half) +#include <cstdint> -# include "../strings/xstring.hpp" +#include "../mmo/extract.hpp" // TODO remove this (requires specializing the *other* half) + +namespace tmwa +{ // originally from script.cpp // These are part of the script API, so they can't change ever, // even though they are silly. @@ -79,5 +81,4 @@ template<> bool extract<MapFlag, void, void>(XString str, MapFlag *mf); MapFlag map_flag_from_int(int shift); - -#endif // TMWA_MAP_MAPFLAG_HPP +} // namespace tmwa diff --git a/src/map/mapflag.py b/src/map/mapflag.py index 3bc9f1a..fec8c05 100644 --- a/src/map/mapflag.py +++ b/src/map/mapflag.py @@ -2,7 +2,7 @@ class MapFlags(object): ''' print a set of map flags ''' __slots__ = ('_value') - name = 'MapFlags' + name = 'tmwa::MapFlags' enabled = True def __init__(self, value): diff --git a/src/map/mob.cpp b/src/map/mob.cpp index a96f829..1fd8cf3 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -23,8 +23,6 @@ #include <cassert> #include <cmath> -#include <cstdlib> -#include <cstring> #include <algorithm> @@ -32,6 +30,7 @@ #include "../compat/nullpo.hpp" #include "../strings/astring.hpp" +#include "../strings/zstring.hpp" #include "../strings/xstring.hpp" #include "../generic/random.hpp" @@ -39,10 +38,11 @@ #include "../io/cxxstdio.hpp" #include "../io/read.hpp" +#include "../net/socket.hpp" +#include "../net/timer.hpp" + #include "../mmo/config_parse.hpp" #include "../mmo/extract.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" #include "battle.hpp" #include "clif.hpp" @@ -56,14 +56,22 @@ #include "../poison.hpp" -constexpr interval_t MIN_MOBTHINKTIME = std::chrono::milliseconds(100); + +namespace tmwa +{ +constexpr interval_t MIN_MOBTHINKTIME = 100_ms; // Move probability in the negligent mode MOB (rate of 1000 minute) constexpr random_::Fraction MOB_LAZYMOVEPERC {50, 1000}; // Warp probability in the negligent mode MOB (rate of 1000 minute) constexpr random_::Fraction MOB_LAZYWARPPERC {20, 1000}; +static struct mob_db_ mob_db[2001]; +struct mob_db_& get_mob_db(Species s) +{ + return mob_db[unwrap<Species>(s)]; +} /*========================================== * Local prototype declaration (only required thing) @@ -72,9 +80,9 @@ struct mob_db_ mob_db[2001]; static int distance(int, int, int, int); static -int mob_makedummymobdb(int); +int mob_makedummymobdb(Species); static -void mob_timer(TimerData *, tick_t, int, unsigned char); +void mob_timer(TimerData *, tick_t, BlockId, unsigned char); static int mobskill_use_id(dumb_ptr<mob_data> md, dumb_ptr<block_list> target, mob_skill& skill_idx); @@ -83,30 +91,29 @@ int mobskill_use_id(dumb_ptr<mob_data> md, dumb_ptr<block_list> target, * Mob is searched with a name. *------------------------------------------ */ -int mobdb_searchname(MobName str) +Species mobdb_searchname(MobName str) { int i; for (i = 0; i < sizeof(mob_db) / sizeof(mob_db[0]); i++) { if (mob_db[i].name == str || mob_db[i].jname == str) - return i; + return wrap<Species>(i); } - return 0; + return Species(); } /*========================================== * Id Mob is checked. *------------------------------------------ */ -int mobdb_checkid(const int id) +Species mobdb_checkid(Species id) { - if (id <= 0 || id >= (sizeof(mob_db) / sizeof(mob_db[0])) - || !mob_db[id].name) - return 0; - - return id; + // value range is [1001, 2000] + if (wrap<Species>(1000) < id && id < wrap<Species>(2001)) + return id; + return Species(); } static @@ -117,27 +124,27 @@ void mob_init(dumb_ptr<mob_data> md); *------------------------------------------ */ static -void mob_spawn_dataset(dumb_ptr<mob_data> md, MobName mobname, int mob_class) +void mob_spawn_dataset(dumb_ptr<mob_data> md, MobName mobname, Species mob_class) { nullpo_retv(md); if (mobname == ENGLISH_NAME) - md->name = mob_db[mob_class].name; + md->name = get_mob_db(mob_class).name; else if (mobname == JAPANESE_NAME) - md->name = mob_db[mob_class].jname; + md->name = get_mob_db(mob_class).jname; else md->name = mobname; - md->bl_prev = NULL; - md->bl_next = NULL; + md->bl_prev = nullptr; + md->bl_next = nullptr; md->n = 0; md->mob_class = mob_class; md->bl_id = npc_get_new_npc_id(); really_memzero_this(&md->state); // md->timer = nullptr; - md->target_id = 0; - md->attacked_id = 0; + md->target_id = BlockId(); + md->attacked_id = BlockId(); mob_init(md); } @@ -265,12 +272,16 @@ void mob_mutate(dumb_ptr<mob_data> md, mob_stat stat, int intensity) int real_intensity2 = (((new_stat - old_stat) << 8) / mut_base); if (real_intensity < 0) + { if (real_intensity2 > real_intensity) real_intensity = real_intensity2; + } if (real_intensity > 0) + { if (real_intensity2 < real_intensity) real_intensity = real_intensity2; + } } real_intensity *= sign; @@ -322,7 +333,7 @@ int mob_gen_exp(mob_db_ *mob) * static_cast<double>(battle_config.base_exp_rate) / 100.); if (xp < 1) xp = 1; - PRINTF("Exp for mob '%s' generated: %d\n", mob->name, xp); + PRINTF("Exp for mob '%s' generated: %d\n"_fmt, mob->name, xp); return xp; } @@ -330,24 +341,24 @@ static void mob_init(dumb_ptr<mob_data> md) { int i; - const int mob_class = md->mob_class; - const int mutations_nr = mob_db[mob_class].mutations_nr; - const int mutation_power = mob_db[mob_class].mutation_power; - - md->stats[mob_stat::LV] = mob_db[mob_class].lv; - md->stats[mob_stat::MAX_HP] = mob_db[mob_class].max_hp; - md->stats[mob_stat::STR] = mob_db[mob_class].attrs[ATTR::STR]; - md->stats[mob_stat::AGI] = mob_db[mob_class].attrs[ATTR::AGI]; - md->stats[mob_stat::VIT] = mob_db[mob_class].attrs[ATTR::VIT]; - md->stats[mob_stat::INT] = mob_db[mob_class].attrs[ATTR::INT]; - md->stats[mob_stat::DEX] = mob_db[mob_class].attrs[ATTR::DEX]; - md->stats[mob_stat::LUK] = mob_db[mob_class].attrs[ATTR::LUK]; - md->stats[mob_stat::ATK1] = mob_db[mob_class].atk1; - md->stats[mob_stat::ATK2] = mob_db[mob_class].atk2; - md->stats[mob_stat::ADELAY] = mob_db[mob_class].adelay; - md->stats[mob_stat::DEF] = mob_db[mob_class].def; - md->stats[mob_stat::MDEF] = mob_db[mob_class].mdef; - md->stats[mob_stat::SPEED] = mob_db[mob_class].speed; + const Species mob_class = md->mob_class; + const int mutations_nr = get_mob_db(mob_class).mutations_nr; + const int mutation_power = get_mob_db(mob_class).mutation_power; + + md->stats[mob_stat::LV] = get_mob_db(mob_class).lv; + md->stats[mob_stat::MAX_HP] = get_mob_db(mob_class).max_hp; + md->stats[mob_stat::STR] = get_mob_db(mob_class).attrs[ATTR::STR]; + md->stats[mob_stat::AGI] = get_mob_db(mob_class).attrs[ATTR::AGI]; + md->stats[mob_stat::VIT] = get_mob_db(mob_class).attrs[ATTR::VIT]; + md->stats[mob_stat::INT] = get_mob_db(mob_class).attrs[ATTR::INT]; + md->stats[mob_stat::DEX] = get_mob_db(mob_class).attrs[ATTR::DEX]; + md->stats[mob_stat::LUK] = get_mob_db(mob_class).attrs[ATTR::LUK]; + md->stats[mob_stat::ATK1] = get_mob_db(mob_class).atk1; + md->stats[mob_stat::ATK2] = get_mob_db(mob_class).atk2; + md->stats[mob_stat::ADELAY] = get_mob_db(mob_class).adelay; + md->stats[mob_stat::DEF] = get_mob_db(mob_class).def; + md->stats[mob_stat::MDEF] = get_mob_db(mob_class).mdef; + md->stats[mob_stat::SPEED] = get_mob_db(mob_class).speed; md->stats[mob_stat::XP_BONUS] = MOB_XP_BONUS_BASE; for (i = 0; i < mutations_nr; i++) @@ -391,22 +402,22 @@ void mob_init(dumb_ptr<mob_data> md) * The MOB appearance for one time (for scripts) *------------------------------------------ */ -int mob_once_spawn(dumb_ptr<map_session_data> sd, +BlockId mob_once_spawn(dumb_ptr<map_session_data> sd, MapName mapname, int x, int y, - MobName mobname, int mob_class, int amount, + MobName mobname, Species mob_class, int amount, NpcEvent event) { - dumb_ptr<mob_data> md = NULL; + dumb_ptr<mob_data> md = nullptr; map_local *m; - int count, r = mob_class; + int count; if (sd && mapname == MOB_THIS_MAP) m = sd->bl_m; else m = map_mapname2mapid(mapname); - if (m == nullptr || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000) // 値が異常なら召喚を止める - return 0; + if (m == nullptr || amount <= 0 || mobdb_checkid(mob_class) == Species()) + return BlockId(); if (sd) { @@ -417,7 +428,7 @@ int mob_once_spawn(dumb_ptr<map_session_data> sd, } else if (x <= 0 || y <= 0) { - PRINTF("mob_once_spawn: ??\n"); + PRINTF("mob_once_spawn: ??\n"_fmt); } for (count = 0; count < amount; count++) @@ -429,9 +440,6 @@ int mob_once_spawn(dumb_ptr<map_session_data> sd, md->bl_m = m; md->bl_x = x; md->bl_y = y; - if (r < 0 && battle_config.dead_branch_active == 1) - //移動してアクティブで反撃する - md->mode = MobMode::war; md->spawn.m = m; md->spawn.x0 = x; md->spawn.y0 = y; @@ -446,19 +454,20 @@ int mob_once_spawn(dumb_ptr<map_session_data> sd, map_addiddb(md); mob_spawn(md->bl_id); } - return (amount > 0) ? md->bl_id : 0; + return (amount > 0) ? md->bl_id : BlockId(); } /*========================================== * The MOB appearance for one time (& area specification for scripts) *------------------------------------------ */ -int mob_once_spawn_area(dumb_ptr<map_session_data> sd, +BlockId mob_once_spawn_area(dumb_ptr<map_session_data> sd, MapName mapname, int x0, int y0, int x1, int y1, - MobName mobname, int mob_class, int amount, + MobName mobname, Species mob_class, int amount, NpcEvent event) { - int x, y, i, max, lx = -1, ly = -1, id = 0; + int x, y, i, max, lx = -1, ly = -1; + BlockId id; map_local *m; if (mapname == MOB_THIS_MAP) @@ -470,8 +479,8 @@ int mob_once_spawn_area(dumb_ptr<map_session_data> sd, if (max > 1000) max = 1000; - if (m == nullptr || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000) // A summon is stopped if a value is unusual - return 0; + if (m == nullptr || amount <= 0 || (mobdb_checkid(mob_class) == Species())) // A summon is stopped if a value is unusual + return BlockId(); for (i = 0; i < amount; i++) { @@ -491,7 +500,7 @@ int mob_once_spawn_area(dumb_ptr<map_session_data> sd, y = ly; } else - return 0; // Since reference of the place which boils first went wrong, it stops. + return BlockId(); // Since reference of the place which boils first went wrong, it stops. } id = mob_once_spawn(sd, mapname, x, y, mobname, mob_class, 1, event); lx = x; @@ -501,49 +510,49 @@ int mob_once_spawn_area(dumb_ptr<map_session_data> sd, } // TODO: deprecate these -short mob_get_hair(int mob_class) +short mob_get_hair(Species mob_class) { - return mob_db[mob_class].hair; + return get_mob_db(mob_class).hair; } -short mob_get_hair_color(int mob_class) +short mob_get_hair_color(Species mob_class) { - return mob_db[mob_class].hair_color; + return get_mob_db(mob_class).hair_color; } -short mob_get_weapon(int mob_class) +short mob_get_weapon(Species mob_class) { - return mob_db[mob_class].weapon; + return get_mob_db(mob_class).weapon; } -short mob_get_shield(int mob_class) +ItemNameId mob_get_shield(Species mob_class) { - return mob_db[mob_class].shield; + return get_mob_db(mob_class).shield; } -short mob_get_head_top(int mob_class) +ItemNameId mob_get_head_top(Species mob_class) { - return mob_db[mob_class].head_top; + return get_mob_db(mob_class).head_top; } -short mob_get_head_mid(int mob_class) +ItemNameId mob_get_head_mid(Species mob_class) { - return mob_db[mob_class].head_mid; + return get_mob_db(mob_class).head_mid; } -short mob_get_head_buttom(int mob_class) +ItemNameId mob_get_head_buttom(Species mob_class) { - return mob_db[mob_class].head_buttom; + return get_mob_db(mob_class).head_buttom; } -short mob_get_clothes_color(int mob_class) // Add for player monster dye - Valaris +short mob_get_clothes_color(Species mob_class) // Add for player monster dye - Valaris { - return mob_db[mob_class].clothes_color; // End + return get_mob_db(mob_class).clothes_color; // End } -int mob_get_equip(int mob_class) // mob equip [Valaris] +int mob_get_equip(Species mob_class) // mob equip [Valaris] { - return mob_db[mob_class].equip; + return get_mob_db(mob_class).equip; } /*========================================== @@ -553,7 +562,7 @@ int mob_get_equip(int mob_class) // mob equip [Valaris] static int mob_can_move(dumb_ptr<mob_data> md) { - nullpo_ret(md); + nullpo_retz(md); if (md->canmove_tick > gettick() || (bool(md->opt1) && md->opt1 != Opt1::_stone6)) @@ -591,7 +600,7 @@ int mob_walk(dumb_ptr<mob_data> md, tick_t tick, unsigned char data) int moveblock; int x, y, dx, dy; - nullpo_ret(md); + nullpo_retz(md); md->state.state = MS::IDLE; if (md->walkpath.path_pos >= md->walkpath.path_len @@ -667,7 +676,7 @@ int mob_walk(dumb_ptr<mob_data> md, tick_t tick, unsigned char data) { i = i / 2; if (md->walkpath.path_half == 0) - i = std::max(i, std::chrono::milliseconds(1)); + i = std::max(i, 1_ms); md->timer = Timer(tick + i, std::bind(mob_timer, ph::_1, ph::_2, md->bl_id, md->walkpath.path_pos)); @@ -686,14 +695,14 @@ int mob_walk(dumb_ptr<mob_data> md, tick_t tick, unsigned char data) static int mob_check_attack(dumb_ptr<mob_data> md) { - dumb_ptr<block_list> tbl = NULL; - dumb_ptr<map_session_data> tsd = NULL; - dumb_ptr<mob_data> tmd = NULL; + dumb_ptr<block_list> tbl = nullptr; + dumb_ptr<map_session_data> tsd = nullptr; + dumb_ptr<mob_data> tmd = nullptr; MobMode mode; int range; - nullpo_ret(md); + nullpo_retz(md); md->min_chase = 13; md->state.state = MS::IDLE; @@ -705,9 +714,9 @@ int mob_check_attack(dumb_ptr<mob_data> md) if (bool(md->opt1)) return 0; - if ((tbl = map_id2bl(md->target_id)) == NULL) + if ((tbl = map_id2bl(md->target_id)) == nullptr) { - md->target_id = 0; + md->target_id = BlockId(); md->state.attackable = false; return 0; } @@ -722,34 +731,34 @@ int mob_check_attack(dumb_ptr<mob_data> md) if (tsd) { if (pc_isdead(tsd) || tsd->invincible_timer - || pc_isinvisible(tsd) || md->bl_m != tbl->bl_m || tbl->bl_prev == NULL + || pc_isinvisible(tsd) || md->bl_m != tbl->bl_m || tbl->bl_prev == nullptr || distance(md->bl_x, md->bl_y, tbl->bl_x, tbl->bl_y) >= 13) { - md->target_id = 0; + md->target_id = BlockId(); md->state.attackable = false; return 0; } } if (tmd) { - if (md->bl_m != tbl->bl_m || tbl->bl_prev == NULL + if (md->bl_m != tbl->bl_m || tbl->bl_prev == nullptr || distance(md->bl_x, md->bl_y, tbl->bl_x, tbl->bl_y) >= 13) { - md->target_id = 0; + md->target_id = BlockId(); md->state.attackable = false; return 0; } } if (md->mode == MobMode::ZERO) - mode = mob_db[md->mob_class].mode; + mode = get_mob_db(md->mob_class).mode; else mode = md->mode; - Race race = mob_db[md->mob_class].race; + Race race = get_mob_db(md->mob_class).race; if (!bool(mode & MobMode::CAN_ATTACK)) { - md->target_id = 0; + md->target_id = BlockId(); md->state.attackable = false; return 0; } @@ -759,12 +768,12 @@ int mob_check_attack(dumb_ptr<mob_data> md) && race != Race::_insect && race != Race::_demon)) { - md->target_id = 0; + md->target_id = BlockId(); md->state.attackable = false; return 0; } - range = mob_db[md->mob_class].range; + range = get_mob_db(md->mob_class).range; if (bool(mode & MobMode::CAN_MOVE)) range++; if (distance(md->bl_x, md->bl_y, tbl->bl_x, tbl->bl_y) > range) @@ -788,11 +797,11 @@ void mob_ancillary_attack(dumb_ptr<block_list> bl, static int mob_attack(dumb_ptr<mob_data> md, tick_t tick) { - dumb_ptr<block_list> tbl = NULL; + dumb_ptr<block_list> tbl = nullptr; - nullpo_ret(md); + nullpo_retz(md); - if ((tbl = map_id2bl(md->target_id)) == NULL) + if ((tbl = map_id2bl(md->target_id)) == nullptr) return 0; if (!mob_check_attack(md)) @@ -834,7 +843,7 @@ int mob_attack(dumb_ptr<mob_data> md, tick_t tick) *------------------------------------------ */ static -void mob_stopattacked(dumb_ptr<map_session_data> sd, int id) +void mob_stopattacked(dumb_ptr<map_session_data> sd, BlockId id) { nullpo_retv(sd); @@ -849,7 +858,7 @@ void mob_stopattacked(dumb_ptr<map_session_data> sd, int id) static int mob_changestate(dumb_ptr<mob_data> md, MS state, bool type) { - nullpo_ret(md); + nullpo_retz(md); md->timer.cancel(); md->state.state = state; @@ -874,7 +883,7 @@ int mob_changestate(dumb_ptr<mob_data> md, MS state, bool type) { tick_t tick = gettick(); interval_t i = md->attackabletime - tick; - if (i > interval_t::zero() && i < std::chrono::seconds(2)) + if (i > interval_t::zero() && i < 2_s) md->timer = Timer(md->attackabletime, std::bind(mob_timer, ph::_1, ph::_2, md->bl_id, 0)); @@ -887,7 +896,7 @@ int mob_changestate(dumb_ptr<mob_data> md, MS state, bool type) } else { - md->attackabletime = tick + std::chrono::milliseconds(1); + md->attackabletime = tick + 1_ms; md->timer = Timer(md->attackabletime, std::bind(mob_timer, ph::_1, ph::_2, md->bl_id, 0)); @@ -903,7 +912,8 @@ int mob_changestate(dumb_ptr<mob_data> md, MS state, bool type) clif_foreachclient(std::bind(mob_stopattacked, ph::_1, md->bl_id)); skill_status_change_clear(md, 2); // The abnormalities in status are canceled. md->deletetimer.cancel(); - md->hp = md->target_id = md->attacked_id = 0; + md->hp = 0; + md->target_id = md->attacked_id = BlockId(); md->state.attackable = false; } break; @@ -918,12 +928,12 @@ int mob_changestate(dumb_ptr<mob_data> md, MS state, bool type) *------------------------------------------ */ static -void mob_timer(TimerData *, tick_t tick, int id, unsigned char data) +void mob_timer(TimerData *, tick_t tick, BlockId id, unsigned char data) { dumb_ptr<mob_data> md; dumb_ptr<block_list> bl; bl = map_id2bl(id); - if (bl == NULL) + if (bl == nullptr) { //攻撃してきた敵がもういないのは正常のようだ return; } @@ -933,7 +943,7 @@ void mob_timer(TimerData *, tick_t tick, int id, unsigned char data) md = bl->is_mob(); - if (md->bl_prev == NULL || md->state.state == MS::DEAD) + if (md->bl_prev == nullptr || md->state.state == MS::DEAD) return; MapBlockLock lock; @@ -948,7 +958,7 @@ void mob_timer(TimerData *, tick_t tick, int id, unsigned char data) break; default: if (battle_config.error_log == 1) - PRINTF("mob_timer : %d ?\n", + PRINTF("mob_timer : %d ?\n"_fmt, md->state.state); break; } @@ -963,7 +973,7 @@ int mob_walktoxy_sub(dumb_ptr<mob_data> md) { struct walkpath_data wpd; - nullpo_ret(md); + nullpo_retz(md); if (path_search(&wpd, md->bl_m, md->bl_x, md->bl_y, md->to_x, md->to_y, md->state.walk_easy)) @@ -986,7 +996,7 @@ int mob_walktoxy(dumb_ptr<mob_data> md, int x, int y, int easy) { struct walkpath_data wpd; - nullpo_ret(md); + nullpo_retz(md); if (md->state.state == MS::WALK && path_search(&wpd, md->bl_m, md->bl_x, md->bl_y, x, y, easy)) @@ -1012,7 +1022,7 @@ int mob_walktoxy(dumb_ptr<mob_data> md, int x, int y, int easy) *------------------------------------------ */ static -void mob_delayspawn(TimerData *, tick_t, int m) +void mob_delayspawn(TimerData *, tick_t, BlockId m) { mob_spawn(m); } @@ -1022,12 +1032,12 @@ void mob_delayspawn(TimerData *, tick_t, int m) *------------------------------------------ */ static -int mob_setdelayspawn(int id) +int mob_setdelayspawn(BlockId id) { dumb_ptr<mob_data> md; dumb_ptr<block_list> bl; - if ((bl = map_id2bl(id)) == NULL) + if ((bl = map_id2bl(id)) == nullptr) return -1; if (!bl || bl->bl_type == BL::NUL || bl->bl_type != BL::MOB) @@ -1052,7 +1062,7 @@ int mob_setdelayspawn(int id) tick_t spawntime1 = md->last_spawntime + md->spawn.delay1; tick_t spawntime2 = md->last_deadtime + md->spawn.delay2; - tick_t spawntime3 = gettick() + std::chrono::seconds(5); + tick_t spawntime3 = gettick() + 5_s; tick_t spawntime = std::max({spawntime1, spawntime2, spawntime3}); Timer(spawntime, @@ -1066,7 +1076,7 @@ int mob_setdelayspawn(int id) * Mob spawning. Initialization is also variously here. *------------------------------------------ */ -int mob_spawn(int id) +int mob_spawn(BlockId id) { int x = 0, y = 0; tick_t tick = gettick(); @@ -1086,7 +1096,7 @@ int mob_spawn(int id) return -1; md->last_spawntime = tick; - if (md->bl_prev != NULL) + if (md->bl_prev != nullptr) { map_delblock(md); } @@ -1115,9 +1125,7 @@ int mob_spawn(int id) if (i >= 50) { - // if(battle_config.error_log==1) - // PRINTF("MOB spawn error %d @ %s\n",id,map[md->bl_m].name); - Timer(tick + std::chrono::seconds(5), + Timer(tick + 5_s, std::bind(mob_delayspawn, ph::_1, ph::_2, id) ).detach(); @@ -1132,31 +1140,31 @@ int mob_spawn(int id) map_addblock(md); really_memzero_this(&md->state); - md->attacked_id = 0; - md->target_id = 0; + md->attacked_id = BlockId(); + md->target_id = BlockId(); md->move_fail_count = 0; mob_init(md); if (!md->stats[mob_stat::SPEED]) - md->stats[mob_stat::SPEED] = mob_db[md->mob_class].speed; - md->def_ele = mob_db[md->mob_class].element; - md->master_id = 0; + md->stats[mob_stat::SPEED] = get_mob_db(md->mob_class).speed; + md->def_ele = get_mob_db(md->mob_class).element; + md->master_id = BlockId(); md->master_dist = 0; md->state.state = MS::IDLE; md->state.skillstate = MobSkillState::MSS_IDLE; assert (!md->timer); md->last_thinktime = tick; - md->next_walktime = tick + std::chrono::seconds(5) + std::chrono::milliseconds(random_::to(50)); + md->next_walktime = tick + 5_s + std::chrono::milliseconds(random_::to(50)); md->attackabletime = tick; md->canmove_tick = tick; // md->deletetimer = nullptr; // md->skilltimer = nullptr; - md->skilldelayup = make_unique<tick_t[]>(mob_db[md->mob_class].skills.size()); - for (size_t i = 0; i < mob_db[md->mob_class].skills.size(); i++) - md->skilldelayup[i] = tick - std::chrono::hours(10); + md->skilldelayup = make_unique<tick_t[]>(get_mob_db(md->mob_class).skills.size()); + for (size_t i = 0; i < get_mob_db(md->mob_class).skills.size(); i++) + md->skilldelayup[i] = tick - 10_h; md->skillid = SkillID(); md->skilllv = 0; @@ -1206,9 +1214,9 @@ int distance(int x0, int y0, int x1, int y1) */ int mob_stopattack(dumb_ptr<mob_data> md) { - md->target_id = 0; + md->target_id = BlockId(); md->state.attackable = false; - md->attacked_id = 0; + md->attacked_id = BlockId(); return 0; } @@ -1218,7 +1226,7 @@ int mob_stopattack(dumb_ptr<mob_data> md) */ int mob_stop_walking(dumb_ptr<mob_data> md, int type) { - nullpo_ret(md); + nullpo_retz(md); if (md->state.state == MS::WALK || md->state.state == MS::IDLE) { @@ -1271,8 +1279,8 @@ int mob_can_reach(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl, int range) struct walkpath_data wpd; int i; - nullpo_ret(md); - nullpo_ret(bl); + nullpo_retz(md); + nullpo_retz(bl); dx = abs(bl->bl_x - md->bl_x); dy = abs(bl->bl_y - md->bl_y); @@ -1328,16 +1336,16 @@ int mob_target(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl, int dist) eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; MobMode mode; - nullpo_ret(md); - nullpo_ret(bl); + nullpo_retz(md); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); Option *option = battle_get_option(bl); - Race race = mob_db[md->mob_class].race; + Race race = get_mob_db(md->mob_class).race; if (md->mode == MobMode::ZERO) { - mode = mob_db[md->mob_class].mode; + mode = get_mob_db(md->mob_class).mode; } else { @@ -1345,25 +1353,25 @@ int mob_target(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl, int dist) } if (!bool(mode & MobMode::CAN_ATTACK)) { - md->target_id = 0; + md->target_id = BlockId(); return 0; } // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending. - if ((md->target_id > 0 && md->state.attackable) + if ((md->target_id && md->state.attackable) && (!bool(mode & MobMode::AGGRESSIVE) || !random_::chance({25 + 1, 100}))) return 0; // Coercion is exerted if it is MVPMOB. if (bool(mode & MobMode::BOSS) - || (option != NULL + || (option != nullptr || race == Race::_insect || race == Race::_demon)) { if (bl->bl_type == BL::PC) { sd = bl->is_player(); - nullpo_ret(sd); + nullpo_retz(sd); if (sd->invincible_timer || pc_isinvisible(sd)) return 0; if (!bool(mode & MobMode::BOSS) && race != Race::_insect && race != Race::_demon @@ -1391,8 +1399,8 @@ static void mob_ai_sub_hard_activesearch(dumb_ptr<block_list> bl, dumb_ptr<mob_data> smd, int *pcc) { - dumb_ptr<map_session_data> tsd = NULL; - dumb_ptr<mob_data> tmd = NULL; + dumb_ptr<map_session_data> tsd = nullptr; + dumb_ptr<mob_data> tmd = nullptr; MobMode mode; int dist; @@ -1412,14 +1420,14 @@ void mob_ai_sub_hard_activesearch(dumb_ptr<block_list> bl, return; if (smd->mode == MobMode::ZERO) - mode = mob_db[smd->mob_class].mode; + mode = get_mob_db(smd->mob_class).mode; else mode = smd->mode; // アクティブでターゲット射程内にいるなら、ロックする if (bool(mode & MobMode::AGGRESSIVE)) { - Race race = mob_db[smd->mob_class].race; + Race race = get_mob_db(smd->mob_class).race; //対象がPCの場合 if (tsd && !pc_isdead(tsd) && @@ -1479,7 +1487,7 @@ void mob_ai_sub_hard_lootsearch(dumb_ptr<block_list> bl, dumb_ptr<mob_data> md, if (md->mode == MobMode::ZERO) { - mode = mob_db[md->mob_class].mode; + mode = get_mob_db(md->mob_class).mode; } else { @@ -1518,8 +1526,8 @@ void mob_ai_sub_hard_linksearch(dumb_ptr<block_list> bl, dumb_ptr<mob_data> md, nullpo_retv(md); nullpo_retv(target); - if (md->attacked_id > 0 - && bool(mob_db[md->mob_class].mode & MobMode::ASSIST)) + if (md->attacked_id + && bool(get_mob_db(md->mob_class).mode & MobMode::ASSIST)) { if (tmd->mob_class == md->mob_class && tmd->bl_m == md->bl_m @@ -1543,17 +1551,17 @@ void mob_ai_sub_hard_linksearch(dumb_ptr<block_list> bl, dumb_ptr<mob_data> md, static int mob_ai_sub_hard_slavemob(dumb_ptr<mob_data> md, tick_t tick) { - dumb_ptr<mob_data> mmd = NULL; + dumb_ptr<mob_data> mmd = nullptr; dumb_ptr<block_list> bl; MobMode mode; int old_dist; - nullpo_ret(md); + nullpo_retz(md); - if ((bl = map_id2bl(md->master_id)) != NULL) + if ((bl = map_id2bl(md->master_id)) != nullptr) mmd = bl->is_mob(); - mode = mob_db[md->mob_class].mode; + mode = get_mob_db(md->mob_class).mode; // It is not main monster/leader. if (!mmd || mmd->bl_type != BL::MOB || mmd->bl_id != md->master_id) @@ -1636,20 +1644,20 @@ int mob_ai_sub_hard_slavemob(dumb_ptr<mob_data> md, tick_t tick) while (ret && i < 10); } - md->next_walktime = tick + std::chrono::milliseconds(500); + md->next_walktime = tick + 500_ms; md->state.master_check = 1; } // There is the master, the master locks a target and he does not lock. - if ((mmd->target_id > 0 && mmd->state.attackable) + if ((mmd->target_id && mmd->state.attackable) && (!md->target_id || !md->state.attackable)) { dumb_ptr<map_session_data> sd = map_id2sd(mmd->target_id); - if (sd != NULL && !pc_isdead(sd) && !sd->invincible_timer + if (sd != nullptr && !pc_isdead(sd) && !sd->invincible_timer && !pc_isinvisible(sd)) { - Race race = mob_db[md->mob_class].race; + Race race = get_mob_db(md->mob_class).race; if (bool(mode & MobMode::BOSS) || (!sd->state.gangsterparadise || race == Race::_insect @@ -1675,12 +1683,12 @@ int mob_ai_sub_hard_slavemob(dumb_ptr<mob_data> md, tick_t tick) static int mob_unlocktarget(dumb_ptr<mob_data> md, tick_t tick) { - nullpo_ret(md); + nullpo_retz(md); - md->target_id = 0; + md->target_id = BlockId(); md->state.attackable = false; md->state.skillstate = MobSkillState::MSS_IDLE; - md->next_walktime = tick + std::chrono::seconds(3) + std::chrono::milliseconds(random_::to(3000)); + md->next_walktime = tick + 3_s + std::chrono::milliseconds(random_::to(3000)); return 0; } @@ -1693,7 +1701,7 @@ int mob_randomwalk(dumb_ptr<mob_data> md, tick_t tick) { const int retrycount = 20; - nullpo_ret(md); + nullpo_retz(md); interval_t speed = battle_get_speed(md); if (md->next_walktime < tick) @@ -1718,8 +1726,8 @@ int mob_randomwalk(dumb_ptr<mob_data> md, tick_t tick) if (md->move_fail_count > 1000) { if (battle_config.error_log == 1) - PRINTF("MOB cant move. random spawn %d, mob_class = %d\n", - md->bl_id, md->mob_class); + PRINTF("MOB cant move. random spawn %d, mob_class = %d\n"_fmt, + md->bl_id, md->mob_class); md->move_fail_count = 0; mob_spawn(md->bl_id); } @@ -1734,7 +1742,7 @@ int mob_randomwalk(dumb_ptr<mob_data> md, tick_t tick) else c += speed; } - md->next_walktime = tick + std::chrono::seconds(3) + std::chrono::milliseconds(random_::to(3000)) + c; + md->next_walktime = tick + 3_s + std::chrono::milliseconds(random_::to(3000)) + c; md->state.skillstate = MobSkillState::MSS_WALK; return 1; } @@ -1748,9 +1756,9 @@ int mob_randomwalk(dumb_ptr<mob_data> md, tick_t tick) static void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) { - dumb_ptr<mob_data> md, tmd = NULL; - dumb_ptr<map_session_data> tsd = NULL; - dumb_ptr<block_list> tbl = NULL; + dumb_ptr<mob_data> md, tmd = nullptr; + dumb_ptr<map_session_data> tsd = nullptr; + dumb_ptr<block_list> tbl = nullptr; dumb_ptr<flooritem_data> fitem; int i, dx, dy, ret, dist; int attack_type = 0; @@ -1763,7 +1771,7 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) return; md->last_thinktime = tick; - if (md->skilltimer || md->bl_prev == NULL) + if (md->skilltimer || md->bl_prev == nullptr) { // Under a skill aria and death if (tick > md->next_walktime + MIN_MOBTHINKTIME) @@ -1772,20 +1780,20 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) } if (md->mode == MobMode::ZERO) - mode = mob_db[md->mob_class].mode; + mode = get_mob_db(md->mob_class).mode; else mode = md->mode; - Race race = mob_db[md->mob_class].race; + Race race = get_mob_db(md->mob_class).race; // Abnormalities if (bool(md->opt1) && md->opt1 != Opt1::_stone6) return; - if (!bool(mode & MobMode::CAN_ATTACK) && md->target_id > 0) - md->target_id = 0; + if (!bool(mode & MobMode::CAN_ATTACK) && md->target_id) + md->target_id = BlockId(); - if (md->attacked_id > 0 && bool(mode & MobMode::ASSIST)) + if (md->attacked_id && bool(mode & MobMode::ASSIST)) { // Link monster dumb_ptr<map_session_data> asd = map_id2sd(md->attacked_id); if (asd) @@ -1802,28 +1810,28 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) } // It checks to see it was attacked first (if active, it is target change at 25% of probability). - if (mode != MobMode::ZERO && md->attacked_id > 0 + if (mode != MobMode::ZERO && md->attacked_id && (!md->target_id || !md->state.attackable || (bool(mode & MobMode::AGGRESSIVE) && random_::chance({25, 100})))) { dumb_ptr<block_list> abl = map_id2bl(md->attacked_id); - dumb_ptr<map_session_data> asd = NULL; + dumb_ptr<map_session_data> asd = nullptr; if (abl) { if (abl->bl_type == BL::PC) asd = abl->is_player(); - if (asd == NULL || md->bl_m != abl->bl_m || abl->bl_prev == NULL + if (asd == nullptr || md->bl_m != abl->bl_m || abl->bl_prev == nullptr || asd->invincible_timer || pc_isinvisible(asd) || (dist = distance(md->bl_x, md->bl_y, abl->bl_x, abl->bl_y)) >= 32 || battle_check_target(bl, abl, BCT_ENEMY) == 0) - md->attacked_id = 0; + md->attacked_id = BlockId(); else { md->target_id = md->attacked_id; // set target md->state.attackable = true; attack_type = 1; - md->attacked_id = 0; + md->attacked_id = BlockId(); md->min_chase = dist + 13; if (md->min_chase > 26) md->min_chase = 26; @@ -1833,7 +1841,7 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) md->state.master_check = 0; // Processing of slave monster - if (md->master_id > 0 && md->state.special_mob_ai == 0) + if (md->master_id && md->state.special_mob_ai == 0) mob_ai_sub_hard_slavemob(md, tick); // アクティヴモンスターの策敵 (?? of a bitter taste TIVU monster) @@ -1874,7 +1882,7 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) } // It will attack, if the candidate for an attack is. - if (md->target_id > 0) + if (md->target_id) { if ((tbl = map_id2bl(md->target_id))) { @@ -1884,7 +1892,7 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) tmd = tbl->is_mob(); if (tsd || tmd) { - if (tbl->bl_m != md->bl_m || tbl->bl_prev == NULL + if (tbl->bl_m != md->bl_m || tbl->bl_prev == nullptr || (dist = distance(md->bl_x, md->bl_y, tbl->bl_x, tbl->bl_y)) >= md->min_chase) @@ -1894,7 +1902,7 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) && race != Race::_insect && race != Race::_demon)) mob_unlocktarget(md, tick); // スキルなどによる策敵妨害 - else if (!battle_check_range(md, tbl, mob_db[md->mob_class].range)) + else if (!battle_check_range(md, tbl, get_mob_db(md->mob_class).range)) { // 攻撃範囲外なので移動 if (!bool(mode & MobMode::CAN_MOVE)) @@ -1915,7 +1923,7 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) else { // 追跡 - md->next_walktime = tick + std::chrono::milliseconds(500); + md->next_walktime = tick + 500_ms; i = 0; do { @@ -1973,11 +1981,11 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) } else { // ルートモンスター処理 - if (tbl == NULL || tbl->bl_type != BL::ITEM || tbl->bl_m != md->bl_m + if (tbl == nullptr || tbl->bl_type != BL::ITEM || tbl->bl_m != md->bl_m || (dist = distance(md->bl_x, md->bl_y, tbl->bl_x, tbl->bl_y)) >= md->min_chase - || !bool(mob_db[md->mob_class].mode & MobMode::LOOTER)) + || !bool(get_mob_db(md->mob_class).mode & MobMode::LOOTER)) { // 遠すぎるかアイテムがなくなった mob_unlocktarget(md, tick); @@ -1999,7 +2007,7 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) && (md->next_walktime < tick || distance(md->to_x, md->to_y, tbl->bl_x, tbl->bl_y) <= 0)) return; // 既に移動中 - md->next_walktime = tick + std::chrono::milliseconds(500); + md->next_walktime = tick + 500_ms; dx = tbl->bl_x - md->bl_x; dy = tbl->bl_y - md->bl_y; ret = mob_walktoxy(md, md->bl_x + dx, md->bl_y + dy, 0); @@ -2036,16 +2044,16 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) // mobs that are not slaves can random-walk if (bool(mode & MobMode::CAN_MOVE) && mob_can_move(md) - && (md->master_id == 0 || md->state.special_mob_ai + && (!md->master_id || md->state.special_mob_ai || md->master_dist > 10)) { // if walktime is more than 7 seconds in the future, // set it to somewhere between 3 and 5 seconds - if (md->next_walktime > tick + std::chrono::seconds(7) + if (md->next_walktime > tick + 7_s && (md->walkpath.path_len == 0 || md->walkpath.path_pos >= md->walkpath.path_len)) { - md->next_walktime = tick + std::chrono::seconds(3) + md->next_walktime = tick + 3_s + std::chrono::milliseconds(random_::to(2000)); } @@ -2104,7 +2112,7 @@ void mob_ai_sub_lazy(dumb_ptr<block_list> bl, tick_t tick) return; md->last_thinktime = tick; - if (md->bl_prev == NULL || md->skilltimer) + if (md->bl_prev == nullptr || md->skilltimer) { if (tick > md->next_walktime + MIN_MOBTHINKTIME * 10) md->next_walktime = tick; @@ -2112,7 +2120,7 @@ void mob_ai_sub_lazy(dumb_ptr<block_list> bl, tick_t tick) } if (md->next_walktime < tick - && bool(mob_db[md->mob_class].mode & MobMode::CAN_MOVE) + && bool(get_mob_db(md->mob_class).mode & MobMode::CAN_MOVE) && mob_can_move(md)) { @@ -2127,8 +2135,8 @@ void mob_ai_sub_lazy(dumb_ptr<block_list> bl, tick_t tick) // MOB which is not not the summons MOB but BOSS, either sometimes reboils. else if (random_::chance(MOB_LAZYWARPPERC) && md->spawn.x0 <= 0 - && md->master_id != 0 - && !bool(mob_db[md->mob_class].mode & MobMode::BOSS)) + && md->master_id + && !bool(get_mob_db(md->mob_class).mode & MobMode::BOSS)) mob_spawn(md->bl_id); } @@ -2139,12 +2147,12 @@ void mob_ai_sub_lazy(dumb_ptr<block_list> bl, tick_t tick) // MOB which is not BOSS which is not Summons MOB, either -- a case -- sometimes -- leaping if (random_::chance(MOB_LAZYWARPPERC) && md->spawn.x0 <= 0 - && md->master_id != 0 - && !bool(mob_db[md->mob_class].mode & MobMode::BOSS)) + && md->master_id + && !bool(get_mob_db(md->mob_class).mode & MobMode::BOSS)) mob_warp(md, nullptr, -1, -1, BeingRemoveWhy::NEGATIVE1); } - md->next_walktime = tick + std::chrono::seconds(5) + std::chrono::milliseconds(random_::to(10 * 1000)); + md->next_walktime = tick + 5_s + std::chrono::milliseconds(random_::to(10 * 1000)); } } @@ -2169,7 +2177,8 @@ struct delay_item_drop { map_local *m; int x, y; - int nameid, amount; + ItemNameId nameid; + int amount; dumb_ptr<map_session_data> first_sd, second_sd, third_sd; }; @@ -2177,7 +2186,7 @@ struct delay_item_drop2 { map_local *m; int x, y; - struct item item_data; + Item item_data; dumb_ptr<map_session_data> first_sd, second_sd, third_sd; }; @@ -2188,7 +2197,7 @@ struct delay_item_drop2 static void mob_delay_item_drop(TimerData *, tick_t, struct delay_item_drop ditem) { - struct item temp_item {}; + Item temp_item {}; PickupFail flag; temp_item.nameid = ditem.nameid; @@ -2201,7 +2210,7 @@ void mob_delay_item_drop(TimerData *, tick_t, struct delay_item_drop ditem) pc_additem(ditem.first_sd, &temp_item, ditem.amount)) != PickupFail::OKAY) { - clif_additem(ditem.first_sd, 0, 0, flag); + clif_additem(ditem.first_sd, IOff0::from(0), 0, flag); map_addflooritem(&temp_item, 1, ditem.m, ditem.x, ditem.y, ditem.first_sd, ditem.second_sd, ditem.third_sd); @@ -2231,7 +2240,7 @@ void mob_delay_item_drop2(TimerData *, tick_t, struct delay_item_drop2 ditem) ditem.item_data.amount)) != PickupFail::OKAY) { - clif_additem(ditem.first_sd, 0, 0, flag); + clif_additem(ditem.first_sd, IOff0::from(0), 0, flag); map_addflooritem(&ditem.item_data, ditem.item_data.amount, ditem.m, ditem.x, ditem.y, ditem.first_sd, ditem.second_sd, ditem.third_sd); @@ -2252,7 +2261,7 @@ int mob_delete(dumb_ptr<mob_data> md) { nullpo_retr(1, md); - if (md->bl_prev == NULL) + if (md->bl_prev == nullptr) return 1; mob_changestate(md, MS::DEAD, 0); clif_clearchar(md, BeingRemoveWhy::DEAD); @@ -2266,7 +2275,7 @@ int mob_catch_delete(dumb_ptr<mob_data> md, BeingRemoveWhy type) { nullpo_retr(1, md); - if (md->bl_prev == NULL) + if (md->bl_prev == nullptr) return 1; mob_changestate(md, MS::DEAD, 0); clif_clearchar(md, type); @@ -2275,7 +2284,7 @@ int mob_catch_delete(dumb_ptr<mob_data> md, BeingRemoveWhy type) return 0; } -void mob_timer_delete(TimerData *, tick_t, int id) +void mob_timer_delete(TimerData *, tick_t, BlockId id) { dumb_ptr<block_list> bl = map_id2bl(id); dumb_ptr<mob_data> md; @@ -2291,15 +2300,15 @@ void mob_timer_delete(TimerData *, tick_t, int id) *------------------------------------------ */ static -void mob_deleteslave_sub(dumb_ptr<block_list> bl, int id) +void mob_deleteslave_sub(dumb_ptr<block_list> bl, BlockId id) { dumb_ptr<mob_data> md; nullpo_retv(bl); md = bl->is_mob(); - if (md->master_id > 0 && md->master_id == id) - mob_damage(NULL, md, md->hp, 1); + if (md->master_id && md->master_id == id) + mob_damage(nullptr, md, md->hp, 1); } /*========================================== @@ -2308,7 +2317,7 @@ void mob_deleteslave_sub(dumb_ptr<block_list> bl, int id) */ int mob_deleteslave(dumb_ptr<mob_data> md) { - nullpo_ret(md); + nullpo_retz(md); map_foreachinarea(std::bind(mob_deleteslave_sub, ph::_1, md->bl_id), md->bl_m, @@ -2333,18 +2342,18 @@ double damage_bonus_factor[DAMAGE_BONUS_COUNT + 1] = int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, int type) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; int max_hp; tick_t tick = gettick(); - dumb_ptr<map_session_data> mvp_sd = NULL, second_sd = NULL, third_sd = NULL; + dumb_ptr<map_session_data> mvp_sd = nullptr, second_sd = nullptr, third_sd = nullptr; - nullpo_ret(md); //srcはNULLで呼ばれる場合もあるので、他でチェック + nullpo_retz(md); //srcはNULLで呼ばれる場合もあるので、他でチェック if (src && src->bl_id == md->master_id && bool(md->mode & MobMode::TURNS_AGAINST_BAD_MASTER)) { /* If the master hits a monster, have the monster turn against him */ - md->master_id = 0; + md->master_id = BlockId(); md->mode = MobMode::war; /* Regular war mode */ md->target_id = src->bl_id; md->attacked_id = src->bl_id; @@ -2358,18 +2367,16 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, mvp_sd = sd; } -// if(battle_config.battle_log) -// PRINTF("mob_damage %d %d %d\n",md->hp,max_hp,damage); - if (md->bl_prev == NULL) + if (md->bl_prev == nullptr) { if (battle_config.error_log == 1) - PRINTF("mob_damage : BlockError!!\n"); + PRINTF("mob_damage : BlockError!!\n"_fmt); return 0; } if (md->state.state == MS::DEAD || md->hp <= 0) { - if (md->bl_prev != NULL) + if (md->bl_prev != nullptr) { mob_changestate(md, MS::DEAD, 0); // It is skill at the time of death. @@ -2395,7 +2402,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, if (!(type & 2)) { - if (sd != NULL) + if (sd != nullptr) { for (mob_data::DmgLogEntry& dle : md->dmglogv) { @@ -2414,7 +2421,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, } damage_logged_pc: - if (md->attacked_id <= 0 && md->state.special_mob_ai == 0) + if (!md->attacked_id && md->state.special_mob_ai == 0) md->attacked_id = sd->bl_id; } if (src && src->bl_type == BL::MOB @@ -2425,12 +2432,12 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, if (master_bl && master_bl->bl_type == BL::PC) { MAP_LOG_PC(master_bl->is_player(), - "MOB-TO-MOB-DMG FROM MOB%d %d TO MOB%d %d FOR %d", - md2->bl_id, md2->mob_class, md->bl_id, md->mob_class, - damage); + "MOB-TO-MOB-DMG FROM MOB%d %d TO MOB%d %d FOR %d"_fmt, + md2->bl_id, md2->mob_class, md->bl_id, md->mob_class, + damage); } - nullpo_ret(md2); + nullpo_retz(md2); for (mob_data::DmgLogEntry& dle : md->dmglogv) { if (dle.id == md2->master_id) @@ -2446,7 +2453,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, app.dmg = damage; md->dmglogv.push_back(app); - if (md->attacked_id <= 0 && md->state.special_mob_ai == 0) + if (!md->attacked_id && md->state.special_mob_ai == 0) md->attacked_id = md2->master_id; } damage_logged_slave: @@ -2461,7 +2468,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, return 0; } - MAP_LOG("MOB%d DEAD", md->bl_id); + MAP_LOG("MOB%d DEAD"_fmt, md->bl_id); // ----- ここから死亡処理 ----- @@ -2491,7 +2498,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, { struct DmgLogParty { - struct party *p; + PartyPair p; int base_exp, job_exp; }; std::vector<DmgLogParty> ptv; @@ -2501,7 +2508,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, { dumb_ptr<map_session_data> tmpsdi = map_id2sd(dle.id); int tmpdmg = dle.dmg; - if (tmpsdi == NULL) + if (tmpsdi == nullptr) continue; if (tmpsdi->bl_m != md->bl_m || pc_isdead(tmpsdi)) continue; @@ -2532,7 +2539,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, int base_exp, job_exp, flag = 1; double per; - struct party *p; + PartyPair p; // [Fate] The above is the old formula. We do a more involved computation below. // [o11c] Look in git history for old code, you idiot! @@ -2548,23 +2555,23 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, per = 1; base_exp = - ((mob_db[md->mob_class].base_exp * + ((get_mob_db(md->mob_class).base_exp * md->stats[mob_stat::XP_BONUS]) >> MOB_XP_BONUS_SHIFT) * per / 256; if (base_exp < 1) base_exp = 1; if (sd && md && battle_config.pk_mode == 1 - && (mob_db[md->mob_class].lv - sd->status.base_level >= 20)) + && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20)) { base_exp *= 1.15; // pk_mode additional exp if monster >20 levels [Valaris] } if (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) base_exp = 0; // Added [Valaris] - job_exp = mob_db[md->mob_class].job_exp * per / 256; + job_exp = get_mob_db(md->mob_class).job_exp * per / 256; if (job_exp < 1) job_exp = 1; if (sd && md && battle_config.pk_mode == 1 - && (mob_db[md->mob_class].lv - sd->status.base_level >= 20)) + && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20)) { job_exp *= 1.15; // pk_mode additional exp if monster >20 levels [Valaris] } @@ -2572,19 +2579,19 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, && battle_config.alchemist_summon_reward != 1) job_exp = 0; // Added [Valaris] - int pid = tmpsdi->status.party_id; - if (pid > 0) + PartyId pid = tmpsdi->status.party_id; + if (pid) { std::vector<DmgLogParty>::iterator it = std::find_if(ptv.begin(), ptv.end(), [pid](const DmgLogParty& dlp) { - return dlp.p->party_id == pid; + return dlp.p.party_id == pid; } ); if (it == ptv.end()) { p = party_search(pid); - if (p != NULL && p->exp != 0) + if (p && p->exp != 0) { DmgLogParty pn {}; pn.p = p; @@ -2617,19 +2624,19 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, if (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) // Added [Valaris] break; // End - if (mob_db[md->mob_class].dropitem[i].nameid <= 0) + if (!get_mob_db(md->mob_class).dropitem[i].nameid) continue; - random_::Fixed<int, 10000> drop_rate = mob_db[md->mob_class].dropitem[i].p; + random_::Fixed<int, 10000> drop_rate = get_mob_db(md->mob_class).dropitem[i].p; if (battle_config.drops_by_luk > 0 && sd && md) drop_rate.num += (sd->status.attrs[ATTR::LUK] * battle_config.drops_by_luk) / 100; // drops affected by luk [Valaris] if (sd && md && battle_config.pk_mode == 1 - && (mob_db[md->mob_class].lv - sd->status.base_level >= 20)) + && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20)) drop_rate.num *= 1.25; // pk_mode increase drops if 20 level difference [Valaris] if (!random_::chance(drop_rate)) continue; struct delay_item_drop ditem {}; - ditem.nameid = mob_db[md->mob_class].dropitem[i].nameid; + ditem.nameid = get_mob_db(md->mob_class).dropitem[i].nameid; ditem.amount = 1; ditem.m = md->bl_m; ditem.x = md->bl_x; @@ -2637,14 +2644,14 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, ditem.first_sd = mvp_sd; ditem.second_sd = second_sd; ditem.third_sd = third_sd; - Timer(tick + std::chrono::milliseconds(500) + static_cast<interval_t>(i), + Timer(tick + 500_ms + static_cast<interval_t>(i), std::bind(mob_delay_item_drop, ph::_1, ph::_2, ditem) ).detach(); } { int i = 0; - for (struct item lit : md->lootitemv) + for (Item lit : md->lootitemv) { struct delay_item_drop2 ditem {}; ditem.item_data = lit; @@ -2655,7 +2662,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, ditem.second_sd = second_sd; ditem.third_sd = third_sd; // ? - Timer(tick + std::chrono::milliseconds(540) + static_cast<interval_t>(i), + Timer(tick + 540_ms + static_cast<interval_t>(i), std::bind(mob_delay_item_drop2, ph::_1, ph::_2, ditem) ).detach(); @@ -2668,9 +2675,9 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, // SCRIPT実行 if (md->npc_event) { - if (sd == NULL) + if (sd == nullptr) { - if (mvp_sd != NULL) + if (mvp_sd != nullptr) sd = mvp_sd; else { @@ -2711,7 +2718,7 @@ int mob_heal(dumb_ptr<mob_data> md, int heal) { int max_hp = battle_get_max_hp(md); - nullpo_ret(md); + nullpo_retz(md); md->hp += heal; if (max_hp < md->hp) @@ -2725,7 +2732,7 @@ int mob_heal(dumb_ptr<mob_data> md, int heal) *------------------------------------------ */ static -void mob_warpslave_sub(dumb_ptr<block_list> bl, int id, int x, int y) +void mob_warpslave_sub(dumb_ptr<block_list> bl, BlockId id, int x, int y) { dumb_ptr<mob_data> md = bl->is_mob(); @@ -2742,7 +2749,6 @@ void mob_warpslave_sub(dumb_ptr<block_list> bl, int id, int x, int y) static int mob_warpslave(dumb_ptr<mob_data> md, int x, int y) { -//PRINTF("warp slave\n"); map_foreachinarea(std::bind(mob_warpslave_sub, ph::_1, md->bl_id, md->bl_x, md->bl_y), md->bl_m, x - AREA_SIZE, y - AREA_SIZE, @@ -2759,9 +2765,9 @@ int mob_warp(dumb_ptr<mob_data> md, map_local *m, int x, int y, BeingRemoveWhy t { int i = 0, xs = 0, ys = 0, bx = x, by = y; - nullpo_ret(md); + nullpo_retz(md); - if (md->bl_prev == NULL) + if (md->bl_prev == nullptr) return 0; if (m == nullptr) @@ -2808,12 +2814,12 @@ int mob_warp(dumb_ptr<mob_data> md, map_local *m, int x, int y, BeingRemoveWhy t else { if (battle_config.error_log == 1) - PRINTF("MOB %d warp failed, mob_class = %d\n", md->bl_id, md->mob_class); + PRINTF("MOB %d warp failed, mob_class = %d\n"_fmt, md->bl_id, md->mob_class); } - md->target_id = 0; // タゲを解除する + md->target_id = BlockId(); // タゲを解除する md->state.attackable = false; - md->attacked_id = 0; + md->attacked_id = BlockId(); md->state.skillstate = MobSkillState::MSS_IDLE; mob_changestate(md, MS::IDLE, 0); @@ -2821,7 +2827,7 @@ int mob_warp(dumb_ptr<mob_data> md, map_local *m, int x, int y, BeingRemoveWhy t && i == 1000) { if (battle_config.battle_log == 1) - PRINTF("MOB %d warp to (%d,%d), mob_class = %d\n", md->bl_id, x, y, + PRINTF("MOB %d warp to (%d,%d), mob_class = %d\n"_fmt, md->bl_id, x, y, md->mob_class); } @@ -2840,7 +2846,7 @@ int mob_warp(dumb_ptr<mob_data> md, map_local *m, int x, int y, BeingRemoveWhy t *------------------------------------------ */ static -void mob_countslave_sub(dumb_ptr<block_list> bl, int id, int *c) +void mob_countslave_sub(dumb_ptr<block_list> bl, BlockId id, int *c) { dumb_ptr<mob_data> md; @@ -2860,7 +2866,7 @@ int mob_countslave(dumb_ptr<mob_data> md) { int c = 0; - nullpo_ret(md); + nullpo_retz(md); map_foreachinarea(std::bind(mob_countslave_sub, ph::_1, md->bl_id, &c), md->bl_m, @@ -2874,36 +2880,38 @@ int mob_countslave(dumb_ptr<mob_data> md) * 手下MOB召喚 *------------------------------------------ */ -int mob_summonslave(dumb_ptr<mob_data> md2, int *value, int amount, int flag) +int mob_summonslave(dumb_ptr<mob_data> md2, int *value_, int amount, int flag) { dumb_ptr<mob_data> md; - int bx, by, count = 0, mob_class, k, a = amount; + int bx, by, count = 0, a = amount; - nullpo_ret(md2); - nullpo_ret(value); + nullpo_retz(md2); + nullpo_retz(value_); bx = md2->bl_x; by = md2->bl_y; map_local *m = md2->bl_m; - if (value[0] <= 1000 || value[0] > 2000) // 値が異常なら召喚を止める - return 0; - while (count < 5 && value[count] > 1000 && value[count] <= 2000) - count++; + Species values[5]; + for (count = 0; count < 5 && values[count] != Species(); ++count) + values[count] = wrap<Species>(value_[count]); if (count < 1) return 0; - for (k = 0; k < count; k++) + for (int k = 0; k < count; k++) { amount = a; - mob_class = value[k]; - if (mob_class <= 1000 || mob_class > 2000) + Species mob_class = values[k]; + if (mobdb_checkid(mob_class) == Species()) + { + PRINTF("Warning: bad slave class %u\n"_fmt, mob_class); continue; + } for (; amount > 0; amount--) { int x = 0, y = 0, i = 0; md.new_(); - if (bool(mob_db[mob_class].mode & MobMode::LOOTER)) + if (bool(get_mob_db(mob_class).mode & MobMode::LOOTER)) md->lootitemv.clear(); while ((x <= 0 @@ -2921,8 +2929,8 @@ int mob_summonslave(dumb_ptr<mob_data> md2, int *value, int amount, int flag) } mob_spawn_dataset(md, JAPANESE_NAME, mob_class); - md->bl_prev = NULL; - md->bl_next = NULL; + md->bl_prev = nullptr; + md->bl_next = nullptr; md->bl_m = m; md->bl_x = x; md->bl_y = y; @@ -2954,7 +2962,7 @@ int mob_summonslave(dumb_ptr<mob_data> md2, int *value, int amount, int flag) */ static void mob_counttargeted_sub(dumb_ptr<block_list> bl, - int id, int *c, dumb_ptr<block_list> src, ATK target_lv) + BlockId id, int *c, dumb_ptr<block_list> src, ATK target_lv) { nullpo_retv(bl); nullpo_retv(c); @@ -2986,7 +2994,7 @@ int mob_counttargeted(dumb_ptr<mob_data> md, dumb_ptr<block_list> src, { int c = 0; - nullpo_ret(md); + nullpo_retz(md); map_foreachinarea(std::bind(mob_counttargeted_sub, ph::_1, md->bl_id, &c, src, target_lv), md->bl_m, @@ -3004,21 +3012,21 @@ int mob_counttargeted(dumb_ptr<mob_data> md, dumb_ptr<block_list> src, * スキル使用(詠唱完了、ID指定) *------------------------------------------ */ -void mobskill_castend_id(TimerData *, tick_t tick, int id) +void mobskill_castend_id(TimerData *, tick_t tick, BlockId id) { - dumb_ptr<mob_data> md = NULL; + dumb_ptr<mob_data> md = nullptr; dumb_ptr<block_list> bl; dumb_ptr<block_list> mbl; int range; - if ((mbl = map_id2bl(id)) == NULL) //詠唱したMobがもういないというのは良くある正常処理 + if ((mbl = map_id2bl(id)) == nullptr) //詠唱したMobがもういないというのは良くある正常処理 return; - if ((md = mbl->is_mob()) == NULL) + if ((md = mbl->is_mob()) == nullptr) { - PRINTF("mobskill_castend_id nullpo mbl->bl_id:%d\n", mbl->bl_id); + PRINTF("mobskill_castend_id nullpo mbl->bl_id:%d\n"_fmt, mbl->bl_id); return; } - if (md->bl_type != BL::MOB || md->bl_prev == NULL) + if (md->bl_type != BL::MOB || md->bl_prev == nullptr) return; if (bool(md->opt1)) @@ -3027,9 +3035,8 @@ void mobskill_castend_id(TimerData *, tick_t tick, int id) if (md->skillid != SkillID::NPC_EMOTION) md->last_thinktime = tick + battle_get_adelay(md); - if ((bl = map_id2bl(md->skilltarget)) == NULL || bl->bl_prev == NULL) + if ((bl = map_id2bl(md->skilltarget)) == nullptr || bl->bl_prev == nullptr) { //スキルターゲットが存在しない - //PRINTF("mobskill_castend_id nullpo\n");//ターゲットがいないときはnullpoじゃなくて普通に終了 return; } if (md->bl_m != bl->bl_m) @@ -3044,10 +3051,10 @@ void mobskill_castend_id(TimerData *, tick_t tick, int id) if (range + battle_config.monster_skill_add_range < distance(md->bl_x, md->bl_y, bl->bl_x, bl->bl_y)) return; - md->skilldelayup[md->skillidx - &mob_db[md->mob_class].skills.front()] = tick; + md->skilldelayup[md->skillidx - &get_mob_db(md->mob_class).skills.front()] = tick; if (battle_config.monster_skill_log == 1) - PRINTF("MOB skill castend skill=%d, mob_class = %d\n", + PRINTF("MOB skill castend skill=%d, mob_class = %d\n"_fmt, md->skillid, md->mob_class); mob_stop_walking(md, 0); @@ -3071,20 +3078,20 @@ void mobskill_castend_id(TimerData *, tick_t tick, int id) * スキル使用(詠唱完了、場所指定) *------------------------------------------ */ -void mobskill_castend_pos(TimerData *, tick_t tick, int id) +void mobskill_castend_pos(TimerData *, tick_t tick, BlockId id) { - dumb_ptr<mob_data> md = NULL; + dumb_ptr<mob_data> md = nullptr; dumb_ptr<block_list> bl; int range; //mobskill_castend_id同様詠唱したMobが詠唱完了時にもういないというのはありそうなのでnullpoから除外 - if ((bl = map_id2bl(id)) == NULL) + if ((bl = map_id2bl(id)) == nullptr) return; md = bl->is_mob(); nullpo_retv(md); - if (md->bl_type != BL::MOB || md->bl_prev == NULL) + if (md->bl_type != BL::MOB || md->bl_prev == nullptr) return; if (bool(md->opt1)) @@ -3095,10 +3102,10 @@ void mobskill_castend_pos(TimerData *, tick_t tick, int id) range = battle_get_range(md) - (range + 1); if (range + battle_config.monster_skill_add_range < distance(md->bl_x, md->bl_y, md->skillx, md->skilly)) return; - md->skilldelayup[md->skillidx - &mob_db[md->mob_class].skills.front()] = tick; + md->skilldelayup[md->skillidx - &get_mob_db(md->mob_class).skills.front()] = tick; if (battle_config.monster_skill_log == 1) - PRINTF("MOB skill castend skill=%d, mob_class = %d\n", + PRINTF("MOB skill castend skill=%d, mob_class = %d\n"_fmt, md->skillid, md->mob_class); mob_stop_walking(md, 0); } @@ -3115,13 +3122,13 @@ int mobskill_use_id(dumb_ptr<mob_data> md, dumb_ptr<block_list> target, SkillID skill_id; int skill_lv; - nullpo_ret(md); + nullpo_retz(md); ms = &skill_idx; - if (target == NULL && (target = map_id2bl(md->target_id)) == NULL) + if (target == nullptr && (target = map_id2bl(md->target_id)) == nullptr) return 0; - if (target->bl_prev == NULL || md->bl_prev == NULL) + if (target->bl_prev == nullptr || md->bl_prev == nullptr) return 0; skill_id = ms->skill_id; @@ -3145,10 +3152,10 @@ int mobskill_use_id(dumb_ptr<mob_data> md, dumb_ptr<block_list> target, interval_t casttime = skill_castfix(md, ms->casttime); md->state.skillcastcancel = ms->cancel; - md->skilldelayup[ms - &mob_db[md->mob_class].skills.front()] = gettick(); + md->skilldelayup[ms - &get_mob_db(md->mob_class).skills.front()] = gettick(); if (battle_config.monster_skill_log == 1) - PRINTF("MOB skill use target_id=%d skill=%d lv=%d cast=%d, mob_class = %d\n", + PRINTF("MOB skill use target_id=%d skill=%d lv=%d cast=%d, mob_class = %d\n"_fmt, target->bl_id, skill_id, skill_lv, static_cast<uint32_t>(casttime.count()), md->mob_class); @@ -3190,10 +3197,10 @@ int mobskill_use_pos(dumb_ptr<mob_data> md, struct block_list bl; int skill_lv; - nullpo_ret(md); + nullpo_retz(md); ms = &skill_idx; - if (md->bl_prev == NULL) + if (md->bl_prev == nullptr) return 0; SkillID skill_id = ms->skill_id; @@ -3215,13 +3222,13 @@ int mobskill_use_pos(dumb_ptr<mob_data> md, // delay=skill_delayfix(sd, skill_get_delay( skill_id,skill_lv) ); interval_t casttime = skill_castfix(md, ms->casttime); - md->skilldelayup[ms - &mob_db[md->mob_class].skills.front()] = gettick(); + md->skilldelayup[ms - &get_mob_db(md->mob_class).skills.front()] = gettick(); md->state.skillcastcancel = ms->cancel; if (battle_config.monster_skill_log == 1) - PRINTF("MOB skill use target_pos= (%d,%d) skill=%d lv=%d cast=%d, mob_class = %d\n", - skill_x, skill_y, skill_id, skill_lv, - static_cast<uint32_t>(casttime.count()), md->mob_class); + PRINTF("MOB skill use target_pos= (%d,%d) skill=%d lv=%d cast=%d, mob_class = %d\n"_fmt, + skill_x, skill_y, skill_id, skill_lv, + static_cast<uint32_t>(casttime.count()), md->mob_class); if (casttime <= interval_t::zero()) // A skill without a cast time wont be cancelled. @@ -3229,7 +3236,7 @@ int mobskill_use_pos(dumb_ptr<mob_data> md, md->skillx = skill_x; md->skilly = skill_y; - md->skilltarget = 0; + md->skilltarget = BlockId(); md->skillid = skill_id; md->skilllv = skill_lv; md->skillidx = &skill_idx; @@ -3257,8 +3264,8 @@ int mobskill_use(dumb_ptr<mob_data> md, tick_t tick, { int max_hp; - nullpo_ret(md); - std::vector<mob_skill>& ms = mob_db[md->mob_class].skills; + nullpo_retz(md); + std::vector<mob_skill>& ms = get_mob_db(md->mob_class).skills; max_hp = battle_get_max_hp(md); @@ -3312,7 +3319,7 @@ int mobskill_use(dumb_ptr<mob_data> md, tick_t tick, if (skill_get_inf(msii.skill_id) & 2) { // 場所指定 - dumb_ptr<block_list> bl = NULL; + dumb_ptr<block_list> bl = nullptr; int x = 0, y = 0; { if (msii.target == MobSkillTarget::MST_TARGET) @@ -3334,7 +3341,7 @@ int mobskill_use(dumb_ptr<mob_data> md, tick_t tick, else { { - dumb_ptr<block_list> bl = NULL; + dumb_ptr<block_list> bl = nullptr; if (msii.target == MobSkillTarget::MST_TARGET) bl = map_id2bl(md->target_id); else @@ -3358,7 +3365,7 @@ int mobskill_use(dumb_ptr<mob_data> md, tick_t tick, */ int mobskill_event(dumb_ptr<mob_data> md, BF flag) { - nullpo_ret(md); + nullpo_retz(md); if (flag == BF::NEGATIVE_1 && mobskill_use(md, gettick(), MobSkillCondition::ANY)) @@ -3380,42 +3387,42 @@ int mobskill_event(dumb_ptr<mob_data> md, BF flag) *------------------------------------------ */ static -int mob_makedummymobdb(int mob_class) +int mob_makedummymobdb(Species mob_class) { int i; - SNPRINTF(mob_db[mob_class].name, 24, "mob%d", mob_class); - SNPRINTF(mob_db[mob_class].jname, 24, "mob%d", mob_class); - mob_db[mob_class].lv = 1; - mob_db[mob_class].max_hp = 1000; - mob_db[mob_class].max_sp = 1; - mob_db[mob_class].base_exp = 2; - mob_db[mob_class].job_exp = 1; - mob_db[mob_class].range = 1; - mob_db[mob_class].atk1 = 7; - mob_db[mob_class].atk2 = 10; - mob_db[mob_class].def = 0; - mob_db[mob_class].mdef = 0; - mob_db[mob_class].attrs[ATTR::STR] = 1; - mob_db[mob_class].attrs[ATTR::AGI] = 1; - mob_db[mob_class].attrs[ATTR::VIT] = 1; - mob_db[mob_class].attrs[ATTR::INT] = 1; - mob_db[mob_class].attrs[ATTR::DEX] = 6; - mob_db[mob_class].attrs[ATTR::LUK] = 2; - mob_db[mob_class].range2 = 10; - mob_db[mob_class].range3 = 10; - mob_db[mob_class].size = 0; // 1 - mob_db[mob_class].race = Race::formless; - mob_db[mob_class].element = LevelElement{0, Element::neutral}; - mob_db[mob_class].mode = MobMode::ZERO; - mob_db[mob_class].speed = 300; - mob_db[mob_class].adelay = 1000; - mob_db[mob_class].amotion = 500; - mob_db[mob_class].dmotion = 500; + SNPRINTF(get_mob_db(mob_class).name, 24, "mob%d"_fmt, mob_class); + SNPRINTF(get_mob_db(mob_class).jname, 24, "mob%d"_fmt, mob_class); + get_mob_db(mob_class).lv = 1; + get_mob_db(mob_class).max_hp = 1000; + get_mob_db(mob_class).max_sp = 1; + get_mob_db(mob_class).base_exp = 2; + get_mob_db(mob_class).job_exp = 1; + get_mob_db(mob_class).range = 1; + get_mob_db(mob_class).atk1 = 7; + get_mob_db(mob_class).atk2 = 10; + get_mob_db(mob_class).def = 0; + get_mob_db(mob_class).mdef = 0; + get_mob_db(mob_class).attrs[ATTR::STR] = 1; + get_mob_db(mob_class).attrs[ATTR::AGI] = 1; + get_mob_db(mob_class).attrs[ATTR::VIT] = 1; + get_mob_db(mob_class).attrs[ATTR::INT] = 1; + get_mob_db(mob_class).attrs[ATTR::DEX] = 6; + get_mob_db(mob_class).attrs[ATTR::LUK] = 2; + get_mob_db(mob_class).range2 = 10; + get_mob_db(mob_class).range3 = 10; + get_mob_db(mob_class).size = 0; // 1 + get_mob_db(mob_class).race = Race::formless; + get_mob_db(mob_class).element = LevelElement{0, Element::neutral}; + get_mob_db(mob_class).mode = MobMode::ZERO; + get_mob_db(mob_class).speed = 300; + get_mob_db(mob_class).adelay = 1000; + get_mob_db(mob_class).amotion = 500; + get_mob_db(mob_class).dmotion = 500; for (i = 0; i < 8; i++) { - mob_db[mob_class].dropitem[i].nameid = 0; - mob_db[mob_class].dropitem[i].p.num = 0; + get_mob_db(mob_class).dropitem[i].nameid = ItemNameId(); + get_mob_db(mob_class).dropitem[i].p.num = 0; } return 0; } @@ -3439,13 +3446,13 @@ bool mob_readdb(ZString filename) io::ReadFile in(filename); if (!in.is_open()) { - PRINTF("Unable to read mob db: %s\n", filename); + PRINTF("Unable to read mob db: %s\n"_fmt, filename); return false; } AString line; while (in.getline(line)) { - int mob_class; + Species mob_class; if (is_comment(line)) continue; @@ -3515,62 +3522,62 @@ bool mob_readdb(ZString filename) ) ); - if (!okay || mob_class <= 1000 || mob_class > 2000) + if (!okay || mobdb_checkid(mob_class) == Species()) { - PRINTF("bad mob line: %s\n", line); + PRINTF("bad mob line: %s\n"_fmt, line); rv = false; continue; } // TODO move this lower - mob_db[mob_class] = std::move(mdbv); + get_mob_db(mob_class) = std::move(mdbv); - if (mob_db[mob_class].base_exp < 0) - mob_db[mob_class].base_exp = 0; - else if (mob_db[mob_class].base_exp > 0 - && (mob_db[mob_class].base_exp * + if (get_mob_db(mob_class).base_exp < 0) + get_mob_db(mob_class).base_exp = 0; + else if (get_mob_db(mob_class).base_exp > 0 + && (get_mob_db(mob_class).base_exp * battle_config.base_exp_rate / 100 > 1000000000 - || mob_db[mob_class].base_exp * + || get_mob_db(mob_class).base_exp * battle_config.base_exp_rate / 100 < 0)) - mob_db[mob_class].base_exp = 1000000000; + get_mob_db(mob_class).base_exp = 1000000000; else - mob_db[mob_class].base_exp = mob_db[mob_class].base_exp * battle_config.base_exp_rate / 100; + get_mob_db(mob_class).base_exp = get_mob_db(mob_class).base_exp * battle_config.base_exp_rate / 100; - if (mob_db[mob_class].job_exp < 0) - mob_db[mob_class].job_exp = 0; - else if (mob_db[mob_class].job_exp > 0 - && (mob_db[mob_class].job_exp * battle_config.job_exp_rate / + if (get_mob_db(mob_class).job_exp < 0) + get_mob_db(mob_class).job_exp = 0; + else if (get_mob_db(mob_class).job_exp > 0 + && (get_mob_db(mob_class).job_exp * battle_config.job_exp_rate / 100 > 1000000000 - || mob_db[mob_class].job_exp * + || get_mob_db(mob_class).job_exp * battle_config.job_exp_rate / 100 < 0)) - mob_db[mob_class].job_exp = 1000000000; + get_mob_db(mob_class).job_exp = 1000000000; else - mob_db[mob_class].job_exp = mob_db[mob_class].job_exp * battle_config.job_exp_rate / 100; + get_mob_db(mob_class).job_exp = get_mob_db(mob_class).job_exp * battle_config.job_exp_rate / 100; for (int i = 0; i < 8; i++) { - int rate = mob_db[mob_class].dropitem[i].p.num; + int rate = get_mob_db(mob_class).dropitem[i].p.num; if (rate < 1) rate = 1; if (rate > 10000) rate = 10000; - mob_db[mob_class].dropitem[i].p.num = rate; + get_mob_db(mob_class).dropitem[i].p.num = rate; } - mob_db[mob_class].skills.clear(); + get_mob_db(mob_class).skills.clear(); - mob_db[mob_class].hair = 0; - mob_db[mob_class].hair_color = 0; - mob_db[mob_class].weapon = 0; - mob_db[mob_class].shield = 0; - mob_db[mob_class].head_top = 0; - mob_db[mob_class].head_mid = 0; - mob_db[mob_class].head_buttom = 0; - mob_db[mob_class].clothes_color = 0; //Add for player monster dye - Valaris + get_mob_db(mob_class).hair = 0; + get_mob_db(mob_class).hair_color = 0; + get_mob_db(mob_class).weapon = 0; + get_mob_db(mob_class).shield = ItemNameId(); + get_mob_db(mob_class).head_top = ItemNameId(); + get_mob_db(mob_class).head_mid = ItemNameId(); + get_mob_db(mob_class).head_buttom = ItemNameId(); + get_mob_db(mob_class).clothes_color = 0; //Add for player monster dye - Valaris - if (mob_db[mob_class].base_exp == 0) - mob_db[mob_class].base_exp = mob_gen_exp(&mob_db[mob_class]); + if (get_mob_db(mob_class).base_exp == 0) + get_mob_db(mob_class).base_exp = mob_gen_exp(&get_mob_db(mob_class)); } - PRINTF("read %s done\n", filename); + PRINTF("read %s done\n"_fmt, filename); } return rv; } @@ -3580,15 +3587,15 @@ bool extract<MobSkillCondition, void, void>(XString str, MobSkillCondition *msc) { const struct { - ZString str; + LString str; MobSkillCondition id; } cond1[] = { - {ZString("always"), MobSkillCondition::MSC_ALWAYS}, - {ZString("myhpltmaxrate"), MobSkillCondition::MSC_MYHPLTMAXRATE}, - {ZString("notintown"), MobSkillCondition::MSC_NOTINTOWN}, - {ZString("slavelt"), MobSkillCondition::MSC_SLAVELT}, - {ZString("slavele"), MobSkillCondition::MSC_SLAVELE}, + {"always"_s, MobSkillCondition::MSC_ALWAYS}, + {"myhpltmaxrate"_s, MobSkillCondition::MSC_MYHPLTMAXRATE}, + {"notintown"_s, MobSkillCondition::MSC_NOTINTOWN}, + {"slavelt"_s, MobSkillCondition::MSC_SLAVELT}, + {"slavele"_s, MobSkillCondition::MSC_SLAVELE}, }; for (auto& pair : cond1) if (str == pair.str) @@ -3604,14 +3611,14 @@ bool extract<MobSkillState, void, void>(XString str, MobSkillState *mss) { const struct { - ZString str; + LString str; MobSkillState id; } state[] = { - {ZString("any"), MobSkillState::ANY}, - {ZString("idle"), MobSkillState::MSS_IDLE}, - {ZString("walk"), MobSkillState::MSS_WALK}, - {ZString("attack"), MobSkillState::MSS_ATTACK}, + {"any"_s, MobSkillState::ANY}, + {"idle"_s, MobSkillState::MSS_IDLE}, + {"walk"_s, MobSkillState::MSS_WALK}, + {"attack"_s, MobSkillState::MSS_ATTACK}, }; for (auto& pair : state) if (str == pair.str) @@ -3627,12 +3634,12 @@ bool extract<MobSkillTarget, void, void>(XString str, MobSkillTarget *mst) { const struct { - ZString str; + LString str; MobSkillTarget id; } target[] = { - {ZString("target"), MobSkillTarget::MST_TARGET}, - {ZString("self"), MobSkillTarget::MST_SELF}, + {"target"_s, MobSkillTarget::MST_TARGET}, + {"self"_s, MobSkillTarget::MST_SELF}, }; for (auto& pair : target) if (str == pair.str) @@ -3650,21 +3657,21 @@ bool mob_readskilldb(ZString filename) io::ReadFile in(filename); if (!in.is_open()) { - PRINTF("can't read %s\n", filename); + PRINTF("can't read %s\n"_fmt, filename); return false; } AString line; while (in.getline(line)) { - int mob_id; + Species mob_id; if (is_comment(line)) continue; XString blah; - if (extract(line, record<','>(&mob_id, &blah)) && mob_id > 0 && blah == "clear") + if (extract(line, record<','>(&mob_id, &blah)) && mobdb_checkid(mob_id) != Species() && blah == "clear"_s) { - mob_db[mob_id].skills.clear(); + get_mob_db(mob_id).skills.clear(); continue; } @@ -3699,9 +3706,9 @@ bool mob_readskilldb(ZString filename) ) ) continue; - if (cancellable == "yes") + if (cancellable == "yes"_s) msv.cancel = true; - else if (cancellable == "no") + else if (cancellable == "no"_s) msv.cancel = false; else { @@ -3712,15 +3719,15 @@ bool mob_readskilldb(ZString filename) msv.casttime = std::chrono::milliseconds(casttime); msv.delay = std::chrono::milliseconds(delay); - if (mob_id <= 0) + if (mobdb_checkid(mob_id) == Species()) { rv = false; continue; } - mob_db[mob_id].skills.push_back(std::move(msv)); + get_mob_db(mob_id).skills.push_back(std::move(msv)); } - PRINTF("read %s done\n", filename); + PRINTF("read %s done\n"_fmt, filename); } return rv; } @@ -3736,3 +3743,4 @@ void do_init_mob2(void) MIN_MOBTHINKTIME * 10 ).detach(); } +} // namespace tmwa diff --git a/src/map/mob.hpp b/src/map/mob.hpp index e7d81bd..d0cc07a 100644 --- a/src/map/mob.hpp +++ b/src/map/mob.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MOB_HPP -#define TMWA_MAP_MOB_HPP +#pragma once // mob.hpp - Really scary code. // // Copyright © ????-2004 Athena Dev Teams @@ -21,22 +20,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "mob.t.hpp" +#include "mob.t.hpp" -# include "../generic/random.t.hpp" +#include "../generic/fwd.hpp" +#include "../generic/enum.hpp" +#include "../generic/random.t.hpp" -# include "../mmo/mmo.hpp" -# include "../mmo/timer.t.hpp" +#include "../net/timer.t.hpp" -# include "clif.t.hpp" -# include "map.hpp" -# include "skill.t.hpp" +#include "battle.t.hpp" +#include "clif.t.hpp" +#include "map.hpp" +#include "skill.t.hpp" -# define ENGLISH_NAME stringish<MobName>("--en--") -# define JAPANESE_NAME stringish<MobName>("--ja--") -# define MOB_THIS_MAP stringish<MapName>("this") + +namespace tmwa +{ +#define ENGLISH_NAME stringish<MobName>("--en--"_s) +#define JAPANESE_NAME stringish<MobName>("--ja--"_s) +#define MOB_THIS_MAP stringish<MapName>("this"_s) struct mob_skill { @@ -72,41 +76,43 @@ struct mob_db_ int mutations_nr, mutation_power; struct { - int nameid; + ItemNameId nameid; random_::Fixed<int, 10000> p; } dropitem[8]; - short hair, hair_color, weapon, shield, head_top, head_mid, head_buttom, option, clothes_color; // [Valaris] + short hair, hair_color, weapon; + ItemNameId shield, head_top, head_mid, head_buttom; + short option, clothes_color; // [Valaris] int equip; // [Valaris] std::vector<struct mob_skill> skills; }; -extern struct mob_db_ mob_db[]; +struct mob_db_& get_mob_db(Species); -int mobdb_searchname(MobName str); -int mobdb_checkid(const int id); -int mob_once_spawn(dumb_ptr<map_session_data> sd, +Species mobdb_searchname(MobName str); +Species mobdb_checkid(Species id); +BlockId mob_once_spawn(dumb_ptr<map_session_data> sd, MapName mapname, int x, int y, - MobName mobname, int class_, int amount, + MobName mobname, Species class_, int amount, NpcEvent event); -int mob_once_spawn_area(dumb_ptr<map_session_data> sd, +BlockId mob_once_spawn_area(dumb_ptr<map_session_data> sd, MapName mapname, int x0, int y0, int x1, int y1, - MobName mobname, int class_, int amount, + MobName mobname, Species class_, int amount, NpcEvent event); int mob_target(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl, int dist); int mob_stop_walking(dumb_ptr<mob_data> md, int type); int mob_stopattack(dumb_ptr<mob_data>); -int mob_spawn(int); +int mob_spawn(BlockId); int mob_damage(dumb_ptr<block_list>, dumb_ptr<mob_data>, int, int); int mob_heal(dumb_ptr<mob_data>, int); -short mob_get_hair(int); -short mob_get_hair_color(int); -short mob_get_weapon(int); -short mob_get_shield(int); -short mob_get_head_top(int); -short mob_get_head_mid(int); -short mob_get_head_buttom(int); -short mob_get_clothes_color(int); //player mob dye [Valaris] -int mob_get_equip(int); // mob equip [Valaris] +short mob_get_hair(Species); +short mob_get_hair_color(Species); +short mob_get_weapon(Species); +ItemNameId mob_get_shield(Species); +ItemNameId mob_get_head_top(Species); +ItemNameId mob_get_head_mid(Species); +ItemNameId mob_get_head_buttom(Species); +short mob_get_clothes_color(Species); //player mob dye [Valaris] +int mob_get_equip(Species); // mob equip [Valaris] bool mob_readdb(ZString filename); bool mob_readskilldb(ZString filename); @@ -114,7 +120,7 @@ void do_init_mob2(void); int mob_delete(dumb_ptr<mob_data> md); int mob_catch_delete(dumb_ptr<mob_data> md, BeingRemoveWhy type); -void mob_timer_delete(TimerData *, tick_t, int); +void mob_timer_delete(TimerData *, tick_t, BlockId); int mob_deleteslave(dumb_ptr<mob_data> md); @@ -125,10 +131,9 @@ int mob_warp(dumb_ptr<mob_data> md, map_local *m, int x, int y, BeingRemoveWhy t int mobskill_use(dumb_ptr<mob_data> md, tick_t tick, MobSkillCondition event); int mobskill_event(dumb_ptr<mob_data> md, BF flag); -void mobskill_castend_id(TimerData *tid, tick_t tick, int id); -void mobskill_castend_pos(TimerData *tid, tick_t tick, int id); +void mobskill_castend_id(TimerData *tid, tick_t tick, BlockId id); +void mobskill_castend_pos(TimerData *tid, tick_t tick, BlockId id); int mob_summonslave(dumb_ptr<mob_data> md2, int *value, int amount, int flag); void mob_reload(void); - -#endif // TMWA_MAP_MOB_HPP +} // namespace tmwa diff --git a/src/map/mob.t.hpp b/src/map/mob.t.hpp index 37fd13e..160a8a3 100644 --- a/src/map/mob.t.hpp +++ b/src/map/mob.t.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MOB_T_HPP -#define TMWA_MAP_MOB_T_HPP +#pragma once // mob.t.hpp - Really scary code. // // Copyright © ????-2004 Athena Dev Teams @@ -21,10 +20,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdint> +#include <cstdint> + +namespace tmwa +{ enum class MobSkillTarget { MST_TARGET = 0, @@ -59,5 +61,4 @@ enum class MobSkillState : uint8_t MSS_LOOT, MSS_CHASE, }; - -#endif // TMWA_MAP_MOB_T_HPP +} // namespace tmwa diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 7fe13f1..a6427d6 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -21,10 +21,9 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include <cassert> -#include <cstdlib> -#include <cstring> #include <ctime> +#include <algorithm> #include <list> #include "../compat/fun.hpp" @@ -34,16 +33,20 @@ #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" +#include "../strings/literal.hpp" #include "../generic/db.hpp" #include "../io/cxxstdio.hpp" #include "../io/read.hpp" +#include "../net/timer.hpp" + #include "../mmo/config_parse.hpp" #include "../mmo/extract.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" +#include "../mmo/utils.hpp" + +#include "../proto2/map-user.hpp" #include "battle.hpp" #include "clif.hpp" @@ -56,17 +59,22 @@ #include "../poison.hpp" + +namespace tmwa +{ static std::list<AString> npc_srcs; static -int npc_id = START_NPC_NUM; +BlockId npc_id = START_NPC_NUM; static int npc_warp, npc_shop, npc_script, npc_mob; -int npc_get_new_npc_id(void) +BlockId npc_get_new_npc_id(void) { - return npc_id++; + BlockId rv = npc_id; + npc_id = next(npc_id); + return rv; } struct event_data @@ -107,7 +115,7 @@ void npc_enable_sub(dumb_ptr<block_list> bl, dumb_ptr<npc_data> nd) NpcEvent aname; aname.npc = nd->name; - aname.label = stringish<ScriptLabel>("OnTouch"); + aname.label = stringish<ScriptLabel>("OnTouch"_s); if (sd->areanpc_id == nd->bl_id) return; sd->areanpc_id = nd->bl_id; @@ -118,9 +126,9 @@ void npc_enable_sub(dumb_ptr<block_list> bl, dumb_ptr<npc_data> nd) int npc_enable(NpcName name, bool flag) { dumb_ptr<npc_data> nd = npc_name2id(name); - if (nd == NULL) + if (nd == nullptr) { - PRINTF("npc_enable(%s, %s) failed.\n", name, flag ? "true" : "false"); + PRINTF("npc_enable(%s, %s) failed.\n"_fmt, name, flag ? "true"_s : "false"_s); return 0; } @@ -167,15 +175,15 @@ dumb_ptr<npc_data> npc_name2id(NpcName name) */ int npc_event_dequeue(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); - sd->npc_id = 0; + sd->npc_id = BlockId(); if (!sd->eventqueuel.empty()) { - if (!pc_addeventtimer(sd, std::chrono::milliseconds(100), sd->eventqueuel.front())) + if (!pc_addeventtimer(sd, 100_ms, sd->eventqueuel.front())) { - PRINTF("npc_event_dequeue(): Event timer is full.\n"); + PRINTF("npc_event_dequeue(): Event timer is full.\n"_fmt); return 0; } @@ -190,7 +198,7 @@ int npc_delete(dumb_ptr<npc_data> nd) { nullpo_retr(1, nd); - if (nd->bl_prev == NULL) + if (nd->bl_prev == nullptr) return 1; clif_clearchar(nd, BeingRemoveWhy::DEAD); @@ -204,9 +212,9 @@ void npc_timer_event(NpcEvent eventname) dumb_ptr<npc_data_script> nd; // int xs,ys; - if ((ev == NULL || (nd = ev->nd) == NULL)) + if ((ev == nullptr || (nd = ev->nd) == nullptr)) { - PRINTF("npc_event: event not found [%s]\n", + PRINTF("npc_event: event not found [%s]\n"_fmt, eventname); return; } @@ -220,7 +228,7 @@ void npc_timer_event(NpcEvent eventname) */ static void npc_event_doall_sub(NpcEvent key, struct event_data *ev, - int *c, ScriptLabel name, int rid, Slice<argrec_t> argv) + int *c, ScriptLabel name, BlockId rid, Slice<argrec_t> argv) { ScriptLabel p = key.label; @@ -234,7 +242,7 @@ void npc_event_doall_sub(NpcEvent key, struct event_data *ev, } } -int npc_event_doall_l(ScriptLabel name, int rid, Slice<argrec_t> args) +int npc_event_doall_l(ScriptLabel name, BlockId rid, Slice<argrec_t> args) { int c = 0; @@ -245,7 +253,7 @@ int npc_event_doall_l(ScriptLabel name, int rid, Slice<argrec_t> args) static void npc_event_do_sub(NpcEvent key, struct event_data *ev, - int *c, NpcEvent name, int rid, Slice<argrec_t> argv) + int *c, NpcEvent name, BlockId rid, Slice<argrec_t> argv) { nullpo_retv(ev); @@ -257,7 +265,7 @@ void npc_event_do_sub(NpcEvent key, struct event_data *ev, } } -int npc_event_do_l(NpcEvent name, int rid, Slice<argrec_t> args) +int npc_event_do_l(NpcEvent name, BlockId rid, Slice<argrec_t> args) { int c = 0; @@ -283,19 +291,19 @@ void npc_event_do_clock(TimerData *, tick_t) ScriptLabel buf; if (t.tm_min != ev_tm_b.tm_min) { - SNPRINTF(buf, 24, "OnMinute%02d", t.tm_min); + SNPRINTF(buf, 24, "OnMinute%02d"_fmt, t.tm_min); npc_event_doall(buf); - SNPRINTF(buf, 24, "OnClock%02d%02d", t.tm_hour, t.tm_min); + SNPRINTF(buf, 24, "OnClock%02d%02d"_fmt, t.tm_hour, t.tm_min); npc_event_doall(buf); } if (t.tm_hour != ev_tm_b.tm_hour) { - SNPRINTF(buf, 24, "OnHour%02d", t.tm_hour); + SNPRINTF(buf, 24, "OnHour%02d"_fmt, t.tm_hour); npc_event_doall(buf); } if (t.tm_mday != ev_tm_b.tm_mday) { - SNPRINTF(buf, 24, "OnDay%02d%02d", t.tm_mon + 1, t.tm_mday); + SNPRINTF(buf, 24, "OnDay%02d%02d"_fmt, t.tm_mon + 1, t.tm_mday); npc_event_doall(buf); } ev_tm_b = t; @@ -307,12 +315,12 @@ void npc_event_do_clock(TimerData *, tick_t) */ int npc_event_do_oninit(void) { - int c = npc_event_doall(stringish<ScriptLabel>("OnInit")); - PRINTF("npc: OnInit Event done. (%d npc)\n", c); + int c = npc_event_doall(stringish<ScriptLabel>("OnInit"_s)); + PRINTF("npc: OnInit Event done. (%d npc)\n"_fmt, c); - Timer(gettick() + std::chrono::milliseconds(100), + Timer(gettick() + 100_ms, npc_event_do_clock, - std::chrono::seconds(1) + 1_s ).detach(); return 0; @@ -322,10 +330,10 @@ int npc_event_do_oninit(void) /// This will be called later if you call npc_timerevent_start. /// This function may only expire, but not deactivate, the counter. static -void npc_timerevent(TimerData *, tick_t tick, int id, interval_t data) +void npc_timerevent(TimerData *, tick_t tick, BlockId id, interval_t data) { dumb_ptr<npc_data_script> nd = map_id2bl(id)->is_npc()->is_script(); - assert (nd != NULL); + assert (nd != nullptr); assert (nd->npc_subtype == NpcSubtype::SCRIPT); assert (nd->scr.next_event != nd->scr.timer_eventv.end()); @@ -345,7 +353,7 @@ void npc_timerevent(TimerData *, tick_t tick, int id, interval_t data) id, next)); } - run_script(ScriptPointer(nd->scr.script.get(), te->pos), 0, nd->bl_id); + run_script(ScriptPointer(nd->scr.script.get(), te->pos), BlockId(), nd->bl_id); } /// Start (or resume) counting ticks to the next npc_timerevent. @@ -461,15 +469,15 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, dumb_ptr<npc_data_script> nd; int xs, ys; - if (sd == NULL) + if (sd == nullptr) { - PRINTF("npc_event nullpo?\n"); + PRINTF("npc_event nullpo?\n"_fmt); } - if (ev == NULL && eventname.label == stringish<ScriptLabel>("OnTouch")) + if (ev == nullptr && eventname.label == stringish<ScriptLabel>("OnTouch"_s)) return 1; - if (ev == NULL || (nd = ev->nd) == NULL) + if (ev == nullptr || (nd = ev->nd) == nullptr) { if (mob_kill) { @@ -480,7 +488,7 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, else { if (battle_config.error_log) - PRINTF("npc_event: event not found [%s]\n", + PRINTF("npc_event: event not found [%s]\n"_fmt, eventname); return 0; } @@ -500,7 +508,7 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, return 1; } - if (sd->npc_id != 0) + if (sd->npc_id) { sd->eventqueuel.push_back(eventname); return 1; @@ -521,12 +529,12 @@ static void npc_command_sub(NpcEvent key, struct event_data *ev, NpcName npcname, XString command) { if (ev->nd->name == npcname - && key.label.startswith("OnCommand")) + && key.label.startswith("OnCommand"_s)) { XString temp = key.label.xslice_t(9); if (command == temp) - run_script(ScriptPointer(ev->nd->scr.script.get(), ev->pos), 0, ev->nd->bl_id); + run_script(ScriptPointer(ev->nd->scr.script.get(), ev->pos), BlockId(), ev->nd->bl_id); } } @@ -567,7 +575,7 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, map_local *m, int x, int y) ys = m->npc[i]->is_warp()->warp.ys; break; case NpcSubtype::MESSAGE: - assert (0 && "I'm pretty sure these are never put on a map"); + assert (0 && "I'm pretty sure these are never put on a map"_s); xs = 0; ys = 0; break; @@ -589,7 +597,7 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, map_local *m, int x, int y) if (f) { if (battle_config.error_log) - PRINTF("npc_touch_areanpc : some bug \n"); + PRINTF("npc_touch_areanpc : some bug \n"_fmt); } return 1; } @@ -601,13 +609,13 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, map_local *m, int x, int y) m->npc[i]->is_warp()->warp.x, m->npc[i]->is_warp()->warp.y, BeingRemoveWhy::GONE); break; case NpcSubtype::MESSAGE: - assert (0 && "I'm pretty sure these NPCs are never put on a map."); + assert (0 && "I'm pretty sure these NPCs are never put on a map."_s); break; case NpcSubtype::SCRIPT: { NpcEvent aname; aname.npc = m->npc[i]->name; - aname.label = stringish<ScriptLabel>("OnTouch"); + aname.label = stringish<ScriptLabel>("OnTouch"_s); if (sd->areanpc_id == m->npc[i]->bl_id) return 1; @@ -626,20 +634,20 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, map_local *m, int x, int y) *------------------------------------------ */ static -int npc_checknear(dumb_ptr<map_session_data> sd, int id) +int npc_checknear(dumb_ptr<map_session_data> sd, BlockId id) { dumb_ptr<npc_data> nd; - nullpo_ret(sd); + nullpo_retz(sd); nd = map_id_is_npc(id); // this actually happens - if (nd == NULL) + if (nd == nullptr) return 1; if (nd->bl_type != BL::NPC) return 1; - if (nd->npc_class < 0) // イベント系は常にOK + if (nd->npc_class == NEGATIVE_SPECIES) return 0; // エリア判定 @@ -657,16 +665,16 @@ int npc_checknear(dumb_ptr<map_session_data> sd, int id) * クリック時のNPC処理 *------------------------------------------ */ -int npc_click(dumb_ptr<map_session_data> sd, int id) +int npc_click(dumb_ptr<map_session_data> sd, BlockId id) { dumb_ptr<npc_data> nd; nullpo_retr(1, sd); - if (sd->npc_id != 0) + if (sd->npc_id) { if (battle_config.error_log) - PRINTF("npc_click: npc_id != 0\n"); + PRINTF("npc_click: npc_id != 0\n"_fmt); return 1; } @@ -706,7 +714,7 @@ int npc_click(dumb_ptr<map_session_data> sd, int id) * *------------------------------------------ */ -int npc_scriptcont(dumb_ptr<map_session_data> sd, int id) +int npc_scriptcont(dumb_ptr<map_session_data> sd, BlockId id) { dumb_ptr<npc_data> nd; @@ -738,7 +746,7 @@ int npc_scriptcont(dumb_ptr<map_session_data> sd, int id) * *------------------------------------------ */ -int npc_buysellsel(dumb_ptr<map_session_data> sd, int id, int type) +int npc_buysellsel(dumb_ptr<map_session_data> sd, BlockId id, int type) { dumb_ptr<npc_data> nd; @@ -751,8 +759,8 @@ int npc_buysellsel(dumb_ptr<map_session_data> sd, int id, int type) if (nd->npc_subtype != NpcSubtype::SHOP) { if (battle_config.error_log) - PRINTF("no such shop npc : %d\n", id); - sd->npc_id = 0; + PRINTF("no such shop npc : %d\n"_fmt, id); + sd->npc_id = BlockId(); return 1; } if (nd->flag & 1) // 無効化されている @@ -775,15 +783,14 @@ int npc_buysellsel(dumb_ptr<map_session_data> sd, int id, int type) *------------------------------------------ */ // TODO enumify return type -int npc_buylist(dumb_ptr<map_session_data> sd, int n, - const uint16_t *item_list) +int npc_buylist(dumb_ptr<map_session_data> sd, + const std::vector<Packet_Repeat<0x00c8>>& item_list) { dumb_ptr<npc_data> nd; double z; int i, j, w, itemamount = 0, new_stacks = 0; nullpo_retr(3, sd); - nullpo_retr(3, item_list); if (npc_checknear(sd, sd->npc_shopid)) return 3; @@ -792,26 +799,29 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, if (nd->npc_subtype != NpcSubtype::SHOP) return 3; - for (i = 0, w = 0, z = 0; i < n; i++) + for (i = 0, w = 0, z = 0; i < item_list.size(); i++) { + const uint16_t& item_l_count = item_list[i].count; + const ItemNameId& item_l_id = item_list[i].name_id; + for (j = 0; j < nd->is_shop()->shop_items.size(); j++) { - if (nd->is_shop()->shop_items[j].nameid == item_list[i * 2 + 1]) + if (nd->is_shop()->shop_items[j].nameid == item_l_id) break; } if (j == nd->is_shop()->shop_items.size()) return 3; - z += static_cast<double>(nd->is_shop()->shop_items[j].value) * item_list[i * 2]; - itemamount += item_list[i * 2]; + z += static_cast<double>(nd->is_shop()->shop_items[j].value) * item_l_count; + itemamount += item_l_count; - switch (pc_checkadditem(sd, item_list[i * 2 + 1], item_list[i * 2])) + switch (pc_checkadditem(sd, item_l_id, item_l_count)) { case ADDITEM::EXIST: break; case ADDITEM::NEW: - if (itemdb_isequip(item_list[i * 2 + 1])) - new_stacks += item_list[i * 2]; + if (itemdb_isequip(item_l_id)) + new_stacks += item_l_count; else new_stacks++; break; @@ -819,7 +829,7 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, return 2; } - w += itemdb_weight(item_list[i * 2 + 1]) * item_list[i * 2]; + w += itemdb_weight(item_l_id) * item_l_count; } if (z > static_cast<double>(sd->status.zeny)) @@ -828,18 +838,21 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, return 2; // 重量超過 if (pc_inventoryblank(sd) < new_stacks) return 3; // 種類数超過 - if (sd->trade_partner != 0) + if (sd->trade_partner) return 4; // cant buy while trading pc_payzeny(sd, static_cast<int>(z)); - for (i = 0; i < n; i++) + for (i = 0; i < item_list.size(); i++) { + const uint16_t& item_l_count = item_list[i].count; + const ItemNameId& item_l_id = item_list[i].name_id; + struct item_data *item_data; - if ((item_data = itemdb_exists(item_list[i * 2 + 1])) != NULL) + if ((item_data = itemdb_exists(item_l_id)) != nullptr) { - int amount = item_list[i * 2]; - struct item item_tmp {}; + int amount = item_l_count; + Item item_tmp {}; item_tmp.nameid = item_data->nameid; @@ -868,39 +881,37 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, * *------------------------------------------ */ -int npc_selllist(dumb_ptr<map_session_data> sd, int n, - const uint16_t *item_list) +int npc_selllist(dumb_ptr<map_session_data> sd, + const std::vector<Packet_Repeat<0x00c9>>& item_list) { double z; int i, itemamount = 0; nullpo_retr(1, sd); - nullpo_retr(1, item_list); if (npc_checknear(sd, sd->npc_shopid)) return 1; - for (i = 0, z = 0; i < n; i++) + for (i = 0, z = 0; i < item_list.size(); i++) { - int nameid; - if (item_list[i * 2] - 2 < 0 || item_list[i * 2] - 2 >= MAX_INVENTORY) + if (!item_list[i].ioff2.ok()) return 1; - nameid = sd->status.inventory[item_list[i * 2] - 2].nameid; - if (nameid == 0 || - sd->status.inventory[item_list[i * 2] - 2].amount < item_list[i * 2 + 1]) + ItemNameId nameid = sd->status.inventory[item_list[i].ioff2.unshift()].nameid; + if (!nameid || + sd->status.inventory[item_list[i].ioff2.unshift()].amount < item_list[i].count) return 1; - if (sd->trade_partner != 0) + if (sd->trade_partner) return 2; // cant sell while trading - z += static_cast<double>(itemdb_value_sell(nameid)) * item_list[i * 2 + 1]; - itemamount += item_list[i * 2 + 1]; + z += static_cast<double>(itemdb_value_sell(nameid)) * item_list[i].count; + itemamount += item_list[i].count; } if (z > MAX_ZENY) z = MAX_ZENY; pc_getzeny(sd, static_cast<int>(z)); - for (i = 0; i < n; i++) + for (i = 0; i < item_list.size(); i++) { - int item_id = item_list[i * 2] - 2; - pc_delitem(sd, item_id, item_list[i * 2 + 1], 0); + IOff0 item_id = item_list[i].ioff2.unshift(); + pc_delitem(sd, item_id, item_list[i].count, 0); } return 0; @@ -927,7 +938,7 @@ void npc_clearsrcfile(void) */ void npc_addsrcfile(AString name) { - if (name == "clear") + if (name == "clear"_s) { npc_clearsrcfile(); return; @@ -942,7 +953,7 @@ void npc_addsrcfile(AString name) */ void npc_delsrcfile(XString name) { - if (name == "all") + if (name == "all"_s) { npc_clearsrcfile(); return; @@ -961,19 +972,19 @@ void npc_delsrcfile(XString name) static void register_npc_name(dumb_ptr<npc_data> nd) { - ZString types[4] = - { - {"WARP"}, - {"SHOP"}, - {"SCRIPT"}, - {"MESSAGE"}, - }; + earray<LString, NpcSubtype, NpcSubtype::COUNT> types //= + {{ + "WARP"_s, + "SHOP"_s, + "SCRIPT"_s, + "MESSAGE"_s, + }}; if (!nd->name) { if (nd->npc_subtype == NpcSubtype::MESSAGE) return; - PRINTF("WARNING: npc with no name:\n%s @ %s,%d,%d\n", - types[static_cast<int>(nd->npc_subtype)], + PRINTF("WARNING: npc with no name:\n%s @ %s,%d,%d\n"_fmt, + types[nd->npc_subtype], nd->bl_m->name_, nd->bl_x, nd->bl_y); return; } @@ -982,12 +993,12 @@ void register_npc_name(dumb_ptr<npc_data> nd) if (nd->npc_subtype != NpcSubtype::WARP || nd_old->npc_subtype != NpcSubtype::WARP) { - PRINTF("WARNING: replacing npc with name: %s\n", nd->name); - PRINTF("old: %s @ %s,%d,%d\n", - types[static_cast<int>(nd_old->npc_subtype)], + PRINTF("WARNING: replacing npc with name: %s\n"_fmt, nd->name); + PRINTF("old: %s @ %s,%d,%d\n"_fmt, + types[nd_old->npc_subtype], nd_old->bl_m->name_, nd_old->bl_x, nd_old->bl_y); - PRINTF("new: %s @ %s,%d,%d\n", - types[static_cast<int>(nd->npc_subtype)], + PRINTF("new: %s @ %s,%d,%d\n"_fmt, + types[nd->npc_subtype], nd->bl_m->name_, nd->bl_x, nd->bl_y); } } @@ -1009,7 +1020,7 @@ int npc_parse_warp(XString w1, XString, NpcName w3, XString w4) if (!extract(w1, record<','>(&mapname, &x, &y)) || !extract(w4, record<','>(&xs, &ys, &to_mapname, &to_x, &to_y))) { - PRINTF("bad warp line : %s\n", w3); + PRINTF("bad warp line : %s\n"_fmt, w3); return 1; } @@ -1019,7 +1030,7 @@ int npc_parse_warp(XString w1, XString, NpcName w3, XString w4) nd->bl_id = npc_get_new_npc_id(); nd->n = map_addnpc(m, nd); - nd->bl_prev = nd->bl_next = NULL; + nd->bl_prev = nd->bl_next = nullptr; nd->bl_m = m; nd->bl_x = x; nd->bl_y = y; @@ -1031,7 +1042,7 @@ int npc_parse_warp(XString w1, XString, NpcName w3, XString w4) nd->npc_class = WARP_CLASS; else nd->npc_class = WARP_DEBUG_CLASS; - nd->speed = std::chrono::milliseconds(200); + nd->speed = 200_ms; nd->option = Option::ZERO; nd->opt1 = Opt1::ZERO; nd->opt2 = Opt2::ZERO; @@ -1059,7 +1070,6 @@ int npc_parse_warp(XString w1, XString, NpcName w3, XString w4) } } -// PRINTF("warp npc %s %d read done\n",mapname,nd->bl_id); npc_warp++; nd->bl_type = BL::NPC; nd->npc_subtype = NpcSubtype::WARP; @@ -1077,11 +1087,11 @@ bool extract(XString xs, npc_item_list *itv) if (!extract(xs, record<':'>(&name_or_id, &itv->value))) return false; struct item_data *id = nullptr; - if (extract(name_or_id, &itv->nameid) && itv->nameid > 0) + if (extract(name_or_id, &itv->nameid) && itv->nameid) goto return_true; id = itemdb_searchname(name_or_id.rstrip()); - if (id == NULL) + if (id == nullptr) return false; itv->nameid = id->nameid; goto return_true; @@ -1089,7 +1099,7 @@ bool extract(XString xs, npc_item_list *itv) return_true: if (itv->value < 0) { - if (id == NULL) + if (id == nullptr) id = itemdb_search(itv->nameid); itv->value = id->value_buy * abs(itv->value); } @@ -1108,7 +1118,7 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) MapName mapname; dumb_ptr<npc_data_shop> nd; ZString::iterator w4comma; - int npc_class; + Species npc_class; int dir_; // TODO use enum directly in extract if (!extract(w1, record<','>(&mapname, &x, &y, &dir_)) @@ -1116,7 +1126,7 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) || (w4comma = std::find(w4a.begin(), w4a.end(), ',')) == w4a.end() || !extract(w4a.xislice_h(w4comma), &npc_class)) { - PRINTF("bad shop line : %s\n", w3); + PRINTF("bad shop line : %s\n"_fmt, w3); return 1; } dir = static_cast<DIR>(dir_); @@ -1127,8 +1137,8 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) if (!extract(w4b, vrec<','>(&nd->shop_items))) { - PRINTF("bad shop items : %s\n", w3); - PRINTF(" somewhere --> %s\n", w4b); + PRINTF("bad shop items : %s\n"_fmt, w3); + PRINTF(" somewhere --> %s\n"_fmt, w4b); nd->shop_items.clear(); } @@ -1138,7 +1148,7 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) return 1; } - nd->bl_prev = nd->bl_next = NULL; + nd->bl_prev = nd->bl_next = nullptr; nd->bl_m = m; nd->bl_x = x; nd->bl_y = y; @@ -1147,7 +1157,7 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) nd->flag = 0; nd->name = w3; nd->npc_class = npc_class; - nd->speed = std::chrono::milliseconds(200); + nd->speed = 200_ms; nd->option = Option::ZERO; nd->opt1 = Opt1::ZERO; nd->opt2 = Opt2::ZERO; @@ -1190,13 +1200,14 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, int x, y; DIR dir = DIR::S; map_local *m; - int xs = 0, ys = 0, npc_class = 0; // [Valaris] thanks to fov + int xs = 0, ys = 0; // [Valaris] thanks to fov + Species npc_class; MapName mapname; - std::unique_ptr<const ScriptBuffer> script = NULL; + std::unique_ptr<const ScriptBuffer> script = nullptr; dumb_ptr<npc_data_script> nd; int evflag = 0; - if (w1 == "-") + if (w1 == "-"_s) { x = 0; y = 0; @@ -1207,16 +1218,16 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, int dir_; // TODO use enum directly in extract if (!extract(w1, record<','>(&mapname, &x, &y, &dir_)) || dir_ < 0 || dir_ >= 8 - || (w2 == "script" && !w4.contains(','))) + || (w2 == "script"_s && !w4.contains(','))) { - PRINTF("bad script line : %s\n", w3); + PRINTF("bad script line : %s\n"_fmt, w3); return 1; } dir = static_cast<DIR>(dir_); m = map_mapname2mapid(mapname); } - if (w2 == "script") + if (w2 == "script"_s) { // may be empty MString srcbuf; @@ -1249,13 +1260,13 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, srcbuf += '\n'; } script = parse_script(AString(srcbuf), startline, false); - if (script == NULL) + if (script == nullptr) // script parse error? return 1; } else { - assert(0 && "duplicate() is no longer supported!\n"); + assert(0 && "duplicate() is no longer supported!\n"_s); return 0; } @@ -1271,7 +1282,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, if (ys >= 0) ys = ys * 2 + 1; - if (npc_class >= 0) + if (npc_class != NEGATIVE_SPECIES) { for (int i = 0; i < ys; i++) @@ -1295,26 +1306,31 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, } else { - npc_class = atoi(w4.c_str()); + XString w4x = w4; + if (w4x.endswith(',')) + w4x = w4x.xrslice_h(1); + if (!extract(w4x, &npc_class)) + abort(); nd->scr.xs = 0; nd->scr.ys = 0; } - if (npc_class < 0 && m != nullptr) + if (npc_class == NEGATIVE_SPECIES && m != nullptr) { evflag = 1; } if (w3.contains(':')) { - assert(false && "feature removed"); + assert(false && "feature removed"_s); abort(); } + { nd->name = w3; } - nd->bl_prev = nd->bl_next = NULL; + nd->bl_prev = nd->bl_next = nullptr; nd->bl_m = m; nd->bl_x = x; nd->bl_y = y; @@ -1322,14 +1338,13 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, nd->dir = dir; nd->flag = 0; nd->npc_class = npc_class; - nd->speed = std::chrono::milliseconds(200); + nd->speed = 200_ms; nd->scr.script = std::move(script); nd->option = Option::ZERO; nd->opt1 = Opt1::ZERO; nd->opt2 = Opt2::ZERO; nd->opt3 = Opt3::ZERO; - //PRINTF("script npc %s %d %d read done\n",mapname,nd->bl_id,nd->class); npc_script++; nd->bl_type = BL::NPC; nd->npc_subtype = NpcSubtype::SCRIPT; @@ -1361,7 +1376,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, ScriptLabel lname = el.name; int pos = el.pos; - if (lname.startswith("On")) + if (lname.startswith("On"_s)) { struct event_data ev {}; ev.nd = nd; @@ -1380,7 +1395,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, int t_ = 0; ScriptLabel lname = el.name; int pos = el.pos; - if (lname.startswith("OnTimer") && extract(lname.xslice_t(7), &t_) && t_ > 0) + if (lname.startswith("OnTimer"_s) && extract(lname.xslice_t(7), &t_) && t_ > 0) { interval_t t = static_cast<interval_t>(t_); @@ -1440,7 +1455,7 @@ int npc_parse_function(XString, XString, XString w3, ZString, srcbuf += '\n'; } std::unique_ptr<const ScriptBuffer> script = parse_script(AString(srcbuf), startline, false); - if (script == NULL) + if (script == nullptr) { // script parse error? return 1; @@ -1458,7 +1473,8 @@ int npc_parse_function(XString, XString, XString w3, ZString, static int npc_parse_mob(XString w1, XString, MobName w3, ZString w4) { - int x, y, xs, ys, mob_class, num; + int x, y, xs, ys, num; + Species mob_class; int i; MapName mapname; NpcEvent eventname; @@ -1469,7 +1485,7 @@ int npc_parse_mob(XString w1, XString, MobName w3, ZString w4) if (!extract(w1, record<',', 3>(&mapname, &x, &y, &xs, &ys)) || !extract(w4, record<',', 2>(&mob_class, &num, &delay1_, &delay2_, &eventname))) { - PRINTF("bad monster line : %s\n", w3); + PRINTF("bad monster line : %s\n"_fmt, w3); return 1; } interval_t delay1 = std::chrono::milliseconds(delay1_); @@ -1487,15 +1503,15 @@ int npc_parse_mob(XString w1, XString, MobName w3, ZString w4) { md.new_(); - md->bl_prev = NULL; - md->bl_next = NULL; + md->bl_prev = nullptr; + md->bl_next = nullptr; md->bl_m = m; md->bl_x = x; md->bl_y = y; if (w3 == ENGLISH_NAME) - md->name = mob_db[mob_class].name; + md->name = get_mob_db(mob_class).name; else if (w3 == JAPANESE_NAME) - md->name = mob_db[mob_class].jname; + md->name = get_mob_db(mob_class).jname; else md->name = w3; @@ -1512,8 +1528,8 @@ int npc_parse_mob(XString w1, XString, MobName w3, ZString w4) really_memzero_this(&md->state); // md->timer = nullptr; - md->target_id = 0; - md->attacked_id = 0; + md->target_id = BlockId(); + md->attacked_id = BlockId(); md->lootitemv.clear(); @@ -1525,7 +1541,6 @@ int npc_parse_mob(XString w1, XString, MobName w3, ZString w4) npc_mob++; } - //PRINTF("warp npc %s %d read done\n",mapname,nd->bl_id); return 0; } @@ -1561,9 +1576,9 @@ int npc_parse_mapflag(XString w1, XString, XString w3, ZString w4) if (mf == MapFlag::NOSAVE) { - if (w4 == "SavePoint") + if (w4 == "SavePoint"_s) { - m->save.map_ = stringish<MapName>("SavePoint"); + m->save.map_ = stringish<MapName>("SavePoint"_s); m->save.x = -1; m->save.y = -1; } @@ -1589,7 +1604,7 @@ int npc_parse_mapflag(XString w1, XString, XString w3, ZString w4) } dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y, - int npc_class, NpcName name, AString message) + Species npc_class, NpcName name, AString message) { dumb_ptr<npc_data_message> retval; retval.new_(); @@ -1605,7 +1620,7 @@ dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y, retval->message = message; retval->npc_class = npc_class; - retval->speed = std::chrono::milliseconds(200); + retval->speed = 200_ms; clif_spawnnpc(retval); map_addblock(retval); @@ -1679,11 +1694,11 @@ bool do_init_npc(void) io::ReadFile fp(nsl); if (!fp.is_open()) { - PRINTF("file not found : %s\n", nsl); + PRINTF("file not found : %s\n"_fmt, nsl); rv = false; continue; } - PRINTF("\rLoading NPCs [%d]: %-54s", npc_id - START_NPC_NUM, + PRINTF("\rLoading NPCs [%d]: %-54s"_fmt, unwrap<BlockId>(npc_id) - unwrap<BlockId>(START_NPC_NUM), nsl); int lines = 0; AString zline; @@ -1698,7 +1713,7 @@ bool do_init_npc(void) if (!extract(zline, record<'|', 3>(&w1, &w2, &w3, &w4x)) || !w1 || !w2 || !w3) { - FPRINTF(stderr, "%s:%d: Broken script line: %s\n", nsl, lines, zline); + FPRINTF(stderr, "%s:%d: Broken script line: %s\n"_fmt, nsl, lines, zline); rv = false; continue; } @@ -1708,7 +1723,7 @@ bool do_init_npc(void) } assert(bool(w4x) == bool(w4z)); - if (w1 != "-" && w1 != "function") + if (w1 != "-"_s && w1 != "function"_s) { auto comma = std::find(w1.begin(), w1.end(), ','); MapName mapname = stringish<MapName>(w1.xislice_h(comma)); @@ -1716,24 +1731,24 @@ bool do_init_npc(void) if (m == nullptr) { // "mapname" is not assigned to this server - FPRINTF(stderr, "%s:%d: Map not found: %s\n", nsl, lines, mapname); + FPRINTF(stderr, "%s:%d: Map not found: %s\n"_fmt, nsl, lines, mapname); rv = false; continue; } } - if (w2 == "warp") + if (w2 == "warp"_s) { NpcName npcname = stringish<NpcName>(w3); npc_parse_warp(w1, w2, npcname, w4z); } - else if (w2 == "shop") + else if (w2 == "shop"_s) { NpcName npcname = stringish<NpcName>(w3); npc_parse_shop(w1, w2, npcname, w4z); } - else if (w2 == "script") + else if (w2 == "script"_s) { - if (w1 == "function") + if (w1 == "function"_s) { npc_parse_function(w1, w2, w3, w4z, w4x, fp, &lines); @@ -1745,30 +1760,31 @@ bool do_init_npc(void) w4x, fp, &lines); } } - else if (w2 == "monster") + else if (w2 == "monster"_s) { MobName mobname = stringish<MobName>(w3); npc_parse_mob(w1, w2, mobname, w4z); } - else if (w2 == "mapflag") + else if (w2 == "mapflag"_s) { npc_parse_mapflag(w1, w2, w3, w4z); } else { - PRINTF("odd script line: %s\n", zline); + PRINTF("odd script line: %s\n"_fmt, zline); script_errors++; } } fflush(stdout); } - PRINTF("\rNPCs Loaded: %d [Warps:%d Shops:%d Scripts:%d Mobs:%d] %20s\n", - npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, ""); + PRINTF("\rNPCs Loaded: %d [Warps:%d Shops:%d Scripts:%d Mobs:%d] %20s\n"_fmt, + unwrap<BlockId>(npc_id) - unwrap<BlockId>(START_NPC_NUM), npc_warp, npc_shop, npc_script, npc_mob, ""_s); if (script_errors) { - PRINTF("Cowardly refusing to continue after %d errors\n", script_errors); + PRINTF("Cowardly refusing to continue after %d errors\n"_fmt, script_errors); rv = false; } return rv; } +} // namespace tmwa diff --git a/src/map/npc.hpp b/src/map/npc.hpp index eb9a5eb..33dd378 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_NPC_HPP -#define TMWA_MAP_NPC_HPP +#pragma once // npc.hpp - Noncombatants. // // Copyright © ????-2004 Athena Dev Teams @@ -21,47 +20,55 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstddef> -# include <cstdint> +#include <cstdint> -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "../mmo/timer.t.hpp" +#include "../generic/fwd.hpp" -# include "map.hpp" +#include "../net/timer.t.hpp" -constexpr int START_NPC_NUM = 110000000; +#include "../proto2/fwd.hpp" -constexpr int WARP_CLASS = 45; -constexpr int WARP_DEBUG_CLASS = 722; -constexpr int INVISIBLE_CLASS = 32767; +#include "map.hpp" + + +namespace tmwa +{ +constexpr BlockId START_NPC_NUM = wrap<BlockId>(110000000); + +// TODO make these species, see npc_class in npc_data +constexpr Species WARP_CLASS = wrap<Species>(45); +constexpr Species FAKE_NPC_CLASS = wrap<Species>(127); +constexpr Species WARP_DEBUG_CLASS = wrap<Species>(722); +constexpr Species INVISIBLE_CLASS = wrap<Species>(32767); int npc_event_dequeue(dumb_ptr<map_session_data> sd); int npc_event(dumb_ptr<map_session_data> sd, NpcEvent npcname, int); void npc_timer_event(NpcEvent eventname); // Added by RoVeRT int npc_command(dumb_ptr<map_session_data> sd, NpcName npcname, XString command); int npc_touch_areanpc(dumb_ptr<map_session_data>, map_local *, int, int); -int npc_click(dumb_ptr<map_session_data>, int); -int npc_scriptcont(dumb_ptr<map_session_data>, int); -int npc_buysellsel(dumb_ptr<map_session_data>, int, int); -int npc_buylist(dumb_ptr<map_session_data>, int, const uint16_t *); -int npc_selllist(dumb_ptr<map_session_data>, int, const uint16_t *); +int npc_click(dumb_ptr<map_session_data>, BlockId); +int npc_scriptcont(dumb_ptr<map_session_data>, BlockId); +int npc_buysellsel(dumb_ptr<map_session_data>, BlockId, int); +int npc_buylist(dumb_ptr<map_session_data>, const std::vector<Packet_Repeat<0x00c8>>&); +int npc_selllist(dumb_ptr<map_session_data>, const std::vector<Packet_Repeat<0x00c9>>&); int npc_parse_warp(XString w1, XString, NpcName w3, XString w4); int npc_enable(NpcName name, bool flag); dumb_ptr<npc_data> npc_name2id(NpcName name); -int npc_get_new_npc_id(void); +BlockId npc_get_new_npc_id(void); /** * Spawns and installs a talk-only NPC * - * \param message The message to speak. If message is NULL, the NPC will not do anything at all. + * \param message The message to speak. If message is nullptr, the NPC will not do anything at all. */ dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y, - int class_, NpcName name, AString message); + Species class_, NpcName name, AString message); /** * Uninstalls and frees an NPC @@ -73,17 +80,17 @@ void npc_delsrcfile(XString); bool do_init_npc(void); int npc_event_do_oninit(void); -int npc_event_doall_l(ScriptLabel name, int rid, Slice<argrec_t> argv); -int npc_event_do_l(NpcEvent name, int rid, Slice<argrec_t> argv); +int npc_event_doall_l(ScriptLabel name, BlockId rid, Slice<argrec_t> argv); +int npc_event_do_l(NpcEvent name, BlockId rid, Slice<argrec_t> argv); inline int npc_event_doall(ScriptLabel name) { - return npc_event_doall_l(name, 0, nullptr); + return npc_event_doall_l(name, BlockId(), nullptr); } inline int npc_event_do(NpcEvent name) { - return npc_event_do_l(name, 0, nullptr); + return npc_event_do_l(name, BlockId(), nullptr); } void npc_timerevent_start(dumb_ptr<npc_data_script> nd); @@ -91,5 +98,4 @@ void npc_timerevent_stop(dumb_ptr<npc_data_script> nd); interval_t npc_gettimerevent_tick(dumb_ptr<npc_data_script> nd); void npc_settimerevent_tick(dumb_ptr<npc_data_script> nd, interval_t newtimer); int npc_delete(dumb_ptr<npc_data> nd); - -#endif // TMWA_MAP_NPC_HPP +} // namespace tmwa diff --git a/src/map/party.cpp b/src/map/party.cpp index 75c54cf..8713c60 100644 --- a/src/map/party.cpp +++ b/src/map/party.cpp @@ -21,8 +21,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <cstring> - #include "../compat/nullpo.hpp" #include "../strings/xstring.hpp" @@ -31,23 +29,27 @@ #include "../io/cxxstdio.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" +#include "../net/timer.hpp" + +#include "../mmo/ids.hpp" +#include "../mmo/mmo.hpp" #include "battle.hpp" #include "clif.hpp" #include "intif.hpp" #include "map.hpp" #include "pc.hpp" -#include "tmw.hpp" #include "../poison.hpp" + +namespace tmwa +{ // 座標やHP送信の間隔 -constexpr interval_t PARTY_SEND_XYHP_INVERVAL = std::chrono::seconds(1); +constexpr interval_t PARTY_SEND_XYHP_INVERVAL = 1_s; static -Map<int, struct party> party_db; +Map<PartyId, PartyMost> party_db; static void party_check_conflict(dumb_ptr<map_session_data> sd); @@ -64,31 +66,40 @@ void do_init_party(void) } // 検索 -struct party *party_search(int party_id) +PartyPair party_search(PartyId party_id) { - return party_db.search(party_id); + PartyPair p; + p.party_most = party_db.search(party_id); + if (p) + p.party_id = party_id; + return p; } static -void party_searchname_sub(struct party *p, PartyName str, struct party **dst) +void party_searchname_sub(PartyPair p, PartyName str, PartyPair *dst) { if (p->name == str) *dst = p; } // パーティ名検索 -struct party *party_searchname(PartyName str) +PartyPair party_searchname(PartyName str) { - struct party *p = NULL; + PartyPair p; for (auto& pair : party_db) - party_searchname_sub(&pair.second, str, &p); + { + PartyPair tmp; + tmp.party_id = pair.first; + tmp.party_most = &pair.second; + party_searchname_sub(tmp, str, &p); + } return p; } /* Process a party creation request. */ int party_create(dumb_ptr<map_session_data> sd, PartyName name) { - nullpo_ret(sd); + nullpo_retz(sd); name = stringish<PartyName>(name.strip()); @@ -97,7 +108,7 @@ int party_create(dumb_ptr<map_session_data> sd, PartyName name) clif_party_created(sd, 1); /* Make sure the character isn't already in a party. */ - if (sd->status.party_id == 0) + if (!sd->status.party_id) intif_create_party(sd, name); else clif_party_created(sd, 2); @@ -106,10 +117,10 @@ int party_create(dumb_ptr<map_session_data> sd, PartyName name) } /* Relay the result of a party creation request. */ -void party_created(int account_id, int fail, int party_id, PartyName name) +void party_created(AccountId account_id, int fail, PartyId party_id, PartyName name) { dumb_ptr<map_session_data> sd; - sd = map_id2sd(account_id); + sd = map_id2sd(account_to_block(account_id)); nullpo_retv(sd); @@ -118,15 +129,15 @@ void party_created(int account_id, int fail, int party_id, PartyName name) { sd->status.party_id = party_id; - struct party *p = party_db.search(party_id); - if (p != NULL) + PartyPair p = party_search(party_id); + if (p) { - PRINTF("party_created(): ID already exists!\n"); + PRINTF("party_created(): ID already exists!\n"_fmt); exit(1); } - p = party_db.init(party_id); - p->party_id = party_id; + p.party_most = party_db.init(party_id); + p.party_id = party_id; p->name = name; /* The party was created successfully. */ @@ -138,16 +149,16 @@ void party_created(int account_id, int fail, int party_id, PartyName name) } // 情報要求 -void party_request_info(int party_id) +void party_request_info(PartyId party_id) { intif_request_partyinfo(party_id); } // 所属キャラの確認 static -int party_check_member(struct party *p) +int party_check_member(PartyPair p) { - nullpo_ret(p); + nullpo_retz(p); for (io::FD i : iter_fds()) { @@ -157,7 +168,7 @@ int party_check_member(struct party *p) map_session_data *sd = static_cast<map_session_data *>(s->session_data.get()); if (sd && sd->state.auth) { - if (sd->status.party_id == p->party_id) + if (sd->status.party_id == p.party_id) { int j, f = 1; for (j = 0; j < MAX_PARTY; j++) @@ -169,15 +180,15 @@ int party_check_member(struct party *p) else { // I can prove it was already zeroed - // p->member[j].sd = NULL; // 同垢別キャラだった + // p->member[j].sd = nullptr; // 同垢別キャラだった } } } if (f) { - sd->status.party_id = 0; + sd->status.party_id = PartyId(); if (battle_config.error_log) - PRINTF("party: check_member %d[%s] is not member\n", + PRINTF("party: check_member %d[%s] is not member\n"_fmt, sd->status_key.account_id, sd->status_key.name); } } @@ -187,7 +198,7 @@ int party_check_member(struct party *p) } // 情報所得失敗(そのIDのキャラを全部未所属にする) -int party_recv_noinfo(int party_id) +int party_recv_noinfo(PartyId party_id) { for (io::FD i : iter_fds()) { @@ -198,36 +209,36 @@ int party_recv_noinfo(int party_id) if (sd && sd->state.auth) { if (sd->status.party_id == party_id) - sd->status.party_id = 0; + sd->status.party_id = PartyId(); } } return 0; } // 情報所得 -int party_recv_info(const struct party *sp) +int party_recv_info(const PartyPair sp) { int i; - nullpo_ret(sp); + nullpo_retz(sp); - struct party *p = party_db.search(sp->party_id); - if (p == NULL) + PartyPair p = party_search(sp.party_id); + if (!p) { - p = party_db.init(sp->party_id); + p.party_most = party_db.init(sp.party_id); // 最初のロードなのでユーザーのチェックを行う - *p = *sp; + *p.party_most = *sp.party_most; party_check_member(p); } else - *p = *sp; + *p.party_most = *sp.party_most; for (i = 0; i < MAX_PARTY; i++) { // sdの設定 - dumb_ptr<map_session_data> sd = map_id2sd(p->member[i].account_id); - p->member[i].sd = (sd != NULL - && sd->status.party_id == p->party_id) ? sd.operator->() : NULL; + dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(p->member[i].account_id)); + p->member[i].sd = (sd != nullptr + && sd->status.party_id == p.party_id) ? sd.operator->() : nullptr; } clif_party_info(p, nullptr); @@ -236,7 +247,7 @@ int party_recv_info(const struct party *sp) { // 設定情報の送信 // dumb_ptr<map_session_data> sd = map_id2sd(p->member[i].account_id); dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(p->member[i].sd); - if (sd != NULL && sd->party_sended == 0) + if (sd != nullptr && sd->party_sended == 0) { clif_party_option(p, sd, 0x100); sd->party_sended = 1; @@ -247,14 +258,14 @@ int party_recv_info(const struct party *sp) } /* Process party invitation from sd to account_id. */ -int party_invite(dumb_ptr<map_session_data> sd, int account_id) +int party_invite(dumb_ptr<map_session_data> sd, AccountId account_id) { - dumb_ptr<map_session_data> tsd = map_id2sd(account_id); - struct party *p = party_search(sd->status.party_id); + dumb_ptr<map_session_data> tsd = map_id2sd(account_to_block(account_id)); + PartyPair p = party_search(sd->status.party_id); int i; int full = 1; /* Indicates whether or not there's room for one more. */ - nullpo_ret(sd); + nullpo_retz(sd); if (!tsd || !p || !tsd->sess) return 0; @@ -271,7 +282,7 @@ int party_invite(dumb_ptr<map_session_data> sd, int account_id) } /* The target player is already in a party, or has a pending invitation. */ - if (tsd->status.party_id > 0 || tsd->party_invite > 0) + if (tsd->status.party_id || tsd->party_invite) { clif_party_inviteack(sd, tsd->status_key.name, 0); return 0; @@ -311,9 +322,9 @@ int party_invite(dumb_ptr<map_session_data> sd, int account_id) } /* Process response to party invitation. */ -int party_reply_invite(dumb_ptr<map_session_data> sd, int account_id, int flag) +int party_reply_invite(dumb_ptr<map_session_data> sd, AccountId account_id, int flag) { - nullpo_ret(sd); + nullpo_retz(sd); /* There is no pending invitation. */ if (!sd->party_invite || !sd->party_invite_account) @@ -333,48 +344,48 @@ int party_reply_invite(dumb_ptr<map_session_data> sd, int account_id, int flag) else { /* This is the player who sent the invitation. */ - dumb_ptr<map_session_data> tsd = NULL; + dumb_ptr<map_session_data> tsd = nullptr; - sd->party_invite = 0; - sd->party_invite_account = 0; + sd->party_invite = PartyId(); + sd->party_invite_account = AccountId(); - if ((tsd = map_id2sd(account_id))) + if ((tsd = map_id2sd(account_to_block(account_id)))) clif_party_inviteack(tsd, sd->status_key.name, 1); } return 0; } // パーティが追加された -int party_member_added(int party_id, int account_id, int flag) +int party_member_added(PartyId party_id, AccountId account_id, int flag) { - dumb_ptr<map_session_data> sd = map_id2sd(account_id), sd2; - struct party *p = party_search(party_id); + dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(account_id)), sd2; + PartyPair p = party_search(party_id); - if (sd == NULL) + if (sd == nullptr) { if (flag == 0) { if (battle_config.error_log) - PRINTF("party: member added error %d is not online\n", + PRINTF("party: member added error %d is not online\n"_fmt, account_id); intif_party_leave(party_id, account_id); // キャラ側に登録できなかったため脱退要求を出す } return 0; } - sd2 = map_id2sd(sd->party_invite_account); - sd->party_invite = 0; - sd->party_invite_account = 0; + sd2 = map_id2sd(account_to_block(sd->party_invite_account)); + sd->party_invite = PartyId(); + sd->party_invite_account = AccountId(); - if (p == NULL) + if (!p) { - PRINTF("party_member_added: party %d not found.\n", party_id); + PRINTF("party_member_added: party %d not found.\n"_fmt, party_id); intif_party_leave(party_id, account_id); return 0; } if (flag == 1) { // 失敗 - if (sd2 != NULL) + if (sd2 != nullptr) clif_party_inviteack(sd2, sd->status_key.name, 0); return 0; } @@ -383,7 +394,7 @@ int party_member_added(int party_id, int account_id, int flag) sd->party_sended = 0; sd->status.party_id = party_id; - if (sd2 != NULL) + if (sd2 != nullptr) clif_party_inviteack(sd2, sd->status_key.name, 2); // いちおう競合確認 @@ -395,28 +406,30 @@ int party_member_added(int party_id, int account_id, int flag) } // パーティ除名要求 -int party_removemember(dumb_ptr<map_session_data> sd, int account_id) +int party_removemember(dumb_ptr<map_session_data> sd, AccountId account_id) { - struct party *p; + PartyPair p; int i; - nullpo_ret(sd); + nullpo_retz(sd); - if ((p = party_search(sd->status.party_id)) == NULL) + if (!(p = party_search(sd->status.party_id))) return 0; for (i = 0; i < MAX_PARTY; i++) { // リーダーかどうかチェック if (p->member[i].account_id == sd->status_key.account_id) + { if (p->member[i].leader == 0) return 0; + } } for (i = 0; i < MAX_PARTY; i++) { // 所属しているか調べる if (p->member[i].account_id == account_id) { - intif_party_leave(p->party_id, account_id); + intif_party_leave(p.party_id, account_id); return 0; } } @@ -426,19 +439,19 @@ int party_removemember(dumb_ptr<map_session_data> sd, int account_id) // パーティ脱退要求 int party_leave(dumb_ptr<map_session_data> sd) { - struct party *p; + PartyPair p; int i; - nullpo_ret(sd); + nullpo_retz(sd); - if ((p = party_search(sd->status.party_id)) == NULL) + if (!(p = party_search(sd->status.party_id))) return 0; for (i = 0; i < MAX_PARTY; i++) { // 所属しているか if (p->member[i].account_id == sd->status_key.account_id) { - intif_party_leave(p->party_id, sd->status_key.account_id); + intif_party_leave(p.party_id, sd->status_key.account_id); return 0; } } @@ -446,45 +459,45 @@ int party_leave(dumb_ptr<map_session_data> sd) } // パーティメンバが脱退した -int party_member_leaved(int party_id, int account_id, CharName name) +int party_member_leaved(PartyId party_id, AccountId account_id, CharName name) { - dumb_ptr<map_session_data> sd = map_id2sd(account_id); - struct party *p = party_search(party_id); - if (p != NULL) + dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(account_id)); + PartyPair p = party_search(party_id); + if (p) { int i; for (i = 0; i < MAX_PARTY; i++) if (p->member[i].account_id == account_id) { clif_party_leaved(p, sd, account_id, name, 0x00); - p->member[i].account_id = 0; - p->member[i].sd = NULL; + p->member[i].account_id = AccountId(); + p->member[i].sd = nullptr; } } - if (sd != NULL && sd->status.party_id == party_id) + if (sd != nullptr && sd->status.party_id == party_id) { - sd->status.party_id = 0; + sd->status.party_id = PartyId(); sd->party_sended = 0; } return 0; } // パーティ解散通知 -int party_broken(int party_id) +int party_broken(PartyId party_id) { - struct party *p; + PartyPair p; int i; - if ((p = party_search(party_id)) == NULL) + if (!(p = party_search(party_id))) return 0; for (i = 0; i < MAX_PARTY; i++) { - if (p->member[i].sd != NULL) + if (p->member[i].sd != nullptr) { clif_party_leaved(p, dumb_ptr<map_session_data>(p->member[i].sd), p->member[i].account_id, p->member[i].name, 0x10); - p->member[i].sd->status.party_id = 0; + p->member[i].sd->status.party_id = PartyId(); p->member[i].sd->party_sended = 0; } } @@ -495,12 +508,12 @@ int party_broken(int party_id) // パーティの設定変更要求 int party_changeoption(dumb_ptr<map_session_data> sd, int exp, int item) { - struct party *p; + PartyPair p; - nullpo_ret(sd); + nullpo_retz(sd); - if (sd->status.party_id == 0 - || (p = party_search(sd->status.party_id)) == NULL) + if (!sd->status.party_id + || !(p = party_search(sd->status.party_id))) return 0; intif_party_changeoption(sd->status.party_id, sd->status_key.account_id, exp, item); @@ -508,12 +521,12 @@ int party_changeoption(dumb_ptr<map_session_data> sd, int exp, int item) } // パーティの設定変更通知 -int party_optionchanged(int party_id, int account_id, int exp, int item, +int party_optionchanged(PartyId party_id, AccountId account_id, int exp, int item, int flag) { - struct party *p; - dumb_ptr<map_session_data> sd = map_id2sd(account_id); - if ((p = party_search(party_id)) == NULL) + PartyPair p; + dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(account_id)); + if (!(p = party_search(party_id))) return 0; if (!(flag & 0x01)) @@ -525,19 +538,19 @@ int party_optionchanged(int party_id, int account_id, int exp, int item, } // パーティメンバの移動通知 -void party_recv_movemap(int party_id, int account_id, MapName mapname, +void party_recv_movemap(PartyId party_id, AccountId account_id, MapName mapname, int online, int lv) { - struct party *p; + PartyPair p; int i; - if ((p = party_search(party_id)) == NULL) + if (!(p = party_search(party_id))) return; for (i = 0; i < MAX_PARTY; i++) { - struct party_member *m = &p->member[i]; - if (m == NULL) + PartyMember *m = &p->member[i]; + if (m == nullptr) { - PRINTF("party_recv_movemap nullpo?\n"); + PRINTF("party_recv_movemap nullpo?\n"_fmt); return; } if (m->account_id == account_id) @@ -551,16 +564,16 @@ void party_recv_movemap(int party_id, int account_id, MapName mapname, if (i == MAX_PARTY) { if (battle_config.error_log) - PRINTF("party: not found member %d on %d[%s]", account_id, + PRINTF("party: not found member %d on %d[%s]"_fmt, account_id, party_id, p->name); return; } for (i = 0; i < MAX_PARTY; i++) { // sd再設定 - dumb_ptr<map_session_data> sd = map_id2sd(p->member[i].account_id); - p->member[i].sd = (sd != NULL - && sd->status.party_id == p->party_id) ? sd.operator->() : NULL; + dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(p->member[i].account_id)); + p->member[i].sd = (sd != nullptr + && sd->status.party_id == p.party_id) ? sd.operator->() : nullptr; } party_send_xy_clear(p); // 座標再通知要請 @@ -571,11 +584,11 @@ void party_recv_movemap(int party_id, int account_id, MapName mapname, // パーティメンバの移動 int party_send_movemap(dumb_ptr<map_session_data> sd) { - struct party *p; + PartyPair p; - nullpo_ret(sd); + nullpo_retz(sd); - if (sd->status.party_id == 0) + if (!sd->status.party_id) return 0; intif_party_changemap(sd, 1); @@ -586,10 +599,10 @@ int party_send_movemap(dumb_ptr<map_session_data> sd) party_check_conflict(sd); // あるならパーティ情報送信 - if ((p = party_search(sd->status.party_id)) != NULL) + if ((p = party_search(sd->status.party_id))) { party_check_member(p); // 所属を確認する - if (sd->status.party_id == p->party_id) + if (sd->status.party_id == p.party_id) { clif_party_info(p, sd->sess); clif_party_option(p, sd, 0x100); @@ -603,20 +616,20 @@ int party_send_movemap(dumb_ptr<map_session_data> sd) // パーティメンバのログアウト int party_send_logout(dumb_ptr<map_session_data> sd) { - struct party *p; + PartyPair p; - nullpo_ret(sd); + nullpo_retz(sd); - if (sd->status.party_id > 0) + if (sd->status.party_id) intif_party_changemap(sd, 0); // sdが無効になるのでパーティ情報から削除 - if ((p = party_search(sd->status.party_id)) != NULL) + if ((p = party_search(sd->status.party_id))) { int i; for (i = 0; i < MAX_PARTY; i++) if (dumb_ptr<map_session_data>(p->member[i].sd) == sd) - p->member[i].sd = NULL; + p->member[i].sd = nullptr; } return 0; @@ -625,16 +638,16 @@ int party_send_logout(dumb_ptr<map_session_data> sd) // パーティメッセージ送信 void party_send_message(dumb_ptr<map_session_data> sd, XString mes) { - if (sd->status.party_id == 0) + if (!sd->status.party_id) return; intif_party_message(sd->status.party_id, sd->status_key.account_id, mes); } // パーティメッセージ受信 -void party_recv_message(int party_id, int account_id, XString mes) +void party_recv_message(PartyId party_id, AccountId account_id, XString mes) { - struct party *p; - if ((p = party_search(party_id)) == NULL) + PartyPair p; + if (!(p = party_search(party_id))) return; clif_party_message(p, account_id, mes); } @@ -650,7 +663,7 @@ void party_check_conflict(dumb_ptr<map_session_data> sd) // 位置やHP通知用 static -void party_send_xyhp_timer_sub(struct party *p) +void party_send_xyhp_timer_sub(PartyPair p) { int i; @@ -659,7 +672,7 @@ void party_send_xyhp_timer_sub(struct party *p) for (i = 0; i < MAX_PARTY; i++) { dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(p->member[i].sd); - if (sd != NULL) + if (sd != nullptr) { // 座標通知 if (sd->party_x != sd->bl_x || sd->party_y != sd->bl_y) @@ -683,11 +696,16 @@ void party_send_xyhp_timer_sub(struct party *p) void party_send_xyhp_timer(TimerData *, tick_t) { for (auto& pair : party_db) - party_send_xyhp_timer_sub(&pair.second); + { + PartyPair tmp; + tmp.party_id = pair.first; + tmp.party_most = &pair.second; + party_send_xyhp_timer_sub(tmp); + } } // 位置通知クリア -void party_send_xy_clear(struct party *p) +void party_send_xy_clear(PartyPair p) { int i; @@ -696,7 +714,7 @@ void party_send_xy_clear(struct party *p) for (i = 0; i < MAX_PARTY; i++) { dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(p->member[i].sd); - if (sd != NULL) + if (sd != nullptr) { sd->party_x = -1; sd->party_y = -1; @@ -706,7 +724,7 @@ void party_send_xy_clear(struct party *p) } // HP通知の必要性検査用(map_foreachinmoveareaから呼ばれる) -void party_send_hp_check(dumb_ptr<block_list> bl, int party_id, int *flag) +void party_send_hp_check(dumb_ptr<block_list> bl, PartyId party_id, int *flag) { dumb_ptr<map_session_data> sd; @@ -721,17 +739,17 @@ void party_send_hp_check(dumb_ptr<block_list> bl, int party_id, int *flag) } // 経験値公平分配 -int party_exp_share(struct party *p, map_local *mapid, int base_exp, int job_exp) +int party_exp_share(PartyPair p, map_local *mapid, int base_exp, int job_exp) { dumb_ptr<map_session_data> sd; int i, c; - nullpo_ret(p); + nullpo_retz(p); for (i = c = 0; i < MAX_PARTY; i++) { sd = dumb_ptr<map_session_data>(p->member[i].sd); - if (sd != NULL && sd->bl_m == mapid) + if (sd != nullptr && sd->bl_m == mapid) c++; } if (c == 0) @@ -739,7 +757,7 @@ int party_exp_share(struct party *p, map_local *mapid, int base_exp, int job_exp for (i = 0; i < MAX_PARTY; i++) { sd = dumb_ptr<map_session_data>(p->member[i].sd); - if (sd != NULL && sd->bl_m == mapid) + if (sd != nullptr && sd->bl_m == mapid) pc_gainexp_reason(sd, base_exp / c + 1, job_exp / c + 1, PC_GAINEXP_REASON::SHARING); } @@ -752,7 +770,7 @@ int party_exp_share(struct party *p, map_local *mapid, int base_exp, int job_exp void party_foreachsamemap(std::function<void(dumb_ptr<block_list>)> func, dumb_ptr<map_session_data> sd, int type) { - struct party *p; + PartyPair p; int i; int x0, y0, x1, y1; dumb_ptr<map_session_data> list[MAX_PARTY]; @@ -760,7 +778,7 @@ void party_foreachsamemap(std::function<void(dumb_ptr<block_list>)> func, nullpo_retv(sd); - if ((p = party_search(sd->status.party_id)) == NULL) + if (!(p = party_search(sd->status.party_id))) return; x0 = sd->bl_x - AREA_SIZE; @@ -770,8 +788,8 @@ void party_foreachsamemap(std::function<void(dumb_ptr<block_list>)> func, for (i = 0; i < MAX_PARTY; i++) { - struct party_member *m = &p->member[i]; - if (m->sd != NULL) + PartyMember *m = &p->member[i]; + if (m->sd != nullptr) { if (sd->bl_m != m->sd->bl_m) continue; @@ -789,3 +807,4 @@ void party_foreachsamemap(std::function<void(dumb_ptr<block_list>)> func, if (list[i]->bl_prev) // 有効かどうかチェック func(list[i]); } +} // namespace tmwa diff --git a/src/map/party.hpp b/src/map/party.hpp index 007de6b..01a8125 100644 --- a/src/map/party.hpp +++ b/src/map/party.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_PARTY_HPP -#define TMWA_MAP_PARTY_HPP +#pragma once // party.hpp - Small groups of temporary allies. // // Copyright © ????-2004 Athena Dev Teams @@ -21,38 +20,39 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <functional> +#include <functional> -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "map.hpp" +#include "../generic/fwd.hpp" -struct party; -struct map_session_data; -struct block_list; +#include "../mmo/fwd.hpp" + +namespace tmwa +{ void do_init_party(void); -struct party *party_search(int party_id); -struct party *party_searchname(PartyName str); +PartyPair party_search(PartyId party_id); +PartyPair party_searchname(PartyName str); int party_create(dumb_ptr<map_session_data> sd, PartyName name); -void party_created(int account_id, int fail, int party_id, PartyName name); -void party_request_info(int party_id); -int party_invite(dumb_ptr<map_session_data> sd, int account_id); -int party_member_added(int party_id, int account_id, int flag); +void party_created(AccountId account_id, int fail, PartyId party_id, PartyName name); +void party_request_info(PartyId party_id); +int party_invite(dumb_ptr<map_session_data> sd, AccountId account_id); +int party_member_added(PartyId party_id, AccountId account_id, int flag); int party_leave(dumb_ptr<map_session_data> sd); -int party_removemember(dumb_ptr<map_session_data> sd, int account_id); -int party_member_leaved(int party_id, int account_id, CharName name); -int party_reply_invite(dumb_ptr<map_session_data> sd, int account_id, +int party_removemember(dumb_ptr<map_session_data> sd, AccountId account_id); +int party_member_leaved(PartyId party_id, AccountId account_id, CharName name); +int party_reply_invite(dumb_ptr<map_session_data> sd, AccountId account_id, int flag); -int party_recv_noinfo(int party_id); -int party_recv_info(const struct party *sp); -void party_recv_movemap(int party_id, int account_id, MapName map, +int party_recv_noinfo(PartyId party_id); +int party_recv_info(const PartyPair sp); +void party_recv_movemap(PartyId party_id, AccountId account_id, MapName map, int online, int lv); -int party_broken(int party_id); -int party_optionchanged(int party_id, int account_id, int exp, int item, +int party_broken(PartyId party_id); +int party_optionchanged(PartyId party_id, AccountId account_id, int exp, int item, int flag); int party_changeoption(dumb_ptr<map_session_data> sd, int exp, int item); @@ -60,14 +60,13 @@ int party_send_movemap(dumb_ptr<map_session_data> sd); int party_send_logout(dumb_ptr<map_session_data> sd); void party_send_message(dumb_ptr<map_session_data> sd, XString mes); -void party_recv_message(int party_id, int account_id, XString mes); +void party_recv_message(PartyId party_id, AccountId account_id, XString mes); -void party_send_xy_clear(struct party *p); -void party_send_hp_check(dumb_ptr<block_list> bl, int party_id, int *flag); +void party_send_xy_clear(PartyPair p); +void party_send_hp_check(dumb_ptr<block_list> bl, PartyId party_id, int *flag); -int party_exp_share(struct party *p, map_local *map, int base_exp, int job_exp); +int party_exp_share(PartyPair p, map_local *map, int base_exp, int job_exp); void party_foreachsamemap(std::function<void(dumb_ptr<block_list>)> func, dumb_ptr<map_session_data> sd, int type); - -#endif // TMWA_MAP_PARTY_HPP +} // namespace tmwa diff --git a/src/map/path.cpp b/src/map/path.cpp index f0204a4..6950797 100644 --- a/src/map/path.cpp +++ b/src/map/path.cpp @@ -22,19 +22,23 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include <cassert> +#include <cstddef> +#include <cstdlib> #include "../compat/nullpo.hpp" -#include "../generic/random.hpp" +#include "../strings/literal.hpp" #include "../io/cxxstdio.hpp" -#include "battle.hpp" +#include "clif.t.hpp" +#include "map.hpp" #include "../poison.hpp" -//#define PATH_STANDALONETEST +namespace tmwa +{ constexpr int MAX_HEAP = 150; struct tmp_path { @@ -58,9 +62,9 @@ void push_heap_path(int *heap, struct tmp_path *tp, int index) { int i, h; - if (heap == NULL || tp == NULL) + if (heap == nullptr || tp == nullptr) { - PRINTF("push_heap_path nullpo\n"); + PRINTF("push_heap_path nullpo\n"_fmt); return; } @@ -90,7 +94,7 @@ void update_heap_path(int *heap, struct tmp_path *tp, int index) break; if (h == heap[0]) { - FPRINTF(stderr, "update_heap_path bug\n"); + FPRINTF(stderr, "update_heap_path bug\n"_fmt); exit(1); } for (i = (h - 1) / 2; @@ -144,7 +148,7 @@ int calc_cost(struct tmp_path *p, int x1, int y1) { int xd, yd; - nullpo_ret(p); + nullpo_retz(p); xd = x1 - p->x; if (xd < 0) @@ -165,8 +169,8 @@ int add_path(int *heap, struct tmp_path *tp, int x, int y, int dist, { int i; - nullpo_ret(heap); - nullpo_ret(tp); + nullpo_retz(heap); + nullpo_retz(tp); i = calc_index(x, y); @@ -210,7 +214,7 @@ int add_path(int *heap, struct tmp_path *tp, int x, int y, int dist, static bool can_place(struct map_local *m, int x, int y) { - nullpo_ret(m); + nullpo_retz(m); return !bool(read_gatp(m, x, y) & MapCell::UNWALKABLE); } @@ -222,7 +226,7 @@ bool can_place(struct map_local *m, int x, int y) static int can_move(struct map_local *m, int x0, int y0, int x1, int y1) { - nullpo_ret(m); + nullpo_retz(m); if (x0 - x1 < -1 || x0 - x1 > 1 || y0 - y1 < -1 || y0 - y1 > 1) return 0; @@ -249,7 +253,7 @@ int path_search(struct walkpath_data *wpd, map_local *m, int x0, int y0, int x1, int i, rp, x, y; int dx, dy; - nullpo_ret(wpd); + nullpo_retz(wpd); assert (m->gat); map_local *md = m; @@ -357,3 +361,4 @@ int path_search(struct walkpath_data *wpd, map_local *m, int x0, int y0, int x1, return -1; } } +} // namespace tmwa diff --git a/src/map/path.hpp b/src/map/path.hpp index 47b9814..3619e2e 100644 --- a/src/map/path.hpp +++ b/src/map/path.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_PATH_HPP -#define TMWA_MAP_PATH_HPP +#pragma once // path.hpp - Pathfinding system. // // Copyright © ????-2004 Athena Dev Teams @@ -21,10 +20,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "map.hpp" +namespace tmwa +{ int path_search(struct walkpath_data *, map_local *, int, int, int, int, int); - -#endif // TMWA_MAP_PATH_HPP +} // namespace tmwa diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 0256eff..03e2e76 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -23,24 +23,27 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include <cassert> -#include <cstdlib> -#include <cstring> -#include "../compat/alg.hpp" +#include <algorithm> + #include "../compat/fun.hpp" #include "../compat/nullpo.hpp" #include "../strings/rstring.hpp" #include "../strings/astring.hpp" #include "../strings/zstring.hpp" +#include "../strings/literal.hpp" #include "../generic/random.hpp" #include "../io/cxxstdio.hpp" #include "../io/read.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" +#include "../net/timer.hpp" + +#include "../mmo/utils.hpp" + +#include "../proto2/char-map.hpp" #include "atcommand.hpp" #include "battle.hpp" @@ -48,9 +51,8 @@ #include "clif.hpp" #include "intif.hpp" #include "itemdb.hpp" -#include "magic.hpp" +#include "magic-stmt.hpp" #include "map.hpp" -#include "mob.hpp" #include "npc.hpp" #include "party.hpp" #include "path.hpp" @@ -61,9 +63,12 @@ #include "../poison.hpp" + +namespace tmwa +{ // PVP順位計算の間隔 constexpr std::chrono::milliseconds PVP_CALCRANK_INTERVAL = - std::chrono::seconds(1); + 1_s; //define it here, since the ifdef only occurs in this file #define USE_ASTRAL_SOUL_SKILL @@ -86,7 +91,7 @@ constexpr int MAGIC_SKILL_THRESHOLD = 200; MAP_LOG_PC(sd, "XP %d %d JOB %d %d %d ZENY %d + %d " suffix, \ sd->status.base_level, sd->status.base_exp, \ sd->status.job_level, sd->status.job_exp, sd->status.skill_point, \ - sd->status.zeny, pc_readaccountreg(sd, stringish<VarName>("BankAccount"))) + sd->status.zeny, pc_readaccountreg(sd, stringish<VarName>("BankAccount"_s))) #define MAP_LOG_MAGIC(sd, suffix) \ MAP_LOG_PC(sd, "MAGIC %d %d %d %d %d %d EXP %d %d " suffix, \ @@ -96,8 +101,8 @@ constexpr int MAGIC_SKILL_THRESHOLD = 200; sd->status.skill[SkillID::TMW_MAGIC_TRANSMUTE].lv, \ sd->status.skill[SkillID::TMW_MAGIC_NATURE].lv, \ sd->status.skill[SkillID::TMW_MAGIC_ETHER].lv, \ - pc_readglobalreg(sd, stringish<VarName>("MAGIC_EXPERIENCE")) & 0xffff, \ - (pc_readglobalreg(sd, stringish<VarName>("MAGIC_EXPERIENCE")) >> 24) & 0xff) + pc_readglobalreg(sd, stringish<VarName>("MAGIC_EXPERIENCE"_s)) & 0xffff, \ + (pc_readglobalreg(sd, stringish<VarName>("MAGIC_EXPERIENCE"_s)) >> 24) & 0xff) static //const int max_weight_base_0 = 20000; @@ -116,23 +121,23 @@ int sp_coefficient_0 = 100; static //const earray<interval_t, ItemLook, ItemLook::SINGLE_HANDED_COUNT> aspd_base_0 //= {{ -std::chrono::milliseconds(650), -std::chrono::milliseconds(700), -std::chrono::milliseconds(750), -std::chrono::milliseconds(600), -std::chrono::milliseconds(2000), -std::chrono::milliseconds(2000), -std::chrono::milliseconds(800), -std::chrono::milliseconds(2000), -std::chrono::milliseconds(700), -std::chrono::milliseconds(700), -std::chrono::milliseconds(650), -std::chrono::milliseconds(900), -std::chrono::milliseconds(2000), -std::chrono::milliseconds(2000), -std::chrono::milliseconds(2000), -std::chrono::milliseconds(2000), -std::chrono::milliseconds(2000), +650_ms, +700_ms, +750_ms, +600_ms, +2000_ms, +2000_ms, +800_ms, +2000_ms, +700_ms, +700_ms, +650_ms, +900_ms, +2000_ms, +2000_ms, +2000_ms, +2000_ms, +2000_ms, }}; static const int exp_table_0[MAX_LEVEL] = @@ -248,8 +253,9 @@ earray<EPOS, EQUIP, EQUIP::COUNT> equip_pos //= EPOS::ARROW, }}; +// TODO use DMap<> static -std::map<int, uint8_t> gm_accountm; +std::map<AccountId, GmLevel> gm_accountm; static int pc_checkoverhp(dumb_ptr<map_session_data> sd); @@ -265,20 +271,20 @@ void pc_setdead(dumb_ptr<map_session_data> sd) sd->state.dead_sit = 1; } -uint8_t pc_isGM(dumb_ptr<map_session_data> sd) +GmLevel pc_isGM(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retr(GmLevel(), sd); auto it = gm_accountm.find(sd->status_key.account_id); if (it != gm_accountm.end()) return it->second; - return 0; + return GmLevel(); } int pc_iskiller(dumb_ptr<map_session_data> src, dumb_ptr<map_session_data> target) { - nullpo_ret(src); + nullpo_retz(src); if (src->bl_type != BL::PC) return 0; @@ -293,7 +299,7 @@ int pc_iskiller(dumb_ptr<map_session_data> src, return 0; } -void pc_set_gm_level(int account_id, uint8_t level) +void pc_set_gm_level(AccountId account_id, GmLevel level) { if (level) gm_accountm[account_id] = level; @@ -312,17 +318,17 @@ int distance(int x0, int y0, int x1, int y1) } static -void pc_invincible_timer(TimerData *, tick_t, int id) +void pc_invincible_timer(TimerData *, tick_t, BlockId id) { dumb_ptr<map_session_data> sd = map_id2sd(id); - assert (sd != NULL); + assert (sd != nullptr); assert (sd->bl_type == BL::PC); } int pc_setinvincibletimer(dumb_ptr<map_session_data> sd, interval_t val) { - nullpo_ret(sd); + nullpo_retz(sd); sd->invincible_timer = Timer(gettick() + val, std::bind(pc_invincible_timer, ph::_1, ph::_2, @@ -332,7 +338,7 @@ int pc_setinvincibletimer(dumb_ptr<map_session_data> sd, interval_t val) int pc_delinvincibletimer(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); sd->invincible_timer.cancel(); return 0; @@ -340,7 +346,7 @@ int pc_delinvincibletimer(dumb_ptr<map_session_data> sd) int pc_setrestartvalue(dumb_ptr<map_session_data> sd, int type) { - nullpo_ret(sd); + nullpo_retz(sd); { if (battle_config.restart_hp_rate < 50) @@ -380,7 +386,7 @@ int pc_setrestartvalue(dumb_ptr<map_session_data> sd, int type) */ static void pc_counttargeted_sub(dumb_ptr<block_list> bl, - int id, int *c, dumb_ptr<block_list> src, ATK target_lv) + BlockId id, int *c, dumb_ptr<block_list> src, ATK target_lv) { nullpo_retv(bl); @@ -458,7 +464,7 @@ void pc_makesavestatus(dumb_ptr<map_session_data> sd) if (sd->bl_m->flag.get(MapFlag::NOSAVE)) { map_local *m = sd->bl_m; - if (m->save.map_ == "SavePoint") + if (m->save.map_ == "SavePoint"_s) sd->status.last_point = sd->status.save_point; else sd->status.last_point = m->save; @@ -469,16 +475,21 @@ void pc_makesavestatus(dumb_ptr<map_session_data> sd) * 接続時の初期化 *------------------------------------------ */ -int pc_setnewpc(dumb_ptr<map_session_data> sd, int account_id, int char_id, - int login_id1, tick_t client_tick, SEX sex) -{ - nullpo_ret(sd); - - sd->bl_id = account_id; - sd->char_id = char_id; +int pc_setnewpc(dumb_ptr<map_session_data> sd, AccountId account_id, CharId char_id, + int login_id1, uint32_t client_tick, SEX sex) +{ + nullpo_retz(sd); + + // TODO this is the primary surface + sd->bl_id = account_to_block(account_id); + sd->char_id_ = char_id; + // TODO figure out wtf is going on here. + // shouldn't these things be in the .status_key.char_id ? + // My guess is that this stuff happens even for non-auth'ed connections + // Possible fix: char send auth before client is allowed to know my IP? sd->login_id1 = login_id1; sd->login_id2 = 0; // at this point, we can not know the value :( - sd->client_tick = client_tick; + (void)client_tick; sd->sex = sex; sd->state.auth = 0; sd->bl_type = BL::PC; @@ -489,7 +500,7 @@ int pc_setnewpc(dumb_ptr<map_session_data> sd, int account_id, int char_id, return 0; } -EPOS pc_equippoint(dumb_ptr<map_session_data> sd, int n) +EPOS pc_equippoint(dumb_ptr<map_session_data> sd, IOff0 n) { nullpo_retr(EPOS::ZERO, sd); @@ -504,13 +515,11 @@ EPOS pc_equippoint(dumb_ptr<map_session_data> sd, int n) static int pc_setinventorydata(dumb_ptr<map_session_data> sd) { - int i, id; + nullpo_retz(sd); - nullpo_ret(sd); - - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { - id = sd->status.inventory[i].nameid; + ItemNameId id = sd->status.inventory[i].nameid; sd->inventory_data[i] = itemdb_search(id); } return 0; @@ -519,7 +528,7 @@ int pc_setinventorydata(dumb_ptr<map_session_data> sd) static int pc_calcweapontype(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); if (sd->weapontype1 != ItemLook::NONE && sd->weapontype2 == ItemLook::NONE) @@ -562,14 +571,14 @@ int pc_calcweapontype(dumb_ptr<map_session_data> sd) static int pc_setequipindex(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); for (EQUIP i : EQUIPs) - sd->equip_index_maybe[i] = -1; + sd->equip_index_maybe[i] = IOff0::from(-1); - for (int i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { - if (sd->status.inventory[i].nameid <= 0) + if (!sd->status.inventory[i].nameid) continue; if (bool(sd->status.inventory[i].equip)) { @@ -608,22 +617,22 @@ int pc_setequipindex(dumb_ptr<map_session_data> sd) } static -int pc_isequip(dumb_ptr<map_session_data> sd, int n) +int pc_isequip(dumb_ptr<map_session_data> sd, IOff0 n) { struct item_data *item; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; //転生や養子の場合の元の職業を算出する - nullpo_ret(sd); + nullpo_retz(sd); item = sd->inventory_data[n]; sc_data = battle_get_sc_data(sd); - if (battle_config.gm_all_equipment > 0 - && pc_isGM(sd) >= battle_config.gm_all_equipment) + GmLevel gm_all_equipment = GmLevel::from(static_cast<uint32_t>(battle_config.gm_all_equipment)); + if (gm_all_equipment && pc_isGM(sd).satisfies(gm_all_equipment)) return 1; - if (item == NULL) + if (item == nullptr) return 0; if (item->sex != SEX::NEUTRAL && sd->status.sex != item->sex) return 0; @@ -638,16 +647,16 @@ int pc_isequip(dumb_ptr<map_session_data> sd, int n) * char鯖から送られてきたステータスを設定 *------------------------------------------ */ -int pc_authok(int id, int login_id2, TimeT connect_until_time, +int pc_authok(AccountId id, int login_id2, TimeT connect_until_time, short tmw_version, const CharKey *st_key, const CharData *st_data) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; - struct party *p; + PartyPair p; tick_t tick = gettick(); - sd = map_id2sd(id); - if (sd == NULL) + sd = map_id2sd(account_to_block(id)); + if (sd == nullptr) return 1; sd->login_id2 = login_id2; @@ -662,14 +671,14 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time, return 1; } - MAP_LOG_STATS(sd, "LOGIN"); - MAP_LOG_XP(sd, "LOGIN"); - MAP_LOG_MAGIC(sd, "LOGIN"); + MAP_LOG_STATS(sd, "LOGIN"_fmt); + MAP_LOG_XP(sd, "LOGIN"_fmt); + MAP_LOG_MAGIC(sd, "LOGIN"_fmt); really_memzero_this(&sd->state); // 基本的な初期化 sd->state.connect_new = 1; - sd->bl_prev = sd->bl_next = NULL; + sd->bl_prev = sd->bl_next = nullptr; sd->weapontype1 = sd->weapontype2 = ItemLook::NONE; sd->speed = DEFAULT_WALK_SPEED; @@ -682,7 +691,7 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time, // sd->invincible_timer = nullptr; sd->deal_locked = 0; - sd->trade_partner = 0; + sd->trade_partner = AccountId(); sd->inchealhptick = interval_t::zero(); sd->inchealsptick = interval_t::zero(); @@ -702,7 +711,7 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time, // The above is no longer accurate now that we use <chrono>, but // I'm still not reverting this. // -o11c - sd->cast_tick = tick; // + pc_readglobalreg (sd, "MAGIC_CAST_TICK"); + sd->cast_tick = tick; // + pc_readglobalreg (sd, "MAGIC_CAST_TICK"_s); // アカウント変数の送信要求 intif_request_accountreg(sd); @@ -725,17 +734,17 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time, // This would leak information. // It's better to make it obvious that players can see you. if (false && bool(old_option & Option::INVISIBILITY)) - is_atcommand(sd->sess, sd, "@invisible", 0); + is_atcommand(sd->sess, sd, "@invisible"_s, GmLevel()); if (bool(old_option & Option::HIDE)) - is_atcommand(sd->sess, sd, "@hide", 0); + is_atcommand(sd->sess, sd, "@hide"_s, GmLevel()); // atcommand_hide might already send it, but also might not clif_changeoption(sd); } // パーティー関係の初期化 sd->party_sended = 0; - sd->party_invite = 0; + sd->party_invite = PartyId(); sd->party_x = -1; sd->party_y = -1; sd->party_hp = -1; @@ -748,8 +757,8 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time, sd->status.last_point.y, BeingRemoveWhy::GONE); // パーティ、ギルドデータの要求 - if (sd->status.party_id > 0 - && (p = party_search(sd->status.party_id)) == NULL) + if (sd->status.party_id + && !(p = party_search(sd->status.party_id))) party_request_info(sd->status.party_id); // pvpの設定 @@ -765,19 +774,19 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time, map_addchariddb(sd->status_key.char_id, sd->status_key.name); //スパノビ用死にカウンターのスクリプト変数からの読み出しとsdへのセット - sd->die_counter = pc_readglobalreg(sd, stringish<VarName>("PC_DIE_COUNTER")); + sd->die_counter = pc_readglobalreg(sd, stringish<VarName>("PC_DIE_COUNTER"_s)); // ステータス初期計算など pc_calcstatus(sd, 1); if (pc_isGM(sd)) { - PRINTF("Connection accepted: character '%s' (account: %d; GM level %d).\n", - sd->status_key.name, sd->status_key.account_id, pc_isGM(sd)); + PRINTF("Connection accepted: character '%s' (account: %d; GM level %d).\n"_fmt, + sd->status_key.name, sd->status_key.account_id, pc_isGM(sd)); clif_updatestatus(sd, SP::GM); } else - PRINTF("Connection accepted: Character '%s' (account: %d).\n", + PRINTF("Connection accepted: Character '%s' (account: %d).\n"_fmt, sd->status_key.name, sd->status_key.account_id); sd->auto_ban_info.in_progress = 0; @@ -796,11 +805,11 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time, // message of the limited time of the account if (connect_until_time) { - // don't display if it's unlimited or unknow value - char tmpstr[] = WITH_TIMESTAMP("Your account time limit is: "); - REPLACE_TIMESTAMP(tmpstr, connect_until_time); + timestamp_seconds_buffer buffer; + stamp_time(buffer, &connect_until_time); + AString tmpstr = STRPRINTF("Your account time limit is: %s"_fmt, buffer); - clif_wis_message(sd->sess, wisp_server_name, const_(tmpstr)); + clif_wis_message(sd->sess, wisp_server_name, tmpstr); } pc_calcstatus(sd, 1); @@ -817,7 +826,7 @@ void pc_show_motd(dumb_ptr<map_session_data> sd) // If you remove the sending of this message, // the license does not permit you to publicly use this software. - clif_displaymessage(sd->sess, "This server is Free Software, for details type @source in chat or use the tmwa-source tool"); + clif_displaymessage(sd->sess, "This server is Free Software, for details type @source in chat or use the tmwa-source tool"_s); sd->state.seen_motd = true; io::ReadFile in(motd_txt); @@ -835,12 +844,12 @@ void pc_show_motd(dumb_ptr<map_session_data> sd) * session idに問題ありなので後始末 *------------------------------------------ */ -int pc_authfail(int id) +int pc_authfail(AccountId id) { dumb_ptr<map_session_data> sd; - sd = map_id2sd(id); - if (sd == NULL) + sd = map_id2sd(account_to_block(id)); + if (sd == nullptr) return 1; clif_authfail_fd(sd->sess, 0); @@ -853,7 +862,7 @@ int pc_calc_skillpoint(dumb_ptr<map_session_data> sd) { int i, skill_points = 0; - nullpo_ret(sd); + nullpo_retz(sd); for (i = 0; i < skill_pool_skills_size; i++) { int lv = sd->status.skill[skill_pool_skills[i]].lv; @@ -872,7 +881,7 @@ int pc_checkweighticon(dumb_ptr<map_session_data> sd) { int flag = 0; - nullpo_ret(sd); + nullpo_retz(sd); if (sd->weight * 2 >= sd->max_weight && !sd->sc_data[StatusChange::SC_FLYING_BACKPACK].timer) @@ -907,7 +916,7 @@ void pc_set_weapon_look(dumb_ptr<map_session_data> sd) { if (sd->attack_spell_override) clif_changelook(sd, LOOK::WEAPON, - sd->attack_spell_look_override); + unwrap<ItemNameId>(sd->attack_spell_look_override)); else clif_changelook(sd, LOOK::WEAPON, static_cast<uint16_t>(sd->status.weapon)); @@ -931,7 +940,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) int aspd_rate, refinedef = 0; int str, dstr, dex; - nullpo_ret(sd); + nullpo_retz(sd); interval_t b_speed = sd->speed; b_max_hp = sd->status.max_hp; @@ -942,7 +951,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) b_max_weight = sd->max_weight; earray<int, ATTR, ATTR::COUNT> b_paramb = sd->paramb; earray<int, ATTR, ATTR::COUNT> b_parame = sd->paramc; - earray<skill_value, SkillID, MAX_SKILL> b_skill = sd->status.skill; + earray<SkillValue, SkillID, MAX_SKILL> b_skill = sd->status.skill; b_hit = sd->hit; b_flee = sd->flee; interval_t b_aspd = sd->aspd; @@ -964,10 +973,10 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) if (first & 1) { sd->weight = 0; - for (int i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { - if (sd->status.inventory[i].nameid == 0 - || sd->inventory_data[i] == NULL) + if (!sd->status.inventory[i].nameid + || sd->inventory_data[i] == nullptr) continue; sd->weight += sd->inventory_data[i]->weight * @@ -1035,8 +1044,8 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) for (EQUIP i : EQUIPs_noarrow) { - int index = sd->equip_index_maybe[i]; - if (index < 0) + IOff0 index = sd->equip_index_maybe[i]; + if (!index.ok()) continue; if (i == EQUIP::WEAPON && sd->equip_index_maybe[EQUIP::SHIELD] == index) continue; @@ -1060,7 +1069,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) if (sd->spellpower_bonus_target < 0) sd->spellpower_bonus_target = (sd->spellpower_bonus_target * 256) / - (min(128 + skill_power(sd, SkillID::TMW_ASTRAL_SOUL), 256)); + (std::min(128 + skill_power(sd, SkillID::TMW_ASTRAL_SOUL), 256)); #endif if (sd->spellpower_bonus_target < sd->spellpower_bonus_current) @@ -1071,8 +1080,8 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) // 装備品によるステータス変化はここで実行 for (EQUIP i : EQUIPs_noarrow) { - int index = sd->equip_index_maybe[i]; - if (index < 0) + IOff0 index = sd->equip_index_maybe[i]; + if (!index.ok()) continue; if (i == EQUIP::WEAPON && sd->equip_index_maybe[EQUIP::SHIELD] == index) continue; @@ -1099,11 +1108,11 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) { argrec_t arg[2] = { - {"@slotId", static_cast<int>(i)}, - {"@itemId", sd->inventory_data[index]->nameid}, + {"@slotId"_s, static_cast<int>(i)}, + {"@itemId"_s, unwrap<ItemNameId>(sd->inventory_data[index]->nameid)}, }; run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), - sd->bl_id, 0, + sd->bl_id, BlockId(), arg); } sd->state.lr_flag = 0; @@ -1113,14 +1122,14 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) //二刀流武器以外 argrec_t arg[2] = { - {"@slotId", static_cast<int>(i)}, - {"@itemId", sd->inventory_data[index]->nameid}, + {"@slotId"_s, static_cast<int>(i)}, + {"@itemId"_s, unwrap<ItemNameId>(sd->inventory_data[index]->nameid)}, }; sd->watk += sd->inventory_data[index]->atk; sd->attackrange += sd->inventory_data[index]->range; run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), - sd->bl_id, 0, + sd->bl_id, BlockId(), arg); } } @@ -1128,12 +1137,12 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) { argrec_t arg[2] = { - {"@slotId", static_cast<int>(i)}, - {"@itemId", sd->inventory_data[index]->nameid}, + {"@slotId"_s, static_cast<int>(i)}, + {"@itemId"_s, unwrap<ItemNameId>(sd->inventory_data[index]->nameid)}, }; sd->watk += sd->inventory_data[index]->atk; run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), - sd->bl_id, 0, + sd->bl_id, BlockId(), arg); } } @@ -1147,20 +1156,20 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->watk_2 += skill_power(sd, SkillID::TMW_BRAWLING) >> 3; // +25 for 200 } - int aidx = sd->equip_index_maybe[EQUIP::ARROW]; - if (aidx >= 0) - { // 矢 - int index = aidx; + IOff0 aidx = sd->equip_index_maybe[EQUIP::ARROW]; + if (aidx.ok()) + { + IOff0 index = aidx; if (sd->inventory_data[index]) { //まだ属性が入っていない argrec_t arg[2] = { - {"@slotId", static_cast<int>(EQUIP::ARROW)}, - {"@itemId", sd->inventory_data[index]->nameid}, + {"@slotId"_s, static_cast<int>(EQUIP::ARROW)}, + {"@itemId"_s, unwrap<ItemNameId>(sd->inventory_data[index]->nameid)}, }; sd->state.lr_flag = 2; run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), - sd->bl_id, 0, + sd->bl_id, BlockId(), arg); sd->state.lr_flag = 0; sd->arrow_atk += sd->inventory_data[index]->atk; @@ -1189,7 +1198,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->aspd_rate = 20; for (ATTR attr : ATTRs) - sd->paramc[attr] = max(0, sd->status.attrs[attr] + sd->paramb[attr] + sd->parame[attr]); + sd->paramc[attr] = std::max(0, sd->status.attrs[attr] + sd->paramb[attr] + sd->parame[attr]); if (sd->status.weapon == ItemLook::BOW || sd->status.weapon == ItemLook::_13 @@ -1206,7 +1215,6 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) } dstr = str / 10; sd->base_atk += str + dstr * dstr + dex / 5 + sd->paramc[ATTR::LUK] / 5; -//FPRINTF(stderr, "baseatk = %d = x + %d + %d + %d + %d\n", sd->base_atk, str, dstr*dstr, dex/5, sd->paramc[ATTR::LUK]/5); sd->matk1 += sd->paramc[ATTR::INT] + (sd->paramc[ATTR::INT] / 5) * (sd->paramc[ATTR::INT] / 5); sd->matk2 += sd->paramc[ATTR::INT] + (sd->paramc[ATTR::INT] / 7) * (sd->paramc[ATTR::INT] / 7); if (sd->matk1 < sd->matk2) @@ -1304,7 +1312,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) if (sd->attackrange > 2) { // [fate] ranged weapon? - sd->attackrange += min(skill_power(sd, SkillID::AC_OWL) / 60, 3); + sd->attackrange += std::min(skill_power(sd, SkillID::AC_OWL) / 60, 3); sd->hit += skill_power(sd, SkillID::AC_OWL) / 10; // 20 for 200 } @@ -1385,7 +1393,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) if (sd->speed_rate != 100) sd->speed = sd->speed * sd->speed_rate / 100; - sd->speed = std::max(sd->speed, std::chrono::milliseconds(1)); + sd->speed = std::max(sd->speed, 1_ms); if (aspd_rate != 100) sd->aspd = sd->aspd * aspd_rate / 100; @@ -1395,7 +1403,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->aspd = std::max(sd->aspd, static_cast<interval_t>(battle_config.max_aspd)); sd->amotion = sd->aspd; sd->dmotion = std::chrono::milliseconds(800 - sd->paramc[ATTR::AGI] * 4); - sd->dmotion = std::max(sd->dmotion, std::chrono::milliseconds(400)); + sd->dmotion = std::max(sd->dmotion, 400_ms); if (sd->status.hp > sd->status.max_hp) sd->status.hp = sd->status.max_hp; @@ -1479,7 +1487,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) */ int pc_bonus(dumb_ptr<map_session_data> sd, SP type, int val) { - nullpo_ret(sd); + nullpo_retz(sd); switch (type) { @@ -1731,7 +1739,7 @@ int pc_bonus(dumb_ptr<map_session_data> sd, SP type, int val) break; default: if (battle_config.error_log) - PRINTF("pc_bonus: unknown type %d %d !\n", + PRINTF("pc_bonus: unknown type %d %d !\n"_fmt, type, val); break; } @@ -1744,7 +1752,7 @@ int pc_bonus(dumb_ptr<map_session_data> sd, SP type, int val) */ int pc_bonus2(dumb_ptr<map_session_data> sd, SP type, int type2, int val) { - nullpo_ret(sd); + nullpo_retz(sd); switch (type) { @@ -1776,7 +1784,7 @@ int pc_bonus2(dumb_ptr<map_session_data> sd, SP type, int type2, int val) #endif default: if (battle_config.error_log) - PRINTF("pc_bonus2: unknown type %d %d %d!\n", + PRINTF("pc_bonus2: unknown type %d %d %d!\n"_fmt, type, type2, val); break; } @@ -1789,12 +1797,12 @@ int pc_bonus2(dumb_ptr<map_session_data> sd, SP type, int type2, int val) */ int pc_skill(dumb_ptr<map_session_data> sd, SkillID id, int level, int flag) { - nullpo_ret(sd); + nullpo_retz(sd); if (level > MAX_SKILL_LEVEL) { if (battle_config.error_log) - PRINTF("support card skill only!\n"); + PRINTF("support card skill only!\n"_fmt); return 0; } if (!flag && (sd->status.skill[id].lv || level == 0)) @@ -1817,16 +1825,14 @@ int pc_skill(dumb_ptr<map_session_data> sd, SkillID id, int level, int flag) * 3万個制限にかかるか確認 *------------------------------------------ */ -ADDITEM pc_checkadditem(dumb_ptr<map_session_data> sd, int nameid, int amount) +ADDITEM pc_checkadditem(dumb_ptr<map_session_data> sd, ItemNameId nameid, int amount) { - int i; - nullpo_retr(ADDITEM::ZERO, sd); if (itemdb_isequip(nameid)) return ADDITEM::NEW; - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (sd->status.inventory[i].nameid == nameid) { @@ -1847,13 +1853,13 @@ ADDITEM pc_checkadditem(dumb_ptr<map_session_data> sd, int nameid, int amount) */ int pc_inventoryblank(dumb_ptr<map_session_data> sd) { - int i, b; + int b = 0; - nullpo_ret(sd); + nullpo_retz(sd); - for (i = 0, b = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { - if (sd->status.inventory[i].nameid == 0) + if (!sd->status.inventory[i].nameid) b++; } @@ -1866,7 +1872,7 @@ int pc_inventoryblank(dumb_ptr<map_session_data> sd) */ int pc_payzeny(dumb_ptr<map_session_data> sd, int zeny) { - nullpo_ret(sd); + nullpo_retz(sd); double z = sd->status.zeny; if (sd->status.zeny < zeny || z - zeny > MAX_ZENY) @@ -1883,7 +1889,7 @@ int pc_payzeny(dumb_ptr<map_session_data> sd, int zeny) */ int pc_getzeny(dumb_ptr<map_session_data> sd, int zeny) { - nullpo_ret(sd); + nullpo_retz(sd); double z = sd->status.zeny; if (z + zeny > MAX_ZENY) @@ -1901,30 +1907,27 @@ int pc_getzeny(dumb_ptr<map_session_data> sd, int zeny) * アイテムを探して、インデックスを返す *------------------------------------------ */ -int pc_search_inventory(dumb_ptr<map_session_data> sd, int item_id) +IOff0 pc_search_inventory(dumb_ptr<map_session_data> sd, ItemNameId item_id) { - int i; + nullpo_retr(IOff0::from(-1), sd); - nullpo_retr(-1, sd); - - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (sd->status.inventory[i].nameid == item_id && - (sd->status.inventory[i].amount > 0 || item_id == 0)) + (sd->status.inventory[i].amount > 0 || !item_id)) return i; } - return -1; + return IOff0::from(-1); } -int pc_count_all_items(dumb_ptr<map_session_data> player, int item_id) +int pc_count_all_items(dumb_ptr<map_session_data> player, ItemNameId item_id) { - int i; int count = 0; - nullpo_ret(player); + nullpo_retz(player); - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (player->status.inventory[i].nameid == item_id) count += player->status.inventory[i].amount; @@ -1933,14 +1936,14 @@ int pc_count_all_items(dumb_ptr<map_session_data> player, int item_id) return count; } -int pc_remove_items(dumb_ptr<map_session_data> player, int item_id, int count) +int pc_remove_items(dumb_ptr<map_session_data> player, ItemNameId item_id, int count) { - int i; - - nullpo_ret(player); + nullpo_retz(player); - for (i = 0; i < MAX_INVENTORY && count; i++) + for (IOff0 i : IOff0::iter()) { + if (!count) + break; if (player->status.inventory[i].nameid == item_id) { int to_delete = count; @@ -1964,29 +1967,30 @@ int pc_remove_items(dumb_ptr<map_session_data> player, int item_id, int count) * アイテム追加。個数のみitem構造体の数字を無視 *------------------------------------------ */ -PickupFail pc_additem(dumb_ptr<map_session_data> sd, struct item *item_data, +PickupFail pc_additem(dumb_ptr<map_session_data> sd, Item *item_data, int amount) { struct item_data *data; - int i, w; + int w; - MAP_LOG_PC(sd, "PICKUP %d %d", item_data->nameid, amount); + MAP_LOG_PC(sd, "PICKUP %d %d"_fmt, item_data->nameid, amount); nullpo_retr(PickupFail::BAD_ITEM, sd); nullpo_retr(PickupFail::BAD_ITEM, item_data); - if (item_data->nameid <= 0 || amount <= 0) + if (!item_data->nameid || amount <= 0) return PickupFail::BAD_ITEM; data = itemdb_search(item_data->nameid); if ((w = data->weight * amount) + sd->weight > sd->max_weight) return PickupFail::TOO_HEAVY; - i = MAX_INVENTORY; + IOff0 i = IOff0::from(MAX_INVENTORY); if (!itemdb_isequip2(data)) { - // 装 備品ではないので、既所有品なら個数のみ変化させる - for (i = 0; i < MAX_INVENTORY; i++) + // TODO see if there's any nicer way to preserve the foreach var + for (i = IOff0::from(0); i != IOff0::from(MAX_INVENTORY); ++i) + { if (sd->status.inventory[i].nameid == item_data->nameid) { if (sd->status.inventory[i].amount + amount > MAX_AMOUNT) @@ -1995,12 +1999,12 @@ PickupFail pc_additem(dumb_ptr<map_session_data> sd, struct item *item_data, clif_additem(sd, i, amount, PickupFail::OKAY); break; } + } } - if (i >= MAX_INVENTORY) + if (!i.ok()) { - // 装 備品か未所有品だったので空き欄へ追加 - i = pc_search_inventory(sd, 0); - if (i >= 0) + i = pc_search_inventory(sd, ItemNameId()); + if (i.ok()) { sd->status.inventory[i] = *item_data; @@ -2024,16 +2028,16 @@ PickupFail pc_additem(dumb_ptr<map_session_data> sd, struct item *item_data, * アイテムを減らす *------------------------------------------ */ -int pc_delitem(dumb_ptr<map_session_data> sd, int n, int amount, int type) +int pc_delitem(dumb_ptr<map_session_data> sd, IOff0 n, int amount, int type) { nullpo_retr(1, sd); - if (sd->trade_partner != 0) + if (sd->trade_partner) trade_tradecancel(sd); - if (sd->status.inventory[n].nameid == 0 || amount <= 0 + if (!sd->status.inventory[n].nameid || amount <= 0 || sd->status.inventory[n].amount < amount - || sd->inventory_data[n] == NULL) + || sd->inventory_data[n] == nullptr) return 1; sd->status.inventory[n].amount -= amount; @@ -2042,8 +2046,8 @@ int pc_delitem(dumb_ptr<map_session_data> sd, int n, int amount, int type) { if (bool(sd->status.inventory[n].equip)) pc_unequipitem(sd, n, CalcStatus::NOW); - sd->status.inventory[n] = item{}; - sd->inventory_data[n] = NULL; + sd->status.inventory[n] = Item{}; + sd->inventory_data[n] = nullptr; } if (!(type & 1)) clif_delitem(sd, n, amount); @@ -2057,14 +2061,14 @@ int pc_delitem(dumb_ptr<map_session_data> sd, int n, int amount, int type) * アイテムを落す *------------------------------------------ */ -int pc_dropitem(dumb_ptr<map_session_data> sd, int n, int amount) +int pc_dropitem(dumb_ptr<map_session_data> sd, IOff0 n, int amount) { nullpo_retr(1, sd); - if (sd->trade_partner != 0 || sd->npc_id != 0 || sd->state.storage_open) + if (sd->trade_partner || sd->npc_id || sd->state.storage_open) return 0; // no dropping while trading/npc/storage - if (n < 0 || n >= MAX_INVENTORY) + if (!n.ok()) return 0; if (amount <= 0) @@ -2072,13 +2076,13 @@ int pc_dropitem(dumb_ptr<map_session_data> sd, int n, int amount) pc_unequipinvyitem(sd, n, CalcStatus::NOW); - if (sd->status.inventory[n].nameid <= 0 || + if (!sd->status.inventory[n].nameid || sd->status.inventory[n].amount < amount || - sd->trade_partner != 0 || sd->status.inventory[n].amount <= 0) + sd->trade_partner || sd->status.inventory[n].amount <= 0) return 1; map_addflooritem(&sd->status.inventory[n], amount, sd->bl_m, sd->bl_x, sd->bl_y, - NULL, NULL, NULL); + nullptr, nullptr, nullptr); pc_delitem(sd, n, amount, 0); return 0; @@ -2090,9 +2094,9 @@ int pc_dropitem(dumb_ptr<map_session_data> sd, int n, int amount) */ static -int can_pick_item_up_from(dumb_ptr<map_session_data> self, int other_id) +int can_pick_item_up_from(dumb_ptr<map_session_data> self, BlockId other_id) { - struct party *p = party_search(self->status.party_id); + PartyPair p = party_search(self->status.party_id); /* From ourselves or from no-one? */ if (!self || self->bl_id == other_id || !other_id) @@ -2133,19 +2137,19 @@ int pc_takeitem(dumb_ptr<map_session_data> sd, dumb_ptr<flooritem_data> fitem) tick_t tick = gettick(); int can_take; - nullpo_ret(sd); - nullpo_ret(fitem); + nullpo_retz(sd); + nullpo_retz(fitem); /* Sometimes the owners reported to us are buggy: */ if (fitem->first_get_id == fitem->third_get_id || fitem->second_get_id == fitem->third_get_id) - fitem->third_get_id = 0; + fitem->third_get_id = BlockId(); if (fitem->first_get_id == fitem->second_get_id) { fitem->second_get_id = fitem->third_get_id; - fitem->third_get_id = 0; + fitem->third_get_id = BlockId(); } can_take = can_pick_item_up_from(sd, fitem->first_get_id); @@ -2167,7 +2171,7 @@ int pc_takeitem(dumb_ptr<map_session_data> sd, dumb_ptr<flooritem_data> fitem) PickupFail flag = pc_additem(sd, &fitem->item_data, fitem->item_data.amount); if (flag != PickupFail::OKAY) // 重量overで取得失敗 - clif_additem(sd, 0, 0, flag); + clif_additem(sd, IOff0::from(0), 0, flag); else { // 取得成功 @@ -2180,22 +2184,22 @@ int pc_takeitem(dumb_ptr<map_session_data> sd, dumb_ptr<flooritem_data> fitem) } /* Otherwise, we can't pick up */ - clif_additem(sd, 0, 0, PickupFail::DROP_STEAL); + clif_additem(sd, IOff0::from(0), 0, PickupFail::DROP_STEAL); return 0; } static -int pc_isUseitem(dumb_ptr<map_session_data> sd, int n) +int pc_isUseitem(dumb_ptr<map_session_data> sd, IOff0 n) { struct item_data *item; - int nameid; + ItemNameId nameid; - nullpo_ret(sd); + nullpo_retz(sd); item = sd->inventory_data[n]; nameid = sd->status.inventory[n].nameid; - if (item == NULL) + if (item == nullptr) return 0; if (itemdb_type(nameid) != ItemType::USE) return 0; @@ -2212,16 +2216,16 @@ int pc_isUseitem(dumb_ptr<map_session_data> sd, int n) * アイテムを使う *------------------------------------------ */ -int pc_useitem(dumb_ptr<map_session_data> sd, int n) +int pc_useitem(dumb_ptr<map_session_data> sd, IOff0 n) { int amount; nullpo_retr(1, sd); - if (n >= 0 && n < MAX_INVENTORY && sd->inventory_data[n]) + if (n.ok() && sd->inventory_data[n]) { amount = sd->status.inventory[n].amount; - if (sd->status.inventory[n].nameid <= 0 + if (!sd->status.inventory[n].nameid || sd->status.inventory[n].amount <= 0 || !pc_isUseitem(sd, n)) { @@ -2233,7 +2237,7 @@ int pc_useitem(dumb_ptr<map_session_data> sd, int n) clif_useitemack(sd, n, amount - 1, 1); pc_delitem(sd, n, 1, 1); - run_script(ScriptPointer(script, 0), sd->bl_id, 0); + run_script(ScriptPointer(script, 0), sd->bl_id, BlockId()); } return 0; @@ -2251,14 +2255,14 @@ int pc_setpos(dumb_ptr<map_session_data> sd, { MapName mapname_; - nullpo_ret(sd); + nullpo_retz(sd); if (sd->trade_partner) // 取引を中断する trade_tradecancel(sd); if (sd->state.storage_open) storage_storage_quit(sd); // 倉庫を開いてるなら保存する - if (sd->party_invite > 0) // パーティ勧誘を拒否する + if (sd->party_invite) // パーティ勧誘を拒否する party_reply_invite(sd, sd->party_invite_account, 0); skill_castcancel(sd, 0); // 詠唱中断 @@ -2314,7 +2318,7 @@ int pc_setpos(dumb_ptr<map_session_data> sd, if (x || y) { if (battle_config.error_log) - PRINTF("stacked (%d,%d)\n", x, y); + PRINTF("stacked (%d,%d)\n"_fmt, x, y); } do { @@ -2324,7 +2328,7 @@ int pc_setpos(dumb_ptr<map_session_data> sd, while (bool(read_gatp(m, x, y) & MapCell::UNWALKABLE)); } - if (sd->mapname_ && sd->bl_prev != NULL) + if (sd->mapname_ && sd->bl_prev != nullptr) { clif_clearchar(sd, clrtype); map_delblock(sd); @@ -2355,7 +2359,7 @@ int pc_randomwarp(dumb_ptr<map_session_data> sd, BeingRemoveWhy type) { int x, y, i = 0; - nullpo_ret(sd); + nullpo_retz(sd); map_local *m = sd->bl_m; @@ -2385,7 +2389,7 @@ int pc_can_reach(dumb_ptr<map_session_data> sd, int x, int y) { struct walkpath_data wpd; - nullpo_ret(sd); + nullpo_retz(sd); if (sd->bl_x == x && sd->bl_y == y) // 同じマス return 1; @@ -2422,14 +2426,14 @@ interval_t calc_next_walk_step(dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void pc_walk(TimerData *, tick_t tick, int id, unsigned char data) +void pc_walk(TimerData *, tick_t tick, BlockId id, unsigned char data) { dumb_ptr<map_session_data> sd; int moveblock; int x, y, dx, dy; sd = map_id2sd(id); - if (sd == NULL) + if (sd == nullptr) return; if (sd->walkpath.path_pos >= sd->walkpath.path_len @@ -2497,10 +2501,10 @@ void pc_walk(TimerData *, tick_t tick, int id, unsigned char data) BL::NUL); // sd->walktimer = nullptr; - if (sd->status.party_id > 0) + if (sd->status.party_id) { // パーティのHP情報通知検査 - struct party *p = party_search(sd->status.party_id); - if (p != NULL) + PartyPair p = party_search(sd->status.party_id); + if (p) { int p_flag = 0; map_foreachinmovearea(std::bind(party_send_hp_check, ph::_1, sd->status.party_id, &p_flag), @@ -2517,14 +2521,14 @@ void pc_walk(TimerData *, tick_t tick, int id, unsigned char data) if (bool(map_getcell(sd->bl_m, x, y) & MapCell::NPC_NEAR)) npc_touch_areanpc(sd, sd->bl_m, x, y); else - sd->areanpc_id = 0; + sd->areanpc_id = BlockId(); } interval_t i = calc_next_walk_step(sd); if (i > interval_t::zero()) { i = i / 2; if (sd->walkpath.path_half == 0) - i = std::max(i, std::chrono::milliseconds(1)); + i = std::max(i, 1_ms); sd->walktimer = Timer(tick + i, std::bind(pc_walk, ph::_1, ph::_2, @@ -2570,7 +2574,7 @@ int pc_walktoxy_sub(dumb_ptr<map_session_data> sd) int pc_walktoxy(dumb_ptr<map_session_data> sd, int x, int y) { - nullpo_ret(sd); + nullpo_retz(sd); sd->to_x = x; sd->to_y = y; @@ -2598,7 +2602,7 @@ int pc_walktoxy(dumb_ptr<map_session_data> sd, int x, int y) */ int pc_stop_walking(dumb_ptr<map_session_data> sd, int type) { - nullpo_ret(sd); + nullpo_retz(sd); sd->walktimer.cancel(); @@ -2623,7 +2627,7 @@ void pc_touch_all_relevant_npcs(dumb_ptr<map_session_data> sd) if (bool(map_getcell(sd->bl_m, sd->bl_x, sd->bl_y) & MapCell::NPC_NEAR)) npc_touch_areanpc(sd, sd->bl_m, sd->bl_x, sd->bl_y); else - sd->areanpc_id = 0; + sd->areanpc_id = BlockId(); } /*========================================== @@ -2637,7 +2641,7 @@ int pc_movepos(dumb_ptr<map_session_data> sd, int dst_x, int dst_y) struct walkpath_data wpd; - nullpo_ret(sd); + nullpo_retz(sd); if (path_search(&wpd, sd->bl_m, sd->bl_x, sd->bl_y, dst_x, dst_y, 0)) return 1; @@ -2671,10 +2675,10 @@ int pc_movepos(dumb_ptr<map_session_data> sd, int dst_x, int dst_y) -dx, -dy, BL::NUL); - if (sd->status.party_id > 0) + if (sd->status.party_id) { // パーティのHP情報通知検査 - struct party *p = party_search(sd->status.party_id); - if (p != NULL) + PartyPair p = party_search(sd->status.party_id); + if (p) { int flag = 0; map_foreachinmovearea(std::bind(party_send_hp_check, ph::_1, sd->status.party_id, &flag), @@ -2701,7 +2705,7 @@ int pc_movepos(dumb_ptr<map_session_data> sd, int dst_x, int dst_y) */ int pc_checkskill(dumb_ptr<map_session_data> sd, SkillID skill_id) { - if (sd == NULL) + if (sd == nullptr) return 0; return sd->status.skill[skill_id].lv; @@ -2711,9 +2715,9 @@ int pc_checkskill(dumb_ptr<map_session_data> sd, SkillID skill_id) * 装 備品のチェック *------------------------------------------ */ -int pc_checkequip(dumb_ptr<map_session_data> sd, EPOS pos) +IOff0 pc_checkequip(dumb_ptr<map_session_data> sd, EPOS pos) { - nullpo_retr(-1, sd); + nullpo_retr(IOff0::from(-1), sd); for (EQUIP i : EQUIPs) { @@ -2721,7 +2725,7 @@ int pc_checkequip(dumb_ptr<map_session_data> sd, EPOS pos) return sd->equip_index_maybe[i]; } - return -1; + return IOff0::from(-1); } /*========================================== @@ -2729,7 +2733,7 @@ int pc_checkequip(dumb_ptr<map_session_data> sd, EPOS pos) *------------------------------------------ */ static -void pc_attack_timer(TimerData *, tick_t tick, int id) +void pc_attack_timer(TimerData *, tick_t tick, BlockId id) { dumb_ptr<map_session_data> sd; dumb_ptr<block_list> bl; @@ -2737,14 +2741,14 @@ void pc_attack_timer(TimerData *, tick_t tick, int id) int dist, range; sd = map_id2sd(id); - if (sd == NULL) + if (sd == nullptr) return; - if (sd->bl_prev == NULL) + if (sd->bl_prev == nullptr) return; bl = map_id2bl(sd->attacktarget); - if (bl == NULL || bl->bl_prev == NULL) + if (bl == nullptr || bl->bl_prev == nullptr) return; if (bl->bl_type == BL::PC && pc_isdead(bl->is_player())) @@ -2760,7 +2764,7 @@ void pc_attack_timer(TimerData *, tick_t tick, int id) return; Option *opt = battle_get_option(bl); - if (opt != NULL && bool(*opt & Option::REAL_ANY_HIDE)) + if (opt != nullptr && bool(*opt & Option::REAL_ANY_HIDE)) return; if (!battle_config.skill_delay_attack_enable) @@ -2836,19 +2840,19 @@ void pc_attack_timer(TimerData *, tick_t tick, int id) * typeが1なら継続攻撃 *------------------------------------------ */ -int pc_attack(dumb_ptr<map_session_data> sd, int target_id, int type) +int pc_attack(dumb_ptr<map_session_data> sd, BlockId target_id, int type) { dumb_ptr<block_list> bl; - nullpo_ret(sd); + nullpo_retz(sd); bl = map_id2bl(target_id); - if (bl == NULL) + if (bl == nullptr) return 1; if (bl->bl_type == BL::NPC) { // monster npcs [Valaris] - npc_click(sd, RFIFOL(sd->sess, 2)); + npc_click(sd, target_id); return 0; } @@ -2860,7 +2864,7 @@ int pc_attack(dumb_ptr<map_session_data> sd, int target_id, int type) sd->state.attack_continue = type; interval_t d = sd->attackabletime - gettick(); - if (d > interval_t::zero() && d < std::chrono::seconds(2)) + if (d > interval_t::zero() && d < 2_s) { // 攻撃delay中 sd->attacktimer = Timer(sd->attackabletime, std::bind(pc_attack_timer, ph::_1, ph::_2, @@ -2881,11 +2885,11 @@ int pc_attack(dumb_ptr<map_session_data> sd, int target_id, int type) */ int pc_stopattack(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); sd->attacktimer.cancel(); - sd->attacktarget = 0; + sd->attacktarget = BlockId(); sd->state.attack_continue = 0; return 0; @@ -2896,7 +2900,7 @@ int pc_checkbaselevelup(dumb_ptr<map_session_data> sd) { int next = pc_nextbaseexp(sd); - nullpo_ret(sd); + nullpo_retz(sd); if (sd->status.base_exp >= next && next > 0) { @@ -2915,7 +2919,7 @@ int pc_checkbaselevelup(dumb_ptr<map_session_data> sd) //レベルアップしたのでパーティー情報を更新する //(公平範囲チェック) party_send_movemap(sd); - MAP_LOG_XP(sd, "LEVELUP"); + MAP_LOG_XP(sd, "LEVELUP"_fmt); return 1; } @@ -2937,8 +2941,7 @@ int pc_skillpt_potential(dumb_ptr<map_session_data> sd) { int potential = 0; - for (SkillID skill_id = SkillID(); skill_id < MAX_SKILL; - skill_id = SkillID(uint16_t(skill_id) + 1)) + for (SkillID skill_id : erange(SkillID(), MAX_SKILL)) if (sd->status.skill[skill_id].lv && sd->status.skill[skill_id].lv < skill_db[skill_id].max_raise) potential += RAISE_COST(skill_db[skill_id].max_raise) @@ -2952,7 +2955,7 @@ int pc_checkjoblevelup(dumb_ptr<map_session_data> sd) { int next = pc_nextjobexp(sd); - nullpo_ret(sd); + nullpo_retz(sd); if (sd->status.job_exp >= next && next > 0) { @@ -2971,7 +2974,7 @@ int pc_checkjoblevelup(dumb_ptr<map_session_data> sd) clif_updatestatus(sd, SP::SKILLPOINT); pc_calcstatus(sd, 0); - MAP_LOG_PC(sd, "SKILLPOINTS-UP %d", sd->status.skill_point); + MAP_LOG_PC(sd, "SKILLPOINTS-UP %d"_fmt, sd->status.skill_point); if (sd->status.job_level < 250 && sd->status.job_level < sd->status.base_level * 2) @@ -2987,21 +2990,21 @@ int pc_checkjoblevelup(dumb_ptr<map_session_data> sd) int pc_gainexp_reason(dumb_ptr<map_session_data> sd, int base_exp, int job_exp, PC_GAINEXP_REASON reason) { - nullpo_ret(sd); + nullpo_retz(sd); - if (sd->bl_prev == NULL || pc_isdead(sd)) + if (sd->bl_prev == nullptr || pc_isdead(sd)) return 0; - earray<const char *, PC_GAINEXP_REASON, PC_GAINEXP_REASON::COUNT> reasons //= + earray<LString, PC_GAINEXP_REASON, PC_GAINEXP_REASON::COUNT> reasons //= {{ - "KILLXP", - "HEALXP", - "SCRIPTXP", - "SHAREXP", + "KILLXP"_s, + "HEALXP"_s, + "SCRIPTXP"_s, + "SHAREXP"_s, /* Insert new types here */ - "UNKNOWNXP" + "UNKNOWNXP"_s }}; - MAP_LOG_PC(sd, "GAINXP %d %d %s", base_exp, job_exp, reasons[reason]); + MAP_LOG_PC(sd, "GAINXP %d %d %s"_fmt, base_exp, job_exp, reasons[reason]); if (!battle_config.multi_level_up && pc_nextbaseafter(sd)) { @@ -3029,7 +3032,8 @@ int pc_gainexp_reason(dumb_ptr<map_session_data> sd, int base_exp, int job_exp, if (sd->status.base_exp < 0) sd->status.base_exp = 0; - while (pc_checkbaselevelup(sd)); + while (pc_checkbaselevelup(sd)) + {} clif_updatestatus(sd, SP::BASEEXP); if (!battle_config.multi_level_up && pc_nextjobafter(sd)) @@ -3046,14 +3050,15 @@ int pc_gainexp_reason(dumb_ptr<map_session_data> sd, int base_exp, int job_exp, if (sd->status.job_exp < 0) sd->status.job_exp = 0; - while (pc_checkjoblevelup(sd)); + while (pc_checkjoblevelup(sd)) + {} clif_updatestatus(sd, SP::JOBEXP); if (battle_config.disp_experience) { AString output = STRPRINTF( - "Experienced Gained Base:%d Job:%d", + "Experienced Gained Base:%d Job:%d"_fmt, base_exp, job_exp); clif_displaymessage(sd->sess, output); } @@ -3064,7 +3069,7 @@ int pc_gainexp_reason(dumb_ptr<map_session_data> sd, int base_exp, int job_exp, int pc_extract_healer_exp(dumb_ptr<map_session_data> sd, int max) { int amount; - nullpo_ret(sd); + nullpo_retz(sd); amount = sd->heal_xp; if (max < amount) @@ -3080,7 +3085,7 @@ int pc_extract_healer_exp(dumb_ptr<map_session_data> sd, int max) */ int pc_nextbaseexp(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); if (sd->status.base_level >= MAX_LEVEL || sd->status.base_level <= 0) return 0; @@ -3108,7 +3113,7 @@ int pc_nextjobexp(dumb_ptr<map_session_data> sd) */ int pc_nextbaseafter(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); if (sd->status.base_level >= MAX_LEVEL || sd->status.base_level <= 0) return 0; @@ -3122,7 +3127,7 @@ int pc_nextbaseafter(dumb_ptr<map_session_data> sd) */ int pc_nextjobafter(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); if (sd->status.job_level >= MAX_LEVEL || sd->status.job_level <= 0) return 0; @@ -3156,7 +3161,7 @@ int pc_statusup(dumb_ptr<map_session_data> sd, SP type) { int need, val = 0; - nullpo_ret(sd); + nullpo_retz(sd); if (SP::STR <= type && type <= SP::LUK) val = sd->status.attrs[sp_to_attr(type)]; @@ -3181,7 +3186,7 @@ int pc_statusup(dumb_ptr<map_session_data> sd, SP type) pc_calcstatus(sd, 0); clif_statusupack(sd, type, 1, val); - MAP_LOG_STATS(sd, "STATUP"); + MAP_LOG_STATS(sd, "STATUP"_fmt); return 0; } @@ -3192,7 +3197,7 @@ int pc_statusup(dumb_ptr<map_session_data> sd, SP type) */ int pc_statusup2(dumb_ptr<map_session_data> sd, SP type, int val) { - nullpo_ret(sd); + nullpo_retz(sd); if (type < SP::STR || type > SP::LUK) { @@ -3208,7 +3213,7 @@ int pc_statusup2(dumb_ptr<map_session_data> sd, SP type, int val) clif_updatestatus(sd, type); pc_calcstatus(sd, 0); clif_statusupack(sd, type, 1, val); - MAP_LOG_STATS(sd, "STATUP2"); + MAP_LOG_STATS(sd, "STATUP2"_fmt); return 0; } @@ -3219,7 +3224,7 @@ int pc_statusup2(dumb_ptr<map_session_data> sd, SP type, int val) */ int pc_skillup(dumb_ptr<map_session_data> sd, SkillID skill_num) { - nullpo_ret(sd); + nullpo_retz(sd); if (sd->status.skill[skill_num].lv && sd->status.skill_point >= sd->status.skill[skill_num].lv @@ -3232,7 +3237,7 @@ int pc_skillup(dumb_ptr<map_session_data> sd, SkillID skill_num) clif_skillup(sd, skill_num); clif_updatestatus(sd, SP::SKILLPOINT); clif_skillinfoblock(sd); - MAP_LOG_PC(sd, "SKILLUP %d %d %d", + MAP_LOG_PC(sd, "SKILLUP %d %d %d"_fmt, skill_num, sd->status.skill[skill_num].lv, skill_power(sd, skill_num)); } @@ -3246,7 +3251,7 @@ int pc_skillup(dumb_ptr<map_session_data> sd, SkillID skill_num) */ int pc_resetlvl(dumb_ptr<map_session_data> sd, int type) { - nullpo_ret(sd); + nullpo_retz(sd); for (SkillID i : erange(SkillID(1), MAX_SKILL)) { @@ -3309,13 +3314,13 @@ int pc_resetlvl(dumb_ptr<map_session_data> sd, int type) for (EQUIP i : EQUIPs) { // unequip items that can't be equipped by base 1 [Valaris] - short *idx = &sd->equip_index_maybe[i]; - if (*idx >= 0) + IOff0 *idx = &sd->equip_index_maybe[i]; + if ((*idx).ok()) { if (!pc_isequip(sd, *idx)) { pc_unequipitem(sd, *idx, CalcStatus::LATER); - *idx = -1; + *idx = IOff0::from(-1); } } } @@ -3323,7 +3328,7 @@ int pc_resetlvl(dumb_ptr<map_session_data> sd, int type) clif_skillinfoblock(sd); pc_calcstatus(sd, 0); - MAP_LOG_STATS(sd, "STATRESET"); + MAP_LOG_STATS(sd, "STATRESET"_fmt); return 0; } @@ -3335,7 +3340,7 @@ int pc_resetlvl(dumb_ptr<map_session_data> sd, int type) int pc_resetstate(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); sd->status.status_point = stat_p[sd->status.base_level - 1]; @@ -3361,7 +3366,7 @@ int pc_resetskill(dumb_ptr<map_session_data> sd) { int skill; - nullpo_ret(sd); + nullpo_retz(sd); sd->status.skill_point += pc_calc_skillpoint(sd); @@ -3386,7 +3391,7 @@ int pc_resetskill(dumb_ptr<map_session_data> sd) int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, int damage) { - nullpo_ret(sd); + nullpo_retz(sd); // 既に死んでいたら無効 if (pc_isdead(sd)) @@ -3401,17 +3406,17 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, { if (src->bl_type == BL::PC) { - MAP_LOG_PC(sd, "INJURED-BY PC%d FOR %d", - src->is_player()->status_key.char_id, - damage); + MAP_LOG_PC(sd, "INJURED-BY PC%d FOR %d"_fmt, + src->is_player()->status_key.char_id, + damage); } else { - MAP_LOG_PC(sd, "INJURED-BY MOB%d FOR %d", src->bl_id, damage); + MAP_LOG_PC(sd, "INJURED-BY MOB%d FOR %d"_fmt, src->bl_id, damage); } } else - MAP_LOG_PC(sd, "INJURED-BY null FOR %d", damage); + MAP_LOG_PC(sd, "INJURED-BY null FOR %d"_fmt, damage); pc_stop_walking(sd, 3); // 演奏/ダンスの中断 @@ -3427,17 +3432,17 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, sd->canlog_tick = gettick(); - if (sd->status.party_id > 0) + if (sd->status.party_id) { // on-the-fly party hp updates [Valaris] - struct party *p = party_search(sd->status.party_id); - if (p != NULL) + PartyPair p = party_search(sd->status.party_id); + if (p) clif_party_hp(p, sd); } // end addition [Valaris] return 0; } - MAP_LOG_PC(sd, "DEAD%s", ""); + MAP_LOG_PC(sd, "DEAD%s"_fmt, ""_s); // Character is dead! @@ -3452,7 +3457,7 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, pc_stop_walking(sd, 0); skill_castcancel(sd, 0); // 詠唱の中止 clif_clearchar(sd, BeingRemoveWhy::DEAD); - pc_setglobalreg(sd, stringish<VarName>("PC_DIE_COUNTER"), ++sd->die_counter); //死にカウンター書き込み + pc_setglobalreg(sd, stringish<VarName>("PC_DIE_COUNTER"_s), ++sd->die_counter); //死にカウンター書き込み skill_status_change_clear(sd, 0); // ステータス異常を解除する clif_updatestatus(sd, SP::HP); pc_calcstatus(sd, 0); @@ -3544,14 +3549,14 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, // [Fate] PK death, trigger scripts argrec_t arg[3] = { - {"@killerrid", src->bl_id}, - {"@victimrid", sd->bl_id}, - {"@victimlvl", sd->status.base_level}, + {"@killerrid"_s, static_cast<int32_t>(unwrap<BlockId>(src->bl_id))}, + {"@victimrid"_s, static_cast<int32_t>(unwrap<BlockId>(sd->bl_id))}, + {"@victimlvl"_s, sd->status.base_level}, }; - npc_event_doall_l(stringish<ScriptLabel>("OnPCKilledEvent"), sd->bl_id, arg); - npc_event_doall_l(stringish<ScriptLabel>("OnPCKillEvent"), src->bl_id, arg); + npc_event_doall_l(stringish<ScriptLabel>("OnPCKilledEvent"_s), sd->bl_id, arg); + npc_event_doall_l(stringish<ScriptLabel>("OnPCKillEvent"_s), src->bl_id, arg); } - npc_event_doall_l(stringish<ScriptLabel>("OnPCDieEvent"), sd->bl_id, nullptr); + npc_event_doall_l(stringish<ScriptLabel>("OnPCDieEvent"_s), sd->bl_id, nullptr); return 0; } @@ -3567,7 +3572,7 @@ int pc_readparam(dumb_ptr<map_session_data> sd, SP type) { int val = 0; - nullpo_ret(sd); + nullpo_retz(sd); switch (type) { @@ -3587,7 +3592,7 @@ int pc_readparam(dumb_ptr<map_session_data> sd, SP type) val = sd->status.job_level; break; case SP::CLASS: - val = sd->status.species; + val = unwrap<Species>(sd->status.species); break; case SP::SEX: val = static_cast<uint8_t>(sd->sex); @@ -3643,7 +3648,7 @@ int pc_setparam(dumb_ptr<map_session_data> sd, SP type, int val) { int i = 0, up_level = 50; - nullpo_ret(sd); + nullpo_retz(sd); switch (type) { @@ -3691,7 +3696,7 @@ int pc_setparam(dumb_ptr<map_session_data> sd, SP type, int val) clif_updatestatus(sd, type); break; case SP::CLASS: - sd->status.species = val; + sd->status.species = wrap<Species>(val); break; case SP::SKILLPOINT: sd->status.skill_point = val; @@ -3762,10 +3767,7 @@ int pc_setparam(dumb_ptr<map_session_data> sd, SP type, int val) */ int pc_heal(dumb_ptr<map_session_data> sd, int hp, int sp) { -// if(battle_config.battle_log) -// PRINTF("heal %d %d\n",hp,sp); - - nullpo_ret(sd); + nullpo_retz(sd); if (pc_checkoverhp(sd)) { @@ -3786,7 +3788,7 @@ int pc_heal(dumb_ptr<map_session_data> sd, int hp, int sp) if (sd->status.hp <= 0) { sd->status.hp = 0; - pc_damage(NULL, sd, 1); + pc_damage(nullptr, sd, 1); hp = 0; } sd->status.sp += sp; @@ -3797,10 +3799,10 @@ int pc_heal(dumb_ptr<map_session_data> sd, int hp, int sp) if (sp) clif_updatestatus(sd, SP::SP); - if (sd->status.party_id > 0) + if (sd->status.party_id) { // on-the-fly party hp updates [Valaris] - struct party *p = party_search(sd->status.party_id); - if (p != NULL) + PartyPair p = party_search(sd->status.party_id); + if (p) clif_party_hp(p, sd); } // end addition [Valaris] @@ -3847,9 +3849,9 @@ void pc_heal_quick_accumulate(int new_amount, int average_speed = ((new_speed * new_amount) + (current_speed * current_amount)) / (current_amount + new_amount); // new_amount > 0, current_amount >= 0 quick_regen->speed = average_speed; - quick_regen->amount = min(current_amount + new_amount, max); + quick_regen->amount = std::min(current_amount + new_amount, max); - quick_regen->tickdelay = min(quick_regen->speed, quick_regen->tickdelay); + quick_regen->tickdelay = std::min(quick_regen->speed, quick_regen->tickdelay); } int pc_itemheal(dumb_ptr<map_session_data> sd, int hp, int sp) @@ -3884,7 +3886,7 @@ int pc_itemheal(dumb_ptr<map_session_data> sd, int hp, int sp) static int pc_itemheal_effect(dumb_ptr<map_session_data> sd, int hp, int sp) { - nullpo_ret(sd); + nullpo_retz(sd); if (pc_checkoverhp(sd)) { @@ -3914,7 +3916,7 @@ int pc_itemheal_effect(dumb_ptr<map_session_data> sd, int hp, int sp) if (sd->status.hp <= 0) { sd->status.hp = 0; - pc_damage(NULL, sd, 1); + pc_damage(nullptr, sd, 1); hp = 0; } sd->status.sp += sp; @@ -3934,7 +3936,7 @@ int pc_itemheal_effect(dumb_ptr<map_session_data> sd, int hp, int sp) */ int pc_percentheal(dumb_ptr<map_session_data> sd, int hp, int sp) { - nullpo_ret(sd); + nullpo_retz(sd); if (pc_checkoverhp(sd)) { @@ -3955,7 +3957,7 @@ int pc_percentheal(dumb_ptr<map_session_data> sd, int hp, int sp) else if (hp <= -100) { sd->status.hp = 0; - pc_damage(NULL, sd, 1); + pc_damage(nullptr, sd, 1); } else { @@ -3965,7 +3967,7 @@ int pc_percentheal(dumb_ptr<map_session_data> sd, int hp, int sp) if (sd->status.hp <= 0) { sd->status.hp = 0; - pc_damage(NULL, sd, 1); + pc_damage(nullptr, sd, 1); hp = 0; } } @@ -4003,7 +4005,7 @@ int pc_percentheal(dumb_ptr<map_session_data> sd, int hp, int sp) */ int pc_changelook(dumb_ptr<map_session_data> sd, LOOK type, int val) { - nullpo_ret(sd); + nullpo_retz(sd); switch (type) { @@ -4014,13 +4016,13 @@ int pc_changelook(dumb_ptr<map_session_data> sd, LOOK type, int val) sd->status.weapon = static_cast<ItemLook>(static_cast<uint16_t>(val)); break; case LOOK::HEAD_BOTTOM: - sd->status.head_bottom = val; + sd->status.head_bottom = wrap<ItemNameId>(val); break; case LOOK::HEAD_TOP: - sd->status.head_top = val; + sd->status.head_top = wrap<ItemNameId>(val); break; case LOOK::HEAD_MID: - sd->status.head_mid = val; + sd->status.head_mid = wrap<ItemNameId>(val); break; case LOOK::HAIR_COLOR: sd->status.hair_color = val; @@ -4029,7 +4031,7 @@ int pc_changelook(dumb_ptr<map_session_data> sd, LOOK type, int val) sd->status.clothes_color = val; break; case LOOK::SHIELD: - sd->status.shield = val; + sd->status.shield = wrap<ItemNameId>(val); break; case LOOK::SHOES: break; @@ -4045,7 +4047,7 @@ int pc_changelook(dumb_ptr<map_session_data> sd, LOOK type, int val) */ int pc_setoption(dumb_ptr<map_session_data> sd, Option type) { - nullpo_ret(sd); + nullpo_retz(sd); sd->status.option = type; clif_changeoption(sd); @@ -4060,7 +4062,7 @@ int pc_setoption(dumb_ptr<map_session_data> sd, Option type) */ int pc_readreg(dumb_ptr<map_session_data> sd, SIR reg) { - nullpo_ret(sd); + nullpo_retz(sd); return sd->regm.get(reg); } @@ -4116,7 +4118,7 @@ int pc_readglobalreg(dumb_ptr<map_session_data> sd, VarName reg) { int i; - nullpo_ret(sd); + nullpo_retz(sd); assert (sd->status.global_reg_num < GLOBAL_REG_NUM); for (i = 0; i < sd->status.global_reg_num; i++) @@ -4136,10 +4138,10 @@ int pc_setglobalreg(dumb_ptr<map_session_data> sd, VarName reg, int val) { int i; - nullpo_ret(sd); + nullpo_retz(sd); //PC_DIE_COUNTERがスクリプトなどで変更された時の処理 - if (reg == stringish<VarName>("PC_DIE_COUNTER") && sd->die_counter != val) + if (reg == stringish<VarName>("PC_DIE_COUNTER"_s) && sd->die_counter != val) { sd->die_counter = val; pc_calcstatus(sd, 0); @@ -4175,7 +4177,7 @@ int pc_setglobalreg(dumb_ptr<map_session_data> sd, VarName reg, int val) return 0; } if (battle_config.error_log) - PRINTF("pc_setglobalreg : couldn't set %s (GLOBAL_REG_NUM = %d)\n", + PRINTF("pc_setglobalreg : couldn't set %s (GLOBAL_REG_NUM = %d)\n"_fmt, reg, GLOBAL_REG_NUM); return 1; @@ -4189,7 +4191,7 @@ int pc_readaccountreg(dumb_ptr<map_session_data> sd, VarName reg) { int i; - nullpo_ret(sd); + nullpo_retz(sd); assert (sd->status.account_reg_num < ACCOUNT_REG_NUM); for (i = 0; i < sd->status.account_reg_num; i++) @@ -4209,7 +4211,7 @@ int pc_setaccountreg(dumb_ptr<map_session_data> sd, VarName reg, int val) { int i; - nullpo_ret(sd); + nullpo_retz(sd); if (val == 0) { @@ -4244,7 +4246,7 @@ int pc_setaccountreg(dumb_ptr<map_session_data> sd, VarName reg, int val) return 0; } if (battle_config.error_log) - PRINTF("pc_setaccountreg : couldn't set %s (ACCOUNT_REG_NUM = %d)\n", + PRINTF("pc_setaccountreg : couldn't set %s (ACCOUNT_REG_NUM = %zu)\n"_fmt, reg, ACCOUNT_REG_NUM); return 1; @@ -4258,7 +4260,7 @@ int pc_readaccountreg2(dumb_ptr<map_session_data> sd, VarName reg) { int i; - nullpo_ret(sd); + nullpo_retz(sd); for (i = 0; i < sd->status.account_reg2_num; i++) { @@ -4312,8 +4314,8 @@ int pc_setaccountreg2(dumb_ptr<map_session_data> sd, VarName reg, int val) return 0; } if (battle_config.error_log) - PRINTF("pc_setaccountreg2 : couldn't set %s (ACCOUNT_REG2_NUM = %d)\n", - reg, ACCOUNT_REG2_NUM); + PRINTF("pc_setaccountreg2 : couldn't set %s (ACCOUNT_REG2_NUM = %zu)\n"_fmt, + reg, ACCOUNT_REG2_NUM); return 1; } @@ -4323,10 +4325,10 @@ int pc_setaccountreg2(dumb_ptr<map_session_data> sd, VarName reg, int val) *------------------------------------------ */ static -void pc_eventtimer(TimerData *, tick_t, int id, NpcEvent data) +void pc_eventtimer(TimerData *, tick_t, BlockId id, NpcEvent data) { dumb_ptr<map_session_data> sd = map_id2sd(id); - assert (sd != NULL); + assert (sd != nullptr); npc_event(sd, data, 0); } @@ -4339,7 +4341,7 @@ int pc_addeventtimer(dumb_ptr<map_session_data> sd, interval_t tick, NpcEvent na { int i; - nullpo_ret(sd); + nullpo_retz(sd); for (i = 0; i < MAX_EVENTTIMER; i++) if (!sd->eventtimer[i]) @@ -4362,7 +4364,7 @@ int pc_addeventtimer(dumb_ptr<map_session_data> sd, interval_t tick, NpcEvent na */ int pc_cleareventtimer(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); for (int i = 0; i < MAX_EVENTTIMER; i++) sd->eventtimer[i].cancel(); @@ -4378,7 +4380,7 @@ int pc_cleareventtimer(dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -int pc_signal_advanced_equipment_change(dumb_ptr<map_session_data> sd, int n) +int pc_signal_advanced_equipment_change(dumb_ptr<map_session_data> sd, IOff0 n) { if (bool(sd->status.inventory[n].equip & EPOS::SHOES)) clif_changelook(sd, LOOK::SHOES, 0); @@ -4393,17 +4395,17 @@ int pc_signal_advanced_equipment_change(dumb_ptr<map_session_data> sd, int n) return 0; } -int pc_equipitem(dumb_ptr<map_session_data> sd, int n, EPOS) +int pc_equipitem(dumb_ptr<map_session_data> sd, IOff0 n, EPOS) { - int nameid; + ItemNameId nameid; struct item_data *id; //ソス]ソスソスソスソスソス{ソスqソスフ場合ソスフ鯉ソスソスフ職ソスニゑソスソスZソスoソスソスソスソス - nullpo_ret(sd); + nullpo_retz(sd); - if (n < 0 || n >= MAX_INVENTORY) + if (!n.ok()) { - clif_equipitemack(sd, 0, EPOS::ZERO, 0); + clif_equipitemack(sd, IOff0::from(0), EPOS::ZERO, 0); return 0; } @@ -4414,7 +4416,7 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, int n, EPOS) EPOS pos = pc_equippoint(sd, n); if (battle_config.battle_log) - PRINTF("equip %d (%d) %x:%x\n", + PRINTF("equip %d (%d) %x:%x\n"_fmt, nameid, n, id->equip, pos); if (!pc_isequip(sd, n) || pos == EPOS::ZERO) { @@ -4428,11 +4430,11 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, int n, EPOS) { // アクセサリ用例外処理 EPOS epor = EPOS::ZERO; - int midx = sd->equip_index_maybe[EQUIP::MISC2]; - int cidx = sd->equip_index_maybe[EQUIP::CAPE]; - if (midx >= 0) + IOff0 midx = sd->equip_index_maybe[EQUIP::MISC2]; + IOff0 cidx = sd->equip_index_maybe[EQUIP::CAPE]; + if (midx.ok()) epor |= sd->status.inventory[midx].equip; - if (cidx >= 0) + if (cidx.ok()) epor |= sd->status.inventory[cidx].equip; epor &= (EPOS::MISC2 | EPOS::CAPE); pos = (epor == EPOS::CAPE ? EPOS::MISC2 : EPOS::CAPE); @@ -4442,8 +4444,8 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, int n, EPOS) { if (bool(pos & equip_pos[i])) { - short *idx = &sd->equip_index_maybe[i]; - if (*idx >= 0) //Slot taken, remove item from there. + IOff0 *idx = &sd->equip_index_maybe[i]; + if ((*idx).ok()) //Slot taken, remove item from there. pc_unequipitem(sd, *idx, CalcStatus::LATER); *idx = n; } @@ -4468,7 +4470,7 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, int n, EPOS) } sd->status.inventory[n].equip = pos; - int view_i = 0; + ItemNameId view_i; ItemLook view_l = ItemLook::NONE; // TODO: This is ugly. if (sd->inventory_data[n]) @@ -4495,7 +4497,7 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, int n, EPOS) { if (sd->inventory_data[n]->type == ItemType::WEAPON) { - sd->status.shield = 0; + sd->status.shield = ItemNameId(); if (sd->status.inventory[n].equip == EPOS::SHIELD) sd->weapontype2 = view_l; } @@ -4507,26 +4509,26 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, int n, EPOS) } else { - sd->status.shield = 0; + sd->status.shield = ItemNameId(); sd->weapontype2 = ItemLook::NONE; } pc_calcweapontype(sd); - clif_changelook(sd, LOOK::SHIELD, sd->status.shield); + clif_changelook(sd, LOOK::SHIELD, unwrap<ItemNameId>(sd->status.shield)); } if (bool(sd->status.inventory[n].equip & EPOS::LEGS)) { sd->status.head_bottom = view_i; - clif_changelook(sd, LOOK::HEAD_BOTTOM, sd->status.head_bottom); + clif_changelook(sd, LOOK::HEAD_BOTTOM, unwrap<ItemNameId>(sd->status.head_bottom)); } if (bool(sd->status.inventory[n].equip & EPOS::HAT)) { sd->status.head_top = view_i; - clif_changelook(sd, LOOK::HEAD_TOP, sd->status.head_top); + clif_changelook(sd, LOOK::HEAD_TOP, unwrap<ItemNameId>(sd->status.head_top)); } if (bool(sd->status.inventory[n].equip & EPOS::TORSO)) { sd->status.head_mid = view_i; - clif_changelook(sd, LOOK::HEAD_MID, sd->status.head_mid); + clif_changelook(sd, LOOK::HEAD_MID, unwrap<ItemNameId>(sd->status.head_mid)); } pc_signal_advanced_equipment_change(sd, n); @@ -4539,14 +4541,14 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, int n, EPOS) * 装 備した物を外す *------------------------------------------ */ -int pc_unequipitem(dumb_ptr<map_session_data> sd, int n, CalcStatus type) +int pc_unequipitem(dumb_ptr<map_session_data> sd, IOff0 n, CalcStatus type) { - nullpo_ret(sd); + nullpo_retz(sd); // -- moonsoul (if player is berserk then cannot unequip) // if (battle_config.battle_log) - PRINTF("unequip %d %x:%x\n", + PRINTF("unequip %d %x:%x\n"_fmt, n, pc_equippoint(sd, n), sd->status.inventory[n].equip); if (bool(sd->status.inventory[n].equip)) @@ -4554,7 +4556,7 @@ int pc_unequipitem(dumb_ptr<map_session_data> sd, int n, CalcStatus type) for (EQUIP i : EQUIPs) { if (bool(sd->status.inventory[n].equip & equip_pos[i])) - sd->equip_index_maybe[i] = -1; + sd->equip_index_maybe[i] = IOff0::from(-1); } if (bool(sd->status.inventory[n].equip & EPOS::WEAPON)) { @@ -4565,26 +4567,25 @@ int pc_unequipitem(dumb_ptr<map_session_data> sd, int n, CalcStatus type) } if (bool(sd->status.inventory[n].equip & EPOS::SHIELD)) { - sd->status.shield = 0; + sd->status.shield = ItemNameId(); sd->weapontype2 = ItemLook::NONE; pc_calcweapontype(sd); - clif_changelook(sd, LOOK::SHIELD, sd->status.shield); + clif_changelook(sd, LOOK::SHIELD, unwrap<ItemNameId>(sd->status.shield)); } if (bool(sd->status.inventory[n].equip & EPOS::LEGS)) { - sd->status.head_bottom = 0; - clif_changelook(sd, LOOK::HEAD_BOTTOM, - sd->status.head_bottom); + sd->status.head_bottom = ItemNameId(); + clif_changelook(sd, LOOK::HEAD_BOTTOM, unwrap<ItemNameId>(sd->status.head_bottom)); } if (bool(sd->status.inventory[n].equip & EPOS::HAT)) { - sd->status.head_top = 0; - clif_changelook(sd, LOOK::HEAD_TOP, sd->status.head_top); + sd->status.head_top = ItemNameId(); + clif_changelook(sd, LOOK::HEAD_TOP, unwrap<ItemNameId>(sd->status.head_top)); } if (bool(sd->status.inventory[n].equip & EPOS::TORSO)) { - sd->status.head_mid = 0; - clif_changelook(sd, LOOK::HEAD_MID, sd->status.head_mid); + sd->status.head_mid = ItemNameId(); + clif_changelook(sd, LOOK::HEAD_MID, unwrap<ItemNameId>(sd->status.head_mid)); } pc_signal_advanced_equipment_change(sd, n); @@ -4603,7 +4604,7 @@ int pc_unequipitem(dumb_ptr<map_session_data> sd, int n, CalcStatus type) return 0; } -int pc_unequipinvyitem(dumb_ptr<map_session_data> sd, int n, CalcStatus type) +int pc_unequipinvyitem(dumb_ptr<map_session_data> sd, IOff0 n, CalcStatus type) { nullpo_retr(1, sd); @@ -4615,7 +4616,7 @@ int pc_unequipinvyitem(dumb_ptr<map_session_data> sd, int n, CalcStatus type) { //Slot taken, remove item from there. pc_unequipitem(sd, sd->equip_index_maybe[i], type); - sd->equip_index_maybe[i] = -1; + sd->equip_index_maybe[i] = IOff0::from(-1); } } @@ -4629,30 +4630,31 @@ int pc_unequipinvyitem(dumb_ptr<map_session_data> sd, int n, CalcStatus type) */ int pc_checkitem(dumb_ptr<map_session_data> sd) { - int i, j, k, id, calc_flag = 0; + int calc_flag = 0; - nullpo_ret(sd); + nullpo_retz(sd); - // 所持品空き詰め - for (i = j = 0; i < MAX_INVENTORY; i++) + IOff0 j = IOff0::from(0); + for (IOff0 i : IOff0::iter()) { - if ((id = sd->status.inventory[i].nameid) == 0) + if (!(sd->status.inventory[i].nameid)) continue; - if (i > j) + if (i != j) { sd->status.inventory[j] = sd->status.inventory[i]; sd->inventory_data[j] = sd->inventory_data[i]; } - j++; + ++j; + } + for (IOff0 k = j; k != IOff0::from(MAX_INVENTORY); ++k) + { + sd->status.inventory[k] = Item{}; + sd->inventory_data[k] = nullptr; } - for (k = j; k < MAX_INVENTORY; ++k) - sd->status.inventory[k] = item{}; - for (k = j; k < MAX_INVENTORY; k++) - sd->inventory_data[k] = NULL; - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { - if (sd->status.inventory[i].nameid == 0) + if (!sd->status.inventory[i].nameid) continue; if (bool(sd->status.inventory[i].equip & ~pc_equippoint(sd, i))) { @@ -4670,7 +4672,7 @@ int pc_checkitem(dumb_ptr<map_session_data> sd) int pc_checkoverhp(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); if (sd->status.hp == sd->status.max_hp) return 1; @@ -4686,7 +4688,7 @@ int pc_checkoverhp(dumb_ptr<map_session_data> sd) int pc_checkoversp(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); if (sd->status.sp == sd->status.max_sp) return 1; @@ -4723,9 +4725,9 @@ void pc_calc_pvprank_sub(dumb_ptr<block_list> bl, dumb_ptr<map_session_data> sd2 */ int pc_calc_pvprank(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); map_local *m = sd->bl_m; - nullpo_ret(m); + nullpo_retz(m); if (!(m->flag.get(MapFlag::PVP))) return 0; @@ -4742,20 +4744,22 @@ int pc_calc_pvprank(dumb_ptr<map_session_data> sd) * PVP順位計算(timer) *------------------------------------------ */ -void pc_calc_pvprank_timer(TimerData *, tick_t, int id) +void pc_calc_pvprank_timer(TimerData *, tick_t, BlockId id) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; if (battle_config.pk_mode) // disable pvp ranking if pk_mode on [Valaris] return; sd = map_id2sd(id); - if (sd == NULL) + if (sd == nullptr) return; sd->pvp_timer.cancel(); if (pc_calc_pvprank(sd) > 0) + { sd->pvp_timer = Timer(gettick() + PVP_CALCRANK_INTERVAL, std::bind(pc_calc_pvprank_timer, ph::_1, ph::_2, id)); + } } /*========================================== @@ -4763,14 +4767,14 @@ void pc_calc_pvprank_timer(TimerData *, tick_t, int id) *------------------------------------------ */ static -int pc_ismarried(dumb_ptr<map_session_data> sd) +CharId pc_ismarried(dumb_ptr<map_session_data> sd) { - if (sd == NULL) - return -1; - if (sd->status.partner_id > 0) + if (sd == nullptr) + return CharId(); + if (sd->status.partner_id) return sd->status.partner_id; else - return 0; + return CharId(); } /*========================================== @@ -4779,8 +4783,8 @@ int pc_ismarried(dumb_ptr<map_session_data> sd) */ int pc_marriage(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> dstsd) { - if (sd == NULL || dstsd == NULL || sd->status.partner_id > 0 - || dstsd->status.partner_id > 0) + if (sd == nullptr || dstsd == nullptr || sd->status.partner_id + || dstsd->status.partner_id) return -1; sd->status.partner_id = dstsd->status_key.char_id; dstsd->status.partner_id = sd->status_key.char_id; @@ -4793,23 +4797,23 @@ int pc_marriage(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> dstsd) */ int pc_divorce(dumb_ptr<map_session_data> sd) { - dumb_ptr<map_session_data> p_sd = NULL; - if (sd == NULL || !pc_ismarried(sd)) + dumb_ptr<map_session_data> p_sd = nullptr; + if (sd == nullptr || !pc_ismarried(sd)) return -1; // If both are on map server we don't need to bother the char server if ((p_sd = - map_nick2sd(map_charid2nick(sd->status.partner_id))) != NULL) + map_nick2sd(map_charid2nick(sd->status.partner_id))) != nullptr) { if (p_sd->status.partner_id != sd->status_key.char_id || sd->status.partner_id != p_sd->status_key.char_id) { - PRINTF("pc_divorce: Illegal partner_id sd=%d p_sd=%d\n", + PRINTF("pc_divorce: Illegal partner_id sd=%d p_sd=%d\n"_fmt, sd->status.partner_id, p_sd->status.partner_id); return -1; } - p_sd->status.partner_id = 0; - sd->status.partner_id = 0; + p_sd->status.partner_id = CharId(); + sd->status.partner_id = CharId(); if (sd->npc_flags.divorce) { @@ -4829,17 +4833,17 @@ int pc_divorce(dumb_ptr<map_session_data> sd) */ dumb_ptr<map_session_data> pc_get_partner(dumb_ptr<map_session_data> sd) { - dumb_ptr<map_session_data> p_sd = NULL; - if (sd == NULL || !pc_ismarried(sd)) - return NULL; + dumb_ptr<map_session_data> p_sd = nullptr; + if (sd == nullptr || !pc_ismarried(sd)) + return nullptr; CharName nick = map_charid2nick(sd->status.partner_id); if (!nick.to__actual()) - return NULL; + return nullptr; - if ((p_sd = map_nick2sd(nick)) == NULL) - return NULL; + if ((p_sd = map_nick2sd(nick)) == nullptr) + return nullptr; return p_sd; } @@ -4890,7 +4894,7 @@ int pc_natural_heal_hp(dumb_ptr<map_session_data> sd) int bhp; int bonus; - nullpo_ret(sd); + nullpo_retz(sd); if (pc_checkoverhp(sd)) { @@ -4962,7 +4966,7 @@ int pc_natural_heal_sp(dumb_ptr<map_session_data> sd) int bsp; int bonus; - nullpo_ret(sd); + nullpo_retz(sd); if (pc_checkoversp(sd)) { @@ -5035,7 +5039,7 @@ int pc_quickregenerate_effect(struct quick_regeneration *quick_regen, if (!(quick_regen->tickdelay--)) { int bonus = - min(heal_speed * battle_config.itemheal_regeneration_factor, + std::min(heal_speed * battle_config.itemheal_regeneration_factor, quick_regen->amount); quick_regen->amount -= bonus; @@ -5171,21 +5175,20 @@ void pc_autosave(TimerData *, tick_t) interval_t interval = autosave_time / (clif_countusers() + 1); if (interval <= interval_t::zero()) - interval = std::chrono::milliseconds(1); + interval = 1_ms; Timer(gettick() + interval, pc_autosave ).detach(); } -int pc_read_gm_account(Session *s) +int pc_read_gm_account(Session *, const std::vector<Packet_Repeat<0x2b15>>& repeat) { gm_accountm.clear(); - // (RFIFOW(fd, 2) - 4) / 5 - for (int i = 4; i < RFIFOW(s, 2); i += 5) + for (const auto& i : repeat) { - int account_id = RFIFOL(s, i); - uint8_t level = RFIFOB(s, i + 4); + AccountId account_id = i.account_id; + GmLevel level = i.gm_level; gm_accountm[account_id] = level; } return gm_accountm.size(); @@ -5265,13 +5268,14 @@ int pc_logout(dumb_ptr<map_session_data> sd) // [fate] Player logs out // Removed because it's buggy, see above. if (sd->cast_tick > tick) { - if (pc_setglobalreg(sd, "MAGIC_CAST_TICK", sd->cast_tick - tick)) + if (pc_setglobalreg(sd, "MAGIC_CAST_TICK"_s, sd->cast_tick - tick)) sd->status.sp = 1; } else #endif - pc_setglobalreg(sd, stringish<VarName>("MAGIC_CAST_TICK"), 0); + pc_setglobalreg(sd, stringish<VarName>("MAGIC_CAST_TICK"_s), 0); - MAP_LOG_STATS(sd, "LOGOUT"); + MAP_LOG_STATS(sd, "LOGOUT"_fmt); return 0; } +} // namespace tmwa diff --git a/src/map/pc.hpp b/src/map/pc.hpp index 35d9c70..3187cd9 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_PC_HPP -#define TMWA_MAP_PC_HPP +#pragma once // pc.hpp - Player state changes. // // Copyright © ????-2004 Athena Dev Teams @@ -21,15 +20,24 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "pc.t.hpp" +#include "pc.t.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "clif.t.hpp" -# include "map.hpp" +#include "../generic/dumb_ptr.hpp" +#include "../mmo/utils.hpp" + +#include "../proto2/fwd.hpp" + +#include "clif.t.hpp" +#include "map.hpp" + + +namespace tmwa +{ inline void pc_setsit(dumb_ptr<map_session_data> sd) { @@ -66,7 +74,7 @@ bool pc_is90overweight(dumb_ptr<map_session_data> sd) // should do something with the specified player. void pc_touch_all_relevant_npcs(dumb_ptr<map_session_data> sd); -uint8_t pc_isGM(dumb_ptr<map_session_data> sd); +GmLevel pc_isGM(dumb_ptr<map_session_data> sd); int pc_iskiller(dumb_ptr<map_session_data> src, dumb_ptr<map_session_data> target); // [MouseJstr] void pc_invisibility(dumb_ptr<map_session_data> sd, int enabled); // [Fate] @@ -74,14 +82,14 @@ int pc_counttargeted(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> src, ATK target_lv); int pc_setrestartvalue(dumb_ptr<map_session_data> sd, int type); void pc_makesavestatus(dumb_ptr<map_session_data>); -int pc_setnewpc(dumb_ptr<map_session_data>, int, int, int, tick_t, SEX); -int pc_authok(int, int, TimeT, short tmw_version, const CharKey *, const CharData *); -int pc_authfail(int accid); +int pc_setnewpc(dumb_ptr<map_session_data>, AccountId, CharId, int, uint32_t /*tick_t*/, SEX); +int pc_authok(AccountId, int, TimeT, short tmw_version, const CharKey *, const CharData *); +int pc_authfail(AccountId accid); -EPOS pc_equippoint(dumb_ptr<map_session_data> sd, int n); +EPOS pc_equippoint(dumb_ptr<map_session_data> sd, IOff0 n); int pc_checkskill(dumb_ptr<map_session_data> sd, SkillID skill_id); -int pc_checkequip(dumb_ptr<map_session_data> sd, EPOS pos); +IOff0 pc_checkequip(dumb_ptr<map_session_data> sd, EPOS pos); int pc_walktoxy(dumb_ptr<map_session_data>, int, int); int pc_stop_walking(dumb_ptr<map_session_data>, int); @@ -90,20 +98,20 @@ int pc_setpos(dumb_ptr<map_session_data>, MapName, int, int, BeingRemoveWhy); void pc_setsavepoint(dumb_ptr<map_session_data>, MapName, int, int); int pc_randomwarp(dumb_ptr<map_session_data> sd, BeingRemoveWhy type); -ADDITEM pc_checkadditem(dumb_ptr<map_session_data>, int, int); +ADDITEM pc_checkadditem(dumb_ptr<map_session_data>, ItemNameId, int); int pc_inventoryblank(dumb_ptr<map_session_data>); -int pc_search_inventory(dumb_ptr<map_session_data> sd, int item_id); +IOff0 pc_search_inventory(dumb_ptr<map_session_data> sd, ItemNameId item_id); int pc_payzeny(dumb_ptr<map_session_data>, int); -PickupFail pc_additem(dumb_ptr<map_session_data>, struct item *, int); +PickupFail pc_additem(dumb_ptr<map_session_data>, Item *, int); int pc_getzeny(dumb_ptr<map_session_data>, int); -int pc_delitem(dumb_ptr<map_session_data>, int, int, int); +int pc_delitem(dumb_ptr<map_session_data>, IOff0, int, int); int pc_checkitem(dumb_ptr<map_session_data>); -int pc_count_all_items(dumb_ptr<map_session_data> player, int item_id); +int pc_count_all_items(dumb_ptr<map_session_data> player, ItemNameId item_id); int pc_remove_items(dumb_ptr<map_session_data> player, - int item_id, int count); + ItemNameId item_id, int count); int pc_takeitem(dumb_ptr<map_session_data>, dumb_ptr<flooritem_data>); -int pc_dropitem(dumb_ptr<map_session_data>, int, int); +int pc_dropitem(dumb_ptr<map_session_data>, IOff0, int); int pc_checkweighticon(dumb_ptr<map_session_data> sd); @@ -112,7 +120,7 @@ int pc_bonus(dumb_ptr<map_session_data>, SP, int); int pc_bonus2(dumb_ptr<map_session_data> sd, SP, int, int); int pc_skill(dumb_ptr<map_session_data>, SkillID, int, int); -int pc_attack(dumb_ptr<map_session_data>, int, int); +int pc_attack(dumb_ptr<map_session_data>, BlockId, int); int pc_stopattack(dumb_ptr<map_session_data>); int pc_gainexp_reason(dumb_ptr<map_session_data>, int, int, @@ -128,10 +136,10 @@ int pc_skillup(dumb_ptr<map_session_data>, SkillID); int pc_resetlvl(dumb_ptr<map_session_data>, int type); int pc_resetstate(dumb_ptr<map_session_data>); int pc_resetskill(dumb_ptr<map_session_data>); -int pc_equipitem(dumb_ptr<map_session_data>, int, EPOS); -int pc_unequipitem(dumb_ptr<map_session_data>, int, CalcStatus); -int pc_unequipinvyitem(dumb_ptr<map_session_data>, int, CalcStatus); -int pc_useitem(dumb_ptr<map_session_data>, int); +int pc_equipitem(dumb_ptr<map_session_data>, IOff0, EPOS); +int pc_unequipitem(dumb_ptr<map_session_data>, IOff0, CalcStatus); +int pc_unequipinvyitem(dumb_ptr<map_session_data>, IOff0, CalcStatus); +int pc_useitem(dumb_ptr<map_session_data>, IOff0); int pc_damage(dumb_ptr<block_list>, dumb_ptr<map_session_data>, int); int pc_heal(dumb_ptr<map_session_data>, int, int); @@ -158,17 +166,17 @@ int pc_addeventtimer(dumb_ptr<map_session_data> sd, interval_t tick, int pc_cleareventtimer(dumb_ptr<map_session_data> sd); int pc_calc_pvprank(dumb_ptr<map_session_data> sd); -void pc_calc_pvprank_timer(TimerData *, tick_t, int); +void pc_calc_pvprank_timer(TimerData *, tick_t, BlockId); int pc_marriage(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> dstsd); int pc_divorce(dumb_ptr<map_session_data> sd); dumb_ptr<map_session_data> pc_get_partner(dumb_ptr<map_session_data> sd); -void pc_set_gm_level(int account_id, uint8_t level); +void pc_set_gm_level(AccountId account_id, GmLevel level); void pc_setstand(dumb_ptr<map_session_data> sd); void pc_cleanup(dumb_ptr<map_session_data> sd); // [Fate] Clean up after a logged-out PC -int pc_read_gm_account(Session *); +int pc_read_gm_account(Session *, const std::vector<Packet_Repeat<0x2b15>>&); int pc_setinvincibletimer(dumb_ptr<map_session_data> sd, interval_t); int pc_delinvincibletimer(dumb_ptr<map_session_data> sd); int pc_logout(dumb_ptr<map_session_data> sd); // [fate] Player logs out @@ -176,5 +184,4 @@ int pc_logout(dumb_ptr<map_session_data> sd); // [fate] Player logs out void pc_show_motd(dumb_ptr<map_session_data> sd); void do_init_pc(void); - -#endif // TMWA_MAP_PC_HPP +} // namespace tmwa diff --git a/src/map/pc.t.hpp b/src/map/pc.t.hpp index 65e1046..427e8c3 100644 --- a/src/map/pc.t.hpp +++ b/src/map/pc.t.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_PC_T_HPP -#define TMWA_MAP_PC_T_HPP +#pragma once // pc.t.hpp - Player state changes. // // Copyright © ????-2004 Athena Dev Teams @@ -22,10 +21,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdint> +#include <cstdint> + +namespace tmwa +{ enum class PC_GAINEXP_REASON { KILLING = 0, @@ -50,18 +52,6 @@ enum class ADDITEM enum class CalcStatus { NOW, - LATER , -}; - -enum class PickupFail : uint8_t -{ - OKAY = 0, - BAD_ITEM = 1, - TOO_HEAVY = 2, - TOO_FAR = 3, - INV_FULL = 4, - STACK_FULL = 5, - DROP_STEAL = 6, + LATER, }; - -#endif // TMWA_MAP_PC_T_HPP +} // namespace tmwa diff --git a/src/map/script.cpp b/src/map/script.cpp index 93f9d31..0b2d05e 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -23,12 +23,11 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include <cassert> -#include <cctype> #include <cmath> #include <cstdlib> -#include <cstring> #include <ctime> +#include <algorithm> #include <set> #include "../compat/fun.hpp" @@ -38,6 +37,7 @@ #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" +#include "../strings/literal.hpp" #include "../generic/db.hpp" #include "../generic/intern-pool.hpp" @@ -46,13 +46,15 @@ #include "../io/cxxstdio.hpp" #include "../io/lock.hpp" #include "../io/read.hpp" +#include "../io/write.hpp" + +#include "../net/socket.hpp" +#include "../net/timer.hpp" -#include "../mmo/config_parse.hpp" #include "../mmo/core.hpp" #include "../mmo/extract.hpp" -#include "../mmo/socket.hpp" +#include "../mmo/human_time_diff.hpp" #include "../mmo/utils.hpp" -#include "../mmo/timer.hpp" #include "atcommand.hpp" #include "battle.hpp" @@ -60,7 +62,7 @@ #include "clif.hpp" #include "intif.hpp" #include "itemdb.hpp" -#include "magic.hpp" +#include "magic-interpreter-base.hpp" #include "map.hpp" #include "mob.hpp" #include "npc.hpp" @@ -71,6 +73,9 @@ #include "../poison.hpp" + +namespace tmwa +{ constexpr bool DEBUG_DISP = false; constexpr bool DEBUG_RUN = false; @@ -93,8 +98,8 @@ static Map<SIR, RString> mapregstr_db; static int mapreg_dirty = -1; -AString mapreg_txt = "save/mapreg.txt"; -constexpr std::chrono::milliseconds MAPREG_AUTOSAVE_INTERVAL = std::chrono::seconds(10); +AString mapreg_txt = "save/mapreg.txt"_s; +constexpr std::chrono::milliseconds MAPREG_AUTOSAVE_INTERVAL = 10_s; Map<ScriptLabel, int> scriptlabel_db; static @@ -102,19 +107,19 @@ std::set<ScriptLabel> probable_labels; UPMap<RString, const ScriptBuffer> userfunc_db; static -Array<ZString, 11> pos_str //= +Array<LString, 11> pos_str //= {{ - ZString("Head"), - ZString("Body"), - ZString("Left hand"), - ZString("Right hand"), - ZString("Robe"), - ZString("Shoes"), - ZString("Accessory 1"), - ZString("Accessory 2"), - ZString("Head 2"), - ZString("Head 3"), - ZString("Not Equipped"), + "Head"_s, + "Body"_s, + "Left hand"_s, + "Right hand"_s, + "Robe"_s, + "Shoes"_s, + "Accessory 1"_s, + "Accessory 2"_s, + "Head 2"_s, + "Head 3"_s, + "Not Equipped"_s, }}; static @@ -150,8 +155,9 @@ void mapreg_setregstr(SIR num, XString str); struct BuiltinFunction { void (*func)(ScriptState *); - ZString name; - ZString arg; + LString name; + LString arg; + char ret; }; // defined later extern BuiltinFunction builtin_functions[]; @@ -382,15 +388,15 @@ void disp_error_message(ZString mes, ZString::iterator pos_) ZString::iterator lineend = std::find(p, startptr.end(), '\n'); if (pos_ < lineend) { - PRINTF("\n%s\nline %d : ", mes, line); + PRINTF("\n%s\nline %d : "_fmt, mes, line); for (int i = 0; linestart + i != lineend; i++) { if (linestart + i != pos_) - PRINTF("%c", linestart[i]); + PRINTF("%c"_fmt, linestart[i]); else - PRINTF("\'%c\'", linestart[i]); + PRINTF("\'%c\'"_fmt, linestart[i]); } - PRINTF("\a\n"); + PRINTF("\a\n"_fmt); return; } p = lineend + 1; @@ -407,7 +413,7 @@ ZString::iterator ScriptBuffer::parse_simpleexpr(ZString::iterator p) if (*p == ';' || *p == ',') { - disp_error_message("unexpected expr end", p); + disp_error_message("unexpected expr end"_s, p); exit(1); } if (*p == '(') @@ -417,7 +423,7 @@ ZString::iterator ScriptBuffer::parse_simpleexpr(ZString::iterator p) p = skip_space(p); if ((*p++) != ')') { - disp_error_message("unmatch ')'", p); + disp_error_message("unmatch ')'"_s, p); exit(1); } } @@ -438,14 +444,14 @@ ZString::iterator ScriptBuffer::parse_simpleexpr(ZString::iterator p) p++; else if (*p == '\n') { - disp_error_message("unexpected newline @ string", p); + disp_error_message("unexpected newline @ string"_s, p); exit(1); } add_scriptb(*p++); } if (!*p) { - disp_error_message("unexpected eof @ string", p); + disp_error_message("unexpected eof @ string"_s, p); exit(1); } add_scriptb(0); @@ -457,35 +463,35 @@ ZString::iterator ScriptBuffer::parse_simpleexpr(ZString::iterator p) ZString::iterator p2 = skip_word(p); if (p2 == p) { - disp_error_message("unexpected character", p); + disp_error_message("unexpected character"_s, p); exit(1); } XString word(&*p, &*p2, nullptr); - if (word.startswith("On") || word.startswith("L_") || word.startswith("S_")) + if (word.startswith("On"_s) || word.startswith("L_"_s) || word.startswith("S_"_s)) probable_labels.insert(stringish<ScriptLabel>(word)); - if (parse_cmd_if && (word == "callsub" || word == "callfunc" || word == "return")) + if (parse_cmd_if && (word == "callsub"_s || word == "callfunc"_s || word == "return"_s)) { - disp_error_message("Sorry, callsub/callfunc/return have never worked properly in an if statement.", p); + disp_error_message("Sorry, callsub/callfunc/return have never worked properly in an if statement."_s, p); } str_data_t *ld = add_strp(word); parse_cmdp = ld; // warn_*_mismatch_paramnumのために必要 - // why not just check l->str == "if" or std::string(p, p2) == "if"? - if (ld == search_strp("if")) // warn_cmd_no_commaのために必要 + // why not just check l->str == "if"_s or std::string(p, p2) == "if"_s? + if (ld == search_strp("if"_s)) // warn_cmd_no_commaのために必要 parse_cmd_if++; p = p2; if (ld->type != ByteCode::FUNC_ && *p == '[') { // array(name[i] => getelementofarray(name,i) ) - add_scriptl(search_strp("getelementofarray")); + add_scriptl(search_strp("getelementofarray"_s)); add_scriptc(ByteCode::ARG); add_scriptl(ld); p = parse_subexpr(p + 1, -1); p = skip_space(p); if (*p != ']') { - disp_error_message("unmatch ']'", p); + disp_error_message("unmatch ']'"_s, p); exit(1); } p++; @@ -515,7 +521,7 @@ ZString::iterator ScriptBuffer::parse_subexpr(ZString::iterator p, int limit) ZString::iterator tmpp = skip_space(p + 1); if (*tmpp == ';' || *tmpp == ',') { - --script_errors; disp_error_message("deprecated: implicit 'next statement' label", p); + --script_errors; disp_error_message("deprecated: implicit 'next statement' label"_s, p); add_scriptl(&LABEL_NEXTLINE_); p++; return p; @@ -560,7 +566,7 @@ ZString::iterator ScriptBuffer::parse_subexpr(ZString::iterator p, int limit) if (funcp->type != ByteCode::FUNC_) { - disp_error_message("expect function", tmpp); + disp_error_message("expect function"_s, tmpp); exit(0); } @@ -574,7 +580,7 @@ ZString::iterator ScriptBuffer::parse_subexpr(ZString::iterator p, int limit) p++; else if (*p != ')' && script_config.warn_func_no_comma) { - disp_error_message("expect ',' or ')' at func params", + disp_error_message("expect ',' or ')' at func params"_s, p); } p = skip_space(p); @@ -583,7 +589,7 @@ ZString::iterator ScriptBuffer::parse_subexpr(ZString::iterator p, int limit) plist[i] = p; if (*p != ')') { - disp_error_message("func request '(' ')'", p); + disp_error_message("func request '(' ')'"_s, p); exit(1); } p++; @@ -593,14 +599,19 @@ ZString::iterator ScriptBuffer::parse_subexpr(ZString::iterator p, int limit) { ZString arg = builtin_functions[funcp->val].arg; int j = 0; + // TODO handle ? and multiple * correctly for (j = 0; arg[j]; j++) - if (arg[j] == '*') + if (arg[j] == '*' || arg[j] == '?') break; - if ((arg[j] == 0 && i != j) || (arg[j] == '*' && i < j)) + if ((arg[j] == 0 && i != j) || ((arg[j] == '*' || arg[j] == '?') && i < j)) { - disp_error_message("illegal number of parameters", + disp_error_message("illegal number of parameters"_s, plist[std::min(i, j)]); } + if (!builtin_functions[funcp->val].ret) + { + disp_error_message("statement in function context"_s, tmpp); + } } } else // not op == ByteCode::FUNC @@ -627,7 +638,7 @@ ZString::iterator ScriptBuffer::parse_expr(ZString::iterator p) case '[': case ']': case '}': - disp_error_message("unexpected char", p); + disp_error_message("unexpected char"_s, p); exit(1); } p = parse_subexpr(p, -1); @@ -657,21 +668,22 @@ ZString::iterator ScriptBuffer::parse_line(ZString::iterator p, bool *can_step) str_data_t *cmd = parse_cmdp; if (cmd->type != ByteCode::FUNC_) { - disp_error_message("expect command", p2); + disp_error_message("expect command"_s, p2); // exit(0); } { + // TODO should be LString, but no heterogenous lookup yet static std::set<ZString> terminators = { - "goto", - "return", - "close", - "menu", - "end", - "mapexit", - "shop", + "goto"_s, + "return"_s, + "close"_s, + "menu"_s, + "end"_s, + "mapexit"_s, + "shop"_s, }; *can_step = terminators.count(cmd->strs) == 0; } @@ -689,7 +701,7 @@ ZString::iterator ScriptBuffer::parse_line(ZString::iterator p, bool *can_step) else if (*p != ';' && script_config.warn_cmd_no_comma && parse_cmd_if * 2 <= i) { - disp_error_message("expect ',' or ';' at cmd params", p); + disp_error_message("expect ',' or ';' at cmd params"_s, p); } p = skip_space(p); i++; @@ -697,7 +709,7 @@ ZString::iterator ScriptBuffer::parse_line(ZString::iterator p, bool *can_step) plist[i] = p; if (*(p++) != ';') { - disp_error_message("need ';'", p); + disp_error_message("need ';'"_s, p); exit(1); } add_scriptc(ByteCode::FUNC_); @@ -707,14 +719,19 @@ ZString::iterator ScriptBuffer::parse_line(ZString::iterator p, bool *can_step) { ZString arg = builtin_functions[cmd->val].arg; int j = 0; + // TODO see above for (j = 0; arg[j]; j++) - if (arg[j] == '*') + if (arg[j] == '*' || arg[j] == '?') break; - if ((arg[j] == 0 && i != j) || (arg[j] == '*' && i < j)) + if ((arg[j] == 0 && i != j) || ((arg[j] == '*' || arg[j] == '?') && i < j)) { - disp_error_message("illegal number of parameters", + disp_error_message("illegal number of parameters"_s, plist[std::min(i, j)]); } + if (builtin_functions[cmd->val].ret) + { + disp_error_message("function in statement context"_s, p2); + } } return p; @@ -740,24 +757,50 @@ bool read_constdb(ZString filename) io::ReadFile in(filename); if (!in.is_open()) { - PRINTF("can't read %s\n", filename); + PRINTF("can't read %s\n"_fmt, filename); return false; } bool rv = true; - AString line; - while (in.getline(line)) - { - if (is_comment(line)) + AString line_; + while (in.getline(line_)) + { + // is_comment only works for whole-line comments + // that could change once the Z dependency is dropped ... + LString comment = "//"_s; + XString line = line_.xislice_h(std::search(line_.begin(), line_.end(), comment.begin(), comment.end())).rstrip(); + if (!line) continue; + // "%m[A-Za-z0-9_] %i %i" + + // TODO promote either qsplit() or asplit() + auto _it = std::find(line.begin(), line.end(), ' '); + auto name = line.xislice_h(_it); + auto _rest = line.xislice_t(_it); + while (_rest.startswith(' ')) + _rest = _rest.xslice_t(1); + auto _it2 = std::find(_rest.begin(), _rest.end(), ' '); + auto val_ = _rest.xislice_h(_it2); + auto type_ = _rest.xislice_t(_it2); + while (type_.startswith(' ')) + type_ = type_.xslice_t(1); + // yes, the above actually DTRT even for underlength input - AString name; int val; - int type = 0; // if not provided - // TODO get rid of SSCANF - this is the last serious use - if (SSCANF(line, "%m[A-Za-z0-9_] %i %i", &name, &val, &type) < 2) + int type = 0; + // Note for future archeaologists: this code is indented correctly + if (std::find_if_not(name.begin(), name.end(), + [](char c) + { + return ('0' <= c && c <= '9') + || ('A' <= c && c <= 'Z') + || ('a' <= c && c <= 'z') + || (c == '_'); + }) != name.end() + || !extract(val_, &val) + || (!extract(type_, &type) && type_)) { - PRINTF("Bad const line: %s\n", line); + PRINTF("Bad const line: %s\n"_fmt, line_); rv = false; continue; } @@ -815,7 +858,7 @@ void ScriptBuffer::parse_script(ZString src, int line, bool implicit_end) p = skip_space(p); if (*p != '{') { - disp_error_message("not found '{'", p); + disp_error_message("not found '{'"_s, p); abort(); } for (p++; *p && *p != '}';) @@ -825,7 +868,7 @@ void ScriptBuffer::parse_script(ZString src, int line, bool implicit_end) { if (can_step) { - --script_errors; disp_error_message("deprecated: implicit fallthrough", p); + --script_errors; disp_error_message("deprecated: implicit fallthrough"_s, p); } can_step = true; @@ -838,7 +881,7 @@ void ScriptBuffer::parse_script(ZString src, int line, bool implicit_end) assert (e1 == e2 && e2 == e3); if (e3) { - disp_error_message("dup label ", p); + disp_error_message("dup label "_s, p); exit(1); } set_label(ld, script_buf.size()); @@ -849,7 +892,7 @@ void ScriptBuffer::parse_script(ZString src, int line, bool implicit_end) if (!can_step) { - --script_errors; disp_error_message("deprecated: unreachable statement", p); + --script_errors; disp_error_message("deprecated: unreachable statement"_s, p); } // 他は全部一緒くた p = parse_line(p, &can_step); @@ -864,7 +907,7 @@ void ScriptBuffer::parse_script(ZString src, int line, bool implicit_end) if (can_step && !implicit_end) { - --script_errors; disp_error_message("deprecated: implicit end", p); + --script_errors; disp_error_message("deprecated: implicit end"_s, p); } add_scriptc(ByteCode::NOP); @@ -893,17 +936,17 @@ void ScriptBuffer::parse_script(ZString src, int line, bool implicit_end) for (const auto& pair : scriptlabel_db) { ScriptLabel key = pair.first; - if (key.startswith("On")) + if (key.startswith("On"_s)) continue; - if (!(key.startswith("L_") || key.startswith("S_"))) - PRINTF("Warning: ugly label: %s\n", key); + if (!(key.startswith("L_"_s) || key.startswith("S_"_s))) + PRINTF("Warning: ugly label: %s\n"_fmt, key); else if (!probable_labels.count(key)) - PRINTF("Warning: unused label: %s\n", key); + PRINTF("Warning: unused label: %s\n"_fmt, key); } for (ScriptLabel used : probable_labels) { if (!scriptlabel_db.search(used)) - PRINTF("Warning: no such label: %s\n", used); + PRINTF("Warning: no such label: %s\n"_fmt, used); } probable_labels.clear(); @@ -912,12 +955,12 @@ void ScriptBuffer::parse_script(ZString src, int line, bool implicit_end) for (size_t i = 0; i < script_buf.size(); i++) { if ((i & 15) == 0) - PRINTF("%04zx : ", i); - PRINTF("%02x ", script_buf[i]); + PRINTF("%04zx : "_fmt, i); + PRINTF("%02x "_fmt, script_buf[i]); if ((i & 15) == 15) - PRINTF("\n"); + PRINTF("\n"_fmt); } - PRINTF("\n"); + PRINTF("\n"_fmt); } // @@ -943,7 +986,7 @@ dumb_ptr<map_session_data> script_rid2sd(ScriptState *st) dumb_ptr<map_session_data> sd = map_id2sd(st->rid); if (!sd) { - PRINTF("script_rid2sd: fatal error ! player not attached!\n"); + PRINTF("script_rid2sd: fatal error ! player not attached!\n"_fmt); } return sd; } @@ -957,8 +1000,8 @@ void get_val(dumb_ptr<map_session_data> sd, struct script_data *data) { if (data->type == ByteCode::PARAM_) { - if (sd == NULL) - PRINTF("get_val error param SP::%d\n", data->u.reg.sp()); + if (sd == nullptr) + PRINTF("get_val error param SP::%d\n"_fmt, data->u.reg.sp()); data->type = ByteCode::INT; if (sd) data->u.numi = pc_readparam(sd, data->u.reg.sp()); @@ -972,8 +1015,8 @@ void get_val(dumb_ptr<map_session_data> sd, struct script_data *data) if (prefix != '$') { - if (sd == NULL) - PRINTF("get_val error name?:%s\n", name); + if (sd == nullptr) + PRINTF("get_val error name?:%s\n"_fmt, name); } if (postfix == '$') { @@ -990,11 +1033,11 @@ void get_val(dumb_ptr<map_session_data> sd, struct script_data *data) } else { - PRINTF("script: get_val: illegal scope string variable.\n"); - data->u.str = dumb_string::fake("!!ERROR!!"); + PRINTF("script: get_val: illegal scope string variable.\n"_fmt); + data->u.str = dumb_string::fake("!!ERROR!!"_s); } if (!data->u.str) - data->u.str = dumb_string::fake(""); + data->u.str = dumb_string::fake(""_s); } else { @@ -1085,7 +1128,7 @@ void set_reg(dumb_ptr<map_session_data> sd, ByteCode type, SIR reg, struct scrip } else { - PRINTF("script: set_reg: illegal scope string variable !"); + PRINTF("script: set_reg: illegal scope string variable !"_fmt); } } else @@ -1143,7 +1186,7 @@ dumb_string conv_str(ScriptState *st, struct script_data *data) assert (data->type != ByteCode::RETINFO); if (data->type == ByteCode::INT) { - AString buf = STRPRINTF("%d", data->u.numi); + AString buf = STRPRINTF("%d"_fmt, data->u.numi); data->type = ByteCode::STR; data->u.str = dumb_string::copys(buf); } @@ -1285,7 +1328,7 @@ void builtin_goto(ScriptState *st) { if (AARGO2(2).type != ByteCode::POS) { - PRINTF("script: goto: not label !\n"); + PRINTF("script: goto: not label !\n"_fmt); st->state = ScriptEndState::END; return; } @@ -1324,7 +1367,7 @@ void builtin_callfunc(ScriptState *st) } else { - PRINTF("script:callfunc: function not found! [%s]\n", str); + PRINTF("script:callfunc: function not found! [%s]\n"_fmt, str); st->state = ScriptEndState::END; } } @@ -1442,7 +1485,7 @@ void builtin_menu(ScriptState *st) // not just the displayed number that ends with the "". // (Would it be better to pop the stack before rerunning?) int menu_choices = (st->end - (st->start + 2)) / 2; - pc_setreg(sd, SIR::from(variable_names.intern("@menu")), sd->npc_menu); + pc_setreg(sd, SIR::from(variable_names.intern("@menu"_s)), sd->npc_menu); sd->state.menu_or_input = 0; if (sd->npc_menu > 0 && sd->npc_menu <= menu_choices) { @@ -1481,23 +1524,6 @@ void builtin_rand(ScriptState *st) } /*========================================== - * - *------------------------------------------ - */ -static -void builtin_pow(ScriptState *st) -{ - int a, b; - - a = conv_num(st, &AARGO2(2)); - b = conv_num(st, &AARGO2(3)); - -#warning "This is silly" - push_int(st->stack, ByteCode::INT, static_cast<int>(pow(a * 0.001, b))); - -} - -/*========================================== * Check whether the PC is at the specified location *------------------------------------------ */ @@ -1532,9 +1558,9 @@ void builtin_warp(ScriptState *st) MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2)))); x = conv_num(st, &AARGO2(3)); y = conv_num(st, &AARGO2(4)); - if (str == "Random") + if (str == "Random"_s) pc_randomwarp(sd, BeingRemoveWhy::WARPED); - else if (str == "SavePoint" or str == "Save") + else if (str == "SavePoint"_s or str == "Save"_s) { if (sd->bl_m->flag.get(MapFlag::NORETURN)) return; @@ -1554,7 +1580,7 @@ static void builtin_areawarp_sub(dumb_ptr<block_list> bl, MapName mapname, int x, int y) { dumb_ptr<map_session_data> sd = bl->is_player(); - if (mapname == "Random") + if (mapname == "Random"_s) pc_randomwarp(sd, BeingRemoveWhy::WARPED); else pc_setpos(sd, mapname, x, y, BeingRemoveWhy::GONE); @@ -1635,7 +1661,7 @@ void builtin_percentheal(ScriptState *st) static void builtin_input(ScriptState *st) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; script_data& scrd = AARGO2(2); ByteCode type = scrd.type; assert (type == ByteCode::VARIABLE); @@ -1712,7 +1738,7 @@ void builtin_if (ScriptState *st) static void builtin_set(ScriptState *st) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; SIR reg = AARGO2(2).u.reg; if (AARGO2(2).type == ByteCode::PARAM_) { @@ -1753,7 +1779,7 @@ void builtin_set(ScriptState *st) static void builtin_setarray(ScriptState *st) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; assert (AARGO2(2).type == ByteCode::VARIABLE); SIR reg = AARGO2(2).u.reg; ZString name = variable_names.outtern(reg.base()); @@ -1762,7 +1788,7 @@ void builtin_setarray(ScriptState *st) if (prefix != '$' && prefix != '@') { - PRINTF("builtin_setarray: illegal scope !\n"); + PRINTF("builtin_setarray: illegal scope !\n"_fmt); return; } if (prefix != '$') @@ -1784,7 +1810,7 @@ void builtin_setarray(ScriptState *st) static void builtin_cleararray(ScriptState *st) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; assert (AARGO2(2).type == ByteCode::VARIABLE); SIR reg = AARGO2(2).u.reg; ZString name = variable_names.outtern(reg.base()); @@ -1794,7 +1820,7 @@ void builtin_cleararray(ScriptState *st) if (prefix != '$' && prefix != '@') { - PRINTF("builtin_cleararray: illegal scope !\n"); + PRINTF("builtin_cleararray: illegal scope !\n"_fmt); return; } if (prefix != '$') @@ -1839,7 +1865,7 @@ void builtin_getarraysize(ScriptState *st) if (prefix != '$' && prefix != '@') { - PRINTF("builtin_copyarray: illegal scope !\n"); + PRINTF("builtin_copyarray: illegal scope !\n"_fmt); return; } @@ -1858,8 +1884,8 @@ void builtin_getelementofarray(ScriptState *st) int i = conv_num(st, &AARGO2(3)); if (i > 255 || i < 0) { - PRINTF("script: getelementofarray (operator[]): param2 illegal number %d\n", - i); + PRINTF("script: getelementofarray (operator[]): param2 illegal number %d\n"_fmt, + i); push_int(st->stack, ByteCode::INT, 0); } else @@ -1870,7 +1896,7 @@ void builtin_getelementofarray(ScriptState *st) } else { - PRINTF("script: getelementofarray (operator[]): param1 not name !\n"); + PRINTF("script: getelementofarray (operator[]): param1 not name !\n"_fmt); push_int(st->stack, ByteCode::INT, 0); } } @@ -1896,7 +1922,8 @@ void builtin_setlook(ScriptState *st) static void builtin_countitem(ScriptState *st) { - int nameid = 0, count = 0, i; + ItemNameId nameid; + int count = 0; dumb_ptr<map_session_data> sd; struct script_data *data; @@ -1909,22 +1936,24 @@ void builtin_countitem(ScriptState *st) { ZString name = ZString(conv_str(st, data)); struct item_data *item_data = itemdb_searchname(name); - if (item_data != NULL) + if (item_data != nullptr) nameid = item_data->nameid; } else - nameid = conv_num(st, data); + nameid = wrap<ItemNameId>(conv_num(st, data)); - if (nameid >= 500) //if no such ID then skip this iteration - for (i = 0; i < MAX_INVENTORY; i++) + if (nameid) + { + for (IOff0 i : IOff0::iter()) { if (sd->status.inventory[i].nameid == nameid) count += sd->status.inventory[i].amount; } + } else { if (battle_config.error_log) - PRINTF("wrong item ID : countitem (%i)\n", nameid); + PRINTF("wrong item ID : countitem (%i)\n"_fmt, nameid); } push_int(st->stack, ByteCode::INT, count); @@ -1937,7 +1966,8 @@ void builtin_countitem(ScriptState *st) static void builtin_checkweight(ScriptState *st) { - int nameid = 0, amount; + ItemNameId nameid; + int amount; dumb_ptr<map_session_data> sd; struct script_data *data; @@ -1953,10 +1983,10 @@ void builtin_checkweight(ScriptState *st) nameid = item_data->nameid; } else - nameid = conv_num(st, data); + nameid = wrap<ItemNameId>(conv_num(st, data)); amount = conv_num(st, &AARGO2(3)); - if (amount <= 0 || nameid < 500) + if (amount <= 0 || !nameid) { //if get wrong item ID or amount<=0, don't count weight of non existing items push_int(st->stack, ByteCode::INT, 0); @@ -1981,7 +2011,8 @@ void builtin_checkweight(ScriptState *st) static void builtin_getitem(ScriptState *st) { - int nameid, amount; + ItemNameId nameid; + int amount; dumb_ptr<map_session_data> sd; struct script_data *data; @@ -1993,12 +2024,11 @@ void builtin_getitem(ScriptState *st) { ZString name = ZString(conv_str(st, data)); struct item_data *item_data = itemdb_searchname(name); - nameid = 727; //Default to iten - if (item_data != NULL) + if (item_data != nullptr) nameid = item_data->nameid; } else - nameid = conv_num(st, data); + nameid = wrap<ItemNameId>(conv_num(st, data)); if ((amount = conv_num(st, &AARGO2(3))) <= 0) @@ -2006,21 +2036,21 @@ void builtin_getitem(ScriptState *st) return; //return if amount <=0, skip the useles iteration } - if (nameid > 0) + if (nameid) { - struct item item_tmp {}; + Item item_tmp {}; item_tmp.nameid = nameid; if (HARGO2(5)) //アイテムを指定したIDに渡す - sd = map_id2sd(conv_num(st, &AARGO2(5))); - if (sd == NULL) //アイテムを渡す相手がいなかったらお帰り + sd = map_id2sd(wrap<BlockId>(conv_num(st, &AARGO2(5)))); + if (sd == nullptr) //アイテムを渡す相手がいなかったらお帰り return; PickupFail flag; if ((flag = pc_additem(sd, &item_tmp, amount)) != PickupFail::OKAY) { - clif_additem(sd, 0, 0, flag); + clif_additem(sd, IOff0::from(0), 0, flag); map_addflooritem(&item_tmp, amount, sd->bl_m, sd->bl_x, sd->bl_y, - NULL, NULL, NULL); + nullptr, nullptr, nullptr); } } @@ -2033,7 +2063,8 @@ void builtin_getitem(ScriptState *st) static void builtin_makeitem(ScriptState *st) { - int nameid, amount; + ItemNameId nameid; + int amount; int x, y; dumb_ptr<map_session_data> sd; struct script_data *data; @@ -2046,12 +2077,11 @@ void builtin_makeitem(ScriptState *st) { ZString name = ZString(conv_str(st, data)); struct item_data *item_data = itemdb_searchname(name); - nameid = 512; //Apple Item ID if (item_data) nameid = item_data->nameid; } else - nameid = conv_num(st, data); + nameid = wrap<ItemNameId>(conv_num(st, data)); amount = conv_num(st, &AARGO2(3)); MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(4)))); @@ -2064,12 +2094,12 @@ void builtin_makeitem(ScriptState *st) else m = map_mapname2mapid(mapname); - if (nameid > 0) + if (nameid) { - struct item item_tmp {}; + Item item_tmp {}; item_tmp.nameid = nameid; - map_addflooritem(&item_tmp, amount, m, x, y, NULL, NULL, NULL); + map_addflooritem(&item_tmp, amount, m, x, y, nullptr, nullptr, nullptr); } } @@ -2080,7 +2110,8 @@ void builtin_makeitem(ScriptState *st) static void builtin_delitem(ScriptState *st) { - int nameid = 0, amount, i; + ItemNameId nameid; + int amount; dumb_ptr<map_session_data> sd; struct script_data *data; @@ -2092,31 +2123,21 @@ void builtin_delitem(ScriptState *st) { ZString name = ZString(conv_str(st, data)); struct item_data *item_data = itemdb_searchname(name); - //nameid=512; if (item_data) nameid = item_data->nameid; } else - nameid = conv_num(st, data); + nameid = wrap<ItemNameId>(conv_num(st, data)); amount = conv_num(st, &AARGO2(3)); - if (nameid < 500 || amount <= 0) + if (!nameid || amount <= 0) { //by Lupus. Don't run FOR if u got wrong item ID or amount<=0 - //PRINTF("wrong item ID or amount<=0 : delitem %i,\n",nameid,amount); return; } - for (i = 0; i < MAX_INVENTORY; i++) - { - if (sd->status.inventory[i].nameid <= 0 - || sd->inventory_data[i] == NULL - || sd->inventory_data[i]->type != ItemType::_7 - || sd->status.inventory[i].amount <= 0) - continue; - } - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (sd->status.inventory[i].nameid == nameid) { @@ -2153,7 +2174,7 @@ void builtin_readparam(ScriptState *st) else sd = script_rid2sd(st); - if (sd == NULL) + if (sd == nullptr) { push_int(st->stack, ByteCode::INT, -1); return; @@ -2178,19 +2199,19 @@ void builtin_getcharid(ScriptState *st) sd = map_nick2sd(stringish<CharName>(ZString(conv_str(st, &AARGO2(3))))); else sd = script_rid2sd(st); - if (sd == NULL) + if (sd == nullptr) { push_int(st->stack, ByteCode::INT, -1); return; } if (num == 0) - push_int(st->stack, ByteCode::INT, sd->status_key.char_id); + push_int(st->stack, ByteCode::INT, unwrap<CharId>(sd->status_key.char_id)); if (num == 1) - push_int(st->stack, ByteCode::INT, sd->status.party_id); + push_int(st->stack, ByteCode::INT, unwrap<PartyId>(sd->status.party_id)); if (num == 2) push_int(st->stack, ByteCode::INT, 0/*guild_id*/); if (num == 3) - push_int(st->stack, ByteCode::INT, sd->status_key.account_id); + push_int(st->stack, ByteCode::INT, unwrap<AccountId>(sd->status_key.account_id)); } /*========================================== @@ -2198,9 +2219,9 @@ void builtin_getcharid(ScriptState *st) *------------------------------------------ */ static -dumb_string builtin_getpartyname_sub(int party_id) +dumb_string builtin_getpartyname_sub(PartyId party_id) { - struct party *p = party_search(party_id); + PartyPair p = party_search(party_id); if (p) return dumb_string::copys(p->name); @@ -2231,12 +2252,12 @@ void builtin_strcharinfo(ScriptState *st) if (buf) push_str(st->stack, ByteCode::STR, buf); else - push_str(st->stack, ByteCode::CONSTSTR, dumb_string::fake("")); + push_str(st->stack, ByteCode::CONSTSTR, dumb_string::fake(""_s)); } if (num == 2) { // was: guild name - push_str(st->stack, ByteCode::CONSTSTR, dumb_string::fake("")); + push_str(st->stack, ByteCode::CONSTSTR, dumb_string::fake(""_s)); } } @@ -2266,23 +2287,23 @@ Array<EPOS, 11> equip //= static void builtin_getequipid(ScriptState *st) { - int i, num; + int num; dumb_ptr<map_session_data> sd; struct item_data *item; sd = script_rid2sd(st); - if (sd == NULL) + if (sd == nullptr) { - PRINTF("getequipid: sd == NULL\n"); + PRINTF("getequipid: sd == nullptr\n"_fmt); return; } num = conv_num(st, &AARGO2(2)); - i = pc_checkequip(sd, equip[num - 1]); - if (i >= 0) + IOff0 i = pc_checkequip(sd, equip[num - 1]); + if (i.ok()) { item = sd->inventory_data[i]; if (item) - push_int(st->stack, ByteCode::INT, item->nameid); + push_int(st->stack, ByteCode::INT, unwrap<ItemNameId>(item->nameid)); else push_int(st->stack, ByteCode::INT, 0); } @@ -2299,7 +2320,7 @@ void builtin_getequipid(ScriptState *st) static void builtin_getequipname(ScriptState *st) { - int i, num; + int num; dumb_ptr<map_session_data> sd; struct item_data *item; @@ -2307,18 +2328,18 @@ void builtin_getequipname(ScriptState *st) sd = script_rid2sd(st); num = conv_num(st, &AARGO2(2)); - i = pc_checkequip(sd, equip[num - 1]); - if (i >= 0) + IOff0 i = pc_checkequip(sd, equip[num - 1]); + if (i.ok()) { item = sd->inventory_data[i]; if (item) - buf = STRPRINTF("%s-[%s]", pos_str[num - 1], item->jname); + buf = STRPRINTF("%s-[%s]"_fmt, pos_str[num - 1], item->jname); else - buf = STRPRINTF("%s-[%s]", pos_str[num - 1], pos_str[10]); + buf = STRPRINTF("%s-[%s]"_fmt, pos_str[num - 1], pos_str[10]); } else { - buf = STRPRINTF("%s-[%s]", pos_str[num - 1], pos_str[10]); + buf = STRPRINTF("%s-[%s]"_fmt, pos_str[num - 1], pos_str[10]); } push_str(st->stack, ByteCode::STR, dumb_string::copys(buf)); @@ -2423,7 +2444,7 @@ void builtin_getskilllv(ScriptState *st) static void builtin_getgmlevel(ScriptState *st) { - push_int(st->stack, ByteCode::INT, pc_isGM(script_rid2sd(st))); + push_int(st->stack, ByteCode::INT, pc_isGM(script_rid2sd(st)).get_all_bits()); } /*========================================== @@ -2448,7 +2469,7 @@ void builtin_getopt2(ScriptState *st) sd = script_rid2sd(st); - push_int(st->stack, ByteCode::INT, uint16_t(sd->opt2)); + push_int(st->stack, ByteCode::INT, static_cast<uint16_t>(sd->opt2)); } @@ -2613,14 +2634,15 @@ void builtin_getexp(ScriptState *st) static void builtin_monster(ScriptState *st) { - int mob_class, amount, x, y; + Species mob_class; + int amount, x, y; NpcEvent event; MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2)))); x = conv_num(st, &AARGO2(3)); y = conv_num(st, &AARGO2(4)); MobName str = stringish<MobName>(ZString(conv_str(st, &AARGO2(5)))); - mob_class = conv_num(st, &AARGO2(6)); + mob_class = wrap<Species>(conv_num(st, &AARGO2(6))); amount = conv_num(st, &AARGO2(7)); if (HARGO2(8)) extract(ZString(conv_str(st, &AARGO2(8))), &event); @@ -2636,7 +2658,8 @@ void builtin_monster(ScriptState *st) static void builtin_areamonster(ScriptState *st) { - int mob_class, amount, x0, y0, x1, y1; + Species mob_class; + int amount, x0, y0, x1, y1; NpcEvent event; MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2)))); @@ -2645,7 +2668,7 @@ void builtin_areamonster(ScriptState *st) x1 = conv_num(st, &AARGO2(5)); y1 = conv_num(st, &AARGO2(6)); MobName str = stringish<MobName>(ZString(conv_str(st, &AARGO2(7)))); - mob_class = conv_num(st, &AARGO2(8)); + mob_class = wrap<Species>(conv_num(st, &AARGO2(8))); amount = conv_num(st, &AARGO2(9)); if (HARGO2(10)) extract(ZString(conv_str(st, &AARGO2(10))), &event); @@ -2683,7 +2706,7 @@ void builtin_killmonster(ScriptState *st) MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARGO2(2)))); ZString event_ = ZString(conv_str(st, &AARGO2(3))); NpcEvent event; - if (event_ != "All") + if (event_ != "All"_s) extract(event_, &event); map_local *m = map_mapname2mapid(mapname); @@ -2997,7 +3020,7 @@ void builtin_getareausers(ScriptState *st) *------------------------------------------ */ static -void builtin_getareadropitem_sub(dumb_ptr<block_list> bl, int item, int *amount) +void builtin_getareadropitem_sub(dumb_ptr<block_list> bl, ItemNameId item, int *amount) { dumb_ptr<flooritem_data> drop = bl->is_item(); @@ -3007,14 +3030,14 @@ void builtin_getareadropitem_sub(dumb_ptr<block_list> bl, int item, int *amount) } static -void builtin_getareadropitem_sub_anddelete(dumb_ptr<block_list> bl, int item, int *amount) +void builtin_getareadropitem_sub_anddelete(dumb_ptr<block_list> bl, ItemNameId item, int *amount) { dumb_ptr<flooritem_data> drop = bl->is_item(); if (drop->item_data.nameid == item) { (*amount) += drop->item_data.amount; - clif_clearflooritem(drop, 0); + clif_clearflooritem(drop, nullptr); map_delobject(drop->bl_id, drop->bl_type); } } @@ -3022,7 +3045,8 @@ void builtin_getareadropitem_sub_anddelete(dumb_ptr<block_list> bl, int item, in static void builtin_getareadropitem(ScriptState *st) { - int x0, y0, x1, y1, item, amount = 0, delitems = 0; + ItemNameId item; + int x0, y0, x1, y1, amount = 0, delitems = 0; struct script_data *data; MapName str = stringish<MapName>(ZString(conv_str(st, &AARGO2(2)))); @@ -3037,12 +3061,11 @@ void builtin_getareadropitem(ScriptState *st) { ZString name = ZString(conv_str(st, data)); struct item_data *item_data = itemdb_searchname(name); - item = 512; if (item_data) item = item_data->nameid; } else - item = conv_num(st, data); + item = wrap<ItemNameId>(conv_num(st, data)); if (HARGO2(8)) delitems = conv_num(st, &AARGO2(8)); @@ -3102,7 +3125,7 @@ void builtin_sc_start(ScriptState *st) int val1; StatusChange type = static_cast<StatusChange>(conv_num(st, &AARGO2(2))); interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(3))); - if (tick < std::chrono::seconds(1)) + if (tick < 1_s) // work around old behaviour of: // speed potion // atk potion @@ -3113,7 +3136,7 @@ void builtin_sc_start(ScriptState *st) tick *= 1000; val1 = conv_num(st, &AARGO2(4)); if (HARGO2(5)) //指定したキャラを状態異常にする - bl = map_id2bl(conv_num(st, &AARGO2(5))); + bl = map_id2bl(wrap<BlockId>(conv_num(st, &AARGO2(5)))); else bl = map_id2bl(st->rid); skill_status_change_start(bl, type, val1, tick); @@ -3151,7 +3174,7 @@ static void builtin_debugmes(ScriptState *st) { dumb_string mes = conv_str(st, &AARGO2(2)); - PRINTF("script debug : %d %d : %s\n", + PRINTF("script debug : %d %d : %s\n"_fmt, st->rid, st->oid, mes); } @@ -3174,10 +3197,10 @@ void builtin_resetstatus(ScriptState *st) static void builtin_changesex(ScriptState *st) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; sd = script_rid2sd(st); - chrif_char_ask_name(-1, sd->status_key.name, 5, HumanTimeDiff()); // type: 5 - changesex + chrif_char_ask_name(AccountId(), sd->status_key.name, 5, HumanTimeDiff()); // type: 5 - changesex chrif_save(sd); } @@ -3188,8 +3211,8 @@ void builtin_changesex(ScriptState *st) static void builtin_attachrid(ScriptState *st) { - st->rid = conv_num(st, &AARGO2(2)); - push_int(st->stack, ByteCode::INT, (map_id2sd(st->rid) != NULL)); + st->rid = wrap<BlockId>(conv_num(st, &AARGO2(2))); + push_int(st->stack, ByteCode::INT, (map_id2sd(st->rid) != nullptr)); } /*========================================== @@ -3199,7 +3222,7 @@ void builtin_attachrid(ScriptState *st) static void builtin_detachrid(ScriptState *st) { - st->rid = 0; + st->rid = BlockId(); } /*========================================== @@ -3210,8 +3233,7 @@ static void builtin_isloggedin(ScriptState *st) { push_int(st->stack, ByteCode::INT, - map_id2sd(conv_num(st, - &AARGO2(2))) != NULL); + map_id2sd(wrap<BlockId>(conv_num(st, &AARGO2(2)))) != nullptr); } static @@ -3279,7 +3301,7 @@ void builtin_pvpon(ScriptState *st) { if (m == pl_sd->bl_m && !pl_sd->pvp_timer) { - pl_sd->pvp_timer = Timer(gettick() + std::chrono::milliseconds(200), + pl_sd->pvp_timer = Timer(gettick() + 200_ms, std::bind(pc_calc_pvprank_timer, ph::_1, ph::_2, pl_sd->bl_id)); pl_sd->pvp_rank = 0; @@ -3411,7 +3433,7 @@ void builtin_marriage(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); dumb_ptr<map_session_data> p_sd = map_nick2sd(partner); - if (sd == NULL || p_sd == NULL || pc_marriage(sd, p_sd) < 0) + if (sd == nullptr || p_sd == nullptr || pc_marriage(sd, p_sd) < 0) { push_int(st->stack, ByteCode::INT, 0); return; @@ -3428,7 +3450,7 @@ void builtin_divorce(ScriptState *st) sd->npc_flags.divorce = 1; - if (sd == NULL || pc_divorce(sd) < 0) + if (sd == nullptr || pc_divorce(sd) < 0) { push_int(st->stack, ByteCode::INT, 0); return; @@ -3456,7 +3478,7 @@ void builtin_getitemname(ScriptState *st) } else { - int item_id = conv_num(st, data); + ItemNameId item_id = wrap<ItemNameId>(conv_num(st, data)); i_data = itemdb_search(item_id); } @@ -3464,7 +3486,7 @@ void builtin_getitemname(ScriptState *st) if (i_data) item_name = dumb_string::copys(i_data->jname); else - item_name = dumb_string::copys("Unknown Item"); + item_name = dumb_string::copys("Unknown Item"_s); push_str(st->stack, ByteCode::STR, item_name); } @@ -3476,7 +3498,7 @@ void builtin_getspellinvocation(ScriptState *st) AString invocation = magic_find_invocation(name.str()); if (!invocation) - invocation = "..."; + invocation = "..."_s; push_str(st->stack, ByteCode::STR, dumb_string::copys(invocation)); } @@ -3486,7 +3508,7 @@ void builtin_getpartnerid2(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - push_int(st->stack, ByteCode::INT, sd->status.partner_id); + push_int(st->stack, ByteCode::INT, unwrap<CharId>(sd->status.partner_id)); } /*========================================== @@ -3497,24 +3519,24 @@ static void builtin_getinventorylist(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - int i, j = 0; + int j = 0; if (!sd) return; - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { - if (sd->status.inventory[i].nameid > 0 + if (sd->status.inventory[i].nameid && sd->status.inventory[i].amount > 0) { - pc_setreg(sd, SIR::from(variable_names.intern("@inventorylist_id"), j), - sd->status.inventory[i].nameid); - pc_setreg(sd, SIR::from(variable_names.intern("@inventorylist_amount"), j), + pc_setreg(sd, SIR::from(variable_names.intern("@inventorylist_id"_s), j), + unwrap<ItemNameId>(sd->status.inventory[i].nameid)); + pc_setreg(sd, SIR::from(variable_names.intern("@inventorylist_amount"_s), j), sd->status.inventory[i].amount); - pc_setreg(sd, SIR::from(variable_names.intern("@inventorylist_equip"), j), + pc_setreg(sd, SIR::from(variable_names.intern("@inventorylist_equip"_s), j), static_cast<uint16_t>(sd->status.inventory[i].equip)); j++; } } - pc_setreg(sd, SIR::from(variable_names.intern("@inventorylist_count")), j); + pc_setreg(sd, SIR::from(variable_names.intern("@inventorylist_count"_s)), j); } static @@ -3534,18 +3556,18 @@ void builtin_getactivatedpoolskilllist(ScriptState *st) if (sd->status.skill[skill_id].lv) { - pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_id"), count), + pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_id"_s), count), static_cast<uint16_t>(skill_id)); - pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_lv"), count), + pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_lv"_s), count), sd->status.skill[skill_id].lv); - pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_flag"), count), + pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_flag"_s), count), static_cast<uint16_t>(sd->status.skill[skill_id].flags)); - pc_setregstr(sd, SIR::from(variable_names.intern("@skilllist_name$"), count), + pc_setregstr(sd, SIR::from(variable_names.intern("@skilllist_name$"_s), count), skill_name(skill_id)); ++count; } } - pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_count")), count); + pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_count"_s)), count); } @@ -3565,18 +3587,18 @@ void builtin_getunactivatedpoolskilllist(ScriptState *st) if (sd->status.skill[skill_id].lv && !bool(sd->status.skill[skill_id].flags & SkillFlags::POOL_ACTIVATED)) { - pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_id"), count), + pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_id"_s), count), static_cast<uint16_t>(skill_id)); - pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_lv"), count), + pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_lv"_s), count), sd->status.skill[skill_id].lv); - pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_flag"), count), + pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_flag"_s), count), static_cast<uint16_t>(sd->status.skill[skill_id].flags)); - pc_setregstr(sd, SIR::from(variable_names.intern("@skilllist_name$"), count), + pc_setregstr(sd, SIR::from(variable_names.intern("@skilllist_name$"_s), count), skill_name(skill_id)); ++count; } } - pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_count")), count); + pc_setreg(sd, SIR::from(variable_names.intern("@skilllist_count"_s)), count); } static @@ -3616,9 +3638,9 @@ static void builtin_misceffect(ScriptState *st) { int type; - int id = 0; + BlockId id; CharName name; - dumb_ptr<block_list> bl = NULL; + dumb_ptr<block_list> bl = nullptr; type = conv_num(st, &AARGO2(2)); @@ -3631,7 +3653,7 @@ void builtin_misceffect(ScriptState *st) if (sdata->type == ByteCode::STR || sdata->type == ByteCode::CONSTSTR) name = stringish<CharName>(ZString(conv_str(st, sdata))); else - id = conv_num(st, sdata); + id = wrap<BlockId>(conv_num(st, sdata)); } if (name.to__actual()) @@ -3665,7 +3687,7 @@ void builtin_specialeffect(ScriptState *st) { dumb_ptr<block_list> bl = map_id2bl(st->oid); - if (bl == NULL) + if (bl == nullptr) return; clif_specialeffect(bl, @@ -3680,7 +3702,7 @@ void builtin_specialeffect2(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - if (sd == NULL) + if (sd == nullptr) return; clif_specialeffect(sd, @@ -3700,13 +3722,13 @@ void builtin_nude(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - if (sd == NULL) + if (sd == nullptr) return; for (EQUIP i : EQUIPs) { - int idx = sd->equip_index_maybe[i]; - if (idx >= 0) + IOff0 idx = sd->equip_index_maybe[i]; + if (idx.ok()) pc_unequipitem(sd, idx, CalcStatus::LATER); } pc_calcstatus(sd, 0); @@ -3722,15 +3744,15 @@ static void builtin_unequipbyid(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - if (sd == NULL) + if (sd == nullptr) return; EQUIP slot_id = EQUIP(conv_num(st, &AARGO2(2))); if (slot_id >= EQUIP() && slot_id < EQUIP::COUNT) { - int idx = sd->equip_index_maybe[slot_id]; - if (idx >= 0) + IOff0 idx = sd->equip_index_maybe[slot_id]; + if (idx.ok()) pc_unequipitem(sd, idx, CalcStatus::LATER); } @@ -3753,7 +3775,7 @@ void builtin_gmcommand(ScriptState *st) sd = script_rid2sd(st); dumb_string cmd = conv_str(st, &AARGO2(2)); - is_atcommand(sd->sess, sd, cmd, 99); + is_atcommand(sd->sess, sd, cmd, GmLevel::from(-1U)); } @@ -3766,7 +3788,7 @@ static void builtin_npcwarp(ScriptState *st) { int x, y; - dumb_ptr<npc_data> nd = NULL; + dumb_ptr<npc_data> nd = nullptr; x = conv_num(st, &AARGO2(2)); y = conv_num(st, &AARGO2(3)); @@ -3775,7 +3797,7 @@ void builtin_npcwarp(ScriptState *st) if (!nd) { - PRINTF("builtin_npcwarp: no such npc: %s\n", npc); + PRINTF("builtin_npcwarp: no such npc: %s\n"_fmt, npc); return; } @@ -3808,7 +3830,7 @@ void builtin_message(ScriptState *st) ZString msg = ZString(conv_str(st, &AARGO2(3))); dumb_ptr<map_session_data> pl_sd = map_nick2sd(player); - if (pl_sd == NULL) + if (pl_sd == nullptr) return; clif_displaymessage(pl_sd->sess, msg); @@ -3828,11 +3850,7 @@ void builtin_npctalk(ScriptState *st) if (nd) { - MString message; - message += nd->name; - message += " : "; - message += ZString(str); - clif_message(nd, AString(message)); + clif_message(nd, XString(str)); } } @@ -3856,13 +3874,13 @@ void builtin_getlook(ScriptState *st) val = static_cast<uint16_t>(sd->status.weapon); break; case LOOK::HEAD_BOTTOM: //3 - val = sd->status.head_bottom; + val = unwrap<ItemNameId>(sd->status.head_bottom); break; case LOOK::HEAD_TOP: //4 - val = sd->status.head_top; + val = unwrap<ItemNameId>(sd->status.head_top); break; case LOOK::HEAD_MID: //5 - val = sd->status.head_mid; + val = unwrap<ItemNameId>(sd->status.head_mid); break; case LOOK::HAIR_COLOR: //6 val = sd->status.hair_color; @@ -3871,7 +3889,7 @@ void builtin_getlook(ScriptState *st) val = sd->status.clothes_color; break; case LOOK::SHIELD: //8 - val = sd->status.shield; + val = unwrap<ItemNameId>(sd->status.shield); break; case LOOK::SHOES: //9 break; @@ -3988,7 +4006,7 @@ void builtin_shop(ScriptState *st) nd = npc_name2id(name); if (!nd) { - PRINTF("builtin_shop: no such npc: %s\n", name); + PRINTF("builtin_shop: no such npc: %s\n"_fmt, name); return; } @@ -4017,11 +4035,11 @@ void builtin_fakenpcname(ScriptState *st) { NpcName name = stringish<NpcName>(ZString(conv_str(st, &AARGO2(2)))); NpcName newname = stringish<NpcName>(ZString(conv_str(st, &AARGO2(3)))); - int newsprite = conv_num(st, &AARGO2(4)); + Species newsprite = wrap<Species>(static_cast<uint16_t>(conv_num(st, &AARGO2(4)))); dumb_ptr<npc_data> nd = npc_name2id(name); if (!nd) { - PRINTF("builtin_fakenpcname: no such npc: %s\n", name); + PRINTF("builtin_fakenpcname: no such npc: %s\n"_fmt, name); return; } nd->name = newname; @@ -4205,7 +4223,7 @@ void op_2str(ScriptState *st, ByteCode op, dumb_string s1_, dumb_string s2_) a = s1 <= s2; break; default: - PRINTF("illegal string operater\n"); + PRINTF("illegal string operater\n"_fmt); break; } @@ -4308,7 +4326,7 @@ void op_2(ScriptState *st, ByteCode op) else { // si,is => error - PRINTF("script: op_2: int&str, str&int not allow.\n"); + PRINTF("script: op_2: int&str, str&int not allow.\n"_fmt); push_int(st->stack, ByteCode::INT, 0); } } @@ -4351,7 +4369,7 @@ void run_func(ScriptState *st) if (start_sp == 0) { if (battle_config.error_log) - PRINTF("function not found\n"); + PRINTF("function not found\n"_fmt); st->state = ScriptEndState::END; return; } @@ -4364,52 +4382,52 @@ void run_func(ScriptState *st) size_t func = st->stack->stack_datav[st->start].u.numi; if (st->stack->stack_datav[st->start].type != ByteCode::FUNC_REF) { - PRINTF("run_func: not function and command! \n"); + PRINTF("run_func: not function and command! \n"_fmt); st->state = ScriptEndState::END; return; } if (DEBUG_RUN && battle_config.etc_log) { - PRINTF("run_func : %s\n", + PRINTF("run_func : %s\n"_fmt, builtin_functions[func].name); - PRINTF("stack dump :"); + PRINTF("stack dump :"_fmt); for (script_data& d : st->stack->stack_datav) { switch (d.type) { case ByteCode::INT: - PRINTF(" int(%d)", d.u.numi); + PRINTF(" int(%d)"_fmt, d.u.numi); break; case ByteCode::RETINFO: - PRINTF(" retinfo(%p)", static_cast<const void *>(d.u.script)); + PRINTF(" retinfo(%p)"_fmt, static_cast<const void *>(d.u.script)); break; case ByteCode::PARAM_: - PRINTF(" param(%d)", d.u.reg.sp()); + PRINTF(" param(%d)"_fmt, d.u.reg.sp()); break; case ByteCode::VARIABLE: - PRINTF(" name(%s)[%d]", variable_names.outtern(d.u.reg.base()), d.u.reg.index()); + PRINTF(" name(%s)[%d]"_fmt, variable_names.outtern(d.u.reg.base()), d.u.reg.index()); break; case ByteCode::ARG: - PRINTF(" arg"); + PRINTF(" arg"_fmt); break; case ByteCode::POS: - PRINTF(" pos(%d)", d.u.numi); + PRINTF(" pos(%d)"_fmt, d.u.numi); break; case ByteCode::STR: - PRINTF(" str(%s)", d.u.str); + PRINTF(" str(%s)"_fmt, d.u.str); break; case ByteCode::CONSTSTR: - PRINTF(" cstr(%s)", d.u.str); + PRINTF(" cstr(%s)"_fmt, d.u.str); break; case ByteCode::FUNC_REF: - PRINTF(" func(%s)", builtin_functions[d.u.numi].name); + PRINTF(" func(%s)"_fmt, builtin_functions[d.u.numi].name); break; default: - PRINTF(" %d,%d", d.type, d.u.numi); + PRINTF(" %d,%d"_fmt, d.type, d.u.numi); } } - PRINTF("\n"); + PRINTF("\n"_fmt); } builtin_functions[func].func(st); @@ -4424,7 +4442,7 @@ void run_func(ScriptState *st) if (st->defsp < 4 || st->stack->stack_datav[st->defsp - 1].type != ByteCode::RETINFO) { - PRINTF("script:run_func (return) return without callfunc or callsub!\n"); + PRINTF("script:run_func (return) return without callfunc or callsub!\n"_fmt); st->state = ScriptEndState::END; return; } @@ -4449,15 +4467,15 @@ void dump_script(const ScriptBuffer *script) ScriptPointer scriptp(script, 0); while (scriptp.pos < reinterpret_cast<const std::vector<ByteCode> *>(script)->size()) { - PRINTF("%6zu: ", scriptp.pos); + PRINTF("%6zu: "_fmt, scriptp.pos); switch (ByteCode c = get_com(&scriptp)) { case ByteCode::EOL: - PRINTF("EOL\n"); // extra newline between functions + PRINTF("EOL\n"_fmt); // extra newline between functions break; case ByteCode::INT: // synthesized! - PRINTF("INT %d", get_num(&scriptp)); + PRINTF("INT %d"_fmt, get_num(&scriptp)); break; case ByteCode::POS: @@ -4472,103 +4490,103 @@ void dump_script(const ScriptBuffer *script) switch(c) { case ByteCode::POS: - PRINTF("POS %d", arg); + PRINTF("POS %d"_fmt, arg); break; case ByteCode::VARIABLE: - PRINTF("VARIABLE %s", variable_names.outtern(arg)); + PRINTF("VARIABLE %s"_fmt, variable_names.outtern(arg)); break; case ByteCode::FUNC_REF: - PRINTF("FUNC_REF %s", builtin_functions[arg].name); + PRINTF("FUNC_REF %s"_fmt, builtin_functions[arg].name); break; case ByteCode::PARAM_: - PRINTF("PARAM SP::#%d (sorry)", arg); + PRINTF("PARAM SP::#%d (sorry)"_fmt, arg); break; } } break; case ByteCode::ARG: - PRINTF("ARG"); + PRINTF("ARG"_fmt); break; case ByteCode::STR: - PRINTF("STR \"%s\"", scriptp.pops()); + PRINTF("STR \"%s\""_fmt, scriptp.pops()); break; case ByteCode::FUNC_: - PRINTF("FUNC_"); + PRINTF("FUNC_"_fmt); break; case ByteCode::ADD: - PRINTF("ADD"); + PRINTF("ADD"_fmt); break; case ByteCode::SUB: - PRINTF("SUB"); + PRINTF("SUB"_fmt); break; case ByteCode::MUL: - PRINTF("MUL"); + PRINTF("MUL"_fmt); break; case ByteCode::DIV: - PRINTF("DIV"); + PRINTF("DIV"_fmt); break; case ByteCode::MOD: - PRINTF("MOD"); + PRINTF("MOD"_fmt); break; case ByteCode::EQ: - PRINTF("EQ"); + PRINTF("EQ"_fmt); break; case ByteCode::NE: - PRINTF("NE"); + PRINTF("NE"_fmt); break; case ByteCode::GT: - PRINTF("GT"); + PRINTF("GT"_fmt); break; case ByteCode::GE: - PRINTF("GE"); + PRINTF("GE"_fmt); break; case ByteCode::LT: - PRINTF("LT"); + PRINTF("LT"_fmt); break; case ByteCode::LE: - PRINTF("LE"); + PRINTF("LE"_fmt); break; case ByteCode::AND: - PRINTF("AND"); + PRINTF("AND"_fmt); break; case ByteCode::OR: - PRINTF("OR"); + PRINTF("OR"_fmt); break; case ByteCode::XOR: - PRINTF("XOR"); + PRINTF("XOR"_fmt); break; case ByteCode::LAND: - PRINTF("LAND"); + PRINTF("LAND"_fmt); break; case ByteCode::LOR: - PRINTF("LOR"); + PRINTF("LOR"_fmt); break; case ByteCode::R_SHIFT: - PRINTF("R_SHIFT"); + PRINTF("R_SHIFT"_fmt); break; case ByteCode::L_SHIFT: - PRINTF("L_SHIFT"); + PRINTF("L_SHIFT"_fmt); break; case ByteCode::NEG: - PRINTF("NEG"); + PRINTF("NEG"_fmt); break; case ByteCode::NOT: - PRINTF("NOT"); + PRINTF("NOT"_fmt); break; case ByteCode::LNOT: - PRINTF("LNOT"); + PRINTF("LNOT"_fmt); break; case ByteCode::NOP: - PRINTF("NOP"); + PRINTF("NOP"_fmt); break; default: - PRINTF("??? %d", c); + PRINTF("??? %d"_fmt, c); break; } - PRINTF("\n"); + PRINTF("\n"_fmt); } } @@ -4595,7 +4613,7 @@ void run_script_main(ScriptState *st, const ScriptBuffer *rootscript) if (stack->stack_datav.size() != st->defsp) { if (battle_config.error_log) - PRINTF("stack.sp (%zu) != default (%d)\n", + PRINTF("stack.sp (%zu) != default (%d)\n"_fmt, stack->stack_datav.size(), st->defsp); stack->stack_datav.resize(st->defsp); @@ -4650,7 +4668,7 @@ void run_script_main(ScriptState *st, const ScriptBuffer *rootscript) st->state = ScriptEndState::ZERO; if (gotocount > 0 && (--gotocount) <= 0) { - PRINTF("run_script: infinity loop !\n"); + PRINTF("run_script: infinity loop !\n"_fmt); st->state = ScriptEndState::END; } } @@ -4692,14 +4710,14 @@ void run_script_main(ScriptState *st, const ScriptBuffer *rootscript) default: if (battle_config.error_log) - PRINTF("unknown command : %d @ %zu\n", + PRINTF("unknown command : %d @ %zu\n"_fmt, c, st->scriptp.pos); st->state = ScriptEndState::END; break; } if (cmdcount > 0 && (--cmdcount) <= 0) { - PRINTF("run_script: infinity loop !\n"); + PRINTF("run_script: infinity loop !\n"_fmt); st->state = ScriptEndState::END; } } @@ -4739,12 +4757,12 @@ void run_script_main(ScriptState *st, const ScriptBuffer *rootscript) * スクリプトの実行 *------------------------------------------ */ -int run_script(ScriptPointer sp, int rid, int oid) +int run_script(ScriptPointer sp, BlockId rid, BlockId oid) { return run_script_l(sp, rid, oid, nullptr); } -int run_script_l(ScriptPointer sp, int rid, int oid, +int run_script_l(ScriptPointer sp, BlockId rid, BlockId oid, Slice<argrec_t> args) { struct script_stack stack; @@ -4752,7 +4770,7 @@ int run_script_l(ScriptPointer sp, int rid, int oid, dumb_ptr<map_session_data> sd = map_id2sd(rid); const ScriptBuffer *rootscript = sp.code; int i; - if (sp.code == NULL || sp.pos >> 24) + if (sp.code == nullptr || sp.pos >> 24) return -1; if (sd && !sd->npc_stackbuf.empty() && sd->npc_scriptroot == rootscript) @@ -4846,7 +4864,7 @@ void script_load_mapreg(void) else { borken: - PRINTF("%s: %s broken data !\n", mapreg_txt, AString(buf1)); + PRINTF("%s: %s broken data !\n"_fmt, mapreg_txt, AString(buf1)); continue; } } @@ -4865,9 +4883,9 @@ void script_save_mapreg_intsub(SIR key, int data, io::WriteFile& fp) if (name[1] != '@') { if (i == 0) - FPRINTF(fp, "%s\t%d\n", name, data); + FPRINTF(fp, "%s\t%d\n"_fmt, name, data); else - FPRINTF(fp, "%s,%d\t%d\n", name, i, data); + FPRINTF(fp, "%s,%d\t%d\n"_fmt, name, i, data); } } @@ -4879,9 +4897,9 @@ void script_save_mapreg_strsub(SIR key, ZString data, io::WriteFile& fp) if (name[1] != '@') { if (i == 0) - FPRINTF(fp, "%s\t%s\n", name, data); + FPRINTF(fp, "%s\t%s\n"_fmt, name, data); else - FPRINTF(fp, "%s,%d\t%s\n", name, i, data); + FPRINTF(fp, "%s,%d\t%s\n"_fmt, name, i, data); } } @@ -4932,129 +4950,128 @@ void do_init_script(void) ).detach(); } -#define BUILTIN(func, args) \ -{builtin_##func, {#func}, {args}} +#define BUILTIN(func, args, ret) \ +{builtin_##func, #func ## _s, args, ret} BuiltinFunction builtin_functions[] = { - BUILTIN(mes, "s"), - BUILTIN(next, ""), - BUILTIN(close, ""), - BUILTIN(close2, ""), - BUILTIN(menu, "sL*"), - BUILTIN(goto, "L"), - BUILTIN(callsub, "L"), - BUILTIN(callfunc, "F"), - BUILTIN(return, ""), - BUILTIN(input, "N"), - BUILTIN(warp, "Mxy"), - BUILTIN(isat, "Mxy"), - BUILTIN(areawarp, "MxyxyMxy"), - BUILTIN(setlook, "ii"), - BUILTIN(set, "Ne"), - BUILTIN(setarray, "Ne*"), - BUILTIN(cleararray, "Nei"), - BUILTIN(getarraysize, "N"), - BUILTIN(getelementofarray, "Ni"), - BUILTIN(if, "iF*"), - BUILTIN(getitem, "Ii**"), - BUILTIN(makeitem, "IiMxy"), - BUILTIN(delitem, "Ii"), - BUILTIN(heal, "ii"), - BUILTIN(itemheal, "ii"), - BUILTIN(percentheal, "ii"), - BUILTIN(rand, "i*"), - BUILTIN(pow, "ii"), - BUILTIN(countitem, "I"), - BUILTIN(checkweight, "Ii"), - BUILTIN(readparam, "i*"), - BUILTIN(getcharid, "i*"), - BUILTIN(strcharinfo, "i"), - BUILTIN(getequipid, "i"), - BUILTIN(getequipname, "i"), - BUILTIN(statusup2, "ii"), - BUILTIN(bonus, "ii"), - BUILTIN(bonus2, "iii"), - BUILTIN(skill, "ii*"), - BUILTIN(setskill, "ii"), - BUILTIN(getskilllv, "i"), - BUILTIN(getgmlevel, ""), - BUILTIN(end, ""), - BUILTIN(getopt2, ""), - BUILTIN(setopt2, "i"), - BUILTIN(savepoint, "Mxy"), - BUILTIN(gettimetick, "i"), - BUILTIN(gettime, "i"), - BUILTIN(openstorage, "*"), - BUILTIN(monster, "Mxysmi*"), - BUILTIN(areamonster, "Mxyxysmi*"), - BUILTIN(killmonster, "ME"), - BUILTIN(killmonsterall, "M"), - BUILTIN(donpcevent, "E"), - BUILTIN(addtimer, "tE"), - BUILTIN(initnpctimer, ""), - BUILTIN(stopnpctimer, ""), - BUILTIN(startnpctimer, "*"), - BUILTIN(setnpctimer, "i"), - BUILTIN(getnpctimer, "i"), - BUILTIN(announce, "si"), - BUILTIN(mapannounce, "Msi"), - BUILTIN(getusers, "i"), - BUILTIN(getmapusers, "M"), - BUILTIN(getareausers, "Mxyxy*"), - BUILTIN(getareadropitem, "Mxyxyi*"), - BUILTIN(enablenpc, "s"), - BUILTIN(disablenpc, "s"), - BUILTIN(sc_start, "iTi*"), - BUILTIN(sc_end, "i"), - BUILTIN(sc_check, "i"), - BUILTIN(debugmes, "s"), - BUILTIN(resetstatus, ""), - BUILTIN(changesex, ""), - BUILTIN(attachrid, "i"), - BUILTIN(detachrid, ""), - BUILTIN(isloggedin, "i"), - BUILTIN(setmapflag, "Mi"), - BUILTIN(removemapflag, "Mi"), - BUILTIN(getmapflag, "Mi"), - BUILTIN(pvpon, "M"), - BUILTIN(pvpoff, "M"), - BUILTIN(emotion, "i"), - BUILTIN(marriage, "P"), - BUILTIN(divorce, ""), - BUILTIN(getitemname, "I"), - BUILTIN(getspellinvocation, "s"), - BUILTIN(getpartnerid2, ""), - BUILTIN(getexp, "ii"), - BUILTIN(getinventorylist, ""), - BUILTIN(getactivatedpoolskilllist, ""), - BUILTIN(getunactivatedpoolskilllist, ""), - BUILTIN(poolskill, "i"), - BUILTIN(unpoolskill, "i"), - BUILTIN(misceffect, "i*"), - BUILTIN(specialeffect, "i"), - BUILTIN(specialeffect2, "i"), - BUILTIN(nude, ""), - BUILTIN(mapwarp, "MMxy"), - BUILTIN(cmdothernpc, "ss"), - BUILTIN(gmcommand, "s"), - BUILTIN(npcwarp, "xys"), - BUILTIN(message, "Ps"), - BUILTIN(npctalk, "s"), - BUILTIN(mobcount, "ME"), - BUILTIN(getlook, "i"), - BUILTIN(getsavepoint, "i"), - BUILTIN(areatimer, "MxyxytE"), - BUILTIN(isin, "Mxyxy"), - BUILTIN(shop, "s"), - BUILTIN(isdead, ""), - BUILTIN(unequipbyid, "i"), - BUILTIN(fakenpcname, "ssi"), - BUILTIN(getx, ""), - BUILTIN(gety, ""), - BUILTIN(getmap, ""), - BUILTIN(mapexit, ""), - {nullptr, ZString(), ZString()}, + BUILTIN(mes, "s"_s, '\0'), + BUILTIN(goto, "L"_s, '\0'), + BUILTIN(callfunc, "F"_s, '\0'), + BUILTIN(callsub, "L"_s, '\0'), + BUILTIN(return, ""_s, '\0'), + BUILTIN(next, ""_s, '\0'), + BUILTIN(close, ""_s, '\0'), + BUILTIN(close2, ""_s, '\0'), + BUILTIN(menu, "sL**"_s, '\0'), + BUILTIN(rand, "i?"_s, 'i'), + BUILTIN(isat, "Mxy"_s, 'i'), + BUILTIN(warp, "Mxy"_s, '\0'), + BUILTIN(areawarp, "MxyxyMxy"_s, '\0'), + BUILTIN(heal, "ii"_s, '\0'), + BUILTIN(itemheal, "ii"_s, '\0'), + BUILTIN(percentheal, "ii"_s, '\0'), + BUILTIN(input, "N"_s, '\0'), + BUILTIN(if, "iF*"_s, '\0'), + BUILTIN(set, "Ne"_s, '\0'), + BUILTIN(setarray, "Ne*"_s, '\0'), + BUILTIN(cleararray, "Nei"_s, '\0'), + BUILTIN(getarraysize, "N"_s, 'i'), + BUILTIN(getelementofarray, "Ni"_s, '.'), + BUILTIN(setlook, "ii"_s, '\0'), + BUILTIN(countitem, "I"_s, 'i'), + BUILTIN(checkweight, "Ii"_s, 'i'), + BUILTIN(getitem, "Ii??"_s, '\0'), + BUILTIN(makeitem, "IiMxy"_s, '\0'), + BUILTIN(delitem, "Ii"_s, '\0'), + BUILTIN(readparam, "i?"_s, 'i'), + BUILTIN(getcharid, "i?"_s, 'i'), + BUILTIN(strcharinfo, "i"_s, 's'), + BUILTIN(getequipid, "i"_s, 'i'), + BUILTIN(getequipname, "i"_s, 's'), + BUILTIN(statusup2, "ii"_s, '\0'), + BUILTIN(bonus, "ii"_s, '\0'), + BUILTIN(bonus2, "iii"_s, '\0'), + BUILTIN(skill, "ii?"_s, '\0'), + BUILTIN(setskill, "ii"_s, '\0'), + BUILTIN(getskilllv, "i"_s, 'i'), + BUILTIN(getgmlevel, ""_s, 'i'), + BUILTIN(end, ""_s, '\0'), + BUILTIN(getopt2, ""_s, 'i'), + BUILTIN(setopt2, "i"_s, '\0'), + BUILTIN(savepoint, "Mxy"_s, '\0'), + BUILTIN(gettimetick, "i"_s, 'i'), + BUILTIN(gettime, "i"_s, 'i'), + BUILTIN(openstorage, ""_s, '\0'), + BUILTIN(getexp, "ii"_s, '\0'), + BUILTIN(monster, "Mxysmi?"_s, '\0'), + BUILTIN(areamonster, "Mxyxysmi?"_s, '\0'), + BUILTIN(killmonster, "ME"_s, '\0'), + BUILTIN(killmonsterall, "M"_s, '\0'), + BUILTIN(donpcevent, "E"_s, '\0'), + BUILTIN(addtimer, "tE"_s, '\0'), + BUILTIN(initnpctimer, ""_s, '\0'), + BUILTIN(startnpctimer, "?"_s, '\0'), + BUILTIN(stopnpctimer, ""_s, '\0'), + BUILTIN(getnpctimer, "i"_s, 'i'), + BUILTIN(setnpctimer, "i"_s, '\0'), + BUILTIN(announce, "si"_s, '\0'), + BUILTIN(mapannounce, "Msi"_s, '\0'), + BUILTIN(getusers, "i"_s, 'i'), + BUILTIN(getmapusers, "M"_s, 'i'), + BUILTIN(getareausers, "Mxyxy?"_s, 'i'), + BUILTIN(getareadropitem, "Mxyxyi?"_s, 'i'), + BUILTIN(enablenpc, "s"_s, '\0'), + BUILTIN(disablenpc, "s"_s, '\0'), + BUILTIN(sc_start, "iTi?"_s, '\0'), + BUILTIN(sc_end, "i"_s, '\0'), + BUILTIN(sc_check, "i"_s, 'i'), + BUILTIN(debugmes, "s"_s, '\0'), + BUILTIN(resetstatus, ""_s, '\0'), + BUILTIN(changesex, ""_s, '\0'), + BUILTIN(attachrid, "i"_s, 'i'), + BUILTIN(detachrid, ""_s, '\0'), + BUILTIN(isloggedin, "i"_s, 'i'), + BUILTIN(setmapflag, "Mi"_s, '\0'), + BUILTIN(removemapflag, "Mi"_s, '\0'), + BUILTIN(getmapflag, "Mi"_s, 'i'), + BUILTIN(pvpon, "M"_s, '\0'), + BUILTIN(pvpoff, "M"_s, '\0'), + BUILTIN(emotion, "i"_s, '\0'), + BUILTIN(mapwarp, "MMxy"_s, '\0'), + BUILTIN(cmdothernpc, "ss"_s, '\0'), + BUILTIN(mobcount, "ME"_s, 'i'), + BUILTIN(marriage, "P"_s, 'i'), + BUILTIN(divorce, ""_s, 'i'), + BUILTIN(getitemname, "I"_s, 's'), + BUILTIN(getspellinvocation, "s"_s, 's'), + BUILTIN(getpartnerid2, ""_s, 'i'), + BUILTIN(getinventorylist, ""_s, '\0'), + BUILTIN(getactivatedpoolskilllist, ""_s, '\0'), + BUILTIN(getunactivatedpoolskilllist, ""_s, '\0'), + BUILTIN(poolskill, "i"_s, '\0'), + BUILTIN(unpoolskill, "i"_s, '\0'), + BUILTIN(misceffect, "i?"_s, '\0'), + BUILTIN(specialeffect, "i"_s, '\0'), + BUILTIN(specialeffect2, "i"_s, '\0'), + BUILTIN(nude, ""_s, '\0'), + BUILTIN(unequipbyid, "i"_s, '\0'), + BUILTIN(gmcommand, "s"_s, '\0'), + BUILTIN(npcwarp, "xys"_s, '\0'), + BUILTIN(message, "Ps"_s, '\0'), + BUILTIN(npctalk, "s"_s, '\0'), + BUILTIN(getlook, "i"_s, 'i'), + BUILTIN(getsavepoint, "i"_s, '.'), + BUILTIN(areatimer, "MxyxytE"_s, '\0'), + BUILTIN(isin, "Mxyxy"_s, 'i'), + BUILTIN(shop, "s"_s, '\0'), + BUILTIN(isdead, ""_s, 'i'), + BUILTIN(fakenpcname, "ssi"_s, '\0'), + BUILTIN(getx, ""_s, 'i'), + BUILTIN(gety, ""_s, 'i'), + BUILTIN(getmap, ""_s, 's'), + BUILTIN(mapexit, ""_s, '\0'), + {nullptr, ""_s, ""_s, '\0'}, }; void set_script_var_i(dumb_ptr<map_session_data> sd, VarName var, int e, int val) @@ -5079,7 +5096,7 @@ int get_script_var_i(dumb_ptr<map_session_data> sd, VarName var, int e) get_val(sd, &dat); if (dat.type == ByteCode::INT) return dat.u.numi; - PRINTF("Warning: you lied about the type and I'm too lazy to fix it!"); + PRINTF("Warning: you lied about the type and I'm too lazy to fix it!"_fmt); return 0; } ZString get_script_var_s(dumb_ptr<map_session_data> sd, VarName var, int e) @@ -5092,6 +5109,7 @@ ZString get_script_var_s(dumb_ptr<map_session_data> sd, VarName var, int e) get_val(sd, &dat); if (dat.type == ByteCode::CONSTSTR) return dat.u.str; - PRINTF("Warning: you lied about the type and I can't fix it!"); + PRINTF("Warning: you lied about the type and I can't fix it!"_fmt); return ZString(); } +} // namespace tmwa diff --git a/src/map/script.hpp b/src/map/script.hpp index 9ae893d..ee9a5a9 100644 --- a/src/map/script.hpp +++ b/src/map/script.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_SCRIPT_HPP -#define TMWA_MAP_SCRIPT_HPP +#pragma once // script.hpp - EAthena script frontend, engine, and library. // // Copyright © ????-2004 Athena Dev Teams @@ -21,26 +20,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdint> -# include <cstring> // for inlined get_str - TODO remove +#include <cstdint> -# include <vector> +#include <vector> -# include "../range/slice.hpp" +#include "../range/slice.hpp" -# include "../strings/rstring.hpp" -# include "../strings/astring.hpp" -# include "../strings/zstring.hpp" +#include "../strings/zstring.hpp" -# include "../generic/db.hpp" +#include "../generic/db.hpp" +#include "../generic/dumb_ptr.hpp" -# include "../mmo/dumb_ptr.hpp" -# include "../mmo/utils.hpp" +#include "../mmo/ids.hpp" -# include "map.t.hpp" +#include "clif.t.hpp" +#include "map.t.hpp" + +namespace tmwa +{ enum class ByteCode : uint8_t; struct str_data_t; @@ -155,7 +155,7 @@ public: struct script_stack *stack; int start, end; ScriptEndState state; - int rid, oid; + BlockId rid, oid; ScriptPointer scriptp, new_scriptp; int defsp, new_defsp; }; @@ -177,10 +177,9 @@ struct argrec_t argrec_t(ZString n, int i) : name(n), v(i) {} argrec_t(ZString n, ZString z) : name(n), v(z) {} }; -int run_script_l(ScriptPointer, int, int, Slice<argrec_t> args); -int run_script(ScriptPointer, int, int); +int run_script_l(ScriptPointer, BlockId, BlockId, Slice<argrec_t> args); +int run_script(ScriptPointer, BlockId, BlockId); -struct ScriptLabel; extern Map<ScriptLabel, int> scriptlabel_db; extern @@ -200,5 +199,4 @@ void set_script_var_s(dumb_ptr<map_session_data> sd, VarName var, int e, XString int get_script_var_i(dumb_ptr<map_session_data> sd, VarName var, int e); ZString get_script_var_s(dumb_ptr<map_session_data> sd, VarName var, int e); - -#endif // TMWA_MAP_SCRIPT_HPP +} // namespace tmwa diff --git a/src/map/script.py b/src/map/script.py index 068307a..dcde08d 100644 --- a/src/map/script.py +++ b/src/map/script.py @@ -3,7 +3,7 @@ class ByteCode: (workaround for gcc bug 58150) ''' __slots__ = ('_value') - name = 'ByteCode' + name = 'tmwa::ByteCode' enabled = True def __init__(self, value): @@ -34,7 +34,7 @@ class script_data(object): ''' print a script_data ''' __slots__ = ('_value') - name = 'script_data' + name = 'tmwa::script_data' enabled = True def __init__(self, value): diff --git a/src/map/skill-pools.cpp b/src/map/skill-pools.cpp index 6b46d79..e37b7e3 100644 --- a/src/map/skill-pools.cpp +++ b/src/map/skill-pools.cpp @@ -1,3 +1,4 @@ +#include "skill-pools.hpp" #include "skill.hpp" // skill-pools.cpp - Additional support for focusable skills. // @@ -26,6 +27,9 @@ #include "../poison.hpp" + +namespace tmwa +{ Array<SkillID, MAX_POOL_SKILLS> skill_pool_skills; int skill_pool_skills_size = 0; @@ -34,7 +38,7 @@ void skill_pool_register(SkillID id) if (skill_pool_skills_size + 1 >= MAX_POOL_SKILLS) { FPRINTF(stderr, - "Too many pool skills! Increase MAX_POOL_SKILLS and recompile."); + "Too many pool skills! Increase MAX_POOL_SKILLS and recompile."_fmt); return; } @@ -61,7 +65,7 @@ int skill_pool(dumb_ptr<map_session_data> sd, SkillID *skills) int skill_pool_size(dumb_ptr<map_session_data> sd) { - return skill_pool(sd, NULL); + return skill_pool(sd, nullptr); } int skill_pool_max(dumb_ptr<map_session_data> sd) @@ -78,7 +82,7 @@ int skill_pool_activate(dumb_ptr<map_session_data> sd, SkillID skill_id) { sd->status.skill[skill_id].flags |= SkillFlags::POOL_ACTIVATED; pc_calcstatus(sd, 0); - MAP_LOG_PC(sd, "SKILL-ACTIVATE %d %d %d", + MAP_LOG_PC(sd, "SKILL-ACTIVATE %d %d %d"_fmt, skill_id, sd->status.skill[skill_id].lv, skill_power(sd, skill_id)); return 0; @@ -97,7 +101,7 @@ int skill_pool_deactivate(dumb_ptr<map_session_data> sd, SkillID skill_id) if (bool(sd->status.skill[skill_id].flags & SkillFlags::POOL_ACTIVATED)) { sd->status.skill[skill_id].flags &= ~SkillFlags::POOL_ACTIVATED; - MAP_LOG_PC(sd, "SKILL-DEACTIVATE %d", skill_id); + MAP_LOG_PC(sd, "SKILL-DEACTIVATE %d"_fmt, skill_id); pc_calcstatus(sd, 0); return 0; } @@ -142,3 +146,4 @@ int skill_power_bl(dumb_ptr<block_list> bl, SkillID skill) else return 0; } +} // namespace tmwa diff --git a/src/map/skill-pools.hpp b/src/map/skill-pools.hpp index 6781907..c8890e8 100644 --- a/src/map/skill-pools.hpp +++ b/src/map/skill-pools.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_SKILL_POOLS_HPP -#define TMWA_MAP_SKILL_POOLS_HPP +#pragma once // skill-pools.hpp - dummy header to make Make dependencies work. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,6 +18,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -#endif // TMWA_MAP_SKILL_POOLS_HPP + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 37a3b44..f579920 100644 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -22,9 +22,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include <cassert> -#include <cstdlib> -#include <cstring> -#include <ctime> + +#include <algorithm> #include "../compat/attr.hpp" #include "../compat/fun.hpp" @@ -32,56 +31,61 @@ #include "../strings/mstring.hpp" #include "../strings/rstring.hpp" +#include "../strings/astring.hpp" +#include "../strings/zstring.hpp" #include "../strings/xstring.hpp" +#include "../strings/literal.hpp" #include "../generic/random.hpp" #include "../io/cxxstdio.hpp" #include "../io/read.hpp" +#include "../net/timer.hpp" + #include "../mmo/extract.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" #include "battle.hpp" #include "clif.hpp" -#include "magic.hpp" -#include "map.hpp" +#include "magic-stmt.hpp" #include "mob.hpp" #include "pc.hpp" #include "../poison.hpp" + +namespace tmwa +{ struct skill_name_db skill_names[] = { - {SkillID::AC_OWL, "OWL", "Owl's_Eye"}, - - {SkillID::NPC_EMOTION, "EMOTION", "NPC_EMOTION"}, - {SkillID::NPC_POISON, "POISON", "NPC_POISON"}, - {SkillID::NPC_SELFDESTRUCTION, "SELFDESTRUCTION", "Kabooooom!"}, - {SkillID::NPC_SUMMONSLAVE, "SUMMONSLAVE", "NPC_SUMMONSLAVE"}, - - {SkillID::NV_EMOTE, "EMOTE", "Emote_Skill"}, - {SkillID::NV_TRADE, "TRADE", "Trade_Skill"}, - {SkillID::NV_PARTY, "PARTY", "Party_Skill"}, - - {SkillID::TMW_MAGIC, "MAGIC", "General Magic"}, - {SkillID::TMW_MAGIC_LIFE, "MAGIC_LIFE", "Life Magic"}, - {SkillID::TMW_MAGIC_WAR, "MAGIC_WAR", "War Magic"}, - {SkillID::TMW_MAGIC_TRANSMUTE, "MAGIC_TRANSMUTE", "Transmutation Magic"}, - {SkillID::TMW_MAGIC_NATURE, "MAGIC_NATURE", "Nature Magic"}, - {SkillID::TMW_MAGIC_ETHER, "MAGIC_ETHER", "Astral Magic"}, - {SkillID::TMW_MAGIC_DARK, "MAGIC_DARK", "Dark Magic"}, - {SkillID::TMW_MAGIC_LIGHT, "MAGIC_LIGHT", "Light Magic"}, - - {SkillID::TMW_BRAWLING, "BRAWLING", "Brawling"}, - {SkillID::TMW_LUCKY_COUNTER, "LUCKY_COUNTER", "Lucky Counter"}, - {SkillID::TMW_SPEED, "SPEED", "Speed"}, - {SkillID::TMW_RESIST_POISON, "RESIST_POISON", "Resist Poison"}, - {SkillID::TMW_ASTRAL_SOUL, "ASTRAL_SOUL", "Astral Soul"}, - {SkillID::TMW_RAGING, "RAGING", "Raging"}, - - {SkillID::ZERO, "", ""} + {SkillID::AC_OWL, "OWL"_s, "Owl's_Eye"_s}, + + {SkillID::NPC_EMOTION, "EMOTION"_s, "NPC_EMOTION"_s}, + {SkillID::NPC_POISON, "POISON"_s, "NPC_POISON"_s}, + {SkillID::NPC_SELFDESTRUCTION, "SELFDESTRUCTION"_s, "Kabooooom!"_s}, + {SkillID::NPC_SUMMONSLAVE, "SUMMONSLAVE"_s, "NPC_SUMMONSLAVE"_s}, + + {SkillID::NV_EMOTE, "EMOTE"_s, "Emote_Skill"_s}, + {SkillID::NV_TRADE, "TRADE"_s, "Trade_Skill"_s}, + {SkillID::NV_PARTY, "PARTY"_s, "Party_Skill"_s}, + + {SkillID::TMW_MAGIC, "MAGIC"_s, "General Magic"_s}, + {SkillID::TMW_MAGIC_LIFE, "MAGIC_LIFE"_s, "Life Magic"_s}, + {SkillID::TMW_MAGIC_WAR, "MAGIC_WAR"_s, "War Magic"_s}, + {SkillID::TMW_MAGIC_TRANSMUTE, "MAGIC_TRANSMUTE"_s, "Transmutation Magic"_s}, + {SkillID::TMW_MAGIC_NATURE, "MAGIC_NATURE"_s, "Nature Magic"_s}, + {SkillID::TMW_MAGIC_ETHER, "MAGIC_ETHER"_s, "Astral Magic"_s}, + {SkillID::TMW_MAGIC_DARK, "MAGIC_DARK"_s, "Dark Magic"_s}, + {SkillID::TMW_MAGIC_LIGHT, "MAGIC_LIGHT"_s, "Light Magic"_s}, + + {SkillID::TMW_BRAWLING, "BRAWLING"_s, "Brawling"_s}, + {SkillID::TMW_LUCKY_COUNTER, "LUCKY_COUNTER"_s, "Lucky Counter"_s}, + {SkillID::TMW_SPEED, "SPEED"_s, "Speed"_s}, + {SkillID::TMW_RESIST_POISON, "RESIST_POISON"_s, "Resist Poison"_s}, + {SkillID::TMW_ASTRAL_SOUL, "ASTRAL_SOUL"_s, "Astral Soul"_s}, + {SkillID::TMW_RAGING, "RAGING"_s, "Raging"_s}, + + {SkillID::ZERO, ""_s, ""_s} }; earray<skill_db_, SkillID, SkillID::MAX_SKILL_DB> skill_db; @@ -94,7 +98,7 @@ int skill_attack(BF attack_type, dumb_ptr<block_list> src, static void skill_status_change_timer(TimerData *tid, tick_t tick, - int id, StatusChange type); + BlockId id, StatusChange type); int skill_get_hit(SkillID id) { @@ -169,16 +173,16 @@ int skill_get_castnodex(SkillID id, int lv) int skill_additional_effect(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, SkillID skillid, int skilllv) { - dumb_ptr<map_session_data> sd = NULL; - dumb_ptr<mob_data> md = NULL; + dumb_ptr<map_session_data> sd = nullptr; + dumb_ptr<mob_data> md = nullptr; int luk; int sc_def_mdef, sc_def_vit, sc_def_int, sc_def_luk; int sc_def_phys_shield_spell; - nullpo_ret(src); - nullpo_ret(bl); + nullpo_retz(src); + nullpo_retz(bl); if (skilllv < 0) return 0; @@ -256,16 +260,16 @@ int skill_attack(BF attack_type, dumb_ptr<block_list> src, eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int type, lv, damage; - nullpo_ret(src); - nullpo_ret(dsrc); - nullpo_ret(bl); + nullpo_retz(src); + nullpo_retz(dsrc); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); //何もしない判定ここから if (dsrc->bl_m != bl->bl_m) //対象が同じマップにいなければ何もしない return 0; - if (src->bl_prev == NULL || dsrc->bl_prev == NULL || bl->bl_prev == NULL) //prevよくわからない※ + if (src->bl_prev == nullptr || dsrc->bl_prev == nullptr || bl->bl_prev == nullptr) //prevよくわからない※ return 0; if (src->bl_type == BL::PC && pc_isdead(src->is_player())) //術者?がPCですでに死んでいたら何もしない return 0; @@ -304,7 +308,7 @@ int skill_attack(BF attack_type, dumb_ptr<block_list> src, battle_damage(src, bl, damage, 0); /* ダメージがあるなら追加効果判定 */ - if (bl->bl_prev != NULL) + if (bl->bl_prev != nullptr) { dumb_ptr<map_session_data> sd = bl->is_player(); if (bl->bl_type != BL::PC || !pc_isdead(sd)) @@ -316,8 +320,7 @@ int skill_attack(BF attack_type, dumb_ptr<block_list> src, dumb_ptr<mob_data> md = bl->is_mob(); if (battle_config.mob_changetarget_byskill == 1) { - int target; - target = md->target_id; + BlockId target = md->target_id; if (src->bl_type == BL::PC) md->target_id = src->bl_id; mobskill_use(md, tick, MobSkillCondition::ANY); @@ -389,7 +392,9 @@ void skill_area_sub(dumb_ptr<block_list> bl, // these variables are set in the 'else' branches, // and used in the (recursive) 'if' branch -static int skill_area_temp_id, skill_area_temp_hp; +// TODO kill it, kill it with fire. +static BlockId skill_area_temp_id; +static int skill_area_temp_hp; /*========================================== @@ -401,7 +406,7 @@ int skill_castend_damage_id(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, SkillID skillid, int skilllv, tick_t tick, BCT flag) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; nullpo_retr(1, src); nullpo_retr(1, bl); @@ -411,7 +416,7 @@ int skill_castend_damage_id(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, if (sd && pc_isdead(sd)) return 1; - if (bl->bl_prev == NULL) + if (bl->bl_prev == nullptr) return 1; if (bl->bl_type == BL::PC && pc_isdead(bl->is_player())) return 1; @@ -496,10 +501,10 @@ int skill_castend_damage_id(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, int skill_castend_nodamage_id(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, SkillID skillid, int skilllv) { - dumb_ptr<map_session_data> sd = NULL; - dumb_ptr<map_session_data> dstsd = NULL; - dumb_ptr<mob_data> md = NULL; - dumb_ptr<mob_data> dstmd = NULL; + dumb_ptr<map_session_data> sd = nullptr; + dumb_ptr<map_session_data> dstsd = nullptr; + dumb_ptr<mob_data> md = nullptr; + dumb_ptr<mob_data> dstmd = nullptr; int sc_def_vit, sc_def_mdef, strip_fix; nullpo_retr(1, src); @@ -534,7 +539,7 @@ int skill_castend_nodamage_id(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, if (strip_fix < 0) strip_fix = 0; - if (bl == NULL || bl->bl_prev == NULL) + if (bl == nullptr || bl->bl_prev == nullptr) return 1; if (sd && pc_isdead(sd)) return 1; @@ -594,7 +599,7 @@ interval_t skill_castfix(dumb_ptr<block_list> bl, interval_t interval) sc_data = battle_get_sc_data(bl); dex = battle_get_dex(bl); - if (skill > SkillID::MAX_SKILL_DB /*|| skill < SkillID()*/) + if (skill >= SkillID::MAX_SKILL_DB /*|| skill < SkillID()*/) return interval_t::zero(); castnodex = skill_get_castnodex(skill, lv); @@ -649,7 +654,7 @@ interval_t skill_delayfix(dumb_ptr<block_list> bl, interval_t interval) */ int skill_castcancel(dumb_ptr<block_list> bl, int) { - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type == BL::PC) { @@ -686,11 +691,11 @@ int skill_status_change_active(dumb_ptr<block_list> bl, StatusChange type) { eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; - nullpo_ret(bl); + nullpo_retz(bl); if (bl->bl_type != BL::PC && bl->bl_type != BL::MOB) { if (battle_config.error_log) - PRINTF("skill_status_change_active: neither MOB nor PC !\n"); + PRINTF("skill_status_change_active: neither MOB nor PC !\n"_fmt); return 0; } @@ -715,7 +720,7 @@ void skill_status_change_end(dumb_ptr<block_list> bl, StatusChange type, TimerDa if (bl->bl_type != BL::PC && bl->bl_type != BL::MOB) { if (battle_config.error_log) - PRINTF("skill_status_change_end: neither MOB nor PC !\n"); + PRINTF("skill_status_change_end: neither MOB nor PC !\n"_fmt); return; } sc_data = battle_get_sc_data(bl); @@ -804,7 +809,7 @@ int skill_update_heal_animation(dumb_ptr<map_session_data> sd) { const Opt2 mask = Opt2::_heal; - nullpo_ret(sd); + nullpo_retz(sd); bool wis_active = bool(sd->opt2 & mask); bool is_active = sd->quick_regeneration_hp.amount > 0; @@ -823,14 +828,14 @@ int skill_update_heal_animation(dumb_ptr<map_session_data> sd) * ステータス異常終了タイマー *------------------------------------------ */ -void skill_status_change_timer(TimerData *tid, tick_t tick, int id, StatusChange type) +void skill_status_change_timer(TimerData *tid, tick_t tick, BlockId id, StatusChange type) { dumb_ptr<block_list> bl; - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; //short *sc_count; //使ってない? - if ((bl = map_id2bl(id)) == NULL) + if ((bl = map_id2bl(id)) == nullptr) return; //該当IDがすでに消滅しているというのはいかにもありそうなのでスルーしてみる sc_data = battle_get_sc_data(bl); @@ -846,7 +851,7 @@ void skill_status_change_timer(TimerData *tid, tick_t tick, int id, StatusChange { // Must report termination spell_effect_report_termination(sc_data[type].spell_invocation, bl->bl_id, type, 0); - sc_data[type].spell_invocation = 0; + sc_data[type].spell_invocation = BlockId(); } switch (type) @@ -878,7 +883,7 @@ void skill_status_change_timer(TimerData *tid, tick_t tick, int id, StatusChange md->hp -= hp; } } - sc_data[type].timer = Timer(tick + std::chrono::seconds(1), + sc_data[type].timer = Timer(tick + 1_s, std::bind(skill_status_change_timer, ph::_1, ph::_2, bl->bl_id, type)); return; @@ -886,7 +891,7 @@ void skill_status_change_timer(TimerData *tid, tick_t tick, int id, StatusChange } else { - sc_data[type].timer = Timer(tick + std::chrono::seconds(2), + sc_data[type].timer = Timer(tick + 2_s, std::bind(skill_status_change_timer, ph::_1, ph::_2, bl->bl_id, type)); return; @@ -898,7 +903,7 @@ void skill_status_change_timer(TimerData *tid, tick_t tick, int id, StatusChange /* 時間切れ無し?? */ case StatusChange::SC_WEIGHT50: case StatusChange::SC_WEIGHT90: - sc_data[type].timer = Timer(tick + std::chrono::minutes(10), + sc_data[type].timer = Timer(tick + 10_min, std::bind(skill_status_change_timer, ph::_1, ph::_2, bl->bl_id, type)); return; @@ -920,14 +925,14 @@ int skill_status_change_start(dumb_ptr<block_list> bl, StatusChange type, int val1, interval_t tick) { - return skill_status_effect(bl, type, val1, tick, 0); + return skill_status_effect(bl, type, val1, tick, BlockId()); } int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, int val1, - interval_t tick, int spell_invocation) + interval_t tick, BlockId spell_invocation) { - dumb_ptr<map_session_data> sd = NULL; + dumb_ptr<map_session_data> sd = nullptr; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; short *sc_count; Option *option; @@ -938,20 +943,20 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, SP updateflag = SP::ZERO; int scdef = 0; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (not sc_data) return 0; sc_count = battle_get_sc_count(bl); - nullpo_ret(sc_count); + nullpo_retz(sc_count); option = battle_get_option(bl); - nullpo_ret(option); + nullpo_retz(option); opt1 = battle_get_opt1(bl); - nullpo_ret(opt1); + nullpo_retz(opt1); opt2 = battle_get_opt2(bl); - nullpo_ret(opt2); + nullpo_retz(opt2); opt3 = battle_get_opt3(bl); - nullpo_ret(opt3); + nullpo_retz(opt3); switch (type) { @@ -971,7 +976,7 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, else { if (battle_config.error_log) - PRINTF("skill_status_change_start: neither MOB nor PC !\n"); + PRINTF("skill_status_change_start: neither MOB nor PC !\n"_fmt); return 0; } @@ -1024,12 +1029,12 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, } // huh? - tick = std::chrono::seconds(1); + tick = 1_s; break; case StatusChange::SC_WEIGHT50: case StatusChange::SC_WEIGHT90: - tick = std::chrono::minutes(10); + tick = 10_min; break; case StatusChange::SC_HASTE: @@ -1045,7 +1050,7 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, break; default: if (battle_config.error_log) - PRINTF("UnknownStatusChange [%d]\n", type); + PRINTF("UnknownStatusChange [%d]\n"_fmt, type); return 0; } @@ -1109,20 +1114,20 @@ int skill_status_change_clear(dumb_ptr<block_list> bl, int type) Opt2 *opt2; Opt3 *opt3; - nullpo_ret(bl); + nullpo_retz(bl); sc_data = battle_get_sc_data(bl); if (not sc_data) return 0; sc_count = battle_get_sc_count(bl); - nullpo_ret(sc_count); + nullpo_retz(sc_count); option = battle_get_option(bl); - nullpo_ret(option); + nullpo_retz(option); opt1 = battle_get_opt1(bl); - nullpo_ret(opt1); + nullpo_retz(opt1); opt2 = battle_get_opt2(bl); - nullpo_ret(opt2); + nullpo_retz(opt2); opt3 = battle_get_opt3(bl); - nullpo_ret(opt3); + nullpo_retz(opt3); if (*sc_count == 0) return 0; @@ -1175,22 +1180,22 @@ void skill_unit_timer_sub_ondelete(dumb_ptr<block_list> bl, static SP scan_stat(XString statname) { - if (statname == "str") + if (statname == "str"_s) return SP::STR; - if (statname == "dex") + if (statname == "dex"_s) return SP::DEX; - if (statname == "agi") + if (statname == "agi"_s) return SP::AGI; - if (statname == "vit") + if (statname == "vit"_s) return SP::VIT; - if (statname == "int") + if (statname == "int"_s) return SP::INT; - if (statname == "luk") + if (statname == "luk"_s) return SP::LUK; - if (statname == "none") + if (statname == "none"_s) return SP::ZERO; - FPRINTF(stderr, "Unknown stat `%s'\n", AString(statname)); + FPRINTF(stderr, "Unknown stat `%s'\n"_fmt, AString(statname)); return SP::ZERO; } @@ -1199,7 +1204,7 @@ bool skill_readdb(ZString filename) io::ReadFile in(filename); if (!in.is_open()) { - PRINTF("can't read %s\n", filename); + PRINTF("can't read %s\n"_fmt, filename); return false; } @@ -1209,7 +1214,7 @@ bool skill_readdb(ZString filename) { // is_comment only works for whole-line comments // that could change once the Z dependency is dropped ... - XString comment = "//"; + LString comment = "//"_s; XString line = line_.xislice_h(std::search(line_.begin(), line_.end(), comment.begin(), comment.end())).rstrip(); if (!line) continue; @@ -1245,15 +1250,15 @@ bool skill_readdb(ZString filename) rv = false; continue; } - if (/*i < SkillID() ||*/ i > SkillID::MAX_SKILL_DB) + if (/*i < SkillID() ||*/ i >= SkillID::MAX_SKILL_DB) { rv = false; continue; } - if (castcancel == "yes") + if (castcancel == "yes"_s) skdb.castcancel = true; - else if (castcancel == "no") + else if (castcancel == "no"_s) skdb.castcancel = false; else { @@ -1261,17 +1266,17 @@ bool skill_readdb(ZString filename) continue; } - if (flags == "passive") + if (flags == "passive"_s) { skill_pool_register(i); skdb.poolflags = SkillFlags::POOL_FLAG; } - else if (flags == "active") + else if (flags == "active"_s) { skill_pool_register(i); skdb.poolflags = SkillFlags::POOL_FLAG | SkillFlags::POOL_ACTIVE; } - else if (flags == "no") + else if (flags == "no"_s) skdb.poolflags = SkillFlags::ZERO; else { @@ -1290,7 +1295,7 @@ bool skill_readdb(ZString filename) skill_db[i] = skdb; skill_lookup_by_id(i).desc = RString(tmp); } - PRINTF("read %s done\n", filename); + PRINTF("read %s done\n"_fmt, filename); return rv; } @@ -1312,3 +1317,4 @@ skill_name_db& skill_lookup_by_name(XString name) return ner; return skill_names[num_names - 1]; } +} // namespace tmwa diff --git a/src/map/skill.hpp b/src/map/skill.hpp index 1a615c1..ec353ce 100644 --- a/src/map/skill.hpp +++ b/src/map/skill.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_SKILL_HPP -#define TMWA_MAP_SKILL_HPP +#pragma once // skill.hpp - Old-style skills. // // Copyright © ????-2004 Athena Dev Teams @@ -21,17 +20,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "skill.t.hpp" -# include "skill-pools.hpp" +#include "skill.t.hpp" +#include "skill-pools.hpp" -# include "../strings/fwd.hpp" -# include "../strings/rstring.hpp" -# include "../strings/astring.hpp" +#include "../strings/fwd.hpp" +#include "../strings/rstring.hpp" +#include "../strings/literal.hpp" -# include "map.hpp" +#include "../generic/fwd.hpp" +#include "../generic/array.hpp" +#include "map.hpp" + + +namespace tmwa +{ constexpr int MAX_SKILL_PRODUCE_DB = 150; constexpr int MAX_SKILL_ARROW_DB = 150; constexpr int MAX_SKILL_ABRA_DB = 350; @@ -61,11 +66,11 @@ earray<skill_db_, SkillID, SkillID::MAX_SKILL_DB> skill_db; struct skill_name_db { SkillID id; // skill id - RString name; // search strings + LString name; // search strings RString desc; // description that shows up for searches // this makes const char(&)[] not decay into const char * in {} - skill_name_db(SkillID i, RString n, RString d) + skill_name_db(SkillID i, LString n, LString d) : id(i), name(n), desc(d) {} }; @@ -76,9 +81,6 @@ extern struct skill_name_db skill_names[]; skill_name_db& skill_lookup_by_id(SkillID id); skill_name_db& skill_lookup_by_name(XString name); -struct block_list; -struct map_session_data; - bool skill_readdb(ZString filename); // スキルデータベースへのアクセサ @@ -110,7 +112,7 @@ int skill_castcancel(dumb_ptr<block_list> bl, int type); // ステータス異常 int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, int val1, - interval_t tick, int spell_invocation); + interval_t tick, BlockId spell_invocation); int skill_status_change_start(dumb_ptr<block_list> bl, StatusChange type, int val1, interval_t tick); @@ -164,4 +166,4 @@ int skill_power_bl(dumb_ptr<block_list> bl, SkillID skill); // [Fate] Remember that a certain skill ID belongs to a pool skill void skill_pool_register(SkillID id); -#endif // TMWA_MAP_SKILL_HPP +} // namespace tmwa diff --git a/src/map/skill.t.hpp b/src/map/skill.t.hpp index 4e30cba..d0e3926 100644 --- a/src/map/skill.t.hpp +++ b/src/map/skill.t.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_SKILL_T_HPP -#define TMWA_MAP_SKILL_T_HPP +#pragma once // skill.t.hpp - Old-style skills. // // Copyright © ????-2004 Athena Dev Teams @@ -21,12 +20,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdint> +#include <cstdint> -# include "../generic/enum.hpp" +#include "../generic/enum.hpp" + +namespace tmwa +{ // TODO remove most of these as their corresponding SkillIDs get deleted. enum class StatusChange : uint16_t { @@ -131,5 +133,4 @@ enum class SkillFlags : uint16_t ENUM_BITWISE_OPERATORS(SkillFlags) } using e::SkillFlags; - -#endif // TMWA_MAP_SKILL_T_HPP +} // namespace tmwa diff --git a/src/map/storage.cpp b/src/map/storage.cpp index 89357b9..a6e6a0d 100644 --- a/src/map/storage.cpp +++ b/src/map/storage.cpp @@ -1,14 +1,32 @@ #include "storage.hpp" -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see COPYING in the main folder - -#include <cstdlib> -#include <cstring> +// storage.cpp - Storage handling. +// +// Copyright © ????-2004 Athena Dev Teams +// Copyright © 2004-2011 The Mana World Development Team +// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../compat/nullpo.hpp" #include "../generic/db.hpp" +#include "../mmo/ids.hpp" +#include "../mmo/mmo.hpp" + #include "chrif.hpp" #include "clif.hpp" #include "intif.hpp" @@ -18,18 +36,21 @@ #include "../poison.hpp" + +namespace tmwa +{ static -Map<int, struct storage> storage_db; +Map<AccountId, Storage> storage_db; void do_final_storage(void) { storage_db.clear(); } -struct storage *account2storage(int account_id) +Storage *account2storage(AccountId account_id) { - struct storage *stor = storage_db.search(account_id); - if (stor == NULL) + Storage *stor = storage_db.search(account_id); + if (stor == nullptr) { stor = storage_db.init(account_id); stor->account_id = account_id; @@ -38,13 +59,13 @@ struct storage *account2storage(int account_id) } // Just to ask storage, without creation -struct storage *account2storage2(int account_id) +Storage *account2storage2(AccountId account_id) { return storage_db.search(account_id); } static -void storage_delete(int account_id) +void storage_delete(AccountId account_id) { storage_db.erase(account_id); } @@ -55,13 +76,13 @@ void storage_delete(int account_id) */ int storage_storageopen(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); if (sd->state.storage_open) return 1; //Already open? - struct storage *stor = storage_db.search(sd->status_key.account_id); - if (stor == NULL) + Storage *stor = storage_db.search(sd->status_key.account_id); + if (stor == nullptr) { //Request storage. intif_request_storage(sd->status_key.account_id); return 1; @@ -83,20 +104,19 @@ int storage_storageopen(dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -int storage_additem(dumb_ptr<map_session_data> sd, struct storage *stor, - struct item *item_data, int amount) +int storage_additem(dumb_ptr<map_session_data> sd, Storage *stor, + Item *item_data, int amount) { struct item_data *data; - int i; - if (item_data->nameid <= 0 || amount <= 0) + if (!item_data->nameid || amount <= 0) return 1; data = itemdb_search(item_data->nameid); if (!itemdb_isequip2(data)) { //Stackable - for (i = 0; i < MAX_STORAGE; i++) + for (SOff0 i : SOff0::iter()) { if (compare_item(&stor->storage_[i], item_data)) { @@ -110,9 +130,12 @@ int storage_additem(dumb_ptr<map_session_data> sd, struct storage *stor, } } //Add item - for (i = 0; i < MAX_STORAGE && stor->storage_[i].nameid; i++); - - if (i >= MAX_STORAGE) + SOff0 i = *std::find_if(SOff0::iter().begin(), SOff0::iter().end(), + [&stor](SOff0 i_) + { + return !stor->storage_[i_].nameid; + }); + if (!i.ok()) return 1; stor->storage_[i] = *item_data; @@ -129,17 +152,17 @@ int storage_additem(dumb_ptr<map_session_data> sd, struct storage *stor, *------------------------------------------ */ static -int storage_delitem(dumb_ptr<map_session_data> sd, struct storage *stor, - int n, int amount) +int storage_delitem(dumb_ptr<map_session_data> sd, Storage *stor, + SOff0 n, int amount) { - if (stor->storage_[n].nameid == 0 || stor->storage_[n].amount < amount) + if (!stor->storage_[n].nameid || stor->storage_[n].amount < amount) return 1; stor->storage_[n].amount -= amount; if (stor->storage_[n].amount == 0) { - stor->storage_[n] = item{}; + stor->storage_[n] = Item{}; stor->storage_amount--; clif_updatestorageamount(sd, stor); } @@ -153,21 +176,21 @@ int storage_delitem(dumb_ptr<map_session_data> sd, struct storage *stor, * Add an item to the storage from the inventory. *------------------------------------------ */ -int storage_storageadd(dumb_ptr<map_session_data> sd, int index, int amount) +int storage_storageadd(dumb_ptr<map_session_data> sd, IOff0 index, int amount) { - struct storage *stor; + Storage *stor; - nullpo_ret(sd); + nullpo_retz(sd); stor = account2storage2(sd->status_key.account_id); - nullpo_ret(stor); + nullpo_retz(stor); if ((stor->storage_amount > MAX_STORAGE) || !stor->storage_status) return 0; // storage full / storage closed - if (index < 0 || index >= MAX_INVENTORY) + if (!index.ok()) return 0; - if (sd->status.inventory[index].nameid <= 0) + if (!sd->status.inventory[index].nameid) return 0; //No item on that spot if (amount < 1 || amount > sd->status.inventory[index].amount) @@ -188,19 +211,19 @@ int storage_storageadd(dumb_ptr<map_session_data> sd, int index, int amount) * Retrieve an item from the storage. *------------------------------------------ */ -int storage_storageget(dumb_ptr<map_session_data> sd, int index, int amount) +int storage_storageget(dumb_ptr<map_session_data> sd, SOff0 index, int amount) { - struct storage *stor; + Storage *stor; PickupFail flag; - nullpo_ret(sd); + nullpo_retz(sd); stor = account2storage2(sd->status_key.account_id); - nullpo_ret(stor); + nullpo_retz(stor); - if (index < 0 || index >= MAX_STORAGE) + if (!index.ok()) return 0; - if (stor->storage_[index].nameid <= 0) + if (!stor->storage_[index].nameid) return 0; //Nothing there if (amount < 1 || amount > stor->storage_[index].amount) @@ -209,7 +232,7 @@ int storage_storageget(dumb_ptr<map_session_data> sd, int index, int amount) if ((flag = pc_additem(sd, &stor->storage_[index], amount)) == PickupFail::OKAY) storage_delitem(sd, stor, index, amount); else - clif_additem(sd, 0, 0, flag); + clif_additem(sd, IOff0::from(0), 0, flag); // log_fromstorage(sd, index, 0); return 1; } @@ -220,11 +243,11 @@ int storage_storageget(dumb_ptr<map_session_data> sd, int index, int amount) */ int storage_storageclose(dumb_ptr<map_session_data> sd) { - struct storage *stor; + Storage *stor; - nullpo_ret(sd); + nullpo_retz(sd); stor = account2storage2(sd->status_key.account_id); - nullpo_ret(stor); + nullpo_retz(stor); clif_storageclose(sd); if (stor->storage_status) @@ -252,9 +275,9 @@ int storage_storageclose(dumb_ptr<map_session_data> sd) */ int storage_storage_quit(dumb_ptr<map_session_data> sd) { - struct storage *stor; + Storage *stor; - nullpo_ret(sd); + nullpo_retz(sd); stor = account2storage2(sd->status_key.account_id); if (stor) @@ -267,9 +290,9 @@ int storage_storage_quit(dumb_ptr<map_session_data> sd) return 0; } -int storage_storage_save(int account_id, int final) +int storage_storage_save(AccountId account_id, int final) { - struct storage *stor; + Storage *stor; stor = account2storage2(account_id); if (!stor) @@ -295,9 +318,9 @@ int storage_storage_save(int account_id, int final) } //Ack from Char-server indicating the storage was saved. [Skotlex] -int storage_storage_saved(int account_id) +int storage_storage_saved(AccountId account_id) { - struct storage *stor = account2storage2(account_id); + Storage *stor = account2storage2(account_id); if (stor) { @@ -311,3 +334,4 @@ int storage_storage_saved(int account_id) } return 0; } +} // namespace tmwa diff --git a/src/map/storage.hpp b/src/map/storage.hpp index 702c908..f3875c8 100644 --- a/src/map/storage.hpp +++ b/src/map/storage.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_STORAGE_HPP -#define TMWA_MAP_STORAGE_HPP +#pragma once // storage.hpp - Storage handling. // // Copyright © ????-2004 Athena Dev Teams @@ -21,19 +20,25 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "map.hpp" +#include "../generic/fwd.hpp" +#include "../mmo/fwd.hpp" + +#include "clif.t.hpp" + + +namespace tmwa +{ int storage_storageopen(dumb_ptr<map_session_data> sd); -int storage_storageadd(dumb_ptr<map_session_data> sd, int index, int amount); -int storage_storageget(dumb_ptr<map_session_data> sd, int index, int amount); +int storage_storageadd(dumb_ptr<map_session_data> sd, IOff0 index, int amount); +int storage_storageget(dumb_ptr<map_session_data> sd, SOff0 index, int amount); int storage_storageclose(dumb_ptr<map_session_data> sd); void do_final_storage(void); -struct storage *account2storage(int account_id); -struct storage *account2storage2(int account_id); +Storage *account2storage(AccountId account_id); +Storage *account2storage2(AccountId account_id); int storage_storage_quit(dumb_ptr<map_session_data> sd); -int storage_storage_save(int account_id, int final); -int storage_storage_saved(int account_id); - -#endif // TMWA_MAP_STORAGE_HPP +int storage_storage_save(AccountId account_id, int final); +int storage_storage_saved(AccountId account_id); +} // namespace tmwa diff --git a/src/map/tmw.cpp b/src/map/tmw.cpp index 46128d1..60b5027 100644 --- a/src/map/tmw.cpp +++ b/src/map/tmw.cpp @@ -19,17 +19,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <cctype> -#include <cstring> - #include "../compat/nullpo.hpp" #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" +#include "../strings/literal.hpp" #include "../io/cxxstdio.hpp" +#include "../mmo/human_time_diff.hpp" +#include "../mmo/utils.hpp" + #include "atcommand.hpp" #include "battle.hpp" #include "chrif.hpp" @@ -40,6 +41,9 @@ #include "../poison.hpp" + +namespace tmwa +{ static void tmw_AutoBan(dumb_ptr<map_session_data> sd, ZString reason, int length); static @@ -91,7 +95,7 @@ int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, XString message) { sd->chat_lines_in = sd->chat_total_repeats = 0; - tmw_AutoBan(sd, "chat", battle_config.chat_spam_ban); + tmw_AutoBan(sd, "chat"_s, battle_config.chat_spam_ban); return 1; } @@ -100,8 +104,8 @@ int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, XString message) (sd->chat_lines_in >= battle_config.chat_spam_warn || sd->chat_total_repeats >= battle_config.chat_spam_warn)) { - clif_displaymessage(sd->sess, "WARNING: You are about to be automatically banned for spam!"); - clif_displaymessage(sd->sess, "WARNING: Please slow down, do not repeat, and do not SHOUT!"); + clif_displaymessage(sd->sess, "WARNING: You are about to be automatically banned for spam!"_s); + clif_displaymessage(sd->sess, "WARNING: Please slow down, do not repeat, and do not SHOUT!"_s); } return 0; @@ -114,23 +118,23 @@ void tmw_AutoBan(dumb_ptr<map_session_data> sd, ZString reason, int length) sd->auto_ban_info.in_progress = 1; - AString hack_msg = STRPRINTF("[GM] %s has been autobanned for %s spam", + AString hack_msg = STRPRINTF("[GM] %s has been autobanned for %s spam"_fmt, sd->status_key.name, reason); tmw_GmHackMsg(hack_msg); - AString fake_command = STRPRINTF("@autoban %s %dh (%s spam)", + AString fake_command = STRPRINTF("@autoban %s %dh (%s spam)"_fmt, sd->status_key.name, length, reason); log_atcommand(sd, fake_command); - AString anotherbuf = STRPRINTF("You have been banned for %s spamming. Please do not spam.", + AString anotherbuf = STRPRINTF("You have been banned for %s spamming. Please do not spam."_fmt, reason); clif_displaymessage(sd->sess, anotherbuf); /* type: 2 - ban(year, month, day, hour, minute, second) */ HumanTimeDiff ban_len {}; ban_len.hour = length; - chrif_char_ask_name(-1, sd->status_key.name, 2, ban_len); + chrif_char_ask_name(AccountId(), sd->status_key.name, 2, ban_len); clif_setwaitclose(sd->sess); } @@ -159,6 +163,7 @@ bool tmw_CheckChatLameness(dumb_ptr<map_session_data>, XString message) void tmw_GmHackMsg(ZString line) { intif_wis_message_to_gm(wisp_server_name, - battle_config.hack_info_GM_level, + GmLevel::from(static_cast<uint32_t>(battle_config.hack_info_GM_level)), line); } +} // namespace tmwa diff --git a/src/map/tmw.hpp b/src/map/tmw.hpp index 670599e..ffd6f7f 100644 --- a/src/map/tmw.hpp +++ b/src/map/tmw.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_TMW_HPP -#define TMWA_MAP_TMW_HPP +#pragma once // tmw.hpp - Some random functions added by TMW. // // Copyright © 2004-2011 The Mana World Development Team @@ -20,15 +19,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" -# include "../mmo/dumb_ptr.hpp" +#include "../generic/fwd.hpp" -# include "map.hpp" +namespace tmwa +{ int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, XString message); void tmw_GmHackMsg(ZString line); - -#endif // TMWA_MAP_TMW_HPP +} // namespace tmwa diff --git a/src/map/trade.cpp b/src/map/trade.cpp index c877d00..c52377d 100644 --- a/src/map/trade.cpp +++ b/src/map/trade.cpp @@ -34,21 +34,24 @@ #include "../poison.hpp" + +namespace tmwa +{ /*========================================== * 取引要請を相手に送る *------------------------------------------ */ -void trade_traderequest(dumb_ptr<map_session_data> sd, int target_id) +void trade_traderequest(dumb_ptr<map_session_data> sd, BlockId target_id) { dumb_ptr<map_session_data> target_sd; nullpo_retv(sd); - if ((target_sd = map_id2sd(target_id)) != NULL) + if ((target_sd = map_id2sd(target_id)) != nullptr) { if (!battle_config.invite_request_check) { - if (target_sd->party_invite > 0) + if (target_sd->party_invite) { clif_tradestart(sd, 2); // 相手はPT要請中かGuild要請中 return; @@ -60,7 +63,7 @@ void trade_traderequest(dumb_ptr<map_session_data> sd, int target_id) clif_tradestart(sd, 2); return; } - if ((target_sd->trade_partner != 0) || (sd->trade_partner != 0)) + if ((target_sd->trade_partner) || (sd->trade_partner)) { trade_tradecancel(sd); //person is in another trade } @@ -97,20 +100,20 @@ void trade_tradeack(dumb_ptr<map_session_data> sd, int type) dumb_ptr<map_session_data> target_sd; nullpo_retv(sd); - if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) + if ((target_sd = map_id2sd(account_to_block(sd->trade_partner))) != nullptr) { clif_tradestart(target_sd, type); clif_tradestart(sd, type); if (type == 4) { // Cancel sd->deal_locked = 0; - sd->trade_partner = 0; + sd->trade_partner = AccountId(); target_sd->deal_locked = 0; - target_sd->trade_partner = 0; + target_sd->trade_partner = AccountId(); } - if (sd->npc_id != 0) + if (sd->npc_id) npc_event_dequeue(sd); - if (target_sd->npc_id != 0) + if (target_sd->npc_id) npc_event_dequeue(target_sd); //close STORAGE window if it's open. It protects from spooffing packets [Lupus] @@ -123,7 +126,7 @@ void trade_tradeack(dumb_ptr<map_session_data> sd, int type) * アイテム追加 *------------------------------------------ */ -void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount) +void trade_tradeadditem(dumb_ptr<map_session_data> sd, IOff2 index, int amount) { dumb_ptr<map_session_data> target_sd; struct item_data *id; @@ -131,30 +134,29 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount) int trade_weight = 0; int free_ = 0; int c; - int i; nullpo_retv(sd); - if (((target_sd = map_id2sd(sd->trade_partner)) != NULL) + if (((target_sd = map_id2sd(account_to_block(sd->trade_partner))) != nullptr) && (sd->deal_locked < 1)) { - if (index < 2 || index >= MAX_INVENTORY + 2) + if (!index.ok()) { - if (index == 0 && amount > 0 && amount <= sd->status.zeny) + if (index.index == 0 && amount > 0 && amount <= sd->status.zeny) { sd->deal_zeny = amount; - clif_tradeadditem(sd, target_sd, 0, amount); + clif_tradeadditem(sd, target_sd, index, amount); } } // note: amount is overridden below! - else if (amount <= sd->status.inventory[index - 2].amount + else if (amount <= sd->status.inventory[index.unshift()].amount && amount > 0) { // determine free slots of receiver - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { - if (target_sd->status.inventory[i].nameid == 0 - && target_sd->inventory_data[i] == NULL) + if (!target_sd->status.inventory[i].nameid + && target_sd->inventory_data[i] == nullptr) free_++; } for (trade_i = 0; trade_i < TRADE_MAX; trade_i++) @@ -163,14 +165,14 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount) { // calculate trade weight trade_weight += - sd->inventory_data[index - 2]->weight * amount; + sd->inventory_data[index.unshift()]->weight * amount; // determine if item is a stackable already in receivers inventory, and up free count - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (target_sd->status.inventory[i].nameid == - sd->status.inventory[index - 2].nameid - && target_sd->inventory_data[i] != NULL) + sd->status.inventory[index.unshift()].nameid + && target_sd->inventory_data[i] != nullptr) { id = target_sd->inventory_data[i]; if (id->type != ItemType::WEAPON @@ -205,7 +207,7 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount) return; } } - pc_unequipinvyitem(sd, index - 2, CalcStatus::NOW); + pc_unequipinvyitem(sd, index.unshift(), CalcStatus::NOW); sd->deal_item_index[trade_i] = index; sd->deal_item_amount[trade_i] += amount; clif_tradeitemok(sd, index, amount, 0); //success to add item @@ -217,16 +219,16 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount) { // calculate weight for stored deal trade_weight += - sd->inventory_data[sd->deal_item_index[trade_i] - - 2]->weight * + sd->inventory_data[sd->deal_item_index[trade_i].unshift() + ]->weight * sd->deal_item_amount[trade_i]; // count free stackables in stored deal - for (i = 0; i < MAX_INVENTORY; i++) + for (IOff0 i : IOff0::iter()) { if (target_sd->status.inventory[i].nameid == sd->status. - inventory[sd->deal_item_index[trade_i] - 2].nameid - && target_sd->inventory_data[i] != NULL) + inventory[sd->deal_item_index[trade_i].unshift()].nameid + && target_sd->inventory_data[i] != nullptr) { id = target_sd->inventory_data[i]; if (id->type != ItemType::WEAPON @@ -260,11 +262,11 @@ void trade_tradeok(dumb_ptr<map_session_data> sd) for (trade_i = 0; trade_i < TRADE_MAX; trade_i++) { - int index = sd->deal_item_index[trade_i]; - if (index < 2 || index >= MAX_INVENTORY + 2) + IOff2 index = sd->deal_item_index[trade_i]; + if (!index.ok()) continue; if (sd->deal_item_amount[trade_i] > - sd->status.inventory[index - 2].amount + sd->status.inventory[index.unshift()].amount || sd->deal_item_amount[trade_i] < 0) { trade_tradecancel(sd); @@ -273,10 +275,10 @@ void trade_tradeok(dumb_ptr<map_session_data> sd) } - if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) + if ((target_sd = map_id2sd(account_to_block(sd->trade_partner))) != nullptr) { sd->deal_locked = 1; - clif_tradeitemok(sd, 0, 0, 0); + clif_tradeitemok(sd, IOff2::from(0), 0, 0); clif_tradedeal_lock(sd, 0); clif_tradedeal_lock(target_sd, 1); } @@ -293,26 +295,28 @@ void trade_tradecancel(dumb_ptr<map_session_data> sd) nullpo_retv(sd); - if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) + if ((target_sd = map_id2sd(account_to_block(sd->trade_partner))) != nullptr) { for (trade_i = 0; trade_i < TRADE_MAX; trade_i++) { //give items back (only virtual) if (sd->deal_item_amount[trade_i] != 0) { + assert (sd->deal_item_index[trade_i].ok()); clif_additem(sd, - sd->deal_item_index[trade_i] - 2, + sd->deal_item_index[trade_i].unshift(), sd->deal_item_amount[trade_i], PickupFail::OKAY); - sd->deal_item_index[trade_i] = 0; + sd->deal_item_index[trade_i] = IOff2::from(0); sd->deal_item_amount[trade_i] = 0; } if (target_sd->deal_item_amount[trade_i] != 0) { + assert (target_sd->deal_item_index[trade_i].ok()); clif_additem(target_sd, - target_sd->deal_item_index[trade_i] - 2, + target_sd->deal_item_index[trade_i].unshift(), target_sd->deal_item_amount[trade_i], PickupFail::OKAY); - target_sd->deal_item_index[trade_i] = 0; + target_sd->deal_item_index[trade_i] = IOff2::from(0); target_sd->deal_item_amount[trade_i] = 0; } } @@ -327,9 +331,9 @@ void trade_tradecancel(dumb_ptr<map_session_data> sd) target_sd->deal_zeny = 0; } sd->deal_locked = 0; - sd->trade_partner = 0; + sd->trade_partner = AccountId(); target_sd->deal_locked = 0; - target_sd->trade_partner = 0; + target_sd->trade_partner = AccountId(); clif_tradecancelled(sd); clif_tradecancelled(target_sd); } @@ -346,11 +350,11 @@ void trade_tradecommit(dumb_ptr<map_session_data> sd) nullpo_retv(sd); - if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) + if ((target_sd = map_id2sd(account_to_block(sd->trade_partner))) != nullptr) { - MAP_LOG_PC(sd, " TRADECOMMIT WITH %d GIVE %d GET %d", - target_sd->status_key.char_id, sd->deal_zeny, - target_sd->deal_zeny); + MAP_LOG_PC(sd, " TRADECOMMIT WITH %d GIVE %d GET %d"_fmt, + target_sd->status_key.char_id, sd->deal_zeny, + target_sd->deal_zeny); if ((sd->deal_locked >= 1) && (target_sd->deal_locked >= 1)) { // both have pressed 'ok' if (sd->deal_locked < 2) @@ -363,23 +367,24 @@ void trade_tradecommit(dumb_ptr<map_session_data> sd) { sd->deal_zeny = 0; trade_tradecancel(sd); - MAP_LOG_PC(sd, " TRADECANCEL"); + MAP_LOG_PC(sd, " TRADECANCEL"_fmt); return; } if (target_sd->deal_zeny > target_sd->status.zeny) { target_sd->deal_zeny = 0; trade_tradecancel(sd); - MAP_LOG_PC(sd, " TRADECANCEL"); + MAP_LOG_PC(sd, " TRADECANCEL"_fmt); return; } - sd->trade_partner = 0; - target_sd->trade_partner = 0; + sd->trade_partner = AccountId(); + target_sd->trade_partner = AccountId(); for (trade_i = 0; trade_i < TRADE_MAX; trade_i++) { if (sd->deal_item_amount[trade_i] != 0) { - int n = sd->deal_item_index[trade_i] - 2; + assert (sd->deal_item_index[trade_i].ok()); + IOff0 n = sd->deal_item_index[trade_i].unshift(); PickupFail flag = pc_additem(target_sd, &sd->status.inventory[n], sd->deal_item_amount[trade_i]); @@ -390,12 +395,13 @@ void trade_tradecommit(dumb_ptr<map_session_data> sd) clif_additem(sd, n, sd->deal_item_amount[trade_i], PickupFail::OKAY); - sd->deal_item_index[trade_i] = 0; + sd->deal_item_index[trade_i] = IOff2::from(0); sd->deal_item_amount[trade_i] = 0; } if (target_sd->deal_item_amount[trade_i] != 0) { - int n = target_sd->deal_item_index[trade_i] - 2; + assert (target_sd->deal_item_index[trade_i].ok()); + IOff0 n = target_sd->deal_item_index[trade_i].unshift(); PickupFail flag = pc_additem(sd, &target_sd->status.inventory[n], target_sd->deal_item_amount[trade_i]); @@ -405,10 +411,9 @@ void trade_tradecommit(dumb_ptr<map_session_data> sd) 1); else clif_additem(target_sd, n, - target_sd->deal_item_amount[trade_i], PickupFail::OKAY); - target_sd->deal_item_index[trade_i] = 0; + target_sd->deal_item_index[trade_i] = IOff2::from(0); target_sd->deal_item_amount[trade_i] = 0; } } @@ -434,7 +439,7 @@ void trade_tradecommit(dumb_ptr<map_session_data> sd) target_sd->deal_locked = 0; clif_tradecompleted(sd, 0); clif_tradecompleted(target_sd, 0); - MAP_LOG_PC(sd, " TRADEOK"); + MAP_LOG_PC(sd, " TRADEOK"_fmt); } } } @@ -449,14 +454,15 @@ void trade_verifyzeny(dumb_ptr<map_session_data> sd) nullpo_retv(sd); - if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) + if ((target_sd = map_id2sd(account_to_block(sd->trade_partner))) != nullptr) { if (sd->deal_zeny > sd->status.zeny) { if (sd->deal_locked < 1) - trade_tradeadditem(sd, 0, sd->status.zeny); // Fix money ammount + trade_tradeadditem(sd, IOff2::from(0), sd->status.zeny); // Fix money ammount else trade_tradecancel(sd); // Or cancel the trade if we can't fix it } } } +} // namespace tmwa diff --git a/src/map/trade.hpp b/src/map/trade.hpp index dc81c54..91ed954 100644 --- a/src/map/trade.hpp +++ b/src/map/trade.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_TRADE_HPP -#define TMWA_MAP_TRADE_HPP +#pragma once // trade.hpp - Inter-player item and money transactions. // // Copyright © ????-2004 Athena Dev Teams @@ -21,16 +20,20 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "map.hpp" +#include "../generic/fwd.hpp" -void trade_traderequest(dumb_ptr<map_session_data> sd, int target_id); +#include "clif.t.hpp" + + +namespace tmwa +{ +void trade_traderequest(dumb_ptr<map_session_data> sd, BlockId target_id); void trade_tradeack(dumb_ptr<map_session_data> sd, int type); -void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount); +void trade_tradeadditem(dumb_ptr<map_session_data> sd, IOff2 index, int amount); void trade_tradeok(dumb_ptr<map_session_data> sd); void trade_tradecancel(dumb_ptr<map_session_data> sd); void trade_tradecommit(dumb_ptr<map_session_data> sd); void trade_verifyzeny(dumb_ptr<map_session_data> sd); - -#endif // TMWA_MAP_TRADE_HPP +} // namespace tmwa diff --git a/src/mmo/config_parse.cpp b/src/mmo/config_parse.cpp index b954e8b..8362810 100644 --- a/src/mmo/config_parse.cpp +++ b/src/mmo/config_parse.cpp @@ -18,6 +18,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include <algorithm> + #include "../strings/xstring.hpp" #include "../strings/zstring.hpp" @@ -28,9 +30,12 @@ #include "../poison.hpp" + +namespace tmwa +{ bool is_comment(XString line) { - return not line or line.startswith("//"); + return not line or line.startswith("//"_s); } template<class ZS> @@ -72,7 +77,7 @@ bool load_config_file(ZString filename, ConfigItemParser slave) io::LineReader in(filename); if (!in.is_open()) { - PRINTF("Unable to open file: %s\n", filename); + PRINTF("Unable to open file: %s\n"_fmt, filename); return false; } io::Line line; @@ -85,16 +90,16 @@ bool load_config_file(ZString filename, ConfigItemParser slave) ZString value; if (!config_split(line.text, &key, &value)) { - line.error("Bad config line"); + line.error("Bad config line"_s); rv = false; continue; } - if (key == "import") + if (key == "import"_s) { rv &= load_config_file(value, slave); continue; } - else if (key == "version-lt") + else if (key == "version-lt"_s) { Version vers; if (!extract(value, &vers)) @@ -106,7 +111,7 @@ bool load_config_file(ZString filename, ConfigItemParser slave) continue; break; } - else if (key == "version-le") + else if (key == "version-le"_s) { Version vers; if (!extract(value, &vers)) @@ -118,7 +123,7 @@ bool load_config_file(ZString filename, ConfigItemParser slave) continue; break; } - else if (key == "version-gt") + else if (key == "version-gt"_s) { Version vers; if (!extract(value, &vers)) @@ -130,7 +135,7 @@ bool load_config_file(ZString filename, ConfigItemParser slave) continue; break; } - else if (key == "version-ge") + else if (key == "version-ge"_s) { Version vers; if (!extract(value, &vers)) @@ -144,7 +149,7 @@ bool load_config_file(ZString filename, ConfigItemParser slave) } else if (!slave(key, value)) { - line.error("Bad config key or value"); + line.error("Bad config key or value"_s); rv = false; continue; } @@ -152,3 +157,4 @@ bool load_config_file(ZString filename, ConfigItemParser slave) } return rv; } +} // namespace tmwa diff --git a/src/mmo/config_parse.hpp b/src/mmo/config_parse.hpp index dd1b79e..50a115e 100644 --- a/src/mmo/config_parse.hpp +++ b/src/mmo/config_parse.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MMO_CONFIG_PARSE_HPP -#define TMWA_MMO_CONFIG_PARSE_HPP +#pragma once // config_parse.hpp - Framework for per-server config parsers. // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,10 +18,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" + +namespace tmwa +{ typedef bool (*ConfigItemParser)(XString key, ZString value); bool is_comment(XString line); @@ -32,5 +34,4 @@ bool config_split(XString line, XString *key, XString *value); /// Master config parser. This handles 'import' and 'version-ge' etc. /// Then it defers to the inferior parser for a line it does not understand. bool load_config_file(ZString filename, ConfigItemParser slave); - -#endif // TMWA_MMO_CONFIG_PARSE_HPP +} // namespace tmwa diff --git a/src/mmo/consts.cpp b/src/mmo/consts.cpp new file mode 100644 index 0000000..e49cdf5 --- /dev/null +++ b/src/mmo/consts.cpp @@ -0,0 +1,26 @@ +#include "consts.hpp" +// consts.cpp - empty mess of constants +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/mmo/consts.hpp b/src/mmo/consts.hpp new file mode 100644 index 0000000..c1a7eb6 --- /dev/null +++ b/src/mmo/consts.hpp @@ -0,0 +1,66 @@ +#pragma once +// consts.hpp - Huge mess of constants. +// +// Copyright © ????-2004 Athena Dev Teams +// Copyright © 2004-2011 The Mana World Development Team +// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include "../net/timer.t.hpp" + +#include "ids.hpp" +#include "strs.hpp" + + +namespace tmwa +{ +constexpr int FIFOSIZE_SERVERLINK = 256 * 1024; + +constexpr int MAX_MAP_PER_SERVER = 512; +constexpr int MAX_INVENTORY = 100; +constexpr int MAX_AMOUNT = 30000; +constexpr int MAX_ZENY = 1000000000; // 1G zeny +constexpr int TRADE_MAX = 10; + +constexpr int GLOBAL_REG_NUM = 96; +constexpr size_t ACCOUNT_REG_NUM = 16; +constexpr size_t ACCOUNT_REG2_NUM = 16; +constexpr interval_t DEFAULT_WALK_SPEED = 150_ms; +constexpr interval_t MIN_WALK_SPEED = interval_t::zero(); +constexpr interval_t MAX_WALK_SPEED = 1_s; +constexpr int MAX_STORAGE = 300; +constexpr int MAX_PARTY = 12; + +#define MIN_HAIR_STYLE battle_config.min_hair_style +#define MAX_HAIR_STYLE battle_config.max_hair_style +#define MIN_HAIR_COLOR battle_config.min_hair_color +#define MAX_HAIR_COLOR battle_config.max_hair_color +#define MIN_CLOTH_COLOR battle_config.min_cloth_color +#define MAX_CLOTH_COLOR battle_config.max_cloth_color + +// WTF is this doing here? +struct PartyMember +{ + AccountId account_id; + CharName name; + MapName map; + int leader, online, lv; + struct map_session_data *sd; +}; +} // namespace tmwa diff --git a/src/mmo/core.cpp b/src/mmo/core.cpp index 68b7823..f1a8d07 100644 --- a/src/mmo/core.cpp +++ b/src/mmo/core.cpp @@ -22,23 +22,26 @@ #include <sys/wait.h> -#include <unistd.h> +#include <alloca.h> #include <csignal> #include <cstdlib> -#include <ctime> -#include "../strings/zstring.hpp" +#include <tmwa/shared.hpp> -#include "../generic/random.hpp" +#include "../strings/zstring.hpp" +#include "../strings/literal.hpp" #include "../io/cxxstdio.hpp" -#include "socket.hpp" -#include "timer.hpp" +#include "../net/socket.hpp" +#include "../net/timer.hpp" #include "../poison.hpp" + +namespace tmwa +{ // Added by Gabuzomeu // // This is an implementation of signal() using sigaction() for portability. @@ -61,10 +64,12 @@ sigfunc compat_signal(int signo, sigfunc func) sact.sa_flags = 0; if (sigaction(signo, &sact, &oact) < 0) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" + { + DIAG_PUSH(); + DIAG_I(old_style_cast); return SIG_ERR; -#pragma GCC diagnostic pop + DIAG_POP(); + } return oact.sa_handler; } @@ -75,16 +80,18 @@ bool runflag = true; static void chld_proc(int) { - wait(NULL); + wait(nullptr); } static void sig_proc(int) { for (int i = 1; i < 31; ++i) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" + { + DIAG_PUSH(); + DIAG_I(old_style_cast); compat_signal(i, SIG_IGN); -#pragma GCC diagnostic pop + DIAG_POP(); + } runflag = false; } @@ -97,8 +104,14 @@ void sig_proc(int) Unless you use SA_SIGINFO and *carefully* check the origin, that means they must be SIG_DFL. */ +} // namespace tmwa + int main(int argc, char **argv) { + using namespace tmwa; + + check_paths(); + // ZString args[argc]; is (deliberately!) not supported by clang yet ZString *args = static_cast<ZString *>(alloca(argc * sizeof(ZString))); for (int i = 0; i < argc; ++i) @@ -107,29 +120,30 @@ int main(int argc, char **argv) if (!runflag) { - PRINTF("Fatal error during startup; exiting\n"); + PRINTF("Fatal error during startup; exiting\n"_fmt); return 1; } // set up exit handlers *after* the initialization has happened. // This is because term_func is likely to depend on successful init. -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" + DIAG_PUSH(); + DIAG_I(old_style_cast); compat_signal(SIGPIPE, SIG_IGN); -#pragma GCC diagnostic pop + DIAG_POP(); compat_signal(SIGTERM, sig_proc); compat_signal(SIGINT, sig_proc); compat_signal(SIGCHLD, chld_proc); // Signal to create coredumps by system when necessary (crash) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" + DIAG_PUSH(); + DIAG_I(old_style_cast); + DIAG_I(zero_as_null_pointer_constant); compat_signal(SIGSEGV, SIG_DFL); compat_signal(SIGBUS, SIG_DFL); compat_signal(SIGTRAP, SIG_DFL); compat_signal(SIGILL, SIG_DFL); compat_signal(SIGFPE, SIG_DFL); -#pragma GCC diagnostic pop + DIAG_POP(); atexit(term_func); diff --git a/src/mmo/core.hpp b/src/mmo/core.hpp index 5699045..5b2dbbb 100644 --- a/src/mmo/core.hpp +++ b/src/mmo/core.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MMO_CORE_HPP -#define TMWA_MMO_CORE_HPP +#pragma once // core.hpp - The main loop. // // Copyright © ????-2004 Athena Dev Teams @@ -21,12 +20,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../range/slice.hpp" +#include "../range/slice.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" + +namespace tmwa +{ /// core.c contains a server-independent main() function /// and then runs a do_sendrecv loop @@ -40,5 +42,4 @@ extern int do_init(Slice<ZString>); /// Cleanup function called whenever a signal kills us /// or when if we manage to exit() gracefully. extern void term_func(void); - -#endif // TMWA_MMO_CORE_HPP +} // namespace tmwa diff --git a/src/mmo/enums.cpp b/src/mmo/enums.cpp new file mode 100644 index 0000000..d05be91 --- /dev/null +++ b/src/mmo/enums.cpp @@ -0,0 +1,26 @@ +#include "enums.hpp" +// enums.cpp - Common enumerated types +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/mmo/enums.hpp b/src/mmo/enums.hpp new file mode 100644 index 0000000..bf8a75c --- /dev/null +++ b/src/mmo/enums.hpp @@ -0,0 +1,162 @@ +#pragma once +// enums.hpp - Common enumerated types +// +// Copyright © ????-2004 Athena Dev Teams +// Copyright © 2004-2011 The Mana World Development Team +// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include <cstdint> + +#include "../generic/enum.hpp" + + +namespace tmwa +{ +enum class SkillID : uint16_t; +constexpr SkillID MAX_SKILL = SkillID(474); // not 450 +constexpr SkillID get_enum_min_value(SkillID) { return SkillID(); } +constexpr SkillID get_enum_max_value(SkillID) { return MAX_SKILL; } + +namespace e +{ +enum class EPOS : uint16_t +{ + ZERO = 0x0000, + + LEGS = 0x0001, + WEAPON = 0x0002, + GLOVES = 0x0004, + CAPE = 0x0008, + MISC1 = 0x0010, + SHIELD = 0x0020, + SHOES = 0x0040, + MISC2 = 0x0080, + HAT = 0x0100, + TORSO = 0x0200, + + ARROW = 0x8000, +}; +ENUM_BITWISE_OPERATORS(EPOS) + +constexpr EPOS get_enum_min_value(EPOS) { return EPOS(0x0000); } +constexpr EPOS get_enum_max_value(EPOS) { return EPOS(0xffff); } +} +using e::EPOS; + +namespace e +{ +enum class SkillFlags : uint16_t; +} +using e::SkillFlags; + +// Option and Opt1..3 in map.hpp +namespace e +{ +enum class Option : uint16_t; +constexpr Option get_enum_min_value(Option) { return Option(0x0000); } +constexpr Option get_enum_max_value(Option) { return Option(0xffff); } +} +using e::Option; + +enum class ATTR +{ + STR = 0, + AGI = 1, + VIT = 2, + INT = 3, + DEX = 4, + LUK = 5, + + COUNT = 6, +}; + +constexpr ATTR ATTRs[6] = +{ + ATTR::STR, + ATTR::AGI, + ATTR::VIT, + ATTR::INT, + ATTR::DEX, + ATTR::LUK, +}; + +enum class ItemLook : uint16_t +{ + NONE = 0, + BLADE = 1, // or some other common weapons + _2, + SETZER_AND_SCYTHE = 3, + _6, + STAFF = 10, + BOW = 11, + _13 = 13, + _14 = 14, + _16 = 16, + SINGLE_HANDED_COUNT = 17, + + DUAL_BLADE = 0x11, + DUAL_2 = 0x12, + DUAL_6 = 0x13, + DUAL_12 = 0x14, + DUAL_16 = 0x15, + DUAL_26 = 0x16, +}; + +enum class SEX : uint8_t +{ + FEMALE = 0, + MALE = 1, + // For items. This is also used as error, sometime. + NEUTRAL = 2, +}; +inline +char sex_to_char(SEX sex) +{ + switch (sex) + { + case SEX::FEMALE: return 'F'; + case SEX::MALE: return 'M'; + default: return '\0'; + } +} +inline +SEX sex_from_char(char c) +{ + switch (c) + { + case 'F': return SEX::FEMALE; + case 'M': return SEX::MALE; + default: return SEX::NEUTRAL; + } +} + +inline +bool native_to_network(char *network, SEX native) +{ + *network = sex_to_char(native); + return true; +} +inline +bool network_to_native(SEX *native, char network) +{ + *native = sex_from_char(network); + return true; +} +} // namespace tmwa diff --git a/src/mmo/extract.cpp b/src/mmo/extract.cpp index 378986d..d486ed5 100644 --- a/src/mmo/extract.cpp +++ b/src/mmo/extract.cpp @@ -18,12 +18,19 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include <algorithm> + #include "../strings/astring.hpp" #include "../strings/xstring.hpp" #include "../strings/vstring.hpp" +#include "mmo.hpp" + #include "../poison.hpp" + +namespace tmwa +{ bool extract(XString str, XString *rv) { *rv = str; @@ -36,20 +43,21 @@ bool extract(XString str, AString *rv) return true; } -bool extract(XString str, struct global_reg *var) +bool extract(XString str, GlobalReg *var) { return extract(str, record<','>(&var->str, &var->value)); } -bool extract(XString str, struct item *it) +bool extract(XString str, Item *it) { XString ignored; - return extract(str, + XString corruption_hack_amount; + bool rv = extract(str, record<',', 11>( - &it->id, + &ignored, &it->nameid, - &it->amount, + &corruption_hack_amount, &it->equip, &ignored, &ignored, @@ -59,4 +67,34 @@ bool extract(XString str, struct item *it) &ignored, &ignored, &ignored)); + if (rv) + { + if (corruption_hack_amount == "-1"_s) + it->amount = 0; + else + rv = extract(corruption_hack_amount, &it->amount); + } + return rv; +} + +bool extract(XString str, MapName *m) +{ + XString::iterator it = std::find(str.begin(), str.end(), '.'); + str = str.xislice_h(it); + VString<15> tmp; + bool rv = extract(str, &tmp); + *m = tmp; + return rv; +} + +bool extract(XString str, CharName *out) +{ + VString<23> tmp; + if (extract(str, &tmp)) + { + *out = CharName(tmp); + return true; + } + return false; } +} // namespace tmwa diff --git a/src/mmo/extract.hpp b/src/mmo/extract.hpp index 622281b..355e2da 100644 --- a/src/mmo/extract.hpp +++ b/src/mmo/extract.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MMO_EXTRACT_HPP -#define TMWA_MMO_EXTRACT_HPP +#pragma once // extract.hpp - a simple, hierarchical, tokenizer // // Copyright © 2012-2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,14 +18,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <algorithm> +#include <cerrno> +#include <cstdlib> -# include "../strings/xstring.hpp" +#include <algorithm> +#include <vector> -# include "mmo.hpp" -# include "utils.hpp" +#include "../ints/wrap.hpp" + +#include "../strings/xstring.hpp" + +#include "../generic/enum.hpp" + +#include "utils.hpp" + + +namespace tmwa +{ +template<class T> +bool do_extract(XString str, T t); template<class T, typename=typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, char>::value && !std::is_same<T, bool>::value>::type> bool extract(XString str, T *iv) @@ -94,6 +106,12 @@ bool extract(XString str, VString<N> *out) return true; } +inline +bool extract(XString str, LString exact) +{ + return str == exact; +} + template<class T> class LStripper { @@ -192,31 +210,23 @@ bool extract(XString str, VRecord<split, T> rec) && extract(str.xislice_t(s + 1), rec); } -bool extract(XString str, struct global_reg *var); +bool extract(XString str, GlobalReg *var); -bool extract(XString str, struct item *it); +bool extract(XString str, Item *it); -inline -bool extract(XString str, MapName *m) -{ - XString::iterator it = std::find(str.begin(), str.end(), '.'); - str = str.xislice_h(it); - VString<15> tmp; - bool rv = extract(str, &tmp); - *m = tmp; - return rv; -} +bool extract(XString str, MapName *m); -inline -bool extract(XString str, CharName *out) +bool extract(XString str, CharName *out); + +template<class T> +bool do_extract(XString str, T t) { - VString<23> tmp; - if (extract(str, &tmp)) - { - *out = CharName(tmp); - return true; - } - return false; + return extract(str, t); } -#endif // TMWA_MMO_EXTRACT_HPP +template<class R> +bool extract(XString str, Wrapped<R> *w) +{ + return extract(str, &w->_value); +} +} // namespace tmwa diff --git a/src/mmo/extract_test.cpp b/src/mmo/extract_test.cpp index 60ab49e..e6dc7b2 100644 --- a/src/mmo/extract_test.cpp +++ b/src/mmo/extract_test.cpp @@ -22,160 +22,165 @@ #include "../strings/xstring.hpp" +#include "mmo.hpp" + #include "../poison.hpp" + +namespace tmwa +{ TEST(extract, record_int) { int x, y, z; x = y = z = 0; - EXPECT_FALSE(extract("1 2 3 4 ", record<' '>(&x, &y, &z))); + EXPECT_FALSE(extract("1 2 3 4 "_s, record<' '>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_FALSE(extract("1 2 3 4", record<' '>(&x, &y, &z))); + EXPECT_FALSE(extract("1 2 3 4"_s, record<' '>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_TRUE(extract("1 2 3 ", record<' '>(&x, &y, &z))); + EXPECT_TRUE(extract("1 2 3 "_s, record<' '>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_TRUE(extract("1 2 3", record<' '>(&x, &y, &z))); + EXPECT_TRUE(extract("1 2 3"_s, record<' '>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_FALSE(extract("1 2 ", record<' '>(&x, &y, &z))); + EXPECT_FALSE(extract("1 2 "_s, record<' '>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract("1 2", record<' '>(&x, &y, &z))); + EXPECT_FALSE(extract("1 2"_s, record<' '>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract("1 ", record<' '>(&x, &y, &z))); + EXPECT_FALSE(extract("1 "_s, record<' '>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract("1", record<' '>(&x, &y, &z))); + EXPECT_FALSE(extract("1"_s, record<' '>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract(" ", record<' '>(&x, &y, &z))); + EXPECT_FALSE(extract(" "_s, record<' '>(&x, &y, &z))); EXPECT_EQ(0, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract("", record<' '>(&x, &y, &z))); + EXPECT_FALSE(extract(""_s, record<' '>(&x, &y, &z))); EXPECT_EQ(0, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract("1 2 3 4 ", record<' ', 2>(&x, &y, &z))); + EXPECT_FALSE(extract("1 2 3 4 "_s, record<' ', 2>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_FALSE(extract("1 2 3 4", record<' ', 2>(&x, &y, &z))); + EXPECT_FALSE(extract("1 2 3 4"_s, record<' ', 2>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_TRUE(extract("1 2 3 ", record<' ', 2>(&x, &y, &z))); + EXPECT_TRUE(extract("1 2 3 "_s, record<' ', 2>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_TRUE(extract("1 2 3", record<' ', 2>(&x, &y, &z))); + EXPECT_TRUE(extract("1 2 3"_s, record<' ', 2>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_TRUE(extract("1 2 ", record<' ', 2>(&x, &y, &z))); + EXPECT_TRUE(extract("1 2 "_s, record<' ', 2>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_TRUE(extract("1 2", record<' ', 2>(&x, &y, &z))); + EXPECT_TRUE(extract("1 2"_s, record<' ', 2>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract("1 ", record<' ', 2>(&x, &y, &z))); + EXPECT_FALSE(extract("1 "_s, record<' ', 2>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract("1", record<' ', 2>(&x, &y, &z))); + EXPECT_FALSE(extract("1"_s, record<' ', 2>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract(" ", record<' ', 2>(&x, &y, &z))); + EXPECT_FALSE(extract(" "_s, record<' ', 2>(&x, &y, &z))); EXPECT_EQ(0, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract("", record<' ', 2>(&x, &y, &z))); + EXPECT_FALSE(extract(""_s, record<' ', 2>(&x, &y, &z))); EXPECT_EQ(0, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract("1 2 3 4 ", record<' ', 1>(&x, &y, &z))); + EXPECT_FALSE(extract("1 2 3 4 "_s, record<' ', 1>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_FALSE(extract("1 2 3 4", record<' ', 1>(&x, &y, &z))); + EXPECT_FALSE(extract("1 2 3 4"_s, record<' ', 1>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_TRUE(extract("1 2 3 ", record<' ', 1>(&x, &y, &z))); + EXPECT_TRUE(extract("1 2 3 "_s, record<' ', 1>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_TRUE(extract("1 2 3", record<' ', 1>(&x, &y, &z))); + EXPECT_TRUE(extract("1 2 3"_s, record<' ', 1>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3, z); x = y = z = 0; - EXPECT_TRUE(extract("1 2 ", record<' ', 1>(&x, &y, &z))); + EXPECT_TRUE(extract("1 2 "_s, record<' ', 1>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_TRUE(extract("1 2", record<' ', 1>(&x, &y, &z))); + EXPECT_TRUE(extract("1 2"_s, record<' ', 1>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_TRUE(extract("1 ", record<' ', 1>(&x, &y, &z))); + EXPECT_TRUE(extract("1 "_s, record<' ', 1>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_TRUE(extract("1", record<' ', 1>(&x, &y, &z))); + EXPECT_TRUE(extract("1"_s, record<' ', 1>(&x, &y, &z))); EXPECT_EQ(1, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract(" ", record<' ', 1>(&x, &y, &z))); + EXPECT_FALSE(extract(" "_s, record<' ', 1>(&x, &y, &z))); EXPECT_EQ(0, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); x = y = z = 0; - EXPECT_FALSE(extract("", record<' ', 1>(&x, &y, &z))); + EXPECT_FALSE(extract(""_s, record<' ', 1>(&x, &y, &z))); EXPECT_EQ(0, x); EXPECT_EQ(0, y); EXPECT_EQ(0, z); @@ -185,170 +190,171 @@ TEST(extract, record_int) TEST(extract, record_str) { XString x, y, z; - x = y = z = ""; - EXPECT_FALSE(extract("1 2 3 4 ", record<' '>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_FALSE(extract("1 2 3 4", record<' '>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 2 3 ", record<' '>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 2 3", record<' '>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 2 ", record<' '>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_FALSE(extract("1 2", record<' '>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_FALSE(extract("1 ", record<' '>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_FALSE(extract("1", record<' '>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_FALSE(extract(" ", record<' '>(&x, &y, &z))); - EXPECT_EQ("", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_FALSE(extract("", record<' '>(&x, &y, &z))); - EXPECT_EQ("", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; + x = y = z = ""_s; + EXPECT_FALSE(extract("1 2 3 4 "_s, record<' '>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_FALSE(extract("1 2 3 4"_s, record<' '>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 2 3 "_s, record<' '>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 2 3"_s, record<' '>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 2 "_s, record<' '>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_FALSE(extract("1 2"_s, record<' '>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_FALSE(extract("1 "_s, record<' '>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_FALSE(extract("1"_s, record<' '>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_FALSE(extract(" "_s, record<' '>(&x, &y, &z))); + EXPECT_EQ(""_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_FALSE(extract(""_s, record<' '>(&x, &y, &z))); + EXPECT_EQ(""_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; - EXPECT_FALSE(extract("1 2 3 4 ", record<' ', 2>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_FALSE(extract("1 2 3 4", record<' ', 2>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 2 3 ", record<' ', 2>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 2 3", record<' ', 2>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 2 ", record<' ', 2>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 2", record<' ', 2>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 ", record<' ', 2>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_FALSE(extract("1", record<' ', 2>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_TRUE(extract(" ", record<' ', 2>(&x, &y, &z))); - EXPECT_EQ("", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_FALSE(extract("", record<' ', 2>(&x, &y, &z))); - EXPECT_EQ("", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; + EXPECT_FALSE(extract("1 2 3 4 "_s, record<' ', 2>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_FALSE(extract("1 2 3 4"_s, record<' ', 2>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 2 3 "_s, record<' ', 2>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 2 3"_s, record<' ', 2>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 2 "_s, record<' ', 2>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 2"_s, record<' ', 2>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 "_s, record<' ', 2>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_FALSE(extract("1"_s, record<' ', 2>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract(" "_s, record<' ', 2>(&x, &y, &z))); + EXPECT_EQ(""_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_FALSE(extract(""_s, record<' ', 2>(&x, &y, &z))); + EXPECT_EQ(""_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; - EXPECT_FALSE(extract("1 2 3 4 ", record<' ', 1>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_FALSE(extract("1 2 3 4", record<' ', 1>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 2 3 ", record<' ', 1>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 2 3", record<' ', 1>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("3", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 2 ", record<' ', 1>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 2", record<' ', 1>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("2", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_TRUE(extract("1 ", record<' ', 1>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_TRUE(extract("1", record<' ', 1>(&x, &y, &z))); - EXPECT_EQ("1", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_TRUE(extract(" ", record<' ', 1>(&x, &y, &z))); - EXPECT_EQ("", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; - EXPECT_TRUE(extract("", record<' ', 1>(&x, &y, &z))); - EXPECT_EQ("", x); - EXPECT_EQ("", y); - EXPECT_EQ("", z); - x = y = z = ""; + EXPECT_FALSE(extract("1 2 3 4 "_s, record<' ', 1>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_FALSE(extract("1 2 3 4"_s, record<' ', 1>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 2 3 "_s, record<' ', 1>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 2 3"_s, record<' ', 1>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ("3"_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 2 "_s, record<' ', 1>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 2"_s, record<' ', 1>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ("2"_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1 "_s, record<' ', 1>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract("1"_s, record<' ', 1>(&x, &y, &z))); + EXPECT_EQ("1"_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract(" "_s, record<' ', 1>(&x, &y, &z))); + EXPECT_EQ(""_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; + EXPECT_TRUE(extract(""_s, record<' ', 1>(&x, &y, &z))); + EXPECT_EQ(""_s, x); + EXPECT_EQ(""_s, y); + EXPECT_EQ(""_s, z); + x = y = z = ""_s; } TEST(extract, mapname) { MapName map; - EXPECT_TRUE(extract("abc", &map)); - EXPECT_EQ(map, "abc"); - EXPECT_TRUE(extract("abc.gat", &map)); - EXPECT_EQ(map, "abc"); - EXPECT_TRUE(extract("abcdefghijklmno", &map)); - EXPECT_EQ(map, "abcdefghijklmno"); - EXPECT_TRUE(extract("abcdefghijklmno.gat", &map)); - EXPECT_EQ(map, "abcdefghijklmno"); + EXPECT_TRUE(extract("abc"_s, &map)); + EXPECT_EQ(map, "abc"_s); + EXPECT_TRUE(extract("abc.gat"_s, &map)); + EXPECT_EQ(map, "abc"_s); + EXPECT_TRUE(extract("abcdefghijklmno"_s, &map)); + EXPECT_EQ(map, "abcdefghijklmno"_s); + EXPECT_TRUE(extract("abcdefghijklmno.gat"_s, &map)); + EXPECT_EQ(map, "abcdefghijklmno"_s); } +} // namespace tmwa diff --git a/src/mmo/fwd.hpp b/src/mmo/fwd.hpp new file mode 100644 index 0000000..3b56bfb --- /dev/null +++ b/src/mmo/fwd.hpp @@ -0,0 +1,68 @@ +#pragma once +// mmo/fwd.hpp - list of type names for mmo lib +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +// meh, add more when I feel like it +class MapName; +class CharName; +class CharPair; + +class HumanTimeDiff; + +class AccountId; +class CharId; +class PartyId; +class ItemUnkId; +class ItemNameId; +class GmLevel; + +class AccountName; +class AccountPass; +class AccountCrypt; +class AccountEmail; +class ServerName; +class PartyName; +class VarName; +class MapName; +class CharName; + +class Item; +#if 0 +class Point; +class SkillValue; +#endif +class GlobalReg; +#if 0 +class CharKey; +class CharData; +class CharPair; +#endif +class Storage; +#if 0 +class GM_Account; +class PartyMember; +#endif +class PartyMost; +class PartyPair; +} // namespace tmwa diff --git a/src/mmo/human_time_diff.cpp b/src/mmo/human_time_diff.cpp index f2f720e..49a7664 100644 --- a/src/mmo/human_time_diff.cpp +++ b/src/mmo/human_time_diff.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/mmo/human_time_diff.hpp b/src/mmo/human_time_diff.hpp index 689b8d9..b5c19fb 100644 --- a/src/mmo/human_time_diff.hpp +++ b/src/mmo/human_time_diff.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MMO_HUMAN_TIME_DIFF_HPP -#define TMWA_MMO_HUMAN_TIME_DIFF_HPP +#pragma once // human_time_diff.hpp - broken deltas // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,12 +18,17 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/xstring.hpp" +#include <algorithm> -# include "extract.hpp" +#include "../strings/xstring.hpp" +#include "extract.hpp" + + +namespace tmwa +{ struct HumanTimeDiff { short year, month, day, hour, minute, second; @@ -61,26 +65,25 @@ bool extract(XString str, HumanTimeDiff *iv) str = str.xislice_t(it2); short *ptr = nullptr; - if (suffix == "y" || suffix == "a") + if (suffix == "y"_s || suffix == "a"_s) ptr = &iv->year; - else if (suffix == "m") + else if (suffix == "m"_s) ptr = &iv->month; - else if (suffix == "j" || suffix == "d") + else if (suffix == "j"_s || suffix == "d"_s) ptr = &iv->day; - else if (suffix == "h") + else if (suffix == "h"_s) ptr = &iv->hour; - else if (suffix == "mn") + else if (suffix == "mn"_s) ptr = &iv->minute; - else if (suffix == "s") + else if (suffix == "s"_s) ptr = &iv->second; else return false; - if (number.startswith('+') && !number.startswith("+-")) + if (number.startswith('+') && !number.startswith("+-"_s)) number = number.xslice_t(1); if (*ptr || !extract(number, ptr)) return false; } return true; } - -#endif // TMWA_MMO_HUMAN_TIME_DIFF_HPP +} // namespace tmwa diff --git a/src/mmo/human_time_diff_test.cpp b/src/mmo/human_time_diff_test.cpp index 138849b..c18599d 100644 --- a/src/mmo/human_time_diff_test.cpp +++ b/src/mmo/human_time_diff_test.cpp @@ -1,5 +1,5 @@ #include "human_time_diff.hpp" -// human_time_diff.hpp - Testwuite for broken deltas +// human_time_diff_test.cpp - Testwuite for broken deltas // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> // @@ -22,13 +22,16 @@ #include "../poison.hpp" + +namespace tmwa +{ // a sequence of [-+]?[0-9]+([ay]|m|[jd]|h|mn|s) TEST(humantimediff, single) { HumanTimeDiff diff; - EXPECT_TRUE(extract("42y", &diff)); + EXPECT_TRUE(extract("42y"_s, &diff)); EXPECT_EQ(42, diff.year); EXPECT_EQ(0, diff.month); EXPECT_EQ(0, diff.day); @@ -36,7 +39,7 @@ TEST(humantimediff, single) EXPECT_EQ(0, diff.minute); EXPECT_EQ(0, diff.second); - EXPECT_TRUE(extract("42m", &diff)); + EXPECT_TRUE(extract("42m"_s, &diff)); EXPECT_EQ(0, diff.year); EXPECT_EQ(42, diff.month); EXPECT_EQ(0, diff.day); @@ -44,7 +47,7 @@ TEST(humantimediff, single) EXPECT_EQ(0, diff.minute); EXPECT_EQ(0, diff.second); - EXPECT_TRUE(extract("42d", &diff)); + EXPECT_TRUE(extract("42d"_s, &diff)); EXPECT_EQ(0, diff.year); EXPECT_EQ(0, diff.month); EXPECT_EQ(42, diff.day); @@ -52,7 +55,7 @@ TEST(humantimediff, single) EXPECT_EQ(0, diff.minute); EXPECT_EQ(0, diff.second); - EXPECT_TRUE(extract("42h", &diff)); + EXPECT_TRUE(extract("42h"_s, &diff)); EXPECT_EQ(0, diff.year); EXPECT_EQ(0, diff.month); EXPECT_EQ(0, diff.day); @@ -60,7 +63,7 @@ TEST(humantimediff, single) EXPECT_EQ(0, diff.minute); EXPECT_EQ(0, diff.second); - EXPECT_TRUE(extract("42mn", &diff)); + EXPECT_TRUE(extract("42mn"_s, &diff)); EXPECT_EQ(0, diff.year); EXPECT_EQ(0, diff.month); EXPECT_EQ(0, diff.day); @@ -68,7 +71,7 @@ TEST(humantimediff, single) EXPECT_EQ(42, diff.minute); EXPECT_EQ(0, diff.second); - EXPECT_TRUE(extract("42s", &diff)); + EXPECT_TRUE(extract("42s"_s, &diff)); EXPECT_EQ(0, diff.year); EXPECT_EQ(0, diff.month); EXPECT_EQ(0, diff.day); @@ -76,28 +79,29 @@ TEST(humantimediff, single) EXPECT_EQ(0, diff.minute); EXPECT_EQ(42, diff.second); - EXPECT_TRUE(extract("+42y", &diff)); + EXPECT_TRUE(extract("+42y"_s, &diff)); EXPECT_EQ(42, diff.year); - EXPECT_TRUE(extract("-42y", &diff)); + EXPECT_TRUE(extract("-42y"_s, &diff)); EXPECT_EQ(-42, diff.year); - EXPECT_FALSE(extract("++42y", &diff)); - EXPECT_FALSE(extract("+-42y", &diff)); - EXPECT_FALSE(extract("-+42y", &diff)); - EXPECT_FALSE(extract("--42y", &diff)); - EXPECT_FALSE(extract("4+2y", &diff)); - EXPECT_FALSE(extract("42z", &diff)); + EXPECT_FALSE(extract("++42y"_s, &diff)); + EXPECT_FALSE(extract("+-42y"_s, &diff)); + EXPECT_FALSE(extract("-+42y"_s, &diff)); + EXPECT_FALSE(extract("--42y"_s, &diff)); + EXPECT_FALSE(extract("4+2y"_s, &diff)); + EXPECT_FALSE(extract("42z"_s, &diff)); } TEST(humantimediff, multiple) { HumanTimeDiff diff; - EXPECT_TRUE(extract("42y23m-2d", &diff)); + EXPECT_TRUE(extract("42y23m-2d"_s, &diff)); EXPECT_EQ(42, diff.year); EXPECT_EQ(23, diff.month); EXPECT_EQ(-2, diff.day); EXPECT_EQ(0, diff.hour); EXPECT_EQ(0, diff.minute); EXPECT_EQ(0, diff.second); - EXPECT_FALSE(extract("1y2y", &diff)); + EXPECT_FALSE(extract("1y2y"_s, &diff)); } +} // namespace tmwa diff --git a/src/mmo/ids.cpp b/src/mmo/ids.cpp new file mode 100644 index 0000000..d40d5c3 --- /dev/null +++ b/src/mmo/ids.cpp @@ -0,0 +1,26 @@ +#include "ids.hpp" +// ids.cpp - special integer classes for various object IDs +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/mmo/ids.hpp b/src/mmo/ids.hpp new file mode 100644 index 0000000..4e2b97c --- /dev/null +++ b/src/mmo/ids.hpp @@ -0,0 +1,168 @@ +#pragma once +// ids.hpp - special integer classes for various object IDs +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include "../ints/little.hpp" +#include "../ints/wrap.hpp" + +#include "extract.hpp" + + +namespace tmwa +{ +class Species : public Wrapped<uint16_t> { public: explicit operator bool() const = delete; bool operator !() const = delete; constexpr Species() : Wrapped<uint16_t>() {} protected: constexpr explicit Species(uint16_t a) : Wrapped<uint16_t>(a) {} }; + +constexpr Species NEGATIVE_SPECIES = Species(); + +inline +bool extract(XString str, Species *w) +{ + // lots of data files use this + if (str == "-1"_s) + { + *w = NEGATIVE_SPECIES; + return true; + } + return extract(str, &w->_value); +} + + +class AccountId : public Wrapped<uint32_t> { public: constexpr AccountId() : Wrapped<uint32_t>() {} protected: constexpr explicit AccountId(uint32_t a) : Wrapped<uint32_t>(a) {} }; +class CharId : public Wrapped<uint32_t> { public: constexpr CharId() : Wrapped<uint32_t>() {} protected: constexpr explicit CharId(uint32_t a) : Wrapped<uint32_t>(a) {} }; +// important note: slave mobs synthesize PartyId as -BlockId of master +class PartyId : public Wrapped<uint32_t> { public: constexpr PartyId() : Wrapped<uint32_t>() {} protected: constexpr explicit PartyId(uint32_t a) : Wrapped<uint32_t>(a) {} }; +class ItemNameId : public Wrapped<uint16_t> { public: constexpr ItemNameId() : Wrapped<uint16_t>() {} protected: constexpr explicit ItemNameId(uint16_t a) : Wrapped<uint16_t>(a) {} }; + +class BlockId : public Wrapped<uint32_t> { public: constexpr BlockId() : Wrapped<uint32_t>() {} protected: constexpr explicit BlockId(uint32_t a) : Wrapped<uint32_t>(a) {} }; + +class GmLevel +{ + uint32_t bits; + + friend bool extract(XString str, GmLevel *lvl) { return extract(str, &lvl->bits); } + constexpr explicit + GmLevel(uint32_t b) : bits(b) {} + constexpr explicit + operator uint32_t() const { return bits; } + + template<class T> + explicit + GmLevel(T) = delete; + template<class T, typename=typename std::enable_if<!std::is_same<T, uint32_t>::value && !std::is_same<T, bool>::value>::type> + explicit + operator T() = delete; +public: + constexpr + GmLevel() : bits() {} + constexpr static + GmLevel from(uint32_t bits) { return GmLevel(bits); } + template<class T> + constexpr static + GmLevel from(T) = delete; + + constexpr explicit + operator bool() const { return bits; } + constexpr + bool operator !() const { return !bits; } + + // the argument is the level of a command + constexpr + bool satisfies(GmLevel perm) const { return bits >= perm.bits; } + // the argument is another player's gm level, for info commands + constexpr + bool detects(GmLevel other) const { return bits >= other.bits; } + // the argument is another player's gm level, for aggressive commands + constexpr + bool overwhelms(GmLevel other) const { return bits >= other.bits; } + // the argument is another potential permission level + constexpr + bool obsoletes(GmLevel plvl) const { return bits >= plvl.bits; } + + constexpr + uint16_t get_public_word() const + { + return (bits == 60 || bits == 99) ? 0x0080 : 0; + } + + constexpr + uint32_t get_all_bits() const + { + return bits; + } + + friend constexpr + bool operator == (GmLevel l, GmLevel r) + { + return l.bits == r.bits; + } + friend constexpr + bool operator != (GmLevel l, GmLevel r) + { + return l.bits != r.bits; + } + + friend + bool native_to_network(Byte *network, GmLevel native) + { + network->value = native.bits; + return true; // LIES. But this code is going away soon anyway + } + friend + bool network_to_native(GmLevel *native, Byte network) + { + native->bits = network.value; + return true; // LIES. But this code is going away soon anyway + } + + // TODO kill this code too + friend + bool native_to_network(Little16 *network, GmLevel native) + { + uint16_t tmp = native.bits; + return native_to_network(network, tmp); + } + friend + bool network_to_native(GmLevel *native, Little16 network) + { + uint16_t tmp; + bool rv = network_to_native(&tmp, network); + native->bits = tmp; + return rv; + } + + friend + bool native_to_network(Little32 *network, GmLevel native) + { + return native_to_network(network, native.bits); + } + friend + bool network_to_native(GmLevel *native, Little32 network) + { + return network_to_native(&native->bits, network); + } +}; + +inline +uint32_t convert_for_printf(GmLevel g) +{ + return g.get_all_bits(); +} +} // namespace tmwa diff --git a/src/mmo/ip_test.cpp b/src/mmo/ip_test.cpp deleted file mode 100644 index 8e50453..0000000 --- a/src/mmo/ip_test.cpp +++ /dev/null @@ -1,352 +0,0 @@ -#include "ip.hpp" -// ip_test.cpp - Testsuite for implementation of IP address functions. -// -// Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> -// -// This file is part of The Mana World (Athena server) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. - -#include <gtest/gtest.h> - -#include "../io/cxxstdio.hpp" - -#include "../poison.hpp" - -#define CB(X) (std::integral_constant<bool, (X)>::value) -TEST(ip4addr, cmp) -{ - constexpr static - IP4Address a = IP4_LOCALHOST; - constexpr static - IP4Address b = IP4_BROADCAST; - - EXPECT_FALSE(CB(a < a)); - EXPECT_TRUE (CB(a < b)); - EXPECT_FALSE(CB(b < a)); - EXPECT_FALSE(CB(b < b)); - - EXPECT_FALSE(CB(a > a)); - EXPECT_FALSE(CB(a > b)); - EXPECT_TRUE (CB(b > a)); - EXPECT_FALSE(CB(b > b)); - - EXPECT_TRUE (CB(a <= a)); - EXPECT_TRUE (CB(a <= b)); - EXPECT_FALSE(CB(b <= a)); - EXPECT_TRUE (CB(b <= b)); - - EXPECT_TRUE (CB(a >= a)); - EXPECT_FALSE(CB(a >= b)); - EXPECT_TRUE (CB(b >= a)); - EXPECT_TRUE (CB(b >= b)); - - EXPECT_TRUE (CB(a == a)); - EXPECT_FALSE(CB(a == b)); - EXPECT_FALSE(CB(b == a)); - EXPECT_TRUE (CB(b == b)); - - EXPECT_FALSE(CB(a != a)); - EXPECT_TRUE (CB(a != b)); - EXPECT_TRUE (CB(b != a)); - EXPECT_FALSE(CB(b != b)); -} - -TEST(ip4addr, str) -{ - IP4Address a; - EXPECT_EQ("0.0.0.0", STRNPRINTF(17, "%s", a)); - EXPECT_EQ("127.0.0.1", STRNPRINTF(17, "%s", IP4_LOCALHOST)); - EXPECT_EQ("255.255.255.255", STRNPRINTF(17, "%s", IP4_BROADCAST)); -} - -TEST(ip4addr, extract) -{ - IP4Address a; - EXPECT_TRUE(extract("0.0.0.0", &a)); - EXPECT_EQ("0.0.0.0", STRNPRINTF(16, "%s", a)); - EXPECT_TRUE(extract("127.0.0.1", &a)); - EXPECT_EQ("127.0.0.1", STRNPRINTF(16, "%s", a)); - EXPECT_TRUE(extract("255.255.255.255", &a)); - EXPECT_EQ("255.255.255.255", STRNPRINTF(16, "%s", a)); - EXPECT_TRUE(extract("1.2.3.4", &a)); - EXPECT_EQ("1.2.3.4", STRNPRINTF(16, "%s", a)); - - EXPECT_FALSE(extract("1.2.3.4.5", &a)); - EXPECT_FALSE(extract("1.2.3.4.", &a)); - EXPECT_FALSE(extract("1.2.3.", &a)); - EXPECT_FALSE(extract("1.2.3", &a)); - EXPECT_FALSE(extract("1.2.", &a)); - EXPECT_FALSE(extract("1.2", &a)); - EXPECT_FALSE(extract("1.", &a)); - EXPECT_FALSE(extract("1", &a)); - EXPECT_FALSE(extract("", &a)); -} - - -TEST(ip4mask, body) -{ - IP4Mask m; - EXPECT_EQ(IP4Address(), m.addr()); - EXPECT_EQ(IP4Address(), m.mask()); - m = IP4Mask(IP4_LOCALHOST, IP4_BROADCAST); - EXPECT_EQ(IP4_LOCALHOST, m.addr()); - EXPECT_EQ(IP4_BROADCAST, m.mask()); -} - -TEST(ip4mask, str) -{ - IP4Mask m; - EXPECT_EQ("0.0.0.0/0.0.0.0", STRNPRINTF(33, "%s", m)); - m = IP4Mask(IP4_LOCALHOST, IP4_BROADCAST); - EXPECT_EQ("127.0.0.1/255.255.255.255", STRNPRINTF(33, "%s", m)); -} - -TEST(ip4mask, extract) -{ - IP4Mask m; - EXPECT_FALSE(extract("9.8.7.6/33", &m)); - EXPECT_FALSE(extract("9.8.7.6.5", &m)); - EXPECT_FALSE(extract("9.8.7.6/", &m)); - EXPECT_FALSE(extract("9.8.7", &m)); - EXPECT_FALSE(extract("9.8", &m)); - EXPECT_FALSE(extract("9", &m)); - - EXPECT_TRUE(extract("127.0.0.1", &m)); - EXPECT_EQ("127.0.0.1/255.255.255.255", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("127.0.0.1.", &m)); - EXPECT_EQ("127.0.0.1/255.255.255.255", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("127.0.0.", &m)); - EXPECT_EQ("127.0.0.0/255.255.255.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("127.0.", &m)); - EXPECT_EQ("127.0.0.0/255.255.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("127.", &m)); - EXPECT_EQ("127.0.0.0/255.0.0.0", STRNPRINTF(32, "%s", m)); - - EXPECT_TRUE(extract("1.2.3.4/255.255.255.255", &m)); - EXPECT_EQ("1.2.3.4/255.255.255.255", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("1.2.3.0/255.255.255.0", &m)); - EXPECT_EQ("1.2.3.0/255.255.255.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("1.2.0.4/255.255.0.255", &m)); - EXPECT_EQ("1.2.0.4/255.255.0.255", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("1.2.0.0/255.255.0.0", &m)); - EXPECT_EQ("1.2.0.0/255.255.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("1.0.3.4/255.0.255.255", &m)); - EXPECT_EQ("1.0.3.4/255.0.255.255", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("1.0.3.0/255.0.255.0", &m)); - EXPECT_EQ("1.0.3.0/255.0.255.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("1.0.0.4/255.0.0.255", &m)); - EXPECT_EQ("1.0.0.4/255.0.0.255", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("1.0.0.0/255.0.0.0", &m)); - EXPECT_EQ("1.0.0.0/255.0.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.2.3.4/0.255.255.255", &m)); - EXPECT_EQ("0.2.3.4/0.255.255.255", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.2.3.0/0.255.255.0", &m)); - EXPECT_EQ("0.2.3.0/0.255.255.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.2.0.4/0.255.0.255", &m)); - EXPECT_EQ("0.2.0.4/0.255.0.255", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.2.0.0/0.255.0.0", &m)); - EXPECT_EQ("0.2.0.0/0.255.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.3.4/0.0.255.255", &m)); - EXPECT_EQ("0.0.3.4/0.0.255.255", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.3.0/0.0.255.0", &m)); - EXPECT_EQ("0.0.3.0/0.0.255.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.4/0.0.0.255", &m)); - EXPECT_EQ("0.0.0.4/0.0.0.255", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/0.0.0.0", &m)); - EXPECT_EQ("0.0.0.0/0.0.0.0", STRNPRINTF(32, "%s", m)); - - // please don't do this - EXPECT_TRUE(extract("120.248.200.217/89.57.126.5", &m)); - EXPECT_EQ("88.56.72.1/89.57.126.5", STRNPRINTF(32, "%s", m)); - - EXPECT_TRUE(extract("0.0.0.0/32", &m)); - EXPECT_EQ("0.0.0.0/255.255.255.255", STRNPRINTF(32, "%s", m)); - - EXPECT_TRUE(extract("0.0.0.0/31", &m)); - EXPECT_EQ("0.0.0.0/255.255.255.254", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/30", &m)); - EXPECT_EQ("0.0.0.0/255.255.255.252", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/29", &m)); - EXPECT_EQ("0.0.0.0/255.255.255.248", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/28", &m)); - EXPECT_EQ("0.0.0.0/255.255.255.240", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/27", &m)); - EXPECT_EQ("0.0.0.0/255.255.255.224", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/26", &m)); - EXPECT_EQ("0.0.0.0/255.255.255.192", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/25", &m)); - EXPECT_EQ("0.0.0.0/255.255.255.128", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/24", &m)); - EXPECT_EQ("0.0.0.0/255.255.255.0", STRNPRINTF(32, "%s", m)); - - EXPECT_TRUE(extract("0.0.0.0/23", &m)); - EXPECT_EQ("0.0.0.0/255.255.254.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/22", &m)); - EXPECT_EQ("0.0.0.0/255.255.252.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/21", &m)); - EXPECT_EQ("0.0.0.0/255.255.248.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/20", &m)); - EXPECT_EQ("0.0.0.0/255.255.240.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/19", &m)); - EXPECT_EQ("0.0.0.0/255.255.224.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/18", &m)); - EXPECT_EQ("0.0.0.0/255.255.192.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/17", &m)); - EXPECT_EQ("0.0.0.0/255.255.128.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/16", &m)); - EXPECT_EQ("0.0.0.0/255.255.0.0", STRNPRINTF(32, "%s", m)); - - EXPECT_TRUE(extract("0.0.0.0/15", &m)); - EXPECT_EQ("0.0.0.0/255.254.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/14", &m)); - EXPECT_EQ("0.0.0.0/255.252.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/13", &m)); - EXPECT_EQ("0.0.0.0/255.248.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/12", &m)); - EXPECT_EQ("0.0.0.0/255.240.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/11", &m)); - EXPECT_EQ("0.0.0.0/255.224.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/10", &m)); - EXPECT_EQ("0.0.0.0/255.192.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/9", &m)); - EXPECT_EQ("0.0.0.0/255.128.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/8", &m)); - EXPECT_EQ("0.0.0.0/255.0.0.0", STRNPRINTF(32, "%s", m)); - - EXPECT_TRUE(extract("0.0.0.0/7", &m)); - EXPECT_EQ("0.0.0.0/254.0.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/6", &m)); - EXPECT_EQ("0.0.0.0/252.0.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/5", &m)); - EXPECT_EQ("0.0.0.0/248.0.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/4", &m)); - EXPECT_EQ("0.0.0.0/240.0.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/3", &m)); - EXPECT_EQ("0.0.0.0/224.0.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/2", &m)); - EXPECT_EQ("0.0.0.0/192.0.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/1", &m)); - EXPECT_EQ("0.0.0.0/128.0.0.0", STRNPRINTF(32, "%s", m)); - EXPECT_TRUE(extract("0.0.0.0/0", &m)); - EXPECT_EQ("0.0.0.0/0.0.0.0", STRNPRINTF(32, "%s", m)); -} - -TEST(ip4mask, cover) -{ - IP4Address a; - IP4Address b = IP4_BROADCAST; - IP4Address l = IP4_LOCALHOST; - IP4Address h({127, 255, 255, 255}); - IP4Address p24l({10, 0, 0, 0}); - IP4Address p24h({10, 255, 255, 255}); - IP4Address p20l({172, 16, 0, 0}); - IP4Address p20h({172, 31, 255, 255}); - IP4Address p16l({192, 168, 0, 0}); - IP4Address p16h({192, 168, 255, 255}); - IP4Mask m; - EXPECT_TRUE(m.covers(a)); - EXPECT_TRUE(m.covers(b)); - EXPECT_TRUE(m.covers(l)); - EXPECT_TRUE(m.covers(h)); - EXPECT_TRUE(m.covers(p24l)); - EXPECT_TRUE(m.covers(p24h)); - EXPECT_TRUE(m.covers(p20l)); - EXPECT_TRUE(m.covers(p20h)); - EXPECT_TRUE(m.covers(p16l)); - EXPECT_TRUE(m.covers(p16h)); - m = IP4Mask(l, a); - EXPECT_TRUE(m.covers(a)); - EXPECT_TRUE(m.covers(b)); - EXPECT_TRUE(m.covers(l)); - EXPECT_TRUE(m.covers(h)); - EXPECT_TRUE(m.covers(p24l)); - EXPECT_TRUE(m.covers(p24h)); - EXPECT_TRUE(m.covers(p20l)); - EXPECT_TRUE(m.covers(p20h)); - EXPECT_TRUE(m.covers(p16l)); - EXPECT_TRUE(m.covers(p16h)); - m = IP4Mask(l, b); - EXPECT_FALSE(m.covers(a)); - EXPECT_FALSE(m.covers(b)); - EXPECT_TRUE(m.covers(l)); - EXPECT_FALSE(m.covers(h)); - EXPECT_FALSE(m.covers(p24l)); - EXPECT_FALSE(m.covers(p24h)); - EXPECT_FALSE(m.covers(p20l)); - EXPECT_FALSE(m.covers(p20h)); - EXPECT_FALSE(m.covers(p16l)); - EXPECT_FALSE(m.covers(p16h)); - - // but the really useful ones are with partial masks - m = IP4Mask(IP4Address({10, 0, 0, 0}), IP4Address({255, 0, 0, 0})); - EXPECT_FALSE(m.covers(a)); - EXPECT_FALSE(m.covers(b)); - EXPECT_FALSE(m.covers(l)); - EXPECT_FALSE(m.covers(h)); - EXPECT_TRUE(m.covers(p24l)); - EXPECT_TRUE(m.covers(p24h)); - EXPECT_FALSE(m.covers(p20l)); - EXPECT_FALSE(m.covers(p20h)); - EXPECT_FALSE(m.covers(p16l)); - EXPECT_FALSE(m.covers(p16h)); - EXPECT_FALSE(m.covers(IP4Address({9, 255, 255, 255}))); - EXPECT_FALSE(m.covers(IP4Address({11, 0, 0, 0}))); - m = IP4Mask(IP4Address({127, 0, 0, 0}), IP4Address({255, 0, 0, 0})); - EXPECT_FALSE(m.covers(a)); - EXPECT_FALSE(m.covers(b)); - EXPECT_TRUE(m.covers(l)); - EXPECT_TRUE(m.covers(h)); - EXPECT_FALSE(m.covers(p24l)); - EXPECT_FALSE(m.covers(p24h)); - EXPECT_FALSE(m.covers(p20l)); - EXPECT_FALSE(m.covers(p20h)); - EXPECT_FALSE(m.covers(p16l)); - EXPECT_FALSE(m.covers(p16h)); - EXPECT_FALSE(m.covers(IP4Address({126, 255, 255, 255}))); - EXPECT_FALSE(m.covers(IP4Address({128, 0, 0, 0}))); - m = IP4Mask(IP4Address({172, 16, 0, 0}), IP4Address({255, 240, 0, 0})); - EXPECT_FALSE(m.covers(a)); - EXPECT_FALSE(m.covers(b)); - EXPECT_FALSE(m.covers(l)); - EXPECT_FALSE(m.covers(h)); - EXPECT_FALSE(m.covers(p24l)); - EXPECT_FALSE(m.covers(p24h)); - EXPECT_TRUE(m.covers(p20l)); - EXPECT_TRUE(m.covers(p20h)); - EXPECT_FALSE(m.covers(p16l)); - EXPECT_FALSE(m.covers(p16h)); - EXPECT_FALSE(m.covers(IP4Address({172, 15, 255, 255}))); - EXPECT_FALSE(m.covers(IP4Address({172, 32, 0, 0}))); - m = IP4Mask(IP4Address({192, 168, 0, 0}), IP4Address({255, 255, 0, 0})); - EXPECT_FALSE(m.covers(a)); - EXPECT_FALSE(m.covers(b)); - EXPECT_FALSE(m.covers(l)); - EXPECT_FALSE(m.covers(h)); - EXPECT_FALSE(m.covers(p24l)); - EXPECT_FALSE(m.covers(p24h)); - EXPECT_FALSE(m.covers(p20l)); - EXPECT_FALSE(m.covers(p20h)); - EXPECT_TRUE(m.covers(p16l)); - EXPECT_TRUE(m.covers(p16h)); - EXPECT_FALSE(m.covers(IP4Address({192, 167, 255, 255}))); - EXPECT_FALSE(m.covers(IP4Address({192, 169, 0, 0}))); - - // OTOH this is crazy - EXPECT_TRUE(extract("120.248.200.217/89.57.126.5", &m)); - EXPECT_TRUE(m.covers(IP4Address({120, 248, 200, 217}))); - EXPECT_TRUE(m.covers(IP4Address({88, 56, 72, 1}))); - EXPECT_FALSE(m.covers(IP4Address({88, 56, 72, 0}))); - EXPECT_FALSE(m.covers(IP4Address({88, 56, 72, 255}))); -} diff --git a/src/mmo/md5more.cpp b/src/mmo/md5more.cpp index 3fce5c7..4e5d2da 100644 --- a/src/mmo/md5more.cpp +++ b/src/mmo/md5more.cpp @@ -20,14 +20,24 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include <algorithm> + #include "../compat/rawmem.hpp" #include "../generic/random.hpp" #include "../io/cxxstdio.hpp" +#include "../io/read.hpp" + +#include "../net/ip.hpp" + +#include "../mmo/mmo.hpp" #include "../poison.hpp" + +namespace tmwa +{ #define X block.data // TODO - refactor MD5 into a stream, and merge the implementations @@ -103,7 +113,7 @@ AccountCrypt MD5_saltcrypt(AccountPass key, SaltString salt) VString<31> obuf; // This truncates the string, but we have to keep it like that for compatibility - SNPRINTF(obuf, 32, "!%s$%s", salt, tbuf3); + SNPRINTF(obuf, 32, "!%s$%s"_fmt, salt, tbuf3); return stringish<AccountCrypt>(obuf); } @@ -134,7 +144,7 @@ IP4Address MD5_ip(IP4Address ip) // MD5sum a secret + the IP address VString<31> ipbuf; - SNPRINTF(ipbuf, 32, "%s %s", ip, secret); + SNPRINTF(ipbuf, 32, "%s %s"_fmt, ip, secret); md5_binary obuf; MD5_to_bin(MD5_from_string(ipbuf), obuf); @@ -146,3 +156,4 @@ IP4Address MD5_ip(IP4Address ip) static_cast<uint8_t>(obuf[6] ^ obuf[7] ^ obuf[14] ^ obuf[15]), }); } +} // namespace tmwa diff --git a/src/mmo/md5more.hpp b/src/mmo/md5more.hpp index b1da783..7d50713 100644 --- a/src/mmo/md5more.hpp +++ b/src/mmo/md5more.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MMO_MD5MORE_HPP -#define TMWA_MMO_MD5MORE_HPP +#pragma once // md5more.hpp - Non-basic MD5 functions. // // Copyright © ????-2004 Athena Dev Teams @@ -21,15 +20,17 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../generic/md5.hpp" +#include "../generic/md5.hpp" -# include "../io/read.hpp" +#include "../io/fwd.hpp" -# include "ip.hpp" -# include "mmo.hpp" +#include "../net/fwd.hpp" + +namespace tmwa +{ MD5_state MD5_from_FILE(io::ReadFile& in); // whoever wrote this fails basic understanding of @@ -44,5 +45,4 @@ bool pass_ok(AccountPass password, AccountCrypt crypted); /// This returns an IP4Address because it is configurable whether it gets called at all IP4Address MD5_ip(IP4Address ip); - -#endif // TMWA_MMO_MD5MORE_HPP +} // namespace tmwa diff --git a/src/mmo/mmo.cpp b/src/mmo/mmo.cpp index 8bf7edf..aafa431 100644 --- a/src/mmo/mmo.cpp +++ b/src/mmo/mmo.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/mmo/mmo.hpp b/src/mmo/mmo.hpp index c9d62ca..cfa278d 100644 --- a/src/mmo/mmo.hpp +++ b/src/mmo/mmo.hpp @@ -1,6 +1,5 @@ -#ifndef TMWA_MMO_MMO_HPP -#define TMWA_MMO_MMO_HPP -// mmo.hpp - Huge mess of structures and constants. +#pragma once +// mmo.hpp - Huge mess of structures. // // Copyright © ????-2004 Athena Dev Teams // Copyright © 2004-2011 The Mana World Development Team @@ -21,347 +20,25 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../compat/memory.hpp" +#include "../compat/memory.hpp" -# include "../strings/vstring.hpp" +#include "../proto2/types.hpp" -# include "../generic/enum.hpp" -# include "timer.t.hpp" - -// affects CharName -# define NAME_IGNORING_CASE 1 - -constexpr int FIFOSIZE_SERVERLINK = 256 * 1024; - -constexpr int MAX_MAP_PER_SERVER = 512; -constexpr int MAX_INVENTORY = 100; -constexpr int MAX_AMOUNT = 30000; -constexpr int MAX_ZENY = 1000000000; // 1G zeny -constexpr int TRADE_MAX = 10; - -enum class SkillID : uint16_t; -constexpr SkillID MAX_SKILL = SkillID(474); // not 450 -constexpr SkillID get_enum_min_value(SkillID) { return SkillID(); } -constexpr SkillID get_enum_max_value(SkillID) { return MAX_SKILL; } - -constexpr int GLOBAL_REG_NUM = 96; -constexpr int ACCOUNT_REG_NUM = 16; -constexpr int ACCOUNT_REG2_NUM = 16; -constexpr interval_t DEFAULT_WALK_SPEED = std::chrono::milliseconds(150); -constexpr interval_t MIN_WALK_SPEED = interval_t::zero(); -constexpr interval_t MAX_WALK_SPEED = std::chrono::seconds(1); -constexpr int MAX_STORAGE = 300; -constexpr int MAX_PARTY = 12; - -# define MIN_HAIR_STYLE battle_config.min_hair_style -# define MAX_HAIR_STYLE battle_config.max_hair_style -# define MIN_HAIR_COLOR battle_config.min_hair_color -# define MAX_HAIR_COLOR battle_config.max_hair_color -# define MIN_CLOTH_COLOR battle_config.min_cloth_color -# define MAX_CLOTH_COLOR battle_config.max_cloth_color - -template<class T, size_t n> -struct Array +namespace tmwa { - T data[n]; -public: - T& operator [](size_t i) { assert (i < n); return data[i]; } - const T& operator [](size_t i) const { assert (i < n); return data[i]; } - - T *begin() { return data + 0; } - T *end() { return data + n; } - const T *begin() const { return data + 0; } - const T *end() const { return data + n; } -}; - -struct AccountName : VString<23> {}; -struct AccountPass : VString<23> {}; -struct AccountCrypt : VString<39> {}; -struct AccountEmail : VString<39> {}; -struct ServerName : VString<19> {}; -struct PartyName : VString<23> {}; -struct VarName : VString<31> {}; - -# define DEFAULT_EMAIL stringish<AccountEmail>("a@a.com") - -// It is decreed: a mapname shall not contain an extension -class MapName : public strings::_crtp_string<MapName, MapName, strings::ZPair> -{ - VString<15> _impl; -public: - MapName() = default; - MapName(VString<15> v) : _impl(v.xislice_h(std::find(v.begin(), v.end(), '.'))) {} - - iterator begin() const { return &*_impl.begin(); } - iterator end() const { return &*_impl.end(); } - const char *c_str() const { return _impl.c_str(); } - - operator RString() const { return _impl; } - operator AString() const { return _impl; } - operator TString() const { return _impl; } - operator SString() const { return _impl; } - operator ZString() const { return _impl; } - operator XString() const { return _impl; } -}; -template<> inline -MapName stringish<MapName>(VString<15> iv) +bool operator == (const SkillValue& l, const SkillValue& r) { - return iv; + return l.lv == r.lv && l.flags == r.flags; } inline -const char *decay_for_printf(const MapName& vs) { return vs.c_str(); } - -// It is decreed: a charname is sometimes case sensitive -struct CharName +bool operator != (const SkillValue& l, const SkillValue& r) { -private: - VString<23> _impl; -public: - CharName() = default; - explicit CharName(VString<23> name) - : _impl(name) - {} - - VString<23> to__actual() const - { - return _impl; - } - VString<23> to__lower() const - { - return _impl.to_lower(); - } - VString<23> to__upper() const - { - return _impl.to_upper(); - } - VString<23> to__canonical() const - { -# if NAME_IGNORING_CASE == 0 - return to__actual(); -# endif -# if NAME_IGNORING_CASE == 1 - return to__lower(); -# endif - } - - friend bool operator == (const CharName& l, const CharName& r) - { return l.to__canonical() == r.to__canonical(); } - friend bool operator != (const CharName& l, const CharName& r) - { return l.to__canonical() != r.to__canonical(); } - friend bool operator < (const CharName& l, const CharName& r) - { return l.to__canonical() < r.to__canonical(); } - friend bool operator <= (const CharName& l, const CharName& r) - { return l.to__canonical() <= r.to__canonical(); } - friend bool operator > (const CharName& l, const CharName& r) - { return l.to__canonical() > r.to__canonical(); } - friend bool operator >= (const CharName& l, const CharName& r) - { return l.to__canonical() >= r.to__canonical(); } - - friend - VString<23> convert_for_printf(const CharName& vs) { return vs.to__actual(); } -}; -template<> -inline -CharName stringish<CharName>(VString<23> iv) -{ - return CharName(iv); -} - -namespace e -{ -enum class EPOS : uint16_t -{ - ZERO = 0x0000, - - LEGS = 0x0001, - WEAPON = 0x0002, - GLOVES = 0x0004, - CAPE = 0x0008, - MISC1 = 0x0010, - SHIELD = 0x0020, - SHOES = 0x0040, - MISC2 = 0x0080, - HAT = 0x0100, - TORSO = 0x0200, - - ARROW = 0x8000, -}; -ENUM_BITWISE_OPERATORS(EPOS) - -constexpr EPOS get_enum_min_value(EPOS) { return EPOS(0x0000); } -constexpr EPOS get_enum_max_value(EPOS) { return EPOS(0xffff); } -} -using e::EPOS; - -struct item -{ - int id; - short nameid; - short amount; - EPOS equip; -}; - -struct point -{ - MapName map_; - short x, y; -}; - -namespace e -{ -enum class SkillFlags : uint16_t; + return !(l == r); } -using e::SkillFlags; - -struct skill_value -{ - unsigned short lv; - SkillFlags flags; - - friend bool operator == (const skill_value& l, const skill_value& r) - { - return l.lv == r.lv && l.flags == r.flags; - } - friend bool operator != (const skill_value& l, const skill_value& r) - { - return !(l == r); - } -}; - -struct global_reg -{ - VarName str; - int value; -}; - -// Option and Opt1..3 in map.hpp -namespace e -{ -enum class Option : uint16_t; -constexpr Option get_enum_min_value(Option) { return Option(0x0000); } -constexpr Option get_enum_max_value(Option) { return Option(0xffff); } -} -using e::Option; - -enum class ATTR -{ - STR = 0, - AGI = 1, - VIT = 2, - INT = 3, - DEX = 4, - LUK = 5, - - COUNT = 6, -}; - -constexpr ATTR ATTRs[6] = -{ - ATTR::STR, - ATTR::AGI, - ATTR::VIT, - ATTR::INT, - ATTR::DEX, - ATTR::LUK, -}; - -enum class ItemLook : uint16_t -{ - NONE = 0, - BLADE = 1, // or some other common weapons - _2, - SETZER_AND_SCYTHE = 3, - _6, - STAFF = 10, - BOW = 11, - _13 = 13, - _14 = 14, - _16 = 16, - SINGLE_HANDED_COUNT = 17, - - DUAL_BLADE = 0x11, - DUAL_2 = 0x12, - DUAL_6 = 0x13, - DUAL_12 = 0x14, - DUAL_16 = 0x15, - DUAL_26 = 0x16, -}; - -enum class SEX : uint8_t -{ - FEMALE = 0, - MALE = 1, - // For items. This is also used as error, sometime. - NEUTRAL = 2, -}; -inline -char sex_to_char(SEX sex) -{ - switch (sex) - { - case SEX::FEMALE: return 'F'; - case SEX::MALE: return 'M'; - default: return '\0'; - } -} -inline -SEX sex_from_char(char c) -{ - switch (c) - { - case 'F': return SEX::FEMALE; - case 'M': return SEX::MALE; - default: return SEX::NEUTRAL; - } -} - -struct CharKey -{ - CharName name; - int account_id; - int char_id; - unsigned char char_num; -}; - -struct CharData -{ - int partner_id; - - int base_exp, job_exp, zeny; - - short species; - short status_point, skill_point; - int hp, max_hp, sp, max_sp; - Option option; - short karma, manner; - short hair, hair_color, clothes_color; - int party_id; - - ItemLook weapon; - short shield; - short head_top, head_mid, head_bottom; - - unsigned char base_level, job_level; - earray<short, ATTR, ATTR::COUNT> attrs; - SEX sex; - - unsigned long mapip; - unsigned int mapport; - - struct point last_point, save_point; - Array<struct item, MAX_INVENTORY> inventory; - earray<skill_value, SkillID, MAX_SKILL> skill; - int global_reg_num; - Array<struct global_reg, GLOBAL_REG_NUM> global_reg; - int account_reg_num; - Array<struct global_reg, ACCOUNT_REG_NUM> account_reg; - int account_reg2_num; - Array<struct global_reg, ACCOUNT_REG2_NUM> account_reg2; -}; struct CharPair { @@ -373,37 +50,20 @@ struct CharPair {} }; -struct storage -{ - int dirty; - int account_id; - short storage_status; - short storage_amount; - Array<struct item, MAX_STORAGE> storage_; -}; - struct GM_Account { - int account_id; - uint8_t level; + AccountId account_id; + GmLevel level; }; -struct party_member +struct PartyPair { - int account_id; - CharName name; - MapName map; - int leader, online, lv; - struct map_session_data *sd; -}; + PartyId party_id = {}; + PartyMost *party_most = {}; -struct party -{ - int party_id; - PartyName name; - int exp; - int item; - Array<struct party_member, MAX_PARTY> member; + explicit + operator bool() const { return party_most; } + bool operator !() const { return !party_most; } + PartyMost *operator->() const { return party_most; } }; - -#endif // TMWA_MMO_MMO_HPP +} // namespace tmwa diff --git a/src/mmo/socket.hpp b/src/mmo/socket.hpp deleted file mode 100644 index c166794..0000000 --- a/src/mmo/socket.hpp +++ /dev/null @@ -1,424 +0,0 @@ -#ifndef TMWA_MMO_SOCKET_HPP -#define TMWA_MMO_SOCKET_HPP -// socket.hpp - Network event system. -// -// Copyright © ????-2004 Athena Dev Teams -// Copyright © 2004-2011 The Mana World Development Team -// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> -// -// This file is part of The Mana World (Athena server) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. - -# include "../sanity.hpp" - -# include <netinet/in.h> - -# include <cstdio> - -# include <array> - -# include "../compat/rawmem.hpp" - -# include "../strings/astring.hpp" -# include "../strings/vstring.hpp" -# include "../strings/xstring.hpp" - -# include "../io/fd.hpp" - -# include "dumb_ptr.hpp" -# include "ip.hpp" -# include "utils.hpp" -# include "timer.t.hpp" - -struct SessionData -{ -}; -struct SessionDeleter -{ - // defined per-server - void operator()(SessionData *sd); -}; - -struct Session; -struct SessionIO -{ - void (*func_recv)(Session *); - void (*func_send)(Session *); -}; - -struct SessionParsers -{ - void (*func_parse)(Session *); - void (*func_delete)(Session *); -}; - -struct Session -{ - Session(SessionIO, SessionParsers); - Session(Session&&) = delete; - Session& operator = (Session&&) = delete; - - void set_io(SessionIO); - void set_parsers(SessionParsers); - - /// Checks whether a newly-connected socket actually does anything - TimeT created; - bool connected; - -private: - /// Flag needed since structure must be freed in a server-dependent manner - bool eof; -public: - void set_eof() { eof = true; } - - /// Currently used by clif_setwaitclose - Timer timed_close; - - /// Since this is a single-threaded application, it can't block - /// These are the read/write queues - dumb_ptr<uint8_t[]> rdata, wdata; - size_t max_rdata, max_wdata; - /// How much is actually in the queue - size_t rdata_size, wdata_size; - /// How much has already been read from the queue - /// Note that there is no need for a wdata_pos - size_t rdata_pos; - - IP4Address client_ip; - -private: - /// Send or recieve - /// Only called when select() indicates the socket is ready - /// If, after that, nothing is read, it sets eof - // These could probably be hard-coded with a little work - void (*func_recv)(Session *); - void (*func_send)(Session *); - /// This is the important one - /// Set to different functions depending on whether the connection - /// is a player or a server/ladmin - void (*func_parse)(Session *); - /// Cleanup function since we're not fully RAII yet - void (*func_delete)(Session *); - -public: - // this really ought to be part of session_data, once that gets sane - SessionParsers for_inferior; - - /// Server-specific data type - // (this really should include the deleter, but ...) - std::unique_ptr<SessionData, SessionDeleter> session_data; - - io::FD fd; - - friend void do_sendrecv(interval_t next); - friend void do_parsepacket(void); - friend void delete_session(Session *); -}; - -inline -int convert_for_printf(Session *s) -{ - return s->fd.uncast_dammit(); -} - -// save file descriptors for important stuff -constexpr int SOFT_LIMIT = FD_SETSIZE - 50; - -// socket timeout to establish a full connection in seconds -constexpr int CONNECT_TIMEOUT = 15; - - -void set_session(io::FD fd, std::unique_ptr<Session> sess); -Session *get_session(io::FD fd); -void reset_session(io::FD fd); -int get_fd_max(); - -class IncrFD -{ -public: - static - io::FD inced(io::FD v) - { - return io::FD::cast_dammit(v.uncast_dammit() + 1); - } -}; -IteratorPair<ValueIterator<io::FD, IncrFD>> iter_fds(); - - -/// open a socket, bind, and listen. Return an fd, or -1 if socket() fails, -/// but exit if bind() or listen() fails -Session *make_listen_port(uint16_t port, SessionParsers inferior); -/// Connect to an address, return a connected socket or -1 -// FIXME - this is IPv4 only! -Session *make_connection(IP4Address ip, uint16_t port, SessionParsers); -/// free() the structure and close() the fd -void delete_session(Session *); -/// Make a the internal queues bigger -void realloc_fifo(Session *s, size_t rfifo_size, size_t wfifo_size); -/// Update all sockets that can be read/written from the queues -void do_sendrecv(interval_t next); -/// Call the parser function for every socket that has read data -void do_parsepacket(void); - -template<class T> -uint8_t *pod_addressof_m(T& structure) -{ - static_assert(is_trivially_copyable<T>::value, "Can only byte-copy POD-ish structs"); - return &reinterpret_cast<uint8_t&>(structure); -} - -template<class T> -const uint8_t *pod_addressof_c(const T& structure) -{ - static_assert(is_trivially_copyable<T>::value, "Can only byte-copy POD-ish structs"); - return &reinterpret_cast<const uint8_t&>(structure); -} - - -/// Check how much can be read -inline -size_t RFIFOREST(Session *s) -{ - return s->rdata_size - s->rdata_pos; -} -/// Read from the queue -inline -const void *RFIFOP(Session *s, size_t pos) -{ - return &s->rdata[s->rdata_pos + pos]; -} -inline -uint8_t RFIFOB(Session *s, size_t pos) -{ - return *static_cast<const uint8_t *>(RFIFOP(s, pos)); -} -inline -uint16_t RFIFOW(Session *s, size_t pos) -{ - return *static_cast<const uint16_t *>(RFIFOP(s, pos)); -} -inline -uint32_t RFIFOL(Session *s, size_t pos) -{ - return *static_cast<const uint32_t *>(RFIFOP(s, pos)); -} -template<class T> -void RFIFO_STRUCT(Session *s, size_t pos, T& structure) -{ - really_memcpy(pod_addressof_m(structure), static_cast<const uint8_t *>(RFIFOP(s, pos)), sizeof(T)); -} -inline -IP4Address RFIFOIP(Session *s, size_t pos) -{ - IP4Address o; - RFIFO_STRUCT(s, pos, o); - return o; -} -template<uint8_t len> -inline -VString<len-1> RFIFO_STRING(Session *s, size_t pos) -{ - const char *const begin = static_cast<const char *>(RFIFOP(s, pos)); - const char *const end = begin + len-1; - const char *const mid = std::find(begin, end, '\0'); - return XString(begin, mid, nullptr); -} -inline -AString RFIFO_STRING(Session *s, size_t pos, size_t len) -{ - const char *const begin = static_cast<const char *>(RFIFOP(s, pos)); - const char *const end = begin + len; - const char *const mid = std::find(begin, end, '\0'); - return XString(begin, mid, nullptr); -} -inline -void RFIFO_BUF_CLONE(Session *s, uint8_t *buf, size_t len) -{ - really_memcpy(buf, static_cast<const uint8_t *>(RFIFOP(s, 0)), len); -} - -/// Done reading -void RFIFOSKIP(Session *s, size_t len); - -/// Read from an arbitrary buffer -inline -const void *RBUFP(const uint8_t *p, size_t pos) -{ - return p + pos; -} -inline -uint8_t RBUFB(const uint8_t *p, size_t pos) -{ - return *static_cast<const uint8_t *>(RBUFP(p, pos)); -} -inline -uint16_t RBUFW(const uint8_t *p, size_t pos) -{ - return *static_cast<const uint16_t *>(RBUFP(p, pos)); -} -inline -uint32_t RBUFL(const uint8_t *p, size_t pos) -{ - return *static_cast<const uint32_t *>(RBUFP(p, pos)); -} -template<class T> -void RBUF_STRUCT(const uint8_t *p, size_t pos, T& structure) -{ - really_memcpy(pod_addressof_m(structure), p + pos, sizeof(T)); -} -inline -IP4Address RBUFIP(const uint8_t *p, size_t pos) -{ - IP4Address o; - RBUF_STRUCT(p, pos, o); - return o; -} -template<uint8_t len> -inline -VString<len-1> RBUF_STRING(const uint8_t *p, size_t pos) -{ - const char *const begin = static_cast<const char *>(RBUFP(p, pos)); - const char *const end = begin + len-1; - const char *const mid = std::find(begin, end, '\0'); - return XString(begin, mid, nullptr); -} -inline -AString RBUF_STRING(const uint8_t *p, size_t pos, size_t len) -{ - const char *const begin = static_cast<const char *>(RBUFP(p, pos)); - const char *const end = begin + len; - const char *const mid = std::find(begin, end, '\0'); - return XString(begin, mid, nullptr); -} - - -/// Unused - check how much data can be written -// the existence of this seems scary -inline -size_t WFIFOSPACE(Session *s) -{ - return s->max_wdata - s->wdata_size; -} -/// Write to the queue -inline -void *WFIFOP(Session *s, size_t pos) -{ - return &s->wdata[s->wdata_size + pos]; -} -inline -uint8_t& WFIFOB(Session *s, size_t pos) -{ - return *static_cast<uint8_t *>(WFIFOP(s, pos)); -} -inline -uint16_t& WFIFOW(Session *s, size_t pos) -{ - return *static_cast<uint16_t *>(WFIFOP(s, pos)); -} -inline -uint32_t& WFIFOL(Session *s, size_t pos) -{ - return *static_cast<uint32_t *>(WFIFOP(s, pos)); -} -template<class T> -void WFIFO_STRUCT(Session *s, size_t pos, T& structure) -{ - really_memcpy(static_cast<uint8_t *>(WFIFOP(s, pos)), pod_addressof_c(structure), sizeof(T)); -} -inline -IP4Address& WFIFOIP(Session *s, size_t pos) -{ - static_assert(is_trivially_copyable<IP4Address>::value, "That was the whole point"); - return *static_cast<IP4Address *>(WFIFOP(s, pos)); -} -inline -void WFIFO_STRING(Session *s, size_t pos, XString str, size_t len) -{ - char *const begin = static_cast<char *>(WFIFOP(s, pos)); - char *const end = begin + len; - char *const mid = std::copy(str.begin(), str.end(), begin); - std::fill(mid, end, '\0'); -} -inline -void WFIFO_ZERO(Session *s, size_t pos, size_t len) -{ - uint8_t *b = static_cast<uint8_t *>(WFIFOP(s, pos)); - uint8_t *e = b + len; - std::fill(b, e, '\0'); -} -inline -void WFIFO_BUF_CLONE(Session *s, const uint8_t *buf, size_t len) -{ - really_memcpy(static_cast<uint8_t *>(WFIFOP(s, 0)), buf, len); -} - -/// Finish writing -void WFIFOSET(Session *s, size_t len); - -/// Write to an arbitrary buffer -inline -void *WBUFP(uint8_t *p, size_t pos) -{ - return p + pos; -} -inline -uint8_t& WBUFB(uint8_t *p, size_t pos) -{ - return *static_cast<uint8_t *>(WBUFP(p, pos)); -} -inline -uint16_t& WBUFW(uint8_t *p, size_t pos) -{ - return *static_cast<uint16_t *>(WBUFP(p, pos)); -} -inline -uint32_t& WBUFL(uint8_t *p, size_t pos) -{ - return *static_cast<uint32_t *>(WBUFP(p, pos)); -} -template<class T> -void WBUF_STRUCT(uint8_t *p, size_t pos, T& structure) -{ - really_memcpy(p + pos, pod_addressof_c(structure), sizeof(T)); -} -inline -IP4Address& WBUFIP(uint8_t *p, size_t pos) -{ - return *static_cast<IP4Address *>(WBUFP(p, pos)); -} -inline -void WBUF_STRING(uint8_t *p, size_t pos, XString s, size_t len) -{ - char *const begin = static_cast<char *>(WBUFP(p, pos)); - char *const end = begin + len; - char *const mid = std::copy(s.begin(), s.end(), begin); - std::fill(mid, end, '\0'); -} -inline -void WBUF_ZERO(uint8_t *p, size_t pos, size_t len) -{ - uint8_t *b = static_cast<uint8_t *>(WBUFP(p, pos)); - uint8_t *e = b + len; - std::fill(b, e, '\0'); -} - -inline -void RFIFO_WFIFO_CLONE(Session *rs, Session *ws, size_t len) -{ - really_memcpy(static_cast<uint8_t *>(WFIFOP(ws, 0)), - static_cast<const uint8_t *>(RFIFOP(rs, 0)), len); -} - -#endif // TMWA_MMO_SOCKET_HPP diff --git a/src/map/magic-interpreter-aux.cpp b/src/mmo/strs.cpp index 10a376b..71dceec 100644 --- a/src/map/magic-interpreter-aux.cpp +++ b/src/mmo/strs.cpp @@ -1,5 +1,5 @@ -#include "magic-interpreter-aux.hpp" -// magic-interpreter-aux.cpp - Edge of the magic system. +#include "strs.hpp" +// strs.cpp - common string types // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> // @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/mmo/strs.hpp b/src/mmo/strs.hpp new file mode 100644 index 0000000..fea0c98 --- /dev/null +++ b/src/mmo/strs.hpp @@ -0,0 +1,126 @@ +#pragma once +// strs.hpp - common string types +// +// Copyright © ????-2004 Athena Dev Teams +// Copyright © 2004-2011 The Mana World Development Team +// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include "../strings/vstring.hpp" + + +namespace tmwa +{ +// affects CharName +#define NAME_IGNORING_CASE 1 + +struct AccountName : VString<23> {}; +struct AccountPass : VString<23> {}; +struct AccountCrypt : VString<39> {}; +struct AccountEmail : VString<39> {}; +struct ServerName : VString<19> {}; +struct PartyName : VString<23> {}; +struct VarName : VString<31> {}; + +#define DEFAULT_EMAIL stringish<AccountEmail>("a@a.com"_s) + +// It is decreed: a mapname shall not contain an extension +class MapName : public strings::_crtp_string<MapName, MapName, strings::ZPair> +{ + VString<15> _impl; +public: + MapName() = default; + MapName(VString<15> v) : _impl(v.xislice_h(std::find(v.begin(), v.end(), '.'))) {} + + iterator begin() const { return &*_impl.begin(); } + iterator end() const { return &*_impl.end(); } + const char *c_str() const { return _impl.c_str(); } + + operator RString() const { return _impl; } + operator AString() const { return _impl; } + operator TString() const { return _impl; } + operator SString() const { return _impl; } + operator ZString() const { return _impl; } + operator XString() const { return _impl; } +}; +template<> +inline +MapName stringish<MapName>(VString<15> iv) +{ + return iv; +} +inline +const char *decay_for_printf(const MapName& vs) { return vs.c_str(); } + +// It is decreed: a charname is sometimes case sensitive +struct CharName +{ +private: + VString<23> _impl; +public: + CharName() = default; + explicit CharName(VString<23> name) + : _impl(name) + {} + + VString<23> to__actual() const + { + return _impl; + } + VString<23> to__lower() const + { + return _impl.to_lower(); + } + VString<23> to__upper() const + { + return _impl.to_upper(); + } + VString<23> to__canonical() const + { +#if NAME_IGNORING_CASE == 0 + return to__actual(); +#endif +#if NAME_IGNORING_CASE == 1 + return to__lower(); +#endif + } + + friend bool operator == (const CharName& l, const CharName& r) + { return l.to__canonical() == r.to__canonical(); } + friend bool operator != (const CharName& l, const CharName& r) + { return l.to__canonical() != r.to__canonical(); } + friend bool operator < (const CharName& l, const CharName& r) + { return l.to__canonical() < r.to__canonical(); } + friend bool operator <= (const CharName& l, const CharName& r) + { return l.to__canonical() <= r.to__canonical(); } + friend bool operator > (const CharName& l, const CharName& r) + { return l.to__canonical() > r.to__canonical(); } + friend bool operator >= (const CharName& l, const CharName& r) + { return l.to__canonical() >= r.to__canonical(); } + + friend + VString<23> convert_for_printf(const CharName& vs) { return vs.to__actual(); } +}; +template<> +inline +CharName stringish<CharName>(VString<23> iv) +{ + return CharName(iv); +} +} // namespace tmwa diff --git a/src/mmo/utils.cpp b/src/mmo/utils.cpp index a1316d1..f8aff2e 100644 --- a/src/mmo/utils.cpp +++ b/src/mmo/utils.cpp @@ -20,12 +20,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <netinet/in.h> #include <sys/time.h> #include <algorithm> -#include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" @@ -36,6 +34,9 @@ #include "../poison.hpp" + +namespace tmwa +{ //--------------------------------------------------- // E-mail check: return 0 (not correct) or 1 (valid). //--------------------------------------------------- @@ -57,9 +58,9 @@ bool e_mail_check(XString email) return 0; if (hostname.front() == '.' || hostname.back() == '.') return 0; - if (hostname.contains_seq("..")) + if (hostname.contains_seq(".."_s)) return 0; - if (email.contains_any(" ;")) + if (email.contains_any(" ;"_s)) return 0; return email.is_print(); } @@ -70,18 +71,18 @@ bool e_mail_check(XString email) //------------------------------------------------- int config_switch(ZString str) { - if (str == "true" || str == "on" || str == "yes" - || str == "oui" || str == "ja" - || str == "si") + if (str == "true"_s || str == "on"_s || str == "yes"_s + || str == "oui"_s || str == "ja"_s + || str == "si"_s) return 1; - if (str == "false" || str == "off" || str == "no" - || str == "non" || str == "nein") + if (str == "false"_s || str == "off"_s || str == "no"_s + || str == "non"_s || str == "nein"_s) return 0; int rv; if (extract(str, &rv)) return rv; - FPRINTF(stderr, "Fatal: bad option value %s", str); + FPRINTF(stderr, "Fatal: bad option value %s"_fmt, str); abort(); } @@ -93,17 +94,17 @@ void stamp_time(timestamp_seconds_buffer& out, const TimeT *t) struct tm when = t ? *t : TimeT::now(); char buf[20]; strftime(buf, 20, "%Y-%m-%d %H:%M:%S", &when); - out = stringish<timestamp_seconds_buffer>(const_(buf)); + out = stringish<timestamp_seconds_buffer>(VString<19>(strings::really_construct_from_a_pointer, buf)); } void stamp_time(timestamp_milliseconds_buffer& out) { struct timeval tv; - gettimeofday(&tv, NULL); + gettimeofday(&tv, nullptr); struct tm when = TimeT(tv.tv_sec); char buf[24]; strftime(buf, 20, "%Y-%m-%d %H:%M:%S", &when); sprintf(buf + 19, ".%03d", static_cast<int>(tv.tv_usec / 1000)); - out = stringish<timestamp_milliseconds_buffer>(const_(buf)); + out = stringish<timestamp_milliseconds_buffer>(VString<23>(strings::really_construct_from_a_pointer, buf)); } void log_with_timestamp(io::WriteFile& out, XString line) @@ -119,3 +120,4 @@ void log_with_timestamp(io::WriteFile& out, XString line) out.really_put(": ", 2); out.put_line(line); } +} // namespace tmwa diff --git a/src/mmo/utils.hpp b/src/mmo/utils.hpp index d59f7ac..fc3ea74 100644 --- a/src/mmo/utils.hpp +++ b/src/mmo/utils.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MMO_UTILS_HPP -#define TMWA_MMO_UTILS_HPP +#pragma once // utils.hpp - Useful stuff that hasn't been categorized. // // Copyright © ????-2004 Athena Dev Teams @@ -21,19 +20,25 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdio> +#include <cstring> +#include <ctime> -# include <type_traits> +#include <type_traits> -# include "../strings/fwd.hpp" -# include "../strings/vstring.hpp" +#include "../ints/little.hpp" -# include "../generic/operators.hpp" +#include "../strings/fwd.hpp" +#include "../strings/vstring.hpp" -# include "../io/fwd.hpp" +#include "../generic/operators.hpp" +#include "../io/fwd.hpp" + + +namespace tmwa +{ template<class T> struct is_trivially_copyable : std::integral_constant<bool, @@ -82,7 +87,7 @@ struct TimeT : Comparable TimeT now() { // poisoned, but this is still in header-land - return time(NULL); + return time(nullptr); } bool error() const @@ -101,12 +106,40 @@ long long convert_for_printf(TimeT t) return t.value; } -inline -long long& convert_for_scanf(TimeT& t) +// 2038 problem +inline __attribute__((warn_unused_result)) +bool native_to_network(Little32 *net, TimeT nat) { - return t.value; + time_t tmp = nat; + return native_to_network(net, static_cast<uint32_t>(tmp)); +} + +inline __attribute__((warn_unused_result)) +bool network_to_native(TimeT *nat, Little32 net) +{ + uint32_t tmp; + bool rv = network_to_native(&tmp, net); + *nat = static_cast<time_t>(tmp); + return rv; } +inline __attribute__((warn_unused_result)) +bool native_to_network(Little64 *net, TimeT nat) +{ + time_t tmp = nat; + return native_to_network(net, static_cast<uint64_t>(tmp)); +} + +inline __attribute__((warn_unused_result)) +bool network_to_native(TimeT *nat, Little64 net) +{ + uint64_t tmp; + bool rv = network_to_native(&tmp, net); + *nat = static_cast<time_t>(tmp); + return rv; +} + + struct timestamp_seconds_buffer : VString<19> {}; struct timestamp_milliseconds_buffer : VString<23> {}; void stamp_time(timestamp_seconds_buffer&, const TimeT *t=nullptr); @@ -115,21 +148,20 @@ void stamp_time(timestamp_milliseconds_buffer&); void log_with_timestamp(io::WriteFile& out, XString line); // TODO VString? -# define TIMESTAMP_DUMMY "YYYY-MM-DD HH:MM:SS" +#define TIMESTAMP_DUMMY "YYYY-MM-DD HH:MM:SS" static_assert(sizeof(TIMESTAMP_DUMMY) == sizeof(timestamp_seconds_buffer), "timestamp size"); -# define WITH_TIMESTAMP(str) str TIMESTAMP_DUMMY +#define WITH_TIMESTAMP(str) str TIMESTAMP_DUMMY // str: prefix: YYYY-MM-DD HH:MM:SS // sizeof: 01234567890123456789012345678 // str + sizeof: ^ // -1: ^ // there's probably a better way to do this now -# define REPLACE_TIMESTAMP(str, t) \ +#define REPLACE_TIMESTAMP(str, t) \ stamp_time( \ reinterpret_cast<timestamp_seconds_buffer *>( \ str + sizeof(str) \ )[-1], \ &t \ ) - -#endif // TMWA_MMO_UTILS_HPP +} // namespace tmwa diff --git a/src/mmo/version.cpp b/src/mmo/version.cpp index 54b1709..2e337c1 100644 --- a/src/mmo/version.cpp +++ b/src/mmo/version.cpp @@ -28,6 +28,9 @@ #include "../poison.hpp" + +namespace tmwa +{ Version CURRENT_VERSION = { VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, @@ -61,7 +64,7 @@ Version CURRENT_MAP_SERVER_VERSION = VENDOR_POINT, }; -const char CURRENT_VERSION_STRING[] = VERSION_STRING; +LString CURRENT_VERSION_STRING = VERSION_STRING; bool extract(XString str, Version *vers) { @@ -70,3 +73,4 @@ bool extract(XString str, Version *vers) // It would've been useful during the magic migration. return extract(str, record<'.'>(&vers->major, &vers->minor, &vers->patch)); } +} // namespace tmwa diff --git a/src/mmo/version.hpp b/src/mmo/version.hpp index 11bab39..440dce6 100644 --- a/src/mmo/version.hpp +++ b/src/mmo/version.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MMO_VERSION_HPP -#define TMWA_MMO_VERSION_HPP +#pragma once // version.hpp - Prevent mass rebuild when conf/version.hpp changes. // // Copyright © ????-2004 Athena Dev Teams @@ -21,20 +20,24 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdint> +#include <cstdint> -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" + +namespace tmwa +{ // TODO make these bitwise enums -# define TMWA_FLAG_REGISTRATION 0x01 +#define TMWA_FLAG_REGISTRATION 0x01 -# define TMWA_SERVER_LOGIN 0x01 -# define TMWA_SERVER_CHAR 0x02 -# define TMWA_SERVER_INTER 0x04 -# define TMWA_SERVER_MAP 0x08 +#define TMWA_SERVER_LOGIN 0x01 +#define TMWA_SERVER_CHAR 0x02 +#define TMWA_SERVER_INTER 0x04 +#define TMWA_SERVER_MAP 0x08 +// TODO now that I generate the protocol, split 'flags' out of the struct struct Version { uint8_t major; @@ -46,6 +49,35 @@ struct Version uint8_t which; uint16_t vend; // can't add vendor name yet + + constexpr friend + bool operator < (Version l, Version r) + { + return (l.major < r.major + || (l.major == r.major + && (l.minor < r.minor + || (l.minor == r.minor + && (l.patch < r.patch + || (l.patch == r.patch + && (l.devel < r.devel + || (l.devel == r.devel + && l.vend < r.vend)))))))); + } + constexpr friend + bool operator > (Version l, Version r) + { + return r < l; + } + constexpr friend + bool operator <= (Version l, Version r) + { + return !(r < l); + } + constexpr friend + bool operator >= (Version l, Version r) + { + return !(l < r); + } }; static_assert(sizeof(Version) == 8, "this is sent over the network, can't change"); @@ -55,37 +87,7 @@ extern Version CURRENT_LOGIN_SERVER_VERSION; extern Version CURRENT_CHAR_SERVER_VERSION; extern Version CURRENT_MAP_SERVER_VERSION; -extern const char CURRENT_VERSION_STRING[]; +extern LString CURRENT_VERSION_STRING; bool extract(XString str, Version *vers); - -constexpr -bool operator < (Version l, Version r) -{ - return (l.major < r.major - || (l.major == r.major - && (l.minor < r.minor - || (l.minor == r.minor - && (l.patch < r.patch - || (l.patch == r.patch - && (l.devel < r.devel - || (l.devel == r.devel - && l.vend < r.vend)))))))); -} -constexpr -bool operator > (Version l, Version r) -{ - return r < l; -} -constexpr -bool operator <= (Version l, Version r) -{ - return !(r < l); -} -constexpr -bool operator >= (Version l, Version r) -{ - return !(l < r); -} - -#endif // TMWA_MMO_VERSION_HPP +} // namespace tmwa diff --git a/src/monitor/main.cpp b/src/monitor/main.cpp index c882105..ec1139a 100644 --- a/src/monitor/main.cpp +++ b/src/monitor/main.cpp @@ -24,11 +24,13 @@ #include <unistd.h> #include <csignal> +#include <cstdlib> #include "../strings/mstring.hpp" #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" +#include "../strings/literal.hpp" #include "../io/cxxstdio.hpp" #include "../io/fd.hpp" @@ -39,12 +41,14 @@ #include "../poison.hpp" -#define LOGIN_SERVER "./login-server" -#define MAP_SERVER "./map-server" -#define CHAR_SERVER "./char-server" -#define CONFIG "conf/eathena-monitor.conf" +#define LOGIN_SERVER "./login-server"_s +#define MAP_SERVER "./map-server"_s +#define CHAR_SERVER "./char-server"_s +#define CONFIG "conf/eathena-monitor.conf"_s +namespace tmwa +{ // initialiized to $HOME/tmwserver static AString workdir; @@ -72,17 +76,17 @@ AString make_path(XString base, XString path) static bool parse_option(XString name, ZString value) { - if (name == "login_server") + if (name == "login_server"_s) login_server = value; - else if (name == "map_server") + else if (name == "map_server"_s) map_server = value; - else if (name == "char_server") + else if (name == "char_server"_s) char_server = value; - else if (name == "workdir") + else if (name == "workdir"_s) workdir = value; else { - FPRINTF(stderr, "WARNING: ingnoring invalid option '%s' : '%s'\n", + FPRINTF(stderr, "WARNING: ingnoring invalid option '%s' : '%s'\n"_fmt, AString(name), value); return false; } @@ -96,7 +100,7 @@ bool read_config(ZString filename) io::ReadFile in(filename); if (!in.is_open()) { - FPRINTF(stderr, "Monitor config file not found: %s\n", filename); + FPRINTF(stderr, "Monitor config file not found: %s\n"_fmt, filename); exit(1); } @@ -109,14 +113,14 @@ bool read_config(ZString filename) ZString value; if (!config_split(line, &name, &value)) { - PRINTF("Bad line: %s\n", line); + PRINTF("Bad line: %s\n"_fmt, line); rv = false; continue; } if (!parse_option(name, value)) { - PRINTF("Bad key/value: %s\n", line); + PRINTF("Bad key/value: %s\n"_fmt, line); rv = false; continue; } @@ -127,19 +131,19 @@ bool read_config(ZString filename) static pid_t start_process(ZString exec) { - const char *args[2] = {exec.c_str(), NULL}; + const char *args[2] = {exec.c_str(), nullptr}; pid_t pid = fork(); if (pid == -1) { - FPRINTF(stderr, "Failed to fork"); + FPRINTF(stderr, "Failed to fork"_fmt); return 0; } if (pid == 0) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" + DIAG_PUSH(); + DIAG_I(cast_qual); execv(exec.c_str(), const_cast<char **>(args)); -#pragma GCC diagnostic pop + DIAG_POP(); perror("Failed to exec"); kill(getppid(), SIGABRT); exit(1); @@ -157,15 +161,18 @@ void stop_process(int sig) kill(pid_login, sig); if (pid_char) kill(pid_char, sig); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" + DIAG_PUSH(); + DIAG_I(old_style_cast); + DIAG_I(zero_as_null_pointer_constant); signal(sig, SIG_DFL); -#pragma GCC diagnostic pop + DIAG_POP(); raise(sig); } +} // namespace tmwa int main(int argc, char *argv[]) { + using namespace tmwa; // These are all the signals we are likely to get // The shell handles stop/cont signal(SIGTERM, stop_process); @@ -173,7 +180,7 @@ int main(int argc, char *argv[]) signal(SIGQUIT, stop_process); signal(SIGABRT, stop_process); - workdir = make_path(ZString(strings::really_construct_from_a_pointer, getenv("HOME"), nullptr), "tmwserver"); + workdir = make_path(ZString(strings::really_construct_from_a_pointer, getenv("HOME"), nullptr), "tmwserver"_s); ZString config = CONFIG; if (argc > 1) @@ -186,11 +193,11 @@ int main(int argc, char *argv[]) exit(1); } - PRINTF("Starting:\n"); - PRINTF("* workdir: %s\n", workdir); - PRINTF("* login_server: %s\n", login_server); - PRINTF("* char_server: %s\n", char_server); - PRINTF("* map_server: %s\n", map_server); + PRINTF("Starting:\n"_fmt); + PRINTF("* workdir: %s\n"_fmt, workdir); + PRINTF("* login_server: %s\n"_fmt, login_server); + PRINTF("* char_server: %s\n"_fmt, char_server); + PRINTF("* map_server: %s\n"_fmt, map_server); { //make sure all possible file descriptors are free for use by the servers //if there are file descriptors higher than the max open from before the limit dropped, that's not our problem @@ -198,9 +205,9 @@ int main(int argc, char *argv[]) while ((fd = fd.prev()) > io::FD::stderr()) { if (fd.close() == 0) - FPRINTF(stderr, "close fd %d\n", fd.uncast_dammit()); + FPRINTF(stderr, "close fd %d\n"_fmt, fd.uncast_dammit()); } - fd = io::FD::open("/dev/null", O_RDWR); + fd = io::FD::open("/dev/null"_s, O_RDWR); if (fd == io::FD()) { perror("open /dev/null"); @@ -219,22 +226,22 @@ int main(int argc, char *argv[]) if (!pid_login) { pid_login = start_process(login_server); - FPRINTF(stderr, "[%s] forked login server: %lu\n", + FPRINTF(stderr, "[%s] forked login server: %lu\n"_fmt, timestamp, static_cast<unsigned long>(pid_login)); } if (!pid_char) { pid_char = start_process(char_server); - FPRINTF(stderr, "[%s] forked char server: %lu\n", + FPRINTF(stderr, "[%s] forked char server: %lu\n"_fmt, timestamp, static_cast<unsigned long>(pid_char)); } if (!pid_map) { pid_map = start_process(map_server); - FPRINTF(stderr, "[%s] forked map server: %lu\n", + FPRINTF(stderr, "[%s] forked map server: %lu\n"_fmt, timestamp, static_cast<unsigned long>(pid_map)); } - pid_t dead = wait(NULL); + pid_t dead = wait(nullptr); if (dead == -1) { perror("Failed to wait for child"); diff --git a/src/net/fwd.hpp b/src/net/fwd.hpp new file mode 100644 index 0000000..2097772 --- /dev/null +++ b/src/net/fwd.hpp @@ -0,0 +1,33 @@ +#pragma once +// net/fwd.hpp - list of type names for net lib +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +class Session; + +class IP4Address; + +class TimerData; + +enum class RecvResult; +} // namespace tmwa diff --git a/src/mmo/ip.cpp b/src/net/ip.cpp index 146734a..bfc2028 100644 --- a/src/mmo/ip.cpp +++ b/src/net/ip.cpp @@ -23,8 +23,13 @@ #include "../io/cxxstdio.hpp" +#include "../mmo/extract.hpp" + #include "../poison.hpp" + +namespace tmwa +{ bool extract(XString str, IP4Address *rv) { if (str.endswith('.')) @@ -104,11 +109,12 @@ bool extract(XString str, IP4Mask *rv) VString<15> convert_for_printf(IP4Address a_) { const uint8_t *a = a_.bytes(); - return STRNPRINTF(16, "%hhu.%hhu.%hhu.%hhu", a[0], a[1], a[2], a[3]); + return STRNPRINTF(16, "%hhu.%hhu.%hhu.%hhu"_fmt, a[0], a[1], a[2], a[3]); } VString<31> convert_for_printf(IP4Mask a) { - return STRNPRINTF(32, "%s/%s", + return STRNPRINTF(32, "%s/%s"_fmt, a.addr(), a.mask()); } +} // namespace tmwa diff --git a/src/mmo/ip.hpp b/src/net/ip.hpp index a425710..e9e71f4 100644 --- a/src/mmo/ip.hpp +++ b/src/net/ip.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MMO_IP_HPP -#define TMWA_MMO_IP_HPP +#pragma once // ip.hpp - classes to deal with IP addresses. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,14 +18,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <netinet/in.h> +#include <netinet/in.h> -# include "../strings/fwd.hpp" +#include <cstddef> +#include <cstdint> -# include "extract.hpp" +#include "../strings/fwd.hpp" + +namespace tmwa +{ // TODO - in the long run ports belong here also // and of course, IPv6 stuff. // But what about unix socket addresses? @@ -160,5 +163,4 @@ VString<31> convert_for_printf(IP4Mask m); bool extract(XString str, IP4Address *iv); bool extract(XString str, IP4Mask *iv); - -#endif // TMWA_MMO_IP_HPP +} // namespace tmwa diff --git a/src/mmo/ip.py b/src/net/ip.py index e6a8183..bcf90a2 100644 --- a/src/mmo/ip.py +++ b/src/net/ip.py @@ -2,7 +2,7 @@ class IP4Address(object): ''' print an IP4Address ''' __slots__ = ('_value') - name = 'IP4Address' + name = 'tmwa::IP4Address' enabled = True def __init__(self, value): diff --git a/src/net/ip_test.cpp b/src/net/ip_test.cpp new file mode 100644 index 0000000..419dc03 --- /dev/null +++ b/src/net/ip_test.cpp @@ -0,0 +1,359 @@ +#include "ip.hpp" +// ip_test.cpp - Testsuite for implementation of IP address functions. +// +// Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <gtest/gtest.h> + +#include "../strings/vstring.hpp" +#include "../strings/literal.hpp" + +#include "../io/cxxstdio.hpp" + +#include "../poison.hpp" + + +namespace tmwa +{ +#define CB(X) (std::integral_constant<bool, (X)>::value) +TEST(ip4addr, cmp) +{ + constexpr static + IP4Address a = IP4_LOCALHOST; + constexpr static + IP4Address b = IP4_BROADCAST; + + EXPECT_FALSE(CB(a < a)); + EXPECT_TRUE (CB(a < b)); + EXPECT_FALSE(CB(b < a)); + EXPECT_FALSE(CB(b < b)); + + EXPECT_FALSE(CB(a > a)); + EXPECT_FALSE(CB(a > b)); + EXPECT_TRUE (CB(b > a)); + EXPECT_FALSE(CB(b > b)); + + EXPECT_TRUE (CB(a <= a)); + EXPECT_TRUE (CB(a <= b)); + EXPECT_FALSE(CB(b <= a)); + EXPECT_TRUE (CB(b <= b)); + + EXPECT_TRUE (CB(a >= a)); + EXPECT_FALSE(CB(a >= b)); + EXPECT_TRUE (CB(b >= a)); + EXPECT_TRUE (CB(b >= b)); + + EXPECT_TRUE (CB(a == a)); + EXPECT_FALSE(CB(a == b)); + EXPECT_FALSE(CB(b == a)); + EXPECT_TRUE (CB(b == b)); + + EXPECT_FALSE(CB(a != a)); + EXPECT_TRUE (CB(a != b)); + EXPECT_TRUE (CB(b != a)); + EXPECT_FALSE(CB(b != b)); +} + +TEST(ip4addr, str) +{ + IP4Address a; + EXPECT_EQ("0.0.0.0"_s, STRNPRINTF(17, "%s"_fmt, a)); + EXPECT_EQ("127.0.0.1"_s, STRNPRINTF(17, "%s"_fmt, IP4_LOCALHOST)); + EXPECT_EQ("255.255.255.255"_s, STRNPRINTF(17, "%s"_fmt, IP4_BROADCAST)); +} + +TEST(ip4addr, extract) +{ + IP4Address a; + EXPECT_TRUE(extract("0.0.0.0"_s, &a)); + EXPECT_EQ("0.0.0.0"_s, STRNPRINTF(16, "%s"_fmt, a)); + EXPECT_TRUE(extract("127.0.0.1"_s, &a)); + EXPECT_EQ("127.0.0.1"_s, STRNPRINTF(16, "%s"_fmt, a)); + EXPECT_TRUE(extract("255.255.255.255"_s, &a)); + EXPECT_EQ("255.255.255.255"_s, STRNPRINTF(16, "%s"_fmt, a)); + EXPECT_TRUE(extract("1.2.3.4"_s, &a)); + EXPECT_EQ("1.2.3.4"_s, STRNPRINTF(16, "%s"_fmt, a)); + + EXPECT_FALSE(extract("1.2.3.4.5"_s, &a)); + EXPECT_FALSE(extract("1.2.3.4."_s, &a)); + EXPECT_FALSE(extract("1.2.3."_s, &a)); + EXPECT_FALSE(extract("1.2.3"_s, &a)); + EXPECT_FALSE(extract("1.2."_s, &a)); + EXPECT_FALSE(extract("1.2"_s, &a)); + EXPECT_FALSE(extract("1."_s, &a)); + EXPECT_FALSE(extract("1"_s, &a)); + EXPECT_FALSE(extract(""_s, &a)); +} + + +TEST(ip4mask, body) +{ + IP4Mask m; + EXPECT_EQ(IP4Address(), m.addr()); + EXPECT_EQ(IP4Address(), m.mask()); + m = IP4Mask(IP4_LOCALHOST, IP4_BROADCAST); + EXPECT_EQ(IP4_LOCALHOST, m.addr()); + EXPECT_EQ(IP4_BROADCAST, m.mask()); +} + +TEST(ip4mask, str) +{ + IP4Mask m; + EXPECT_EQ("0.0.0.0/0.0.0.0"_s, STRNPRINTF(33, "%s"_fmt, m)); + m = IP4Mask(IP4_LOCALHOST, IP4_BROADCAST); + EXPECT_EQ("127.0.0.1/255.255.255.255"_s, STRNPRINTF(33, "%s"_fmt, m)); +} + +TEST(ip4mask, extract) +{ + IP4Mask m; + EXPECT_FALSE(extract("9.8.7.6/33"_s, &m)); + EXPECT_FALSE(extract("9.8.7.6.5"_s, &m)); + EXPECT_FALSE(extract("9.8.7.6/"_s, &m)); + EXPECT_FALSE(extract("9.8.7"_s, &m)); + EXPECT_FALSE(extract("9.8"_s, &m)); + EXPECT_FALSE(extract("9"_s, &m)); + + EXPECT_TRUE(extract("127.0.0.1"_s, &m)); + EXPECT_EQ("127.0.0.1/255.255.255.255"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("127.0.0.1."_s, &m)); + EXPECT_EQ("127.0.0.1/255.255.255.255"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("127.0.0."_s, &m)); + EXPECT_EQ("127.0.0.0/255.255.255.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("127.0."_s, &m)); + EXPECT_EQ("127.0.0.0/255.255.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("127."_s, &m)); + EXPECT_EQ("127.0.0.0/255.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + + EXPECT_TRUE(extract("1.2.3.4/255.255.255.255"_s, &m)); + EXPECT_EQ("1.2.3.4/255.255.255.255"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("1.2.3.0/255.255.255.0"_s, &m)); + EXPECT_EQ("1.2.3.0/255.255.255.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("1.2.0.4/255.255.0.255"_s, &m)); + EXPECT_EQ("1.2.0.4/255.255.0.255"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("1.2.0.0/255.255.0.0"_s, &m)); + EXPECT_EQ("1.2.0.0/255.255.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("1.0.3.4/255.0.255.255"_s, &m)); + EXPECT_EQ("1.0.3.4/255.0.255.255"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("1.0.3.0/255.0.255.0"_s, &m)); + EXPECT_EQ("1.0.3.0/255.0.255.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("1.0.0.4/255.0.0.255"_s, &m)); + EXPECT_EQ("1.0.0.4/255.0.0.255"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("1.0.0.0/255.0.0.0"_s, &m)); + EXPECT_EQ("1.0.0.0/255.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.2.3.4/0.255.255.255"_s, &m)); + EXPECT_EQ("0.2.3.4/0.255.255.255"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.2.3.0/0.255.255.0"_s, &m)); + EXPECT_EQ("0.2.3.0/0.255.255.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.2.0.4/0.255.0.255"_s, &m)); + EXPECT_EQ("0.2.0.4/0.255.0.255"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.2.0.0/0.255.0.0"_s, &m)); + EXPECT_EQ("0.2.0.0/0.255.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.3.4/0.0.255.255"_s, &m)); + EXPECT_EQ("0.0.3.4/0.0.255.255"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.3.0/0.0.255.0"_s, &m)); + EXPECT_EQ("0.0.3.0/0.0.255.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.4/0.0.0.255"_s, &m)); + EXPECT_EQ("0.0.0.4/0.0.0.255"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/0.0.0.0"_s, &m)); + EXPECT_EQ("0.0.0.0/0.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + + // please don't do this + EXPECT_TRUE(extract("120.248.200.217/89.57.126.5"_s, &m)); + EXPECT_EQ("88.56.72.1/89.57.126.5"_s, STRNPRINTF(32, "%s"_fmt, m)); + + EXPECT_TRUE(extract("0.0.0.0/32"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.255.255"_s, STRNPRINTF(32, "%s"_fmt, m)); + + EXPECT_TRUE(extract("0.0.0.0/31"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.255.254"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/30"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.255.252"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/29"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.255.248"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/28"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.255.240"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/27"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.255.224"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/26"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.255.192"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/25"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.255.128"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/24"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.255.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + + EXPECT_TRUE(extract("0.0.0.0/23"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.254.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/22"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.252.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/21"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.248.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/20"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.240.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/19"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.224.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/18"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.192.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/17"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.128.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/16"_s, &m)); + EXPECT_EQ("0.0.0.0/255.255.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + + EXPECT_TRUE(extract("0.0.0.0/15"_s, &m)); + EXPECT_EQ("0.0.0.0/255.254.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/14"_s, &m)); + EXPECT_EQ("0.0.0.0/255.252.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/13"_s, &m)); + EXPECT_EQ("0.0.0.0/255.248.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/12"_s, &m)); + EXPECT_EQ("0.0.0.0/255.240.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/11"_s, &m)); + EXPECT_EQ("0.0.0.0/255.224.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/10"_s, &m)); + EXPECT_EQ("0.0.0.0/255.192.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/9"_s, &m)); + EXPECT_EQ("0.0.0.0/255.128.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/8"_s, &m)); + EXPECT_EQ("0.0.0.0/255.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + + EXPECT_TRUE(extract("0.0.0.0/7"_s, &m)); + EXPECT_EQ("0.0.0.0/254.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/6"_s, &m)); + EXPECT_EQ("0.0.0.0/252.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/5"_s, &m)); + EXPECT_EQ("0.0.0.0/248.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/4"_s, &m)); + EXPECT_EQ("0.0.0.0/240.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/3"_s, &m)); + EXPECT_EQ("0.0.0.0/224.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/2"_s, &m)); + EXPECT_EQ("0.0.0.0/192.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/1"_s, &m)); + EXPECT_EQ("0.0.0.0/128.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); + EXPECT_TRUE(extract("0.0.0.0/0"_s, &m)); + EXPECT_EQ("0.0.0.0/0.0.0.0"_s, STRNPRINTF(32, "%s"_fmt, m)); +} + +TEST(ip4mask, cover) +{ + IP4Address a; + IP4Address b = IP4_BROADCAST; + IP4Address l = IP4_LOCALHOST; + IP4Address h({127, 255, 255, 255}); + IP4Address p24l({10, 0, 0, 0}); + IP4Address p24h({10, 255, 255, 255}); + IP4Address p20l({172, 16, 0, 0}); + IP4Address p20h({172, 31, 255, 255}); + IP4Address p16l({192, 168, 0, 0}); + IP4Address p16h({192, 168, 255, 255}); + IP4Mask m; + EXPECT_TRUE(m.covers(a)); + EXPECT_TRUE(m.covers(b)); + EXPECT_TRUE(m.covers(l)); + EXPECT_TRUE(m.covers(h)); + EXPECT_TRUE(m.covers(p24l)); + EXPECT_TRUE(m.covers(p24h)); + EXPECT_TRUE(m.covers(p20l)); + EXPECT_TRUE(m.covers(p20h)); + EXPECT_TRUE(m.covers(p16l)); + EXPECT_TRUE(m.covers(p16h)); + m = IP4Mask(l, a); + EXPECT_TRUE(m.covers(a)); + EXPECT_TRUE(m.covers(b)); + EXPECT_TRUE(m.covers(l)); + EXPECT_TRUE(m.covers(h)); + EXPECT_TRUE(m.covers(p24l)); + EXPECT_TRUE(m.covers(p24h)); + EXPECT_TRUE(m.covers(p20l)); + EXPECT_TRUE(m.covers(p20h)); + EXPECT_TRUE(m.covers(p16l)); + EXPECT_TRUE(m.covers(p16h)); + m = IP4Mask(l, b); + EXPECT_FALSE(m.covers(a)); + EXPECT_FALSE(m.covers(b)); + EXPECT_TRUE(m.covers(l)); + EXPECT_FALSE(m.covers(h)); + EXPECT_FALSE(m.covers(p24l)); + EXPECT_FALSE(m.covers(p24h)); + EXPECT_FALSE(m.covers(p20l)); + EXPECT_FALSE(m.covers(p20h)); + EXPECT_FALSE(m.covers(p16l)); + EXPECT_FALSE(m.covers(p16h)); + + // but the really useful ones are with partial masks + m = IP4Mask(IP4Address({10, 0, 0, 0}), IP4Address({255, 0, 0, 0})); + EXPECT_FALSE(m.covers(a)); + EXPECT_FALSE(m.covers(b)); + EXPECT_FALSE(m.covers(l)); + EXPECT_FALSE(m.covers(h)); + EXPECT_TRUE(m.covers(p24l)); + EXPECT_TRUE(m.covers(p24h)); + EXPECT_FALSE(m.covers(p20l)); + EXPECT_FALSE(m.covers(p20h)); + EXPECT_FALSE(m.covers(p16l)); + EXPECT_FALSE(m.covers(p16h)); + EXPECT_FALSE(m.covers(IP4Address({9, 255, 255, 255}))); + EXPECT_FALSE(m.covers(IP4Address({11, 0, 0, 0}))); + m = IP4Mask(IP4Address({127, 0, 0, 0}), IP4Address({255, 0, 0, 0})); + EXPECT_FALSE(m.covers(a)); + EXPECT_FALSE(m.covers(b)); + EXPECT_TRUE(m.covers(l)); + EXPECT_TRUE(m.covers(h)); + EXPECT_FALSE(m.covers(p24l)); + EXPECT_FALSE(m.covers(p24h)); + EXPECT_FALSE(m.covers(p20l)); + EXPECT_FALSE(m.covers(p20h)); + EXPECT_FALSE(m.covers(p16l)); + EXPECT_FALSE(m.covers(p16h)); + EXPECT_FALSE(m.covers(IP4Address({126, 255, 255, 255}))); + EXPECT_FALSE(m.covers(IP4Address({128, 0, 0, 0}))); + m = IP4Mask(IP4Address({172, 16, 0, 0}), IP4Address({255, 240, 0, 0})); + EXPECT_FALSE(m.covers(a)); + EXPECT_FALSE(m.covers(b)); + EXPECT_FALSE(m.covers(l)); + EXPECT_FALSE(m.covers(h)); + EXPECT_FALSE(m.covers(p24l)); + EXPECT_FALSE(m.covers(p24h)); + EXPECT_TRUE(m.covers(p20l)); + EXPECT_TRUE(m.covers(p20h)); + EXPECT_FALSE(m.covers(p16l)); + EXPECT_FALSE(m.covers(p16h)); + EXPECT_FALSE(m.covers(IP4Address({172, 15, 255, 255}))); + EXPECT_FALSE(m.covers(IP4Address({172, 32, 0, 0}))); + m = IP4Mask(IP4Address({192, 168, 0, 0}), IP4Address({255, 255, 0, 0})); + EXPECT_FALSE(m.covers(a)); + EXPECT_FALSE(m.covers(b)); + EXPECT_FALSE(m.covers(l)); + EXPECT_FALSE(m.covers(h)); + EXPECT_FALSE(m.covers(p24l)); + EXPECT_FALSE(m.covers(p24h)); + EXPECT_FALSE(m.covers(p20l)); + EXPECT_FALSE(m.covers(p20h)); + EXPECT_TRUE(m.covers(p16l)); + EXPECT_TRUE(m.covers(p16h)); + EXPECT_FALSE(m.covers(IP4Address({192, 167, 255, 255}))); + EXPECT_FALSE(m.covers(IP4Address({192, 169, 0, 0}))); + + // OTOH this is crazy + EXPECT_TRUE(extract("120.248.200.217/89.57.126.5"_s, &m)); + EXPECT_TRUE(m.covers(IP4Address({120, 248, 200, 217}))); + EXPECT_TRUE(m.covers(IP4Address({88, 56, 72, 1}))); + EXPECT_FALSE(m.covers(IP4Address({88, 56, 72, 0}))); + EXPECT_FALSE(m.covers(IP4Address({88, 56, 72, 255}))); +} +} // namespace tmwa diff --git a/src/net/packets.cpp b/src/net/packets.cpp new file mode 100644 index 0000000..3cba856 --- /dev/null +++ b/src/net/packets.cpp @@ -0,0 +1,106 @@ +#include "packets.hpp" +// packets.cpp - palatable socket buffer accessors +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../io/cxxstdio.hpp" +#include "../io/write.hpp" + +#include "../poison.hpp" + + +namespace tmwa +{ +size_t packet_avail(Session *s) +{ + return s->rdata_size - s->rdata_pos; +} + +bool packet_fetch(Session *s, size_t offset, Byte *data, size_t sz) +{ + if (packet_avail(s) < offset + sz) + return false; + const Byte *start = reinterpret_cast<const Byte *>(&s->rdata[s->rdata_pos + offset]); + const Byte *end = start + sz; + std::copy(start, end, data); + return true; +} +void packet_discard(Session *s, size_t sz) +{ + s->rdata_pos += sz; + + assert (s->rdata_size >= s->rdata_pos); +} +bool packet_send(Session *s, const Byte *data, size_t sz) +{ + if (s->wdata_size + sz > s->max_wdata) + { + realloc_fifo(s, s->max_rdata, s->max_wdata << 1); + PRINTF("socket: %d wdata expanded to %zu bytes.\n"_fmt, s, s->max_wdata); + } + if (!s->max_wdata || !s->wdata) + { + return false; + } + s->wdata_size += sz; + + Byte *end = reinterpret_cast<Byte *>(&s->wdata[s->wdata_size + 0]); + Byte *start = end - sz; + std::copy(data, data + sz, start); + return true; +} + +void packet_dump(io::WriteFile& logfp, Session *s) +{ + FPRINTF(logfp, + "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F\n"_fmt); + char tmpstr[16 + 1] {}; + int i; + for (i = 0; i < packet_avail(s); i++) + { + if ((i & 15) == 0) + FPRINTF(logfp, "%04X "_fmt, i); + Byte rfifob_ib; + packet_fetch(s, i, &rfifob_ib, 1); + uint8_t rfifob_i = rfifob_ib.value; + FPRINTF(logfp, "%02x "_fmt, rfifob_i); + if (rfifob_i > 0x1f) + tmpstr[i % 16] = rfifob_i; + else + tmpstr[i % 16] = '.'; + if ((i - 7) % 16 == 0) // -8 + 1 + FPRINTF(logfp, " "_fmt); + else if ((i + 1) % 16 == 0) + { + FPRINTF(logfp, " %s\n"_fmt, tmpstr); + std::fill(tmpstr + 0, tmpstr + 17, '\0'); + } + } + if (i % 16 != 0) + { + for (int j = i; j % 16 != 0; j++) + { + FPRINTF(logfp, " "_fmt); + if ((j - 7) % 16 == 0) // -8 + 1 + FPRINTF(logfp, " "_fmt); + } + FPRINTF(logfp, " %s\n"_fmt, tmpstr); + } + FPRINTF(logfp, "\n"_fmt); +} +} // namespace tmwa diff --git a/src/net/packets.hpp b/src/net/packets.hpp new file mode 100644 index 0000000..5cc377c --- /dev/null +++ b/src/net/packets.hpp @@ -0,0 +1,585 @@ +#pragma once +// packets.hpp - palatable socket buffer accessors +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include <vector> + +#include "../compat/cast.hpp" + +#include "../ints/little.hpp" + +#include "../io/fwd.hpp" + +// TODO ordering violation, should invert +#include "../proto2/fwd.hpp" + +#include "socket.hpp" + + +namespace tmwa +{ +struct Buffer +{ + std::vector<Byte> bytes; +}; + +enum class RecvResult +{ + Incomplete, + Complete, + Error, +}; + +enum class SendResult +{ + Success, + Fail, +}; + + +size_t packet_avail(Session *s); +void packet_dump(io::WriteFile& out, Session *s); + +bool packet_fetch(Session *s, size_t offset, Byte *data, size_t sz); +void packet_discard(Session *s, size_t sz); +bool packet_send(Session *s, const Byte *data, size_t sz); + +inline +bool packet_peek_id(Session *s, uint16_t *packet_id) +{ + Little16 id; + bool okay = packet_fetch(s, 0, reinterpret_cast<Byte *>(&id), 2); + if (okay) + { + if (!network_to_native(packet_id, id)) + { + s->set_eof(); + return false; + } + } + return okay; +} + +inline +void send_buffer(Session *s, const Buffer& buffer) +{ + bool ok = !buffer.bytes.empty() && packet_send(s, buffer.bytes.data(), buffer.bytes.size()); + if (!ok) + s->set_eof(); +} + +template<uint16_t id> +__attribute__((warn_unused_result)) +RecvResult net_recv_fpacket(Session *s, NetPacket_Fixed<id>& fixed) +{ + bool ok = packet_fetch(s, 0, reinterpret_cast<Byte *>(&fixed), sizeof(NetPacket_Fixed<id>)); + if (ok) + { + packet_discard(s, sizeof(NetPacket_Fixed<id>)); + return RecvResult::Complete; + } + return RecvResult::Incomplete; +} + +template<uint16_t id> +__attribute__((warn_unused_result)) +RecvResult net_recv_ppacket(Session *s, NetPacket_Payload<id>& payload) +{ + bool ok = packet_fetch(s, 0, reinterpret_cast<Byte *>(&payload), sizeof(NetPacket_Payload<id>)); + if (ok) + { + packet_discard(s, sizeof(NetPacket_Payload<id>)); + return RecvResult::Complete; + } + return RecvResult::Incomplete; +} + +template<uint16_t id> +__attribute__((warn_unused_result)) +RecvResult net_recv_vpacket(Session *s, NetPacket_Head<id>& head, std::vector<NetPacket_Repeat<id>>& repeat) +{ + bool ok = packet_fetch(s, 0, reinterpret_cast<Byte *>(&head), sizeof(NetPacket_Head<id>)); + if (ok) + { + Packet_Head<id> nat; + if (!network_to_native(&nat, head)) + return RecvResult::Error; + if (packet_avail(s) < nat.magic_packet_length) + return RecvResult::Incomplete; + if (nat.magic_packet_length < sizeof(NetPacket_Head<id>)) + return RecvResult::Error; + size_t bytes_repeat = nat.magic_packet_length - sizeof(NetPacket_Head<id>); + if (bytes_repeat % sizeof(NetPacket_Repeat<id>)) + return RecvResult::Error; + repeat.resize(bytes_repeat / sizeof(NetPacket_Repeat<id>)); + if (packet_fetch(s, sizeof(NetPacket_Head<id>), reinterpret_cast<Byte *>(repeat.data()), bytes_repeat)) + { + packet_discard(s, nat.magic_packet_length); + return RecvResult::Complete; + } + return RecvResult::Incomplete; + } + return RecvResult::Incomplete; +} + +template<uint16_t id> +__attribute__((warn_unused_result)) +RecvResult net_recv_opacket(Session *s, NetPacket_Head<id>& head, bool *has_opt, NetPacket_Option<id>& opt) +{ + bool ok = packet_fetch(s, 0, reinterpret_cast<Byte *>(&head), sizeof(NetPacket_Head<id>)); + if (ok) + { + Packet_Head<id> nat; + if (!network_to_native(&nat, head)) + return RecvResult::Error; + if (packet_avail(s) < nat.magic_packet_length) + return RecvResult::Incomplete; + if (nat.magic_packet_length < sizeof(NetPacket_Head<id>)) + return RecvResult::Error; + size_t bytes_repeat = nat.magic_packet_length - sizeof(NetPacket_Head<id>); + if (bytes_repeat % sizeof(NetPacket_Option<id>)) + return RecvResult::Error; + size_t has_opt_pls = bytes_repeat / sizeof(NetPacket_Option<id>); + if (has_opt_pls > 1) + return RecvResult::Error; + *has_opt = has_opt_pls; + if (!*has_opt || packet_fetch(s, sizeof(NetPacket_Head<id>), reinterpret_cast<Byte *>(&opt), sizeof(NetPacket_Option<id>))) + { + packet_discard(s, nat.magic_packet_length); + return RecvResult::Complete; + } + return RecvResult::Incomplete; + } + return RecvResult::Incomplete; +} + + +template<uint16_t id, uint16_t size> +Buffer create_fpacket(const Packet_Fixed<id>& fixed) +{ + static_assert(id == Packet_Fixed<id>::PACKET_ID, "Packet_Fixed<id>::PACKET_ID"); + static_assert(size == sizeof(NetPacket_Fixed<id>), "sizeof(NetPacket_Fixed<id>)"); + + Buffer buf; + buf.bytes.resize(sizeof(NetPacket_Fixed<id>)); + auto& net_fixed = reinterpret_cast<NetPacket_Fixed<id>&>( + *(buf.bytes.begin() + 0)); + if (!native_to_network(&net_fixed, fixed)) + { + return Buffer(); + } + return buf; +} + +template<uint16_t id> +Buffer create_ppacket(Packet_Payload<id>& payload) +{ + static_assert(id == Packet_Payload<id>::PACKET_ID, "Packet_Payload<id>::PACKET_ID"); + + if (id != 0x8000) + payload.magic_packet_length = sizeof(NetPacket_Payload<id>); + + Buffer buf; + buf.bytes.resize(sizeof(NetPacket_Payload<id>)); + auto& net_payload = reinterpret_cast<NetPacket_Payload<id>&>( + *(buf.bytes.begin() + 0)); + if (!native_to_network(&net_payload, payload)) + { + return Buffer(); + } + return buf; +} + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +Buffer create_vpacket(Packet_Head<id>& head, const std::vector<Packet_Repeat<id>>& repeat) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "sizeof(NetPacket_Head<id>)"); + static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "sizeof(NetPacket_Repeat<id>)"); + + // since these are already allocated, can't overflow address space + size_t total_size = sizeof(NetPacket_Head<id>) + repeat.size() * sizeof(NetPacket_Repeat<id>); + // truncates + head.magic_packet_length = total_size; + if (head.magic_packet_length != total_size) + { + return Buffer(); + } + + Buffer buf; + buf.bytes.resize(total_size); + auto& net_head = reinterpret_cast<NetPacket_Head<id>&>( + *(buf.bytes.begin() + 0)); + if (!native_to_network(&net_head, head)) + { + return Buffer(); + } + for (size_t i = 0; i < repeat.size(); ++i) + { + auto& net_repeat_i = reinterpret_cast<NetPacket_Repeat<id>&>( + *(buf.bytes.begin() + + sizeof(NetPacket_Head<id>) + + i * sizeof(NetPacket_Repeat<id>))); + if (!native_to_network(&net_repeat_i, repeat[i])) + { + return Buffer(); + } + } + return buf; +} + +template<uint16_t id, uint16_t headsize, uint16_t optsize> +Buffer create_opacket(Packet_Head<id>& head, bool has_opt, const Packet_Option<id>& opt) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "sizeof(NetPacket_Head<id>)"); + static_assert(id == Packet_Option<id>::PACKET_ID, "Packet_Option<id>::PACKET_ID"); + static_assert(optsize == sizeof(NetPacket_Option<id>), "sizeof(NetPacket_Option<id>)"); + + // since these are already allocated, can't overflow address space + size_t total_size = sizeof(NetPacket_Head<id>) + has_opt * sizeof(NetPacket_Option<id>); + // truncates + head.magic_packet_length = total_size; + if (head.magic_packet_length != total_size) + { + return Buffer(); + } + + Buffer buf; + buf.bytes.resize(total_size); + + auto& net_head = reinterpret_cast<NetPacket_Head<id>&>( + *(buf.bytes.begin() + 0)); + if (!native_to_network(&net_head, head)) + { + return Buffer(); + } + if (has_opt) + { + auto& net_opt = reinterpret_cast<NetPacket_Option<id>&>( + *(buf.bytes.begin() + + sizeof(NetPacket_Head<id>))); + if (!native_to_network(&net_opt, opt)) + { + return Buffer(); + } + } + + return buf; +} + +template<uint16_t id, uint16_t size> +void send_fpacket(Session *s, const Packet_Fixed<id>& fixed) +{ + Buffer pkt = create_fpacket<id, size>(fixed); + send_buffer(s, pkt); +} + +template<uint16_t id> +void send_ppacket(Session *s, Packet_Payload<id>& payload) +{ + Buffer pkt = create_ppacket<id>(payload); + send_buffer(s, pkt); +} + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +void send_vpacket(Session *s, Packet_Head<id>& head, const std::vector<Packet_Repeat<id>>& repeat) +{ + Buffer pkt = create_vpacket<id, headsize, repeatsize>(head, repeat); + send_buffer(s, pkt); +} + +template<uint16_t id, uint16_t headsize, uint16_t optsize> +void send_opacket(Session *s, Packet_Head<id>& head, bool has_opt, const Packet_Option<id>& opt) +{ + Buffer pkt = create_opacket<id, headsize, optsize>(head, has_opt, opt); + send_buffer(s, pkt); +} + +template<uint16_t id, uint16_t size> +__attribute__((warn_unused_result)) +RecvResult recv_fpacket(Session *s, Packet_Fixed<id>& fixed) +{ + static_assert(id == Packet_Fixed<id>::PACKET_ID, "Packet_Fixed<id>::PACKET_ID"); + static_assert(size == sizeof(NetPacket_Fixed<id>), "NetPacket_Fixed<id>"); + + NetPacket_Fixed<id> net_fixed; + RecvResult rv = net_recv_fpacket(s, net_fixed); + if (rv == RecvResult::Complete) + { + if (!network_to_native(&fixed, net_fixed)) + return RecvResult::Error; + assert (fixed.magic_packet_id == Packet_Fixed<id>::PACKET_ID); + } + return rv; +} + +template<uint16_t id> +__attribute__((warn_unused_result)) +RecvResult recv_ppacket(Session *s, Packet_Payload<id>& payload) +{ + static_assert(id == Packet_Payload<id>::PACKET_ID, "Packet_Payload<id>::PACKET_ID"); + + NetPacket_Payload<id> net_payload; + RecvResult rv = net_recv_ppacket(s, net_payload); + if (rv == RecvResult::Complete) + { + if (!network_to_native(&payload, net_payload)) + return RecvResult::Error; + assert (payload.magic_packet_id == Packet_Payload<id>::PACKET_ID); + if (id == 0x8000) + { + // 0x8000 is special + if (packet_avail(s) < payload.magic_packet_length) + return RecvResult::Incomplete; + payload.magic_packet_length = 4; + return RecvResult::Complete; + } + if (payload.magic_packet_length != sizeof(net_payload)) + return RecvResult::Error; + } + return rv; +} + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +__attribute__((warn_unused_result)) +RecvResult recv_vpacket(Session *s, Packet_Head<id>& head, std::vector<Packet_Repeat<id>>& repeat) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "NetPacket_Head<id>"); + static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "NetPacket_Repeat<id>"); + + NetPacket_Head<id> net_head; + std::vector<NetPacket_Repeat<id>> net_repeat; + RecvResult rv = net_recv_vpacket(s, net_head, net_repeat); + if (rv == RecvResult::Complete) + { + if (!network_to_native(&head, net_head)) + return RecvResult::Error; + assert (head.magic_packet_id == Packet_Head<id>::PACKET_ID); + + repeat.resize(net_repeat.size()); + for (size_t i = 0; i < net_repeat.size(); ++i) + { + if (!network_to_native(&repeat[i], net_repeat[i])) + return RecvResult::Error; + } + } + return rv; +} + +template<uint16_t id, uint16_t headsize, uint16_t optsize> +__attribute__((warn_unused_result)) +RecvResult recv_opacket(Session *s, Packet_Head<id>& head, bool *has_opt, Packet_Option<id>& opt) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "NetPacket_Head<id>"); + static_assert(id == Packet_Option<id>::PACKET_ID, "Packet_Option<id>::PACKET_ID"); + static_assert(optsize == sizeof(NetPacket_Option<id>), "NetPacket_Option<id>"); + + NetPacket_Head<id> net_head; + NetPacket_Option<id> net_opt; + RecvResult rv = net_recv_opacket(s, net_head, has_opt, net_opt); + if (rv == RecvResult::Complete) + { + if (!network_to_native(&head, net_head)) + return RecvResult::Error; + assert (head.magic_packet_id == Packet_Head<id>::PACKET_ID); + + if (*has_opt) + { + if (!network_to_native(&opt, net_opt)) + return RecvResult::Error; + } + } + return rv; +} + + +// convenience for trailing strings + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +Buffer create_vpacket(Packet_Head<id>& head, const XString& repeat) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "NetPacket_Head<id>"); + static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "NetPacket_Repeat<id>"); + static_assert(repeatsize == 1, "repeatsize"); + + // since it's already allocated, it can't overflow address space + size_t total_length = sizeof(NetPacket_Head<id>) + (repeat.size() + 1) * sizeof(NetPacket_Repeat<id>); + head.magic_packet_length = total_length; + if (head.magic_packet_length != total_length) + { + return Buffer(); + } + + Buffer buf; + buf.bytes.resize(total_length); + auto& net_head = reinterpret_cast<NetPacket_Head<id>&>( + *(buf.bytes.begin() + 0)); + std::vector<NetPacket_Repeat<id>> net_repeat(repeat.size() + 1); + if (!native_to_network(&net_head, head)) + { + return Buffer(); + } + for (size_t i = 0; i < repeat.size(); ++i) + { + auto& net_repeat_i = reinterpret_cast<NetPacket_Repeat<id>&>( + *(buf.bytes.begin() + + sizeof(NetPacket_Head<id>) + + i)); + net_repeat_i.c = Byte{static_cast<uint8_t>(repeat[i])}; + } + auto& net_repeat_repeat_size = reinterpret_cast<NetPacket_Repeat<id>&>( + *(buf.bytes.begin() + + sizeof(NetPacket_Head<id>) + + repeat.size())); + net_repeat_repeat_size.c = Byte{static_cast<uint8_t>('\0')}; + return buf; +} + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +void send_vpacket(Session *s, Packet_Head<id>& head, const XString& repeat) +{ + Buffer pkt = create_vpacket<id, headsize, repeatsize>(head, repeat); + send_buffer(s, pkt); +} + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +__attribute__((warn_unused_result)) +RecvResult recv_vpacket(Session *s, Packet_Head<id>& head, AString& repeat) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "NetPacket_Head<id>"); + static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "NetPacket_Repeat<id>"); + static_assert(repeatsize == 1, "repeatsize"); + + NetPacket_Head<id> net_head; + std::vector<NetPacket_Repeat<id>> net_repeat; + RecvResult rv = net_recv_vpacket(s, net_head, net_repeat); + assert (head.magic_packet_id == Packet_Head<id>::PACKET_ID); + if (rv == RecvResult::Complete) + { + if (!network_to_native(&head, net_head)) + return RecvResult::Error; + // reinterpret_cast is needed to correctly handle an empty vector + const char *begin = sign_cast<const char *>(net_repeat.data()); + const char *end = begin + net_repeat.size(); + end = std::find(begin, end, '\0'); + repeat = XString(begin, end, nullptr); + } + return rv; +} + + +// if there is nothing in the head but the id and length, use the below + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +Buffer create_packet_repeatonly(const std::vector<Packet_Repeat<id>>& v) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "repeat headsize"); + static_assert(headsize == 4, "repeat headsize"); + static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "sizeof(NetPacket_Repeat<id>)"); + + Packet_Head<id> head; + return create_vpacket<id, 4, repeatsize>(head, v); +} + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +void send_packet_repeatonly(Session *s, const std::vector<Packet_Repeat<id>>& v) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "repeat headsize"); + static_assert(headsize == 4, "repeat headsize"); + static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "sizeof(NetPacket_Repeat<id>)"); + + Packet_Head<id> head; + send_vpacket<id, 4, repeatsize>(s, head, v); +} + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +__attribute__((warn_unused_result)) +RecvResult recv_packet_repeatonly(Session *s, std::vector<Packet_Repeat<id>>& v) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "repeat headsize"); + static_assert(headsize == 4, "repeat headsize"); + static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "sizeof(NetPacket_Repeat<id>)"); + + Packet_Head<id> head; + return recv_vpacket<id, 4, repeatsize>(s, head, v); +} + + +// and the combination of both of the above + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +Buffer create_packet_repeatonly(const XString& repeat) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "repeat headsize"); + static_assert(headsize == 4, "repeat headsize"); + static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "sizeof(NetPacket_Repeat<id>)"); + static_assert(repeatsize == 1, "repeatsize"); + + Packet_Head<id> head; + return create_vpacket<id, 4, repeatsize>(head, repeat); +} + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +void send_packet_repeatonly(Session *s, const XString& repeat) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "repeat headsize"); + static_assert(headsize == 4, "repeat headsize"); + static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "sizeof(NetPacket_Repeat<id>)"); + static_assert(repeatsize == 1, "repeatsize"); + + Packet_Head<id> head; + send_vpacket<id, 4, repeatsize>(s, head, repeat); +} + +template<uint16_t id, uint16_t headsize, uint16_t repeatsize> +__attribute__((warn_unused_result)) +RecvResult recv_packet_repeatonly(Session *s, AString& repeat) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "repeat headsize"); + static_assert(headsize == 4, "repeat headsize"); + static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "sizeof(NetPacket_Repeat<id>)"); + static_assert(repeatsize == 1, "repeatsize"); + + Packet_Head<id> head; + return recv_vpacket<id, 4, repeatsize>(s, head, repeat); +} +} // namespace tmwa diff --git a/src/mmo/socket.cpp b/src/net/socket.cpp index 1e294bd..a01cd81 100644 --- a/src/mmo/socket.cpp +++ b/src/net/socket.cpp @@ -21,25 +21,30 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <arpa/inet.h> #include <netinet/tcp.h> #include <sys/socket.h> -//#include <sys/types.h> #include <fcntl.h> -#include <unistd.h> #include <cstdlib> -#include <cstring> -#include <ctime> + +#include <array> + +#include "../compat/memory.hpp" #include "../io/cxxstdio.hpp" -#include "core.hpp" + +// TODO get rid of ordering violations +#include "../mmo/utils.hpp" +#include "../mmo/core.hpp" + #include "timer.hpp" -#include "utils.hpp" #include "../poison.hpp" + +namespace tmwa +{ static io::FD_Set readfds; static @@ -50,11 +55,11 @@ const uint32_t RFIFO_SIZE = 65536; static const uint32_t WFIFO_SIZE = 65536; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" +DIAG_PUSH(); +DIAG_I(old_style_cast); static std::array<std::unique_ptr<Session>, FD_SETSIZE> session; -#pragma GCC diagnostic pop +DIAG_POP(); Session::Session(SessionIO io, SessionParsers p) : created() @@ -118,8 +123,8 @@ IteratorPair<ValueIterator<io::FD, IncrFD>> iter_fds() inline void RFIFOFLUSH(Session *s) { - really_memmove(&s->rdata[0], &s->rdata[s->rdata_pos], RFIFOREST(s)); - s->rdata_size = RFIFOREST(s); + really_memmove(&s->rdata[0], &s->rdata[s->rdata_pos], s->rdata_size - s->rdata_pos); + s->rdata_size -= s->rdata_pos; s->rdata_pos = 0; } @@ -190,7 +195,7 @@ void connect_client(Session *ls) } if (fd.uncast_dammit() >= SOFT_LIMIT) { - FPRINTF(stderr, "softlimit reached, disconnecting : %d\n", fd.uncast_dammit()); + FPRINTF(stderr, "softlimit reached, disconnecting : %d\n"_fmt, fd.uncast_dammit()); fd.shutdown(SHUT_RDWR); fd.close(); return; @@ -225,7 +230,7 @@ void connect_client(Session *ls) fd.fcntl(F_SETFL, O_NONBLOCK); set_session(fd, make_unique<Session>( - SessionIO{func_recv: recv_to_fifo, func_send: send_from_fifo}, + SessionIO{.func_recv= recv_to_fifo, .func_send= send_from_fifo}, ls->for_inferior)); Session *s = get_session(fd); s->fd = fd; @@ -264,14 +269,12 @@ Session *make_listen_port(uint16_t port, SessionParsers inferior) fd.setsockopt(IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes); server_address.sin_family = AF_INET; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#if __GNUC__ > 4 || __GNUC_MINOR__ >= 8 -# pragma GCC diagnostic ignored "-Wuseless-cast" -#endif + DIAG_PUSH(); + DIAG_I(old_style_cast); + DIAG_I(useless_cast); server_address.sin_addr.s_addr = htonl(INADDR_ANY); server_address.sin_port = htons(port); -#pragma GCC diagnostic pop + DIAG_POP(); if (fd.bind(reinterpret_cast<struct sockaddr *>(&server_address), sizeof(server_address)) == -1) @@ -288,8 +291,8 @@ Session *make_listen_port(uint16_t port, SessionParsers inferior) readfds.set(fd); set_session(fd, make_unique<Session>( - SessionIO{func_recv: connect_client, func_send: nullptr}, - SessionParsers{func_parse: nullptr, func_delete: nothing_delete})); + SessionIO{.func_recv= connect_client, .func_send= nullptr}, + SessionParsers{.func_parse= nullptr, .func_delete= nothing_delete})); Session *s = get_session(fd); s->for_inferior = inferior; s->fd = fd; @@ -325,13 +328,11 @@ Session *make_connection(IP4Address ip, uint16_t port, SessionParsers parsers) server_address.sin_family = AF_INET; server_address.sin_addr = in_addr(ip); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#if __GNUC__ > 4 || __GNUC_MINOR__ >= 8 -# pragma GCC diagnostic ignored "-Wuseless-cast" -#endif + DIAG_PUSH(); + DIAG_I(old_style_cast); + DIAG_I(useless_cast); server_address.sin_port = htons(port); -#pragma GCC diagnostic pop + DIAG_POP(); fd.fcntl(F_SETFL, O_NONBLOCK); @@ -343,7 +344,7 @@ Session *make_connection(IP4Address ip, uint16_t port, SessionParsers parsers) readfds.set(fd); set_session(fd, make_unique<Session>( - SessionIO{func_recv: recv_to_fifo, func_send: send_from_fifo}, + SessionIO{.func_recv= recv_to_fifo, .func_send= send_from_fifo}, parsers)); Session *s = get_session(fd); s->fd = fd; @@ -398,19 +399,6 @@ void realloc_fifo(Session *s, size_t rfifo_size, size_t wfifo_size) } } -void WFIFOSET(Session *s, size_t len) -{ - if (s->wdata_size + len + 16384 > s->max_wdata) - { - realloc_fifo(s, s->max_rdata, s->max_wdata << 1); - PRINTF("socket: %d wdata expanded to %zu bytes.\n", s, s->max_wdata); - } - if (s->wdata_size + len + 2048 < s->max_wdata) - s->wdata_size += len; - else - FPRINTF(stderr, "socket: %d wdata lost !!\n", s), abort(); -} - void do_sendrecv(interval_t next_ms) { bool any = false; @@ -429,7 +417,8 @@ void do_sendrecv(interval_t next_ms) { if (!has_timers()) { - PRINTF("Shutting down - nothing to do\n"); + PRINTF("Shutting down - nothing to do\n"_fmt); + // TODO hoist this runflag = false; } return; @@ -441,7 +430,7 @@ void do_sendrecv(interval_t next_ms) timeout.tv_sec = next_s.count(); timeout.tv_usec = next_us.count(); } - if (io::FD_Set::select(fd_max, &rfd, &wfd, NULL, &timeout) <= 0) + if (io::FD_Set::select(fd_max, &rfd, &wfd, nullptr, &timeout) <= 0) return; for (io::FD i : iter_fds()) { @@ -474,7 +463,7 @@ void do_parsepacket(void) if (!s->connected && static_cast<time_t>(TimeT::now()) - static_cast<time_t>(s->created) > CONNECT_TIMEOUT) { - PRINTF("Session #%d timed out\n", s); + PRINTF("Session #%d timed out\n"_fmt, s); s->set_eof(); } if (s->rdata_size && !s->eof && s->func_parse) @@ -495,14 +484,4 @@ void do_parsepacket(void) RFIFOFLUSH(s); } } - -void RFIFOSKIP(Session *s, size_t len) -{ - s->rdata_pos += len; - - if (s->rdata_size < s->rdata_pos) - { - FPRINTF(stderr, "too many skip\n"); - abort(); - } -} +} // namespace tmwa diff --git a/src/net/socket.hpp b/src/net/socket.hpp new file mode 100644 index 0000000..576ef85 --- /dev/null +++ b/src/net/socket.hpp @@ -0,0 +1,177 @@ +#pragma once +// socket.hpp - Network event system. +// +// Copyright © ????-2004 Athena Dev Teams +// Copyright © 2004-2011 The Mana World Development Team +// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include <algorithm> + +#include <sys/select.h> + +#include <memory> + +#include "../compat/iter.hpp" +#include "../compat/rawmem.hpp" +#include "../compat/time_t.hpp" + +#include "../strings/astring.hpp" +#include "../strings/vstring.hpp" +#include "../strings/xstring.hpp" + +#include "../generic/dumb_ptr.hpp" + +#include "../io/fd.hpp" + +#include "ip.hpp" +#include "timer.t.hpp" + + +namespace tmwa +{ +struct SessionData +{ +}; +struct SessionDeleter +{ + // defined per-server + void operator()(SessionData *sd); +}; + +struct SessionIO +{ + void (*func_recv)(Session *); + void (*func_send)(Session *); +}; + +struct SessionParsers +{ + void (*func_parse)(Session *); + void (*func_delete)(Session *); +}; + +struct Session +{ + Session(SessionIO, SessionParsers); + Session(Session&&) = delete; + Session& operator = (Session&&) = delete; + + void set_io(SessionIO); + void set_parsers(SessionParsers); + + /// Checks whether a newly-connected socket actually does anything + TimeT created; + bool connected; + +private: + /// Flag needed since structure must be freed in a server-dependent manner + bool eof; +public: + void set_eof() { eof = true; } + + /// Currently used by clif_setwaitclose + Timer timed_close; + + /// Since this is a single-threaded application, it can't block + /// These are the read/write queues + dumb_ptr<uint8_t[]> rdata, wdata; + size_t max_rdata, max_wdata; + /// How much is actually in the queue + size_t rdata_size, wdata_size; + /// How much has already been read from the queue + /// Note that there is no need for a wdata_pos + size_t rdata_pos; + + IP4Address client_ip; + +private: + /// Send or recieve + /// Only called when select() indicates the socket is ready + /// If, after that, nothing is read, it sets eof + // These could probably be hard-coded with a little work + void (*func_recv)(Session *); + void (*func_send)(Session *); + /// This is the important one + /// Set to different functions depending on whether the connection + /// is a player or a server/ladmin + void (*func_parse)(Session *); + /// Cleanup function since we're not fully RAII yet + void (*func_delete)(Session *); + +public: + // this really ought to be part of session_data, once that gets sane + SessionParsers for_inferior; + + /// Server-specific data type + // (this really should include the deleter, but ...) + std::unique_ptr<SessionData, SessionDeleter> session_data; + + io::FD fd; + + friend void do_sendrecv(interval_t next); + friend void do_parsepacket(void); + friend void delete_session(Session *); +}; + +inline +int convert_for_printf(Session *s) +{ + return s->fd.uncast_dammit(); +} + +// save file descriptors for important stuff +constexpr int SOFT_LIMIT = FD_SETSIZE - 50; + +// socket timeout to establish a full connection in seconds +constexpr int CONNECT_TIMEOUT = 15; + + +void set_session(io::FD fd, std::unique_ptr<Session> sess); +Session *get_session(io::FD fd); +void reset_session(io::FD fd); +int get_fd_max(); + +class IncrFD +{ +public: + static + io::FD inced(io::FD v) + { + return io::FD::cast_dammit(v.uncast_dammit() + 1); + } +}; +IteratorPair<ValueIterator<io::FD, IncrFD>> iter_fds(); + + +/// open a socket, bind, and listen. Return an fd, or -1 if socket() fails, +/// but exit if bind() or listen() fails +Session *make_listen_port(uint16_t port, SessionParsers inferior); +/// Connect to an address, return a connected socket or -1 +// FIXME - this is IPv4 only! +Session *make_connection(IP4Address ip, uint16_t port, SessionParsers); +/// free() the structure and close() the fd +void delete_session(Session *); +/// Make a the internal queues bigger +void realloc_fifo(Session *s, size_t rfifo_size, size_t wfifo_size); +/// Update all sockets that can be read/written from the queues +void do_sendrecv(interval_t next); +/// Call the parser function for every socket that has read data +void do_parsepacket(void); +} // namespace tmwa diff --git a/src/mmo/timer.cpp b/src/net/timer.cpp index 6e28a12..6a22616 100644 --- a/src/mmo/timer.cpp +++ b/src/net/timer.cpp @@ -24,18 +24,17 @@ #include <sys/time.h> #include <cassert> -#include <cstring> +#include <algorithm> #include <queue> #include "../strings/zstring.hpp" -#include "../io/cxxstdio.hpp" - -#include "utils.hpp" - #include "../poison.hpp" + +namespace tmwa +{ struct TimerData { /// This will be reset on call, to avoid problems. @@ -78,7 +77,7 @@ tick_t milli_clock::now(void) noexcept struct timeval tval; // BUG: This will cause strange behavior if the system clock is changed! // it should be reimplemented in terms of clock_gettime(CLOCK_MONOTONIC, ) - gettimeofday(&tval, NULL); + gettimeofday(&tval, nullptr); return gettick_cache = tick_t(std::chrono::seconds(tval.tv_sec) + std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::microseconds(tval.tv_usec))); @@ -167,7 +166,7 @@ interval_t do_timer(tick_t tick) { /// Number of milliseconds until it calls this again // this says to wait 1 sec if all timers get popped - interval_t nextmin = std::chrono::seconds(1); + interval_t nextmin = 1_s; while (dumb_ptr<TimerData> td = top_timer_heap()) { @@ -187,7 +186,7 @@ interval_t do_timer(tick_t tick) td->owner->detach(); // If we are too far past the requested tick, call with // the current tick instead to fix reregistration problems - if (td->tick + std::chrono::seconds(1) < tick) + if (td->tick + 1_s < tick) td->func(td.operator->(), tick); else td->func(td.operator->(), td->tick); @@ -197,14 +196,14 @@ interval_t do_timer(tick_t tick) td.delete_(); continue; } - if (td->tick + std::chrono::seconds(1) < tick) + if (td->tick + 1_s < tick) td->tick = tick + td->interval; else td->tick += td->interval; push_timer_heap(td); } - return std::max(nextmin, std::chrono::milliseconds(10)); + return std::max(nextmin, 10_ms); } tick_t file_modified(ZString name) @@ -219,3 +218,4 @@ bool has_timers() { return !timer_heap.empty(); } +} // namespace tmwa diff --git a/src/mmo/timer.hpp b/src/net/timer.hpp index 363cf17..338e339 100644 --- a/src/mmo/timer.hpp +++ b/src/net/timer.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MMO_TIMER_HPP -#define TMWA_MMO_TIMER_HPP +#pragma once // timer.hpp - Future event scheduler. // // Copyright © ????-2004 Athena Dev Teams @@ -21,12 +20,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "timer.t.hpp" +#include "timer.t.hpp" -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/fwd.hpp" +#include "../strings/fwd.hpp" + +namespace tmwa +{ // updated automatically when using milli_clock::now() // which is done only by core.cpp extern tick_t gettick_cache; @@ -46,5 +48,4 @@ tick_t file_modified(ZString name); /// Check if there are any events at all scheduled. bool has_timers(); - -#endif // TMWA_MMO_TIMER_HPP +} // namespace tmwa diff --git a/src/mmo/timer.t.hpp b/src/net/timer.t.hpp index 6066e7c..090e62a 100644 --- a/src/mmo/timer.t.hpp +++ b/src/net/timer.t.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MMO_TIMER_T_HPP -#define TMWA_MMO_TIMER_T_HPP +#pragma once // timer.t.hpp - Future event scheduler. // // Copyright © ????-2004 Athena Dev Teams @@ -21,14 +20,41 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <chrono> -# include <functional> +#include <cstdlib> -# include "dumb_ptr.hpp" +#include <chrono> +#include <functional> -struct TimerData; +#include "../ints/little.hpp" + +#include "../generic/dumb_ptr.hpp" + + +namespace tmwa +{ +constexpr +std::chrono::nanoseconds operator "" _ns(unsigned long long ns) +{ return std::chrono::nanoseconds(ns); } +constexpr +std::chrono::microseconds operator "" _us(unsigned long long us) +{ return std::chrono::microseconds(us); } +constexpr +std::chrono::milliseconds operator "" _ms(unsigned long long ms) +{ return std::chrono::milliseconds(ms); } +constexpr +std::chrono::seconds operator "" _s(unsigned long long s) +{ return std::chrono::seconds(s); } +constexpr +std::chrono::minutes operator "" _min(unsigned long long min) +{ return std::chrono::minutes(min); } +constexpr +std::chrono::hours operator "" _h(unsigned long long h) +{ return std::chrono::hours(h); } +constexpr +std::chrono::duration<int, std::ratio<60*60*24>> operator "" _d(unsigned long long d) +{ return std::chrono::duration<int, std::ratio<60*60*24>>(d); } /// An implementation of the C++ "clock" concept, exposing /// durations in milliseconds. @@ -51,6 +77,55 @@ typedef milli_clock::duration interval_t; /// (to get additional arguments, use std::bind or a lambda). typedef std::function<void (TimerData *, tick_t)> timer_func; +// 49.7 day problem +inline __attribute__((warn_unused_result)) +bool native_to_network(Little32 *net, tick_t nat) +{ + auto tmp = nat.time_since_epoch().count(); + return native_to_network(net, static_cast<uint32_t>(tmp)); +} + +inline __attribute__((warn_unused_result)) +bool network_to_native(tick_t *nat, Little32 net) +{ + (void)nat; + (void)net; + abort(); +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(Little32 *net, interval_t nat) +{ + auto tmp = nat.count(); + return native_to_network(net, static_cast<uint32_t>(tmp)); +} + +inline __attribute__((warn_unused_result)) +bool network_to_native(interval_t *nat, Little32 net) +{ + uint32_t tmp; + bool rv = network_to_native(&tmp, net); + *nat = interval_t(tmp); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *net, interval_t nat) +{ + auto tmp = nat.count(); + return native_to_network(net, static_cast<uint16_t>(tmp)); +} + +inline __attribute__((warn_unused_result)) +bool network_to_native(interval_t *nat, Little16 net) +{ + uint16_t tmp; + bool rv = network_to_native(&tmp, net); + *nat = interval_t(tmp); + return rv; +} + + class Timer { friend struct TimerData; @@ -86,5 +161,4 @@ public: /// Check if there is no connected timer. bool operator !() { return !td; } }; - -#endif // TMWA_MMO_TIMER_T_HPP +} // namespace tmwa diff --git a/src/poison.hpp b/src/poison.hpp index 0328825..6903e1a 100644 --- a/src/poison.hpp +++ b/src/poison.hpp @@ -1,4 +1,4 @@ -#ifndef GENERATING_DEPENDENCIES +#pragma once // poison.hpp - List of dangerous functions and objects. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -18,10 +18,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# if 0 -# include "../sanity.hpp" -# endif +// just mention "fwd.hpp" to make formatter happy + +namespace tmwa +{ +#ifndef GENERATING_DEPENDENCIES // impossible(*) to use safely // removed in C11 # pragma GCC poison gets @@ -78,13 +80,12 @@ # pragma GCC poison open_memstream # pragma GCC poison open_wmemstream -// *scanf %ms is done very carefully. -//#pragma GCC poison scanf -//#pragma GCC poison fscanf -//#pragma GCC poison sscanf -//#pragma GCC poison vscanf -//#pragma GCC poison vsscanf -//#pragma GCC poison vfscanf +# pragma GCC poison scanf +# pragma GCC poison fscanf +# pragma GCC poison sscanf +# pragma GCC poison vscanf +# pragma GCC poison vsscanf +# pragma GCC poison vfscanf # pragma GCC poison getcwd # pragma GCC poison get_current_dir_name @@ -119,5 +120,5 @@ # pragma GCC poison ifstream # pragma GCC poison ofstream # pragma GCC poison fstream - #endif // GENERATING_DEPENDENCIES +} // namespace tmwa diff --git a/src/proto2/any-user.hpp b/src/proto2/any-user.hpp new file mode 100644 index 0000000..aeb703b --- /dev/null +++ b/src/proto2/any-user.hpp @@ -0,0 +1,214 @@ +#pragma once +// any-user.hpp - TMWA network protocol: any/user +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "fwd.hpp" + +#include "types.hpp" + +namespace tmwa +{ +// This is a public protocol, and changes require client cooperation + +template<> +struct Packet_Fixed<0x0081> +{ + static const uint16_t PACKET_ID = 0x0081; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t error_code = {}; +}; + +template<> +struct Packet_Fixed<0x7530> +{ + static const uint16_t PACKET_ID = 0x7530; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x7531> +{ + static const uint16_t PACKET_ID = 0x7531; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + Version version = {}; +}; + +template<> +struct Packet_Fixed<0x7532> +{ + static const uint16_t PACKET_ID = 0x7532; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Payload<0x8000> +{ + static const uint16_t PACKET_ID = 0x8000; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; + + +template<> +struct NetPacket_Fixed<0x0081> +{ + Little16 magic_packet_id; + Byte error_code; +}; +static_assert(offsetof(NetPacket_Fixed<0x0081>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0081>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0081>, error_code) == 2, "offsetof(NetPacket_Fixed<0x0081>, error_code) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x0081>) == 3, "sizeof(NetPacket_Fixed<0x0081>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x0081>) == 1, "alignof(NetPacket_Fixed<0x0081>) == 1"); + +template<> +struct NetPacket_Fixed<0x7530> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x7530>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7530>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x7530>) == 2, "sizeof(NetPacket_Fixed<0x7530>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x7530>) == 1, "alignof(NetPacket_Fixed<0x7530>) == 1"); + +template<> +struct NetPacket_Fixed<0x7531> +{ + Little16 magic_packet_id; + NetVersion version; +}; +static_assert(offsetof(NetPacket_Fixed<0x7531>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7531>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7531>, version) == 2, "offsetof(NetPacket_Fixed<0x7531>, version) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x7531>) == 10, "sizeof(NetPacket_Fixed<0x7531>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x7531>) == 1, "alignof(NetPacket_Fixed<0x7531>) == 1"); + +template<> +struct NetPacket_Fixed<0x7532> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x7532>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7532>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x7532>) == 2, "sizeof(NetPacket_Fixed<0x7532>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x7532>) == 1, "alignof(NetPacket_Fixed<0x7532>) == 1"); + +template<> +struct NetPacket_Payload<0x8000> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Payload<0x8000>, magic_packet_id) == 0, "offsetof(NetPacket_Payload<0x8000>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Payload<0x8000>, magic_packet_length) == 2, "offsetof(NetPacket_Payload<0x8000>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Payload<0x8000>) == 4, "sizeof(NetPacket_Payload<0x8000>) == 4"); +static_assert(alignof(NetPacket_Payload<0x8000>) == 1, "alignof(NetPacket_Payload<0x8000>) == 1"); + + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0081> *network, Packet_Fixed<0x0081> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->error_code, native.error_code); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0081> *native, NetPacket_Fixed<0x0081> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->error_code, network.error_code); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7530> *network, Packet_Fixed<0x7530> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7530> *native, NetPacket_Fixed<0x7530> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7531> *network, Packet_Fixed<0x7531> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->version, native.version); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7531> *native, NetPacket_Fixed<0x7531> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->version, network.version); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7532> *network, Packet_Fixed<0x7532> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7532> *native, NetPacket_Fixed<0x7532> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Payload<0x8000> *network, Packet_Payload<0x8000> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Payload<0x8000> *native, NetPacket_Payload<0x8000> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} + +} // namespace tmwa diff --git a/src/proto2/any-user_test.cpp b/src/proto2/any-user_test.cpp new file mode 100644 index 0000000..3cf15bf --- /dev/null +++ b/src/proto2/any-user_test.cpp @@ -0,0 +1,27 @@ +#include "any-user.hpp" +// any-user_test.cpp - TMWA network protocol: any/user +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "../poison.hpp" + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/proto2/char-map.hpp b/src/proto2/char-map.hpp new file mode 100644 index 0000000..8a23be6 --- /dev/null +++ b/src/proto2/char-map.hpp @@ -0,0 +1,3498 @@ +#pragma once +// char-map.hpp - TMWA network protocol: char/map +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "fwd.hpp" + +#include "types.hpp" + +namespace tmwa +{ +// This is an internal protocol, and can be changed without notice + +template<> +struct Packet_Fixed<0x2af7> +{ + static const uint16_t PACKET_ID = 0x2af7; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x2af8> +{ + static const uint16_t PACKET_ID = 0x2af8; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + AccountPass account_pass = {}; + uint32_t unused = {}; + IP4Address ip = {}; + uint16_t port = {}; +}; + +template<> +struct Packet_Fixed<0x2af9> +{ + static const uint16_t PACKET_ID = 0x2af9; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t code = {}; +}; + +template<> +struct Packet_Head<0x2afa> +{ + static const uint16_t PACKET_ID = 0x2afa; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x2afa> +{ + static const uint16_t PACKET_ID = 0x2afa; + + MapName map_name = {}; +}; + +template<> +struct Packet_Fixed<0x2afa> +{ + static const uint16_t PACKET_ID = 0x2afa; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + ItemNameId source_item_id = {}; + ItemNameId dest_item_id = {}; +}; + +template<> +struct Packet_Fixed<0x2afb> +{ + static const uint16_t PACKET_ID = 0x2afb; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t unknown = {}; + CharName whisper_name = {}; +}; + +template<> +struct Packet_Fixed<0x2afc> +{ + static const uint16_t PACKET_ID = 0x2afc; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + CharId char_id = {}; + uint32_t login_id1 = {}; + uint32_t login_id2 = {}; + IP4Address ip = {}; +}; + +template<> +struct Packet_Payload<0x2afd> +{ + static const uint16_t PACKET_ID = 0x2afd; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; + uint32_t login_id2 = {}; + TimeT connect_until = {}; + uint16_t packet_tmw_version = {}; + CharKey char_key = {}; + CharData char_data = {}; +}; + +template<> +struct Packet_Fixed<0x2afe> +{ + static const uint16_t PACKET_ID = 0x2afe; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Head<0x2aff> +{ + static const uint16_t PACKET_ID = 0x2aff; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + uint16_t users = {}; +}; +template<> +struct Packet_Repeat<0x2aff> +{ + static const uint16_t PACKET_ID = 0x2aff; + + CharId char_id = {}; +}; + +template<> +struct Packet_Fixed<0x2b00> +{ + static const uint16_t PACKET_ID = 0x2b00; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint32_t users = {}; +}; + +template<> +struct Packet_Payload<0x2b01> +{ + static const uint16_t PACKET_ID = 0x2b01; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; + CharId char_id = {}; + CharKey char_key = {}; + CharData char_data = {}; +}; + +template<> +struct Packet_Fixed<0x2b02> +{ + static const uint16_t PACKET_ID = 0x2b02; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint32_t login_id1 = {}; + uint32_t login_id2 = {}; + IP4Address ip = {}; +}; + +template<> +struct Packet_Fixed<0x2b03> +{ + static const uint16_t PACKET_ID = 0x2b03; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint8_t unknown = {}; +}; + +template<> +struct Packet_Head<0x2b04> +{ + static const uint16_t PACKET_ID = 0x2b04; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + IP4Address ip = {}; + uint16_t port = {}; +}; +template<> +struct Packet_Repeat<0x2b04> +{ + static const uint16_t PACKET_ID = 0x2b04; + + MapName map_name = {}; +}; + +template<> +struct Packet_Fixed<0x2b05> +{ + static const uint16_t PACKET_ID = 0x2b05; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint32_t login_id1 = {}; + uint32_t login_id2 = {}; + CharId char_id = {}; + MapName map_name = {}; + uint16_t x = {}; + uint16_t y = {}; + IP4Address map_ip = {}; + uint16_t map_port = {}; + SEX sex = {}; + IP4Address client_ip = {}; +}; + +template<> +struct Packet_Fixed<0x2b06> +{ + static const uint16_t PACKET_ID = 0x2b06; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint32_t error = {}; + uint32_t unknown = {}; + CharId char_id = {}; + MapName map_name = {}; + uint16_t x = {}; + uint16_t y = {}; + IP4Address map_ip = {}; + uint16_t map_port = {}; +}; + +template<> +struct Packet_Head<0x2b0a> +{ + static const uint16_t PACKET_ID = 0x2b0a; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; +}; +template<> +struct Packet_Repeat<0x2b0a> +{ + static const uint16_t PACKET_ID = 0x2b0a; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x2b0b> +{ + static const uint16_t PACKET_ID = 0x2b0b; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + GmLevel gm_level = {}; +}; + +template<> +struct Packet_Fixed<0x2b0c> +{ + static const uint16_t PACKET_ID = 0x2b0c; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountEmail old_email = {}; + AccountEmail new_email = {}; +}; + +template<> +struct Packet_Fixed<0x2b0d> +{ + static const uint16_t PACKET_ID = 0x2b0d; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + SEX sex = {}; +}; + +template<> +struct Packet_Fixed<0x2b0e> +{ + static const uint16_t PACKET_ID = 0x2b0e; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + CharName char_name = {}; + uint16_t operation = {}; + HumanTimeDiff ban_add = {}; +}; + +template<> +struct Packet_Fixed<0x2b0f> +{ + static const uint16_t PACKET_ID = 0x2b0f; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + CharName char_name = {}; + uint16_t operation = {}; + uint16_t error = {}; +}; + +template<> +struct Packet_Head<0x2b10> +{ + static const uint16_t PACKET_ID = 0x2b10; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; +}; +template<> +struct Packet_Repeat<0x2b10> +{ + static const uint16_t PACKET_ID = 0x2b10; + + VarName name = {}; + uint32_t value = {}; +}; + +template<> +struct Packet_Head<0x2b11> +{ + static const uint16_t PACKET_ID = 0x2b11; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; +}; +template<> +struct Packet_Repeat<0x2b11> +{ + static const uint16_t PACKET_ID = 0x2b11; + + VarName name = {}; + uint32_t value = {}; +}; + +template<> +struct Packet_Fixed<0x2b12> +{ + static const uint16_t PACKET_ID = 0x2b12; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + CharId char_id = {}; + CharId partner_id = {}; +}; + +template<> +struct Packet_Fixed<0x2b13> +{ + static const uint16_t PACKET_ID = 0x2b13; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Fixed<0x2b14> +{ + static const uint16_t PACKET_ID = 0x2b14; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint8_t ban_not_status = {}; + TimeT status_or_ban_until = {}; +}; + +template<> +struct Packet_Head<0x2b15> +{ + static const uint16_t PACKET_ID = 0x2b15; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x2b15> +{ + static const uint16_t PACKET_ID = 0x2b15; + + AccountId account_id = {}; + GmLevel gm_level = {}; +}; + +template<> +struct Packet_Fixed<0x2b16> +{ + static const uint16_t PACKET_ID = 0x2b16; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + CharId char_id = {}; +}; + +template<> +struct Packet_Head<0x3000> +{ + static const uint16_t PACKET_ID = 0x3000; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x3000> +{ + static const uint16_t PACKET_ID = 0x3000; + + uint8_t c = {}; +}; + +template<> +struct Packet_Head<0x3001> +{ + static const uint16_t PACKET_ID = 0x3001; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + CharName from_char_name = {}; + CharName to_char_name = {}; +}; +template<> +struct Packet_Repeat<0x3001> +{ + static const uint16_t PACKET_ID = 0x3001; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x3002> +{ + static const uint16_t PACKET_ID = 0x3002; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + CharId char_id = {}; + uint8_t flag = {}; +}; + +template<> +struct Packet_Head<0x3003> +{ + static const uint16_t PACKET_ID = 0x3003; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + CharName char_name = {}; + GmLevel min_gm_level = {}; +}; +template<> +struct Packet_Repeat<0x3003> +{ + static const uint16_t PACKET_ID = 0x3003; + + uint8_t c = {}; +}; + +template<> +struct Packet_Head<0x3004> +{ + static const uint16_t PACKET_ID = 0x3004; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; +}; +template<> +struct Packet_Repeat<0x3004> +{ + static const uint16_t PACKET_ID = 0x3004; + + VarName name = {}; + uint32_t value = {}; +}; + +template<> +struct Packet_Fixed<0x3005> +{ + static const uint16_t PACKET_ID = 0x3005; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Fixed<0x3010> +{ + static const uint16_t PACKET_ID = 0x3010; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Payload<0x3011> +{ + static const uint16_t PACKET_ID = 0x3011; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; + Storage storage = {}; +}; + +template<> +struct Packet_Fixed<0x3020> +{ + static const uint16_t PACKET_ID = 0x3020; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + PartyName party_name = {}; + CharName char_name = {}; + MapName map_name = {}; + uint16_t level = {}; +}; + +template<> +struct Packet_Fixed<0x3021> +{ + static const uint16_t PACKET_ID = 0x3021; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyId party_id = {}; +}; + +template<> +struct Packet_Fixed<0x3022> +{ + static const uint16_t PACKET_ID = 0x3022; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyId party_id = {}; + AccountId account_id = {}; + CharName char_name = {}; + MapName map_name = {}; + uint16_t level = {}; +}; + +template<> +struct Packet_Fixed<0x3023> +{ + static const uint16_t PACKET_ID = 0x3023; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyId party_id = {}; + AccountId account_id = {}; + uint16_t exp = {}; + uint16_t item = {}; +}; + +template<> +struct Packet_Fixed<0x3024> +{ + static const uint16_t PACKET_ID = 0x3024; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyId party_id = {}; + AccountId account_id = {}; +}; + +template<> +struct Packet_Fixed<0x3025> +{ + static const uint16_t PACKET_ID = 0x3025; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyId party_id = {}; + AccountId account_id = {}; + MapName map_name = {}; + uint8_t online = {}; + uint16_t level = {}; +}; + +template<> +struct Packet_Head<0x3027> +{ + static const uint16_t PACKET_ID = 0x3027; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + PartyId party_id = {}; + AccountId account_id = {}; +}; +template<> +struct Packet_Repeat<0x3027> +{ + static const uint16_t PACKET_ID = 0x3027; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x3028> +{ + static const uint16_t PACKET_ID = 0x3028; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyId party_id = {}; + AccountId account_id = {}; + CharName char_name = {}; +}; + +template<> +struct Packet_Head<0x3800> +{ + static const uint16_t PACKET_ID = 0x3800; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x3800> +{ + static const uint16_t PACKET_ID = 0x3800; + + uint8_t c = {}; +}; + +template<> +struct Packet_Head<0x3801> +{ + static const uint16_t PACKET_ID = 0x3801; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + CharId whisper_id = {}; + CharName src_char_name = {}; + CharName dst_char_name = {}; +}; +template<> +struct Packet_Repeat<0x3801> +{ + static const uint16_t PACKET_ID = 0x3801; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x3802> +{ + static const uint16_t PACKET_ID = 0x3802; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + CharName sender_char_name = {}; + uint8_t flag = {}; +}; + +template<> +struct Packet_Head<0x3803> +{ + static const uint16_t PACKET_ID = 0x3803; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + CharName char_name = {}; + GmLevel min_gm_level = {}; +}; +template<> +struct Packet_Repeat<0x3803> +{ + static const uint16_t PACKET_ID = 0x3803; + + uint8_t c = {}; +}; + +template<> +struct Packet_Head<0x3804> +{ + static const uint16_t PACKET_ID = 0x3804; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; +}; +template<> +struct Packet_Repeat<0x3804> +{ + static const uint16_t PACKET_ID = 0x3804; + + VarName name = {}; + uint32_t value = {}; +}; + +template<> +struct Packet_Payload<0x3810> +{ + static const uint16_t PACKET_ID = 0x3810; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; + Storage storage = {}; +}; + +template<> +struct Packet_Fixed<0x3811> +{ + static const uint16_t PACKET_ID = 0x3811; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint8_t unknown = {}; +}; + +template<> +struct Packet_Fixed<0x3820> +{ + static const uint16_t PACKET_ID = 0x3820; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint8_t error = {}; + PartyId party_id = {}; + PartyName party_name = {}; +}; + +template<> +struct Packet_Head<0x3821> +{ + static const uint16_t PACKET_ID = 0x3821; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + PartyId party_id = {}; +}; +template<> +struct Packet_Option<0x3821> +{ + static const uint16_t PACKET_ID = 0x3821; + + PartyMost party_most = {}; +}; + +template<> +struct Packet_Fixed<0x3822> +{ + static const uint16_t PACKET_ID = 0x3822; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyId party_id = {}; + AccountId account_id = {}; + uint8_t flag = {}; +}; + +template<> +struct Packet_Fixed<0x3823> +{ + static const uint16_t PACKET_ID = 0x3823; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyId party_id = {}; + AccountId account_id = {}; + uint16_t exp = {}; + uint16_t item = {}; + uint8_t flag = {}; +}; + +template<> +struct Packet_Fixed<0x3824> +{ + static const uint16_t PACKET_ID = 0x3824; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyId party_id = {}; + AccountId account_id = {}; + CharName char_name = {}; +}; + +template<> +struct Packet_Fixed<0x3825> +{ + static const uint16_t PACKET_ID = 0x3825; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyId party_id = {}; + AccountId account_id = {}; + MapName map_name = {}; + uint8_t online = {}; + uint16_t level = {}; +}; + +template<> +struct Packet_Fixed<0x3826> +{ + static const uint16_t PACKET_ID = 0x3826; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyId party_id = {}; + uint8_t flag = {}; +}; + +template<> +struct Packet_Head<0x3827> +{ + static const uint16_t PACKET_ID = 0x3827; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + PartyId party_id = {}; + AccountId account_id = {}; +}; +template<> +struct Packet_Repeat<0x3827> +{ + static const uint16_t PACKET_ID = 0x3827; + + uint8_t c = {}; +}; + + +template<> +struct NetPacket_Fixed<0x2af7> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x2af7>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2af7>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x2af7>) == 2, "sizeof(NetPacket_Fixed<0x2af7>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x2af7>) == 1, "alignof(NetPacket_Fixed<0x2af7>) == 1"); + +template<> +struct NetPacket_Fixed<0x2af8> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + NetString<sizeof(AccountPass)> account_pass; + Little32 unused; + IP4Address ip; + Little16 port; +}; +static_assert(offsetof(NetPacket_Fixed<0x2af8>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2af8>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2af8>, account_name) == 2, "offsetof(NetPacket_Fixed<0x2af8>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2af8>, account_pass) == 26, "offsetof(NetPacket_Fixed<0x2af8>, account_pass) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x2af8>, unused) == 50, "offsetof(NetPacket_Fixed<0x2af8>, unused) == 50"); +static_assert(offsetof(NetPacket_Fixed<0x2af8>, ip) == 54, "offsetof(NetPacket_Fixed<0x2af8>, ip) == 54"); +static_assert(offsetof(NetPacket_Fixed<0x2af8>, port) == 58, "offsetof(NetPacket_Fixed<0x2af8>, port) == 58"); +static_assert(sizeof(NetPacket_Fixed<0x2af8>) == 60, "sizeof(NetPacket_Fixed<0x2af8>) == 60"); +static_assert(alignof(NetPacket_Fixed<0x2af8>) == 1, "alignof(NetPacket_Fixed<0x2af8>) == 1"); + +template<> +struct NetPacket_Fixed<0x2af9> +{ + Little16 magic_packet_id; + Byte code; +}; +static_assert(offsetof(NetPacket_Fixed<0x2af9>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2af9>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2af9>, code) == 2, "offsetof(NetPacket_Fixed<0x2af9>, code) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x2af9>) == 3, "sizeof(NetPacket_Fixed<0x2af9>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x2af9>) == 1, "alignof(NetPacket_Fixed<0x2af9>) == 1"); + +template<> +struct NetPacket_Head<0x2afa> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x2afa>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2afa>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2afa>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x2afa>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x2afa>) == 4, "sizeof(NetPacket_Head<0x2afa>) == 4"); +static_assert(alignof(NetPacket_Head<0x2afa>) == 1, "alignof(NetPacket_Head<0x2afa>) == 1"); +template<> +struct NetPacket_Repeat<0x2afa> +{ + NetString<sizeof(MapName)> map_name; +}; +static_assert(offsetof(NetPacket_Repeat<0x2afa>, map_name) == 0, "offsetof(NetPacket_Repeat<0x2afa>, map_name) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x2afa>) == 16, "sizeof(NetPacket_Repeat<0x2afa>) == 16"); +static_assert(alignof(NetPacket_Repeat<0x2afa>) == 1, "alignof(NetPacket_Repeat<0x2afa>) == 1"); + +template<> +struct NetPacket_Fixed<0x2afa> +{ + Little16 magic_packet_id; + Little32 source_item_id; + Little32 dest_item_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x2afa>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2afa>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2afa>, source_item_id) == 2, "offsetof(NetPacket_Fixed<0x2afa>, source_item_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2afa>, dest_item_id) == 6, "offsetof(NetPacket_Fixed<0x2afa>, dest_item_id) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x2afa>) == 10, "sizeof(NetPacket_Fixed<0x2afa>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x2afa>) == 1, "alignof(NetPacket_Fixed<0x2afa>) == 1"); + +template<> +struct NetPacket_Fixed<0x2afb> +{ + Little16 magic_packet_id; + Byte unknown; + NetString<sizeof(CharName)> whisper_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x2afb>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2afb>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2afb>, unknown) == 2, "offsetof(NetPacket_Fixed<0x2afb>, unknown) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2afb>, whisper_name) == 3, "offsetof(NetPacket_Fixed<0x2afb>, whisper_name) == 3"); +static_assert(sizeof(NetPacket_Fixed<0x2afb>) == 27, "sizeof(NetPacket_Fixed<0x2afb>) == 27"); +static_assert(alignof(NetPacket_Fixed<0x2afb>) == 1, "alignof(NetPacket_Fixed<0x2afb>) == 1"); + +template<> +struct NetPacket_Fixed<0x2afc> +{ + Little16 magic_packet_id; + Little32 account_id; + Little32 char_id; + Little32 login_id1; + Little32 login_id2; + IP4Address ip; +}; +static_assert(offsetof(NetPacket_Fixed<0x2afc>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2afc>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2afc>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2afc>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2afc>, char_id) == 6, "offsetof(NetPacket_Fixed<0x2afc>, char_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2afc>, login_id1) == 10, "offsetof(NetPacket_Fixed<0x2afc>, login_id1) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x2afc>, login_id2) == 14, "offsetof(NetPacket_Fixed<0x2afc>, login_id2) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x2afc>, ip) == 18, "offsetof(NetPacket_Fixed<0x2afc>, ip) == 18"); +static_assert(sizeof(NetPacket_Fixed<0x2afc>) == 22, "sizeof(NetPacket_Fixed<0x2afc>) == 22"); +static_assert(alignof(NetPacket_Fixed<0x2afc>) == 1, "alignof(NetPacket_Fixed<0x2afc>) == 1"); + +template<> +struct NetPacket_Payload<0x2afd> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; + Little32 login_id2; + Little32 connect_until; + Little16 packet_tmw_version; + NetCharKey char_key; + NetCharData char_data; +}; +static_assert(offsetof(NetPacket_Payload<0x2afd>, magic_packet_id) == 0, "offsetof(NetPacket_Payload<0x2afd>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Payload<0x2afd>, magic_packet_length) == 2, "offsetof(NetPacket_Payload<0x2afd>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Payload<0x2afd>, account_id) == 4, "offsetof(NetPacket_Payload<0x2afd>, account_id) == 4"); +static_assert(offsetof(NetPacket_Payload<0x2afd>, login_id2) == 8, "offsetof(NetPacket_Payload<0x2afd>, login_id2) == 8"); +static_assert(offsetof(NetPacket_Payload<0x2afd>, connect_until) == 12, "offsetof(NetPacket_Payload<0x2afd>, connect_until) == 12"); +static_assert(offsetof(NetPacket_Payload<0x2afd>, packet_tmw_version) == 16, "offsetof(NetPacket_Payload<0x2afd>, packet_tmw_version) == 16"); +static_assert(offsetof(NetPacket_Payload<0x2afd>, char_key) == 18, "offsetof(NetPacket_Payload<0x2afd>, char_key) == 18"); +static_assert(alignof(NetPacket_Payload<0x2afd>) == 1, "alignof(NetPacket_Payload<0x2afd>) == 1"); + +template<> +struct NetPacket_Fixed<0x2afe> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x2afe>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2afe>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2afe>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2afe>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x2afe>) == 6, "sizeof(NetPacket_Fixed<0x2afe>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x2afe>) == 1, "alignof(NetPacket_Fixed<0x2afe>) == 1"); + +template<> +struct NetPacket_Head<0x2aff> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little16 users; +}; +static_assert(offsetof(NetPacket_Head<0x2aff>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2aff>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2aff>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x2aff>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x2aff>, users) == 4, "offsetof(NetPacket_Head<0x2aff>, users) == 4"); +static_assert(sizeof(NetPacket_Head<0x2aff>) == 6, "sizeof(NetPacket_Head<0x2aff>) == 6"); +static_assert(alignof(NetPacket_Head<0x2aff>) == 1, "alignof(NetPacket_Head<0x2aff>) == 1"); +template<> +struct NetPacket_Repeat<0x2aff> +{ + Little32 char_id; +}; +static_assert(offsetof(NetPacket_Repeat<0x2aff>, char_id) == 0, "offsetof(NetPacket_Repeat<0x2aff>, char_id) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x2aff>) == 4, "sizeof(NetPacket_Repeat<0x2aff>) == 4"); +static_assert(alignof(NetPacket_Repeat<0x2aff>) == 1, "alignof(NetPacket_Repeat<0x2aff>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b00> +{ + Little16 magic_packet_id; + Little32 users; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b00>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b00>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b00>, users) == 2, "offsetof(NetPacket_Fixed<0x2b00>, users) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x2b00>) == 6, "sizeof(NetPacket_Fixed<0x2b00>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x2b00>) == 1, "alignof(NetPacket_Fixed<0x2b00>) == 1"); + +template<> +struct NetPacket_Payload<0x2b01> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; + Little32 char_id; + NetCharKey char_key; + NetCharData char_data; +}; +static_assert(offsetof(NetPacket_Payload<0x2b01>, magic_packet_id) == 0, "offsetof(NetPacket_Payload<0x2b01>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Payload<0x2b01>, magic_packet_length) == 2, "offsetof(NetPacket_Payload<0x2b01>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Payload<0x2b01>, account_id) == 4, "offsetof(NetPacket_Payload<0x2b01>, account_id) == 4"); +static_assert(offsetof(NetPacket_Payload<0x2b01>, char_id) == 8, "offsetof(NetPacket_Payload<0x2b01>, char_id) == 8"); +static_assert(offsetof(NetPacket_Payload<0x2b01>, char_key) == 12, "offsetof(NetPacket_Payload<0x2b01>, char_key) == 12"); +static_assert(alignof(NetPacket_Payload<0x2b01>) == 1, "alignof(NetPacket_Payload<0x2b01>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b02> +{ + Little16 magic_packet_id; + Little32 account_id; + Little32 login_id1; + Little32 login_id2; + IP4Address ip; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b02>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b02>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b02>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2b02>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2b02>, login_id1) == 6, "offsetof(NetPacket_Fixed<0x2b02>, login_id1) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2b02>, login_id2) == 10, "offsetof(NetPacket_Fixed<0x2b02>, login_id2) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x2b02>, ip) == 14, "offsetof(NetPacket_Fixed<0x2b02>, ip) == 14"); +static_assert(sizeof(NetPacket_Fixed<0x2b02>) == 18, "sizeof(NetPacket_Fixed<0x2b02>) == 18"); +static_assert(alignof(NetPacket_Fixed<0x2b02>) == 1, "alignof(NetPacket_Fixed<0x2b02>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b03> +{ + Little16 magic_packet_id; + Little32 account_id; + Byte unknown; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b03>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b03>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b03>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2b03>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2b03>, unknown) == 6, "offsetof(NetPacket_Fixed<0x2b03>, unknown) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x2b03>) == 7, "sizeof(NetPacket_Fixed<0x2b03>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x2b03>) == 1, "alignof(NetPacket_Fixed<0x2b03>) == 1"); + +template<> +struct NetPacket_Head<0x2b04> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + IP4Address ip; + Little16 port; +}; +static_assert(offsetof(NetPacket_Head<0x2b04>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2b04>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2b04>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x2b04>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x2b04>, ip) == 4, "offsetof(NetPacket_Head<0x2b04>, ip) == 4"); +static_assert(offsetof(NetPacket_Head<0x2b04>, port) == 8, "offsetof(NetPacket_Head<0x2b04>, port) == 8"); +static_assert(sizeof(NetPacket_Head<0x2b04>) == 10, "sizeof(NetPacket_Head<0x2b04>) == 10"); +static_assert(alignof(NetPacket_Head<0x2b04>) == 1, "alignof(NetPacket_Head<0x2b04>) == 1"); +template<> +struct NetPacket_Repeat<0x2b04> +{ + NetString<sizeof(MapName)> map_name; +}; +static_assert(offsetof(NetPacket_Repeat<0x2b04>, map_name) == 0, "offsetof(NetPacket_Repeat<0x2b04>, map_name) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x2b04>) == 16, "sizeof(NetPacket_Repeat<0x2b04>) == 16"); +static_assert(alignof(NetPacket_Repeat<0x2b04>) == 1, "alignof(NetPacket_Repeat<0x2b04>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b05> +{ + Little16 magic_packet_id; + Little32 account_id; + Little32 login_id1; + Little32 login_id2; + Little32 char_id; + NetString<sizeof(MapName)> map_name; + Little16 x; + Little16 y; + IP4Address map_ip; + Little16 map_port; + Byte sex; + IP4Address client_ip; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b05>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b05>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b05>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2b05>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2b05>, login_id1) == 6, "offsetof(NetPacket_Fixed<0x2b05>, login_id1) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2b05>, login_id2) == 10, "offsetof(NetPacket_Fixed<0x2b05>, login_id2) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x2b05>, char_id) == 14, "offsetof(NetPacket_Fixed<0x2b05>, char_id) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x2b05>, map_name) == 18, "offsetof(NetPacket_Fixed<0x2b05>, map_name) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x2b05>, x) == 34, "offsetof(NetPacket_Fixed<0x2b05>, x) == 34"); +static_assert(offsetof(NetPacket_Fixed<0x2b05>, y) == 36, "offsetof(NetPacket_Fixed<0x2b05>, y) == 36"); +static_assert(offsetof(NetPacket_Fixed<0x2b05>, map_ip) == 38, "offsetof(NetPacket_Fixed<0x2b05>, map_ip) == 38"); +static_assert(offsetof(NetPacket_Fixed<0x2b05>, map_port) == 42, "offsetof(NetPacket_Fixed<0x2b05>, map_port) == 42"); +static_assert(offsetof(NetPacket_Fixed<0x2b05>, sex) == 44, "offsetof(NetPacket_Fixed<0x2b05>, sex) == 44"); +static_assert(offsetof(NetPacket_Fixed<0x2b05>, client_ip) == 45, "offsetof(NetPacket_Fixed<0x2b05>, client_ip) == 45"); +static_assert(sizeof(NetPacket_Fixed<0x2b05>) == 49, "sizeof(NetPacket_Fixed<0x2b05>) == 49"); +static_assert(alignof(NetPacket_Fixed<0x2b05>) == 1, "alignof(NetPacket_Fixed<0x2b05>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b06> +{ + Little16 magic_packet_id; + Little32 account_id; + Little32 error; + Little32 unknown; + Little32 char_id; + NetString<sizeof(MapName)> map_name; + Little16 x; + Little16 y; + IP4Address map_ip; + Little16 map_port; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b06>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b06>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b06>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2b06>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2b06>, error) == 6, "offsetof(NetPacket_Fixed<0x2b06>, error) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2b06>, unknown) == 10, "offsetof(NetPacket_Fixed<0x2b06>, unknown) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x2b06>, char_id) == 14, "offsetof(NetPacket_Fixed<0x2b06>, char_id) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x2b06>, map_name) == 18, "offsetof(NetPacket_Fixed<0x2b06>, map_name) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x2b06>, x) == 34, "offsetof(NetPacket_Fixed<0x2b06>, x) == 34"); +static_assert(offsetof(NetPacket_Fixed<0x2b06>, y) == 36, "offsetof(NetPacket_Fixed<0x2b06>, y) == 36"); +static_assert(offsetof(NetPacket_Fixed<0x2b06>, map_ip) == 38, "offsetof(NetPacket_Fixed<0x2b06>, map_ip) == 38"); +static_assert(offsetof(NetPacket_Fixed<0x2b06>, map_port) == 42, "offsetof(NetPacket_Fixed<0x2b06>, map_port) == 42"); +static_assert(sizeof(NetPacket_Fixed<0x2b06>) == 44, "sizeof(NetPacket_Fixed<0x2b06>) == 44"); +static_assert(alignof(NetPacket_Fixed<0x2b06>) == 1, "alignof(NetPacket_Fixed<0x2b06>) == 1"); + +template<> +struct NetPacket_Head<0x2b0a> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Head<0x2b0a>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2b0a>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2b0a>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x2b0a>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x2b0a>, account_id) == 4, "offsetof(NetPacket_Head<0x2b0a>, account_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x2b0a>) == 8, "sizeof(NetPacket_Head<0x2b0a>) == 8"); +static_assert(alignof(NetPacket_Head<0x2b0a>) == 1, "alignof(NetPacket_Head<0x2b0a>) == 1"); +template<> +struct NetPacket_Repeat<0x2b0a> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x2b0a>, c) == 0, "offsetof(NetPacket_Repeat<0x2b0a>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x2b0a>) == 1, "sizeof(NetPacket_Repeat<0x2b0a>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x2b0a>) == 1, "alignof(NetPacket_Repeat<0x2b0a>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b0b> +{ + Little16 magic_packet_id; + Little32 account_id; + Little32 gm_level; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b0b>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b0b>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b0b>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2b0b>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2b0b>, gm_level) == 6, "offsetof(NetPacket_Fixed<0x2b0b>, gm_level) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x2b0b>) == 10, "sizeof(NetPacket_Fixed<0x2b0b>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x2b0b>) == 1, "alignof(NetPacket_Fixed<0x2b0b>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b0c> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountEmail)> old_email; + NetString<sizeof(AccountEmail)> new_email; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b0c>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b0c>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b0c>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2b0c>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2b0c>, old_email) == 6, "offsetof(NetPacket_Fixed<0x2b0c>, old_email) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2b0c>, new_email) == 46, "offsetof(NetPacket_Fixed<0x2b0c>, new_email) == 46"); +static_assert(sizeof(NetPacket_Fixed<0x2b0c>) == 86, "sizeof(NetPacket_Fixed<0x2b0c>) == 86"); +static_assert(alignof(NetPacket_Fixed<0x2b0c>) == 1, "alignof(NetPacket_Fixed<0x2b0c>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b0d> +{ + Little16 magic_packet_id; + Little32 account_id; + Byte sex; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b0d>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b0d>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b0d>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2b0d>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2b0d>, sex) == 6, "offsetof(NetPacket_Fixed<0x2b0d>, sex) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x2b0d>) == 7, "sizeof(NetPacket_Fixed<0x2b0d>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x2b0d>) == 1, "alignof(NetPacket_Fixed<0x2b0d>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b0e> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(CharName)> char_name; + Little16 operation; + NetHumanTimeDiff ban_add; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b0e>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b0e>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b0e>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2b0e>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2b0e>, char_name) == 6, "offsetof(NetPacket_Fixed<0x2b0e>, char_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2b0e>, operation) == 30, "offsetof(NetPacket_Fixed<0x2b0e>, operation) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x2b0e>, ban_add) == 32, "offsetof(NetPacket_Fixed<0x2b0e>, ban_add) == 32"); +static_assert(sizeof(NetPacket_Fixed<0x2b0e>) == 44, "sizeof(NetPacket_Fixed<0x2b0e>) == 44"); +static_assert(alignof(NetPacket_Fixed<0x2b0e>) == 1, "alignof(NetPacket_Fixed<0x2b0e>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b0f> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(CharName)> char_name; + Little16 operation; + Little16 error; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b0f>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b0f>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b0f>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2b0f>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2b0f>, char_name) == 6, "offsetof(NetPacket_Fixed<0x2b0f>, char_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2b0f>, operation) == 30, "offsetof(NetPacket_Fixed<0x2b0f>, operation) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x2b0f>, error) == 32, "offsetof(NetPacket_Fixed<0x2b0f>, error) == 32"); +static_assert(sizeof(NetPacket_Fixed<0x2b0f>) == 34, "sizeof(NetPacket_Fixed<0x2b0f>) == 34"); +static_assert(alignof(NetPacket_Fixed<0x2b0f>) == 1, "alignof(NetPacket_Fixed<0x2b0f>) == 1"); + +template<> +struct NetPacket_Head<0x2b10> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Head<0x2b10>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2b10>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2b10>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x2b10>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x2b10>, account_id) == 4, "offsetof(NetPacket_Head<0x2b10>, account_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x2b10>) == 8, "sizeof(NetPacket_Head<0x2b10>) == 8"); +static_assert(alignof(NetPacket_Head<0x2b10>) == 1, "alignof(NetPacket_Head<0x2b10>) == 1"); +template<> +struct NetPacket_Repeat<0x2b10> +{ + NetString<sizeof(VarName)> name; + Little32 value; +}; +static_assert(offsetof(NetPacket_Repeat<0x2b10>, name) == 0, "offsetof(NetPacket_Repeat<0x2b10>, name) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x2b10>, value) == 32, "offsetof(NetPacket_Repeat<0x2b10>, value) == 32"); +static_assert(sizeof(NetPacket_Repeat<0x2b10>) == 36, "sizeof(NetPacket_Repeat<0x2b10>) == 36"); +static_assert(alignof(NetPacket_Repeat<0x2b10>) == 1, "alignof(NetPacket_Repeat<0x2b10>) == 1"); + +template<> +struct NetPacket_Head<0x2b11> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Head<0x2b11>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2b11>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2b11>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x2b11>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x2b11>, account_id) == 4, "offsetof(NetPacket_Head<0x2b11>, account_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x2b11>) == 8, "sizeof(NetPacket_Head<0x2b11>) == 8"); +static_assert(alignof(NetPacket_Head<0x2b11>) == 1, "alignof(NetPacket_Head<0x2b11>) == 1"); +template<> +struct NetPacket_Repeat<0x2b11> +{ + NetString<sizeof(VarName)> name; + Little32 value; +}; +static_assert(offsetof(NetPacket_Repeat<0x2b11>, name) == 0, "offsetof(NetPacket_Repeat<0x2b11>, name) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x2b11>, value) == 32, "offsetof(NetPacket_Repeat<0x2b11>, value) == 32"); +static_assert(sizeof(NetPacket_Repeat<0x2b11>) == 36, "sizeof(NetPacket_Repeat<0x2b11>) == 36"); +static_assert(alignof(NetPacket_Repeat<0x2b11>) == 1, "alignof(NetPacket_Repeat<0x2b11>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b12> +{ + Little16 magic_packet_id; + Little32 char_id; + Little32 partner_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b12>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b12>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b12>, char_id) == 2, "offsetof(NetPacket_Fixed<0x2b12>, char_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2b12>, partner_id) == 6, "offsetof(NetPacket_Fixed<0x2b12>, partner_id) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x2b12>) == 10, "sizeof(NetPacket_Fixed<0x2b12>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x2b12>) == 1, "alignof(NetPacket_Fixed<0x2b12>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b13> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b13>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b13>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b13>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2b13>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x2b13>) == 6, "sizeof(NetPacket_Fixed<0x2b13>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x2b13>) == 1, "alignof(NetPacket_Fixed<0x2b13>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b14> +{ + Little16 magic_packet_id; + Little32 account_id; + Byte ban_not_status; + Little32 status_or_ban_until; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b14>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b14>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b14>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2b14>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2b14>, ban_not_status) == 6, "offsetof(NetPacket_Fixed<0x2b14>, ban_not_status) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2b14>, status_or_ban_until) == 7, "offsetof(NetPacket_Fixed<0x2b14>, status_or_ban_until) == 7"); +static_assert(sizeof(NetPacket_Fixed<0x2b14>) == 11, "sizeof(NetPacket_Fixed<0x2b14>) == 11"); +static_assert(alignof(NetPacket_Fixed<0x2b14>) == 1, "alignof(NetPacket_Fixed<0x2b14>) == 1"); + +template<> +struct NetPacket_Head<0x2b15> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x2b15>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2b15>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2b15>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x2b15>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x2b15>) == 4, "sizeof(NetPacket_Head<0x2b15>) == 4"); +static_assert(alignof(NetPacket_Head<0x2b15>) == 1, "alignof(NetPacket_Head<0x2b15>) == 1"); +template<> +struct NetPacket_Repeat<0x2b15> +{ + Little32 account_id; + Byte gm_level; +}; +static_assert(offsetof(NetPacket_Repeat<0x2b15>, account_id) == 0, "offsetof(NetPacket_Repeat<0x2b15>, account_id) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x2b15>, gm_level) == 4, "offsetof(NetPacket_Repeat<0x2b15>, gm_level) == 4"); +static_assert(sizeof(NetPacket_Repeat<0x2b15>) == 5, "sizeof(NetPacket_Repeat<0x2b15>) == 5"); +static_assert(alignof(NetPacket_Repeat<0x2b15>) == 1, "alignof(NetPacket_Repeat<0x2b15>) == 1"); + +template<> +struct NetPacket_Fixed<0x2b16> +{ + Little16 magic_packet_id; + Little32 char_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x2b16>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2b16>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2b16>, char_id) == 2, "offsetof(NetPacket_Fixed<0x2b16>, char_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x2b16>) == 6, "sizeof(NetPacket_Fixed<0x2b16>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x2b16>) == 1, "alignof(NetPacket_Fixed<0x2b16>) == 1"); + +template<> +struct NetPacket_Head<0x3000> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x3000>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x3000>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x3000>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x3000>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x3000>) == 4, "sizeof(NetPacket_Head<0x3000>) == 4"); +static_assert(alignof(NetPacket_Head<0x3000>) == 1, "alignof(NetPacket_Head<0x3000>) == 1"); +template<> +struct NetPacket_Repeat<0x3000> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x3000>, c) == 0, "offsetof(NetPacket_Repeat<0x3000>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x3000>) == 1, "sizeof(NetPacket_Repeat<0x3000>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x3000>) == 1, "alignof(NetPacket_Repeat<0x3000>) == 1"); + +template<> +struct NetPacket_Head<0x3001> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + NetString<sizeof(CharName)> from_char_name; + NetString<sizeof(CharName)> to_char_name; +}; +static_assert(offsetof(NetPacket_Head<0x3001>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x3001>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x3001>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x3001>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x3001>, from_char_name) == 4, "offsetof(NetPacket_Head<0x3001>, from_char_name) == 4"); +static_assert(offsetof(NetPacket_Head<0x3001>, to_char_name) == 28, "offsetof(NetPacket_Head<0x3001>, to_char_name) == 28"); +static_assert(sizeof(NetPacket_Head<0x3001>) == 52, "sizeof(NetPacket_Head<0x3001>) == 52"); +static_assert(alignof(NetPacket_Head<0x3001>) == 1, "alignof(NetPacket_Head<0x3001>) == 1"); +template<> +struct NetPacket_Repeat<0x3001> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x3001>, c) == 0, "offsetof(NetPacket_Repeat<0x3001>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x3001>) == 1, "sizeof(NetPacket_Repeat<0x3001>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x3001>) == 1, "alignof(NetPacket_Repeat<0x3001>) == 1"); + +template<> +struct NetPacket_Fixed<0x3002> +{ + Little16 magic_packet_id; + Little32 char_id; + Byte flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x3002>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3002>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3002>, char_id) == 2, "offsetof(NetPacket_Fixed<0x3002>, char_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3002>, flag) == 6, "offsetof(NetPacket_Fixed<0x3002>, flag) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x3002>) == 7, "sizeof(NetPacket_Fixed<0x3002>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x3002>) == 1, "alignof(NetPacket_Fixed<0x3002>) == 1"); + +template<> +struct NetPacket_Head<0x3003> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + NetString<sizeof(CharName)> char_name; + Little16 min_gm_level; +}; +static_assert(offsetof(NetPacket_Head<0x3003>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x3003>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x3003>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x3003>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x3003>, char_name) == 4, "offsetof(NetPacket_Head<0x3003>, char_name) == 4"); +static_assert(offsetof(NetPacket_Head<0x3003>, min_gm_level) == 28, "offsetof(NetPacket_Head<0x3003>, min_gm_level) == 28"); +static_assert(sizeof(NetPacket_Head<0x3003>) == 30, "sizeof(NetPacket_Head<0x3003>) == 30"); +static_assert(alignof(NetPacket_Head<0x3003>) == 1, "alignof(NetPacket_Head<0x3003>) == 1"); +template<> +struct NetPacket_Repeat<0x3003> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x3003>, c) == 0, "offsetof(NetPacket_Repeat<0x3003>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x3003>) == 1, "sizeof(NetPacket_Repeat<0x3003>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x3003>) == 1, "alignof(NetPacket_Repeat<0x3003>) == 1"); + +template<> +struct NetPacket_Head<0x3004> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Head<0x3004>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x3004>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x3004>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x3004>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x3004>, account_id) == 4, "offsetof(NetPacket_Head<0x3004>, account_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x3004>) == 8, "sizeof(NetPacket_Head<0x3004>) == 8"); +static_assert(alignof(NetPacket_Head<0x3004>) == 1, "alignof(NetPacket_Head<0x3004>) == 1"); +template<> +struct NetPacket_Repeat<0x3004> +{ + NetString<sizeof(VarName)> name; + Little32 value; +}; +static_assert(offsetof(NetPacket_Repeat<0x3004>, name) == 0, "offsetof(NetPacket_Repeat<0x3004>, name) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x3004>, value) == 32, "offsetof(NetPacket_Repeat<0x3004>, value) == 32"); +static_assert(sizeof(NetPacket_Repeat<0x3004>) == 36, "sizeof(NetPacket_Repeat<0x3004>) == 36"); +static_assert(alignof(NetPacket_Repeat<0x3004>) == 1, "alignof(NetPacket_Repeat<0x3004>) == 1"); + +template<> +struct NetPacket_Fixed<0x3005> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x3005>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3005>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3005>, account_id) == 2, "offsetof(NetPacket_Fixed<0x3005>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x3005>) == 6, "sizeof(NetPacket_Fixed<0x3005>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x3005>) == 1, "alignof(NetPacket_Fixed<0x3005>) == 1"); + +template<> +struct NetPacket_Fixed<0x3010> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x3010>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3010>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3010>, account_id) == 2, "offsetof(NetPacket_Fixed<0x3010>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x3010>) == 6, "sizeof(NetPacket_Fixed<0x3010>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x3010>) == 1, "alignof(NetPacket_Fixed<0x3010>) == 1"); + +template<> +struct NetPacket_Payload<0x3011> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; + NetStorage storage; +}; +static_assert(offsetof(NetPacket_Payload<0x3011>, magic_packet_id) == 0, "offsetof(NetPacket_Payload<0x3011>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Payload<0x3011>, magic_packet_length) == 2, "offsetof(NetPacket_Payload<0x3011>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Payload<0x3011>, account_id) == 4, "offsetof(NetPacket_Payload<0x3011>, account_id) == 4"); +static_assert(offsetof(NetPacket_Payload<0x3011>, storage) == 8, "offsetof(NetPacket_Payload<0x3011>, storage) == 8"); +static_assert(alignof(NetPacket_Payload<0x3011>) == 1, "alignof(NetPacket_Payload<0x3011>) == 1"); + +template<> +struct NetPacket_Fixed<0x3020> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(PartyName)> party_name; + NetString<sizeof(CharName)> char_name; + NetString<sizeof(MapName)> map_name; + Little16 level; +}; +static_assert(offsetof(NetPacket_Fixed<0x3020>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3020>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3020>, account_id) == 2, "offsetof(NetPacket_Fixed<0x3020>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3020>, party_name) == 6, "offsetof(NetPacket_Fixed<0x3020>, party_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x3020>, char_name) == 30, "offsetof(NetPacket_Fixed<0x3020>, char_name) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x3020>, map_name) == 54, "offsetof(NetPacket_Fixed<0x3020>, map_name) == 54"); +static_assert(offsetof(NetPacket_Fixed<0x3020>, level) == 70, "offsetof(NetPacket_Fixed<0x3020>, level) == 70"); +static_assert(sizeof(NetPacket_Fixed<0x3020>) == 72, "sizeof(NetPacket_Fixed<0x3020>) == 72"); +static_assert(alignof(NetPacket_Fixed<0x3020>) == 1, "alignof(NetPacket_Fixed<0x3020>) == 1"); + +template<> +struct NetPacket_Fixed<0x3021> +{ + Little16 magic_packet_id; + Little32 party_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x3021>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3021>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3021>, party_id) == 2, "offsetof(NetPacket_Fixed<0x3021>, party_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x3021>) == 6, "sizeof(NetPacket_Fixed<0x3021>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x3021>) == 1, "alignof(NetPacket_Fixed<0x3021>) == 1"); + +template<> +struct NetPacket_Fixed<0x3022> +{ + Little16 magic_packet_id; + Little32 party_id; + Little32 account_id; + NetString<sizeof(CharName)> char_name; + NetString<sizeof(MapName)> map_name; + Little16 level; +}; +static_assert(offsetof(NetPacket_Fixed<0x3022>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3022>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3022>, party_id) == 2, "offsetof(NetPacket_Fixed<0x3022>, party_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3022>, account_id) == 6, "offsetof(NetPacket_Fixed<0x3022>, account_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x3022>, char_name) == 10, "offsetof(NetPacket_Fixed<0x3022>, char_name) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x3022>, map_name) == 34, "offsetof(NetPacket_Fixed<0x3022>, map_name) == 34"); +static_assert(offsetof(NetPacket_Fixed<0x3022>, level) == 50, "offsetof(NetPacket_Fixed<0x3022>, level) == 50"); +static_assert(sizeof(NetPacket_Fixed<0x3022>) == 52, "sizeof(NetPacket_Fixed<0x3022>) == 52"); +static_assert(alignof(NetPacket_Fixed<0x3022>) == 1, "alignof(NetPacket_Fixed<0x3022>) == 1"); + +template<> +struct NetPacket_Fixed<0x3023> +{ + Little16 magic_packet_id; + Little32 party_id; + Little32 account_id; + Little16 exp; + Little16 item; +}; +static_assert(offsetof(NetPacket_Fixed<0x3023>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3023>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3023>, party_id) == 2, "offsetof(NetPacket_Fixed<0x3023>, party_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3023>, account_id) == 6, "offsetof(NetPacket_Fixed<0x3023>, account_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x3023>, exp) == 10, "offsetof(NetPacket_Fixed<0x3023>, exp) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x3023>, item) == 12, "offsetof(NetPacket_Fixed<0x3023>, item) == 12"); +static_assert(sizeof(NetPacket_Fixed<0x3023>) == 14, "sizeof(NetPacket_Fixed<0x3023>) == 14"); +static_assert(alignof(NetPacket_Fixed<0x3023>) == 1, "alignof(NetPacket_Fixed<0x3023>) == 1"); + +template<> +struct NetPacket_Fixed<0x3024> +{ + Little16 magic_packet_id; + Little32 party_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x3024>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3024>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3024>, party_id) == 2, "offsetof(NetPacket_Fixed<0x3024>, party_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3024>, account_id) == 6, "offsetof(NetPacket_Fixed<0x3024>, account_id) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x3024>) == 10, "sizeof(NetPacket_Fixed<0x3024>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x3024>) == 1, "alignof(NetPacket_Fixed<0x3024>) == 1"); + +template<> +struct NetPacket_Fixed<0x3025> +{ + Little16 magic_packet_id; + Little32 party_id; + Little32 account_id; + NetString<sizeof(MapName)> map_name; + Byte online; + Little16 level; +}; +static_assert(offsetof(NetPacket_Fixed<0x3025>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3025>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3025>, party_id) == 2, "offsetof(NetPacket_Fixed<0x3025>, party_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3025>, account_id) == 6, "offsetof(NetPacket_Fixed<0x3025>, account_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x3025>, map_name) == 10, "offsetof(NetPacket_Fixed<0x3025>, map_name) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x3025>, online) == 26, "offsetof(NetPacket_Fixed<0x3025>, online) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x3025>, level) == 27, "offsetof(NetPacket_Fixed<0x3025>, level) == 27"); +static_assert(sizeof(NetPacket_Fixed<0x3025>) == 29, "sizeof(NetPacket_Fixed<0x3025>) == 29"); +static_assert(alignof(NetPacket_Fixed<0x3025>) == 1, "alignof(NetPacket_Fixed<0x3025>) == 1"); + +template<> +struct NetPacket_Head<0x3027> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 party_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Head<0x3027>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x3027>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x3027>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x3027>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x3027>, party_id) == 4, "offsetof(NetPacket_Head<0x3027>, party_id) == 4"); +static_assert(offsetof(NetPacket_Head<0x3027>, account_id) == 8, "offsetof(NetPacket_Head<0x3027>, account_id) == 8"); +static_assert(sizeof(NetPacket_Head<0x3027>) == 12, "sizeof(NetPacket_Head<0x3027>) == 12"); +static_assert(alignof(NetPacket_Head<0x3027>) == 1, "alignof(NetPacket_Head<0x3027>) == 1"); +template<> +struct NetPacket_Repeat<0x3027> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x3027>, c) == 0, "offsetof(NetPacket_Repeat<0x3027>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x3027>) == 1, "sizeof(NetPacket_Repeat<0x3027>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x3027>) == 1, "alignof(NetPacket_Repeat<0x3027>) == 1"); + +template<> +struct NetPacket_Fixed<0x3028> +{ + Little16 magic_packet_id; + Little32 party_id; + Little32 account_id; + NetString<sizeof(CharName)> char_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x3028>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3028>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3028>, party_id) == 2, "offsetof(NetPacket_Fixed<0x3028>, party_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3028>, account_id) == 6, "offsetof(NetPacket_Fixed<0x3028>, account_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x3028>, char_name) == 10, "offsetof(NetPacket_Fixed<0x3028>, char_name) == 10"); +static_assert(sizeof(NetPacket_Fixed<0x3028>) == 34, "sizeof(NetPacket_Fixed<0x3028>) == 34"); +static_assert(alignof(NetPacket_Fixed<0x3028>) == 1, "alignof(NetPacket_Fixed<0x3028>) == 1"); + +template<> +struct NetPacket_Head<0x3800> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x3800>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x3800>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x3800>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x3800>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x3800>) == 4, "sizeof(NetPacket_Head<0x3800>) == 4"); +static_assert(alignof(NetPacket_Head<0x3800>) == 1, "alignof(NetPacket_Head<0x3800>) == 1"); +template<> +struct NetPacket_Repeat<0x3800> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x3800>, c) == 0, "offsetof(NetPacket_Repeat<0x3800>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x3800>) == 1, "sizeof(NetPacket_Repeat<0x3800>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x3800>) == 1, "alignof(NetPacket_Repeat<0x3800>) == 1"); + +template<> +struct NetPacket_Head<0x3801> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 whisper_id; + NetString<sizeof(CharName)> src_char_name; + NetString<sizeof(CharName)> dst_char_name; +}; +static_assert(offsetof(NetPacket_Head<0x3801>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x3801>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x3801>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x3801>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x3801>, whisper_id) == 4, "offsetof(NetPacket_Head<0x3801>, whisper_id) == 4"); +static_assert(offsetof(NetPacket_Head<0x3801>, src_char_name) == 8, "offsetof(NetPacket_Head<0x3801>, src_char_name) == 8"); +static_assert(offsetof(NetPacket_Head<0x3801>, dst_char_name) == 32, "offsetof(NetPacket_Head<0x3801>, dst_char_name) == 32"); +static_assert(sizeof(NetPacket_Head<0x3801>) == 56, "sizeof(NetPacket_Head<0x3801>) == 56"); +static_assert(alignof(NetPacket_Head<0x3801>) == 1, "alignof(NetPacket_Head<0x3801>) == 1"); +template<> +struct NetPacket_Repeat<0x3801> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x3801>, c) == 0, "offsetof(NetPacket_Repeat<0x3801>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x3801>) == 1, "sizeof(NetPacket_Repeat<0x3801>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x3801>) == 1, "alignof(NetPacket_Repeat<0x3801>) == 1"); + +template<> +struct NetPacket_Fixed<0x3802> +{ + Little16 magic_packet_id; + NetString<sizeof(CharName)> sender_char_name; + Byte flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x3802>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3802>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3802>, sender_char_name) == 2, "offsetof(NetPacket_Fixed<0x3802>, sender_char_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3802>, flag) == 26, "offsetof(NetPacket_Fixed<0x3802>, flag) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x3802>) == 27, "sizeof(NetPacket_Fixed<0x3802>) == 27"); +static_assert(alignof(NetPacket_Fixed<0x3802>) == 1, "alignof(NetPacket_Fixed<0x3802>) == 1"); + +template<> +struct NetPacket_Head<0x3803> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + NetString<sizeof(CharName)> char_name; + Little16 min_gm_level; +}; +static_assert(offsetof(NetPacket_Head<0x3803>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x3803>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x3803>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x3803>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x3803>, char_name) == 4, "offsetof(NetPacket_Head<0x3803>, char_name) == 4"); +static_assert(offsetof(NetPacket_Head<0x3803>, min_gm_level) == 28, "offsetof(NetPacket_Head<0x3803>, min_gm_level) == 28"); +static_assert(sizeof(NetPacket_Head<0x3803>) == 30, "sizeof(NetPacket_Head<0x3803>) == 30"); +static_assert(alignof(NetPacket_Head<0x3803>) == 1, "alignof(NetPacket_Head<0x3803>) == 1"); +template<> +struct NetPacket_Repeat<0x3803> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x3803>, c) == 0, "offsetof(NetPacket_Repeat<0x3803>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x3803>) == 1, "sizeof(NetPacket_Repeat<0x3803>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x3803>) == 1, "alignof(NetPacket_Repeat<0x3803>) == 1"); + +template<> +struct NetPacket_Head<0x3804> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Head<0x3804>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x3804>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x3804>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x3804>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x3804>, account_id) == 4, "offsetof(NetPacket_Head<0x3804>, account_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x3804>) == 8, "sizeof(NetPacket_Head<0x3804>) == 8"); +static_assert(alignof(NetPacket_Head<0x3804>) == 1, "alignof(NetPacket_Head<0x3804>) == 1"); +template<> +struct NetPacket_Repeat<0x3804> +{ + NetString<sizeof(VarName)> name; + Little32 value; +}; +static_assert(offsetof(NetPacket_Repeat<0x3804>, name) == 0, "offsetof(NetPacket_Repeat<0x3804>, name) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x3804>, value) == 32, "offsetof(NetPacket_Repeat<0x3804>, value) == 32"); +static_assert(sizeof(NetPacket_Repeat<0x3804>) == 36, "sizeof(NetPacket_Repeat<0x3804>) == 36"); +static_assert(alignof(NetPacket_Repeat<0x3804>) == 1, "alignof(NetPacket_Repeat<0x3804>) == 1"); + +template<> +struct NetPacket_Payload<0x3810> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; + NetStorage storage; +}; +static_assert(offsetof(NetPacket_Payload<0x3810>, magic_packet_id) == 0, "offsetof(NetPacket_Payload<0x3810>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Payload<0x3810>, magic_packet_length) == 2, "offsetof(NetPacket_Payload<0x3810>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Payload<0x3810>, account_id) == 4, "offsetof(NetPacket_Payload<0x3810>, account_id) == 4"); +static_assert(offsetof(NetPacket_Payload<0x3810>, storage) == 8, "offsetof(NetPacket_Payload<0x3810>, storage) == 8"); +static_assert(alignof(NetPacket_Payload<0x3810>) == 1, "alignof(NetPacket_Payload<0x3810>) == 1"); + +template<> +struct NetPacket_Fixed<0x3811> +{ + Little16 magic_packet_id; + Little32 account_id; + Byte unknown; +}; +static_assert(offsetof(NetPacket_Fixed<0x3811>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3811>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3811>, account_id) == 2, "offsetof(NetPacket_Fixed<0x3811>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3811>, unknown) == 6, "offsetof(NetPacket_Fixed<0x3811>, unknown) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x3811>) == 7, "sizeof(NetPacket_Fixed<0x3811>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x3811>) == 1, "alignof(NetPacket_Fixed<0x3811>) == 1"); + +template<> +struct NetPacket_Fixed<0x3820> +{ + Little16 magic_packet_id; + Little32 account_id; + Byte error; + Little32 party_id; + NetString<sizeof(PartyName)> party_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x3820>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3820>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3820>, account_id) == 2, "offsetof(NetPacket_Fixed<0x3820>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3820>, error) == 6, "offsetof(NetPacket_Fixed<0x3820>, error) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x3820>, party_id) == 7, "offsetof(NetPacket_Fixed<0x3820>, party_id) == 7"); +static_assert(offsetof(NetPacket_Fixed<0x3820>, party_name) == 11, "offsetof(NetPacket_Fixed<0x3820>, party_name) == 11"); +static_assert(sizeof(NetPacket_Fixed<0x3820>) == 35, "sizeof(NetPacket_Fixed<0x3820>) == 35"); +static_assert(alignof(NetPacket_Fixed<0x3820>) == 1, "alignof(NetPacket_Fixed<0x3820>) == 1"); + +template<> +struct NetPacket_Head<0x3821> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 party_id; +}; +static_assert(offsetof(NetPacket_Head<0x3821>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x3821>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x3821>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x3821>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x3821>, party_id) == 4, "offsetof(NetPacket_Head<0x3821>, party_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x3821>) == 8, "sizeof(NetPacket_Head<0x3821>) == 8"); +static_assert(alignof(NetPacket_Head<0x3821>) == 1, "alignof(NetPacket_Head<0x3821>) == 1"); +template<> +struct NetPacket_Option<0x3821> +{ + NetPartyMost party_most; +}; +static_assert(offsetof(NetPacket_Option<0x3821>, party_most) == 0, "offsetof(NetPacket_Option<0x3821>, party_most) == 0"); +static_assert(alignof(NetPacket_Option<0x3821>) == 1, "alignof(NetPacket_Option<0x3821>) == 1"); + +template<> +struct NetPacket_Fixed<0x3822> +{ + Little16 magic_packet_id; + Little32 party_id; + Little32 account_id; + Byte flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x3822>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3822>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3822>, party_id) == 2, "offsetof(NetPacket_Fixed<0x3822>, party_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3822>, account_id) == 6, "offsetof(NetPacket_Fixed<0x3822>, account_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x3822>, flag) == 10, "offsetof(NetPacket_Fixed<0x3822>, flag) == 10"); +static_assert(sizeof(NetPacket_Fixed<0x3822>) == 11, "sizeof(NetPacket_Fixed<0x3822>) == 11"); +static_assert(alignof(NetPacket_Fixed<0x3822>) == 1, "alignof(NetPacket_Fixed<0x3822>) == 1"); + +template<> +struct NetPacket_Fixed<0x3823> +{ + Little16 magic_packet_id; + Little32 party_id; + Little32 account_id; + Little16 exp; + Little16 item; + Byte flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x3823>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3823>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3823>, party_id) == 2, "offsetof(NetPacket_Fixed<0x3823>, party_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3823>, account_id) == 6, "offsetof(NetPacket_Fixed<0x3823>, account_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x3823>, exp) == 10, "offsetof(NetPacket_Fixed<0x3823>, exp) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x3823>, item) == 12, "offsetof(NetPacket_Fixed<0x3823>, item) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x3823>, flag) == 14, "offsetof(NetPacket_Fixed<0x3823>, flag) == 14"); +static_assert(sizeof(NetPacket_Fixed<0x3823>) == 15, "sizeof(NetPacket_Fixed<0x3823>) == 15"); +static_assert(alignof(NetPacket_Fixed<0x3823>) == 1, "alignof(NetPacket_Fixed<0x3823>) == 1"); + +template<> +struct NetPacket_Fixed<0x3824> +{ + Little16 magic_packet_id; + Little32 party_id; + Little32 account_id; + NetString<sizeof(CharName)> char_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x3824>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3824>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3824>, party_id) == 2, "offsetof(NetPacket_Fixed<0x3824>, party_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3824>, account_id) == 6, "offsetof(NetPacket_Fixed<0x3824>, account_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x3824>, char_name) == 10, "offsetof(NetPacket_Fixed<0x3824>, char_name) == 10"); +static_assert(sizeof(NetPacket_Fixed<0x3824>) == 34, "sizeof(NetPacket_Fixed<0x3824>) == 34"); +static_assert(alignof(NetPacket_Fixed<0x3824>) == 1, "alignof(NetPacket_Fixed<0x3824>) == 1"); + +template<> +struct NetPacket_Fixed<0x3825> +{ + Little16 magic_packet_id; + Little32 party_id; + Little32 account_id; + NetString<sizeof(MapName)> map_name; + Byte online; + Little16 level; +}; +static_assert(offsetof(NetPacket_Fixed<0x3825>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3825>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3825>, party_id) == 2, "offsetof(NetPacket_Fixed<0x3825>, party_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3825>, account_id) == 6, "offsetof(NetPacket_Fixed<0x3825>, account_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x3825>, map_name) == 10, "offsetof(NetPacket_Fixed<0x3825>, map_name) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x3825>, online) == 26, "offsetof(NetPacket_Fixed<0x3825>, online) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x3825>, level) == 27, "offsetof(NetPacket_Fixed<0x3825>, level) == 27"); +static_assert(sizeof(NetPacket_Fixed<0x3825>) == 29, "sizeof(NetPacket_Fixed<0x3825>) == 29"); +static_assert(alignof(NetPacket_Fixed<0x3825>) == 1, "alignof(NetPacket_Fixed<0x3825>) == 1"); + +template<> +struct NetPacket_Fixed<0x3826> +{ + Little16 magic_packet_id; + Little32 party_id; + Byte flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x3826>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x3826>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x3826>, party_id) == 2, "offsetof(NetPacket_Fixed<0x3826>, party_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x3826>, flag) == 6, "offsetof(NetPacket_Fixed<0x3826>, flag) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x3826>) == 7, "sizeof(NetPacket_Fixed<0x3826>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x3826>) == 1, "alignof(NetPacket_Fixed<0x3826>) == 1"); + +template<> +struct NetPacket_Head<0x3827> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 party_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Head<0x3827>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x3827>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x3827>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x3827>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x3827>, party_id) == 4, "offsetof(NetPacket_Head<0x3827>, party_id) == 4"); +static_assert(offsetof(NetPacket_Head<0x3827>, account_id) == 8, "offsetof(NetPacket_Head<0x3827>, account_id) == 8"); +static_assert(sizeof(NetPacket_Head<0x3827>) == 12, "sizeof(NetPacket_Head<0x3827>) == 12"); +static_assert(alignof(NetPacket_Head<0x3827>) == 1, "alignof(NetPacket_Head<0x3827>) == 1"); +template<> +struct NetPacket_Repeat<0x3827> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x3827>, c) == 0, "offsetof(NetPacket_Repeat<0x3827>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x3827>) == 1, "sizeof(NetPacket_Repeat<0x3827>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x3827>) == 1, "alignof(NetPacket_Repeat<0x3827>) == 1"); + + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2af7> *network, Packet_Fixed<0x2af7> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2af7> *native, NetPacket_Fixed<0x2af7> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2af8> *network, Packet_Fixed<0x2af8> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->account_pass, native.account_pass); + rv &= native_to_network(&network->unused, native.unused); + rv &= native_to_network(&network->ip, native.ip); + rv &= native_to_network(&network->port, native.port); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2af8> *native, NetPacket_Fixed<0x2af8> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->account_pass, network.account_pass); + rv &= network_to_native(&native->unused, network.unused); + rv &= network_to_native(&native->ip, network.ip); + rv &= network_to_native(&native->port, network.port); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2af9> *network, Packet_Fixed<0x2af9> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->code, native.code); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2af9> *native, NetPacket_Fixed<0x2af9> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->code, network.code); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2afa> *network, Packet_Head<0x2afa> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2afa> *native, NetPacket_Head<0x2afa> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2afa> *network, Packet_Repeat<0x2afa> native) +{ + bool rv = true; + rv &= native_to_network(&network->map_name, native.map_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2afa> *native, NetPacket_Repeat<0x2afa> network) +{ + bool rv = true; + rv &= network_to_native(&native->map_name, network.map_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2afa> *network, Packet_Fixed<0x2afa> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->source_item_id, native.source_item_id); + rv &= native_to_network(&network->dest_item_id, native.dest_item_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2afa> *native, NetPacket_Fixed<0x2afa> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->source_item_id, network.source_item_id); + rv &= network_to_native(&native->dest_item_id, network.dest_item_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2afb> *network, Packet_Fixed<0x2afb> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->unknown, native.unknown); + rv &= native_to_network(&network->whisper_name, native.whisper_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2afb> *native, NetPacket_Fixed<0x2afb> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->unknown, network.unknown); + rv &= network_to_native(&native->whisper_name, network.whisper_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2afc> *network, Packet_Fixed<0x2afc> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->char_id, native.char_id); + rv &= native_to_network(&network->login_id1, native.login_id1); + rv &= native_to_network(&network->login_id2, native.login_id2); + rv &= native_to_network(&network->ip, native.ip); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2afc> *native, NetPacket_Fixed<0x2afc> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->char_id, network.char_id); + rv &= network_to_native(&native->login_id1, network.login_id1); + rv &= network_to_native(&native->login_id2, network.login_id2); + rv &= network_to_native(&native->ip, network.ip); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Payload<0x2afd> *network, Packet_Payload<0x2afd> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->login_id2, native.login_id2); + rv &= native_to_network(&network->connect_until, native.connect_until); + rv &= native_to_network(&network->packet_tmw_version, native.packet_tmw_version); + rv &= native_to_network(&network->char_key, native.char_key); + rv &= native_to_network(&network->char_data, native.char_data); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Payload<0x2afd> *native, NetPacket_Payload<0x2afd> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->login_id2, network.login_id2); + rv &= network_to_native(&native->connect_until, network.connect_until); + rv &= network_to_native(&native->packet_tmw_version, network.packet_tmw_version); + rv &= network_to_native(&native->char_key, network.char_key); + rv &= network_to_native(&native->char_data, network.char_data); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2afe> *network, Packet_Fixed<0x2afe> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2afe> *native, NetPacket_Fixed<0x2afe> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2aff> *network, Packet_Head<0x2aff> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->users, native.users); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2aff> *native, NetPacket_Head<0x2aff> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->users, network.users); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2aff> *network, Packet_Repeat<0x2aff> native) +{ + bool rv = true; + rv &= native_to_network(&network->char_id, native.char_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2aff> *native, NetPacket_Repeat<0x2aff> network) +{ + bool rv = true; + rv &= network_to_native(&native->char_id, network.char_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b00> *network, Packet_Fixed<0x2b00> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->users, native.users); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b00> *native, NetPacket_Fixed<0x2b00> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->users, network.users); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Payload<0x2b01> *network, Packet_Payload<0x2b01> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->char_id, native.char_id); + rv &= native_to_network(&network->char_key, native.char_key); + rv &= native_to_network(&network->char_data, native.char_data); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Payload<0x2b01> *native, NetPacket_Payload<0x2b01> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->char_id, network.char_id); + rv &= network_to_native(&native->char_key, network.char_key); + rv &= network_to_native(&native->char_data, network.char_data); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b02> *network, Packet_Fixed<0x2b02> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->login_id1, native.login_id1); + rv &= native_to_network(&network->login_id2, native.login_id2); + rv &= native_to_network(&network->ip, native.ip); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b02> *native, NetPacket_Fixed<0x2b02> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->login_id1, network.login_id1); + rv &= network_to_native(&native->login_id2, network.login_id2); + rv &= network_to_native(&native->ip, network.ip); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b03> *network, Packet_Fixed<0x2b03> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->unknown, native.unknown); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b03> *native, NetPacket_Fixed<0x2b03> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->unknown, network.unknown); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2b04> *network, Packet_Head<0x2b04> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->ip, native.ip); + rv &= native_to_network(&network->port, native.port); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2b04> *native, NetPacket_Head<0x2b04> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->ip, network.ip); + rv &= network_to_native(&native->port, network.port); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2b04> *network, Packet_Repeat<0x2b04> native) +{ + bool rv = true; + rv &= native_to_network(&network->map_name, native.map_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2b04> *native, NetPacket_Repeat<0x2b04> network) +{ + bool rv = true; + rv &= network_to_native(&native->map_name, network.map_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b05> *network, Packet_Fixed<0x2b05> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->login_id1, native.login_id1); + rv &= native_to_network(&network->login_id2, native.login_id2); + rv &= native_to_network(&network->char_id, native.char_id); + rv &= native_to_network(&network->map_name, native.map_name); + rv &= native_to_network(&network->x, native.x); + rv &= native_to_network(&network->y, native.y); + rv &= native_to_network(&network->map_ip, native.map_ip); + rv &= native_to_network(&network->map_port, native.map_port); + rv &= native_to_network(&network->sex, native.sex); + rv &= native_to_network(&network->client_ip, native.client_ip); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b05> *native, NetPacket_Fixed<0x2b05> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->login_id1, network.login_id1); + rv &= network_to_native(&native->login_id2, network.login_id2); + rv &= network_to_native(&native->char_id, network.char_id); + rv &= network_to_native(&native->map_name, network.map_name); + rv &= network_to_native(&native->x, network.x); + rv &= network_to_native(&native->y, network.y); + rv &= network_to_native(&native->map_ip, network.map_ip); + rv &= network_to_native(&native->map_port, network.map_port); + rv &= network_to_native(&native->sex, network.sex); + rv &= network_to_native(&native->client_ip, network.client_ip); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b06> *network, Packet_Fixed<0x2b06> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->error, native.error); + rv &= native_to_network(&network->unknown, native.unknown); + rv &= native_to_network(&network->char_id, native.char_id); + rv &= native_to_network(&network->map_name, native.map_name); + rv &= native_to_network(&network->x, native.x); + rv &= native_to_network(&network->y, native.y); + rv &= native_to_network(&network->map_ip, native.map_ip); + rv &= native_to_network(&network->map_port, native.map_port); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b06> *native, NetPacket_Fixed<0x2b06> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->error, network.error); + rv &= network_to_native(&native->unknown, network.unknown); + rv &= network_to_native(&native->char_id, network.char_id); + rv &= network_to_native(&native->map_name, network.map_name); + rv &= network_to_native(&native->x, network.x); + rv &= network_to_native(&native->y, network.y); + rv &= network_to_native(&native->map_ip, network.map_ip); + rv &= network_to_native(&native->map_port, network.map_port); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2b0a> *network, Packet_Head<0x2b0a> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2b0a> *native, NetPacket_Head<0x2b0a> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2b0a> *network, Packet_Repeat<0x2b0a> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2b0a> *native, NetPacket_Repeat<0x2b0a> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b0b> *network, Packet_Fixed<0x2b0b> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->gm_level, native.gm_level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b0b> *native, NetPacket_Fixed<0x2b0b> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->gm_level, network.gm_level); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b0c> *network, Packet_Fixed<0x2b0c> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->old_email, native.old_email); + rv &= native_to_network(&network->new_email, native.new_email); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b0c> *native, NetPacket_Fixed<0x2b0c> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->old_email, network.old_email); + rv &= network_to_native(&native->new_email, network.new_email); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b0d> *network, Packet_Fixed<0x2b0d> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->sex, native.sex); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b0d> *native, NetPacket_Fixed<0x2b0d> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->sex, network.sex); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b0e> *network, Packet_Fixed<0x2b0e> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->char_name, native.char_name); + rv &= native_to_network(&network->operation, native.operation); + rv &= native_to_network(&network->ban_add, native.ban_add); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b0e> *native, NetPacket_Fixed<0x2b0e> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->char_name, network.char_name); + rv &= network_to_native(&native->operation, network.operation); + rv &= network_to_native(&native->ban_add, network.ban_add); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b0f> *network, Packet_Fixed<0x2b0f> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->char_name, native.char_name); + rv &= native_to_network(&network->operation, native.operation); + rv &= native_to_network(&network->error, native.error); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b0f> *native, NetPacket_Fixed<0x2b0f> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->char_name, network.char_name); + rv &= network_to_native(&native->operation, network.operation); + rv &= network_to_native(&native->error, network.error); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2b10> *network, Packet_Head<0x2b10> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2b10> *native, NetPacket_Head<0x2b10> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2b10> *network, Packet_Repeat<0x2b10> native) +{ + bool rv = true; + rv &= native_to_network(&network->name, native.name); + rv &= native_to_network(&network->value, native.value); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2b10> *native, NetPacket_Repeat<0x2b10> network) +{ + bool rv = true; + rv &= network_to_native(&native->name, network.name); + rv &= network_to_native(&native->value, network.value); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2b11> *network, Packet_Head<0x2b11> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2b11> *native, NetPacket_Head<0x2b11> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2b11> *network, Packet_Repeat<0x2b11> native) +{ + bool rv = true; + rv &= native_to_network(&network->name, native.name); + rv &= native_to_network(&network->value, native.value); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2b11> *native, NetPacket_Repeat<0x2b11> network) +{ + bool rv = true; + rv &= network_to_native(&native->name, network.name); + rv &= network_to_native(&native->value, network.value); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b12> *network, Packet_Fixed<0x2b12> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->char_id, native.char_id); + rv &= native_to_network(&network->partner_id, native.partner_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b12> *native, NetPacket_Fixed<0x2b12> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->char_id, network.char_id); + rv &= network_to_native(&native->partner_id, network.partner_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b13> *network, Packet_Fixed<0x2b13> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b13> *native, NetPacket_Fixed<0x2b13> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b14> *network, Packet_Fixed<0x2b14> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->ban_not_status, native.ban_not_status); + rv &= native_to_network(&network->status_or_ban_until, native.status_or_ban_until); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b14> *native, NetPacket_Fixed<0x2b14> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->ban_not_status, network.ban_not_status); + rv &= network_to_native(&native->status_or_ban_until, network.status_or_ban_until); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2b15> *network, Packet_Head<0x2b15> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2b15> *native, NetPacket_Head<0x2b15> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2b15> *network, Packet_Repeat<0x2b15> native) +{ + bool rv = true; + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->gm_level, native.gm_level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2b15> *native, NetPacket_Repeat<0x2b15> network) +{ + bool rv = true; + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->gm_level, network.gm_level); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2b16> *network, Packet_Fixed<0x2b16> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->char_id, native.char_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2b16> *native, NetPacket_Fixed<0x2b16> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->char_id, network.char_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x3000> *network, Packet_Head<0x3000> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x3000> *native, NetPacket_Head<0x3000> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x3000> *network, Packet_Repeat<0x3000> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x3000> *native, NetPacket_Repeat<0x3000> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x3001> *network, Packet_Head<0x3001> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->from_char_name, native.from_char_name); + rv &= native_to_network(&network->to_char_name, native.to_char_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x3001> *native, NetPacket_Head<0x3001> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->from_char_name, network.from_char_name); + rv &= network_to_native(&native->to_char_name, network.to_char_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x3001> *network, Packet_Repeat<0x3001> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x3001> *native, NetPacket_Repeat<0x3001> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3002> *network, Packet_Fixed<0x3002> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->char_id, native.char_id); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3002> *native, NetPacket_Fixed<0x3002> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->char_id, network.char_id); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x3003> *network, Packet_Head<0x3003> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->char_name, native.char_name); + rv &= native_to_network(&network->min_gm_level, native.min_gm_level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x3003> *native, NetPacket_Head<0x3003> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->char_name, network.char_name); + rv &= network_to_native(&native->min_gm_level, network.min_gm_level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x3003> *network, Packet_Repeat<0x3003> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x3003> *native, NetPacket_Repeat<0x3003> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x3004> *network, Packet_Head<0x3004> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x3004> *native, NetPacket_Head<0x3004> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x3004> *network, Packet_Repeat<0x3004> native) +{ + bool rv = true; + rv &= native_to_network(&network->name, native.name); + rv &= native_to_network(&network->value, native.value); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x3004> *native, NetPacket_Repeat<0x3004> network) +{ + bool rv = true; + rv &= network_to_native(&native->name, network.name); + rv &= network_to_native(&native->value, network.value); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3005> *network, Packet_Fixed<0x3005> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3005> *native, NetPacket_Fixed<0x3005> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3010> *network, Packet_Fixed<0x3010> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3010> *native, NetPacket_Fixed<0x3010> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Payload<0x3011> *network, Packet_Payload<0x3011> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->storage, native.storage); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Payload<0x3011> *native, NetPacket_Payload<0x3011> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->storage, network.storage); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3020> *network, Packet_Fixed<0x3020> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->party_name, native.party_name); + rv &= native_to_network(&network->char_name, native.char_name); + rv &= native_to_network(&network->map_name, native.map_name); + rv &= native_to_network(&network->level, native.level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3020> *native, NetPacket_Fixed<0x3020> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->party_name, network.party_name); + rv &= network_to_native(&native->char_name, network.char_name); + rv &= network_to_native(&native->map_name, network.map_name); + rv &= network_to_native(&native->level, network.level); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3021> *network, Packet_Fixed<0x3021> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_id, native.party_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3021> *native, NetPacket_Fixed<0x3021> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_id, network.party_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3022> *network, Packet_Fixed<0x3022> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->char_name, native.char_name); + rv &= native_to_network(&network->map_name, native.map_name); + rv &= native_to_network(&network->level, native.level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3022> *native, NetPacket_Fixed<0x3022> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->char_name, network.char_name); + rv &= network_to_native(&native->map_name, network.map_name); + rv &= network_to_native(&native->level, network.level); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3023> *network, Packet_Fixed<0x3023> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->exp, native.exp); + rv &= native_to_network(&network->item, native.item); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3023> *native, NetPacket_Fixed<0x3023> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->exp, network.exp); + rv &= network_to_native(&native->item, network.item); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3024> *network, Packet_Fixed<0x3024> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3024> *native, NetPacket_Fixed<0x3024> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3025> *network, Packet_Fixed<0x3025> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->map_name, native.map_name); + rv &= native_to_network(&network->online, native.online); + rv &= native_to_network(&network->level, native.level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3025> *native, NetPacket_Fixed<0x3025> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->map_name, network.map_name); + rv &= network_to_native(&native->online, network.online); + rv &= network_to_native(&native->level, network.level); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x3027> *network, Packet_Head<0x3027> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x3027> *native, NetPacket_Head<0x3027> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x3027> *network, Packet_Repeat<0x3027> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x3027> *native, NetPacket_Repeat<0x3027> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3028> *network, Packet_Fixed<0x3028> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->char_name, native.char_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3028> *native, NetPacket_Fixed<0x3028> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->char_name, network.char_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x3800> *network, Packet_Head<0x3800> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x3800> *native, NetPacket_Head<0x3800> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x3800> *network, Packet_Repeat<0x3800> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x3800> *native, NetPacket_Repeat<0x3800> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x3801> *network, Packet_Head<0x3801> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->whisper_id, native.whisper_id); + rv &= native_to_network(&network->src_char_name, native.src_char_name); + rv &= native_to_network(&network->dst_char_name, native.dst_char_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x3801> *native, NetPacket_Head<0x3801> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->whisper_id, network.whisper_id); + rv &= network_to_native(&native->src_char_name, network.src_char_name); + rv &= network_to_native(&native->dst_char_name, network.dst_char_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x3801> *network, Packet_Repeat<0x3801> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x3801> *native, NetPacket_Repeat<0x3801> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3802> *network, Packet_Fixed<0x3802> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->sender_char_name, native.sender_char_name); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3802> *native, NetPacket_Fixed<0x3802> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->sender_char_name, network.sender_char_name); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x3803> *network, Packet_Head<0x3803> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->char_name, native.char_name); + rv &= native_to_network(&network->min_gm_level, native.min_gm_level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x3803> *native, NetPacket_Head<0x3803> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->char_name, network.char_name); + rv &= network_to_native(&native->min_gm_level, network.min_gm_level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x3803> *network, Packet_Repeat<0x3803> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x3803> *native, NetPacket_Repeat<0x3803> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x3804> *network, Packet_Head<0x3804> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x3804> *native, NetPacket_Head<0x3804> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x3804> *network, Packet_Repeat<0x3804> native) +{ + bool rv = true; + rv &= native_to_network(&network->name, native.name); + rv &= native_to_network(&network->value, native.value); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x3804> *native, NetPacket_Repeat<0x3804> network) +{ + bool rv = true; + rv &= network_to_native(&native->name, network.name); + rv &= network_to_native(&native->value, network.value); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Payload<0x3810> *network, Packet_Payload<0x3810> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->storage, native.storage); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Payload<0x3810> *native, NetPacket_Payload<0x3810> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->storage, network.storage); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3811> *network, Packet_Fixed<0x3811> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->unknown, native.unknown); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3811> *native, NetPacket_Fixed<0x3811> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->unknown, network.unknown); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3820> *network, Packet_Fixed<0x3820> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->error, native.error); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->party_name, native.party_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3820> *native, NetPacket_Fixed<0x3820> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->error, network.error); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->party_name, network.party_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x3821> *network, Packet_Head<0x3821> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->party_id, native.party_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x3821> *native, NetPacket_Head<0x3821> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->party_id, network.party_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Option<0x3821> *network, Packet_Option<0x3821> native) +{ + bool rv = true; + rv &= native_to_network(&network->party_most, native.party_most); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Option<0x3821> *native, NetPacket_Option<0x3821> network) +{ + bool rv = true; + rv &= network_to_native(&native->party_most, network.party_most); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3822> *network, Packet_Fixed<0x3822> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3822> *native, NetPacket_Fixed<0x3822> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3823> *network, Packet_Fixed<0x3823> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->exp, native.exp); + rv &= native_to_network(&network->item, native.item); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3823> *native, NetPacket_Fixed<0x3823> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->exp, network.exp); + rv &= network_to_native(&native->item, network.item); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3824> *network, Packet_Fixed<0x3824> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->char_name, native.char_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3824> *native, NetPacket_Fixed<0x3824> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->char_name, network.char_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3825> *network, Packet_Fixed<0x3825> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->map_name, native.map_name); + rv &= native_to_network(&network->online, native.online); + rv &= native_to_network(&network->level, native.level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3825> *native, NetPacket_Fixed<0x3825> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->map_name, network.map_name); + rv &= network_to_native(&native->online, network.online); + rv &= network_to_native(&native->level, network.level); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x3826> *network, Packet_Fixed<0x3826> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x3826> *native, NetPacket_Fixed<0x3826> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x3827> *network, Packet_Head<0x3827> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x3827> *native, NetPacket_Head<0x3827> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x3827> *network, Packet_Repeat<0x3827> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x3827> *native, NetPacket_Repeat<0x3827> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +} // namespace tmwa diff --git a/src/proto2/char-map_test.cpp b/src/proto2/char-map_test.cpp new file mode 100644 index 0000000..b4ba642 --- /dev/null +++ b/src/proto2/char-map_test.cpp @@ -0,0 +1,27 @@ +#include "char-map.hpp" +// char-map_test.cpp - TMWA network protocol: char/map +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "../poison.hpp" + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/proto2/char-user.hpp b/src/proto2/char-user.hpp new file mode 100644 index 0000000..ed58d69 --- /dev/null +++ b/src/proto2/char-user.hpp @@ -0,0 +1,622 @@ +#pragma once +// char-user.hpp - TMWA network protocol: char/user +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "fwd.hpp" + +#include "types.hpp" + +namespace tmwa +{ +// This is a public protocol, and changes require client cooperation + +template<> +struct Packet_Fixed<0x0061> +{ + static const uint16_t PACKET_ID = 0x0061; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountPass old_pass = {}; + AccountPass new_pass = {}; +}; + +template<> +struct Packet_Fixed<0x0062> +{ + static const uint16_t PACKET_ID = 0x0062; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t status = {}; +}; + +template<> +struct Packet_Fixed<0x0065> +{ + static const uint16_t PACKET_ID = 0x0065; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint32_t login_id1 = {}; + uint32_t login_id2 = {}; + uint16_t packet_tmw_version = {}; + SEX sex = {}; +}; + +template<> +struct Packet_Fixed<0x0066> +{ + static const uint16_t PACKET_ID = 0x0066; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t code = {}; +}; + +template<> +struct Packet_Fixed<0x0067> +{ + static const uint16_t PACKET_ID = 0x0067; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + CharName char_name = {}; + Stats6 stats = {}; + uint8_t slot = {}; + uint16_t hair_color = {}; + uint16_t hair_style = {}; +}; + +template<> +struct Packet_Fixed<0x0068> +{ + static const uint16_t PACKET_ID = 0x0068; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + CharId char_id = {}; + AccountEmail email = {}; +}; + +template<> +struct Packet_Head<0x006b> +{ + static const uint16_t PACKET_ID = 0x006b; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + VString<19> unused = {}; +}; +template<> +struct Packet_Repeat<0x006b> +{ + static const uint16_t PACKET_ID = 0x006b; + + CharSelect char_select = {}; +}; + +template<> +struct Packet_Fixed<0x006c> +{ + static const uint16_t PACKET_ID = 0x006c; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t code = {}; +}; + +template<> +struct Packet_Fixed<0x006d> +{ + static const uint16_t PACKET_ID = 0x006d; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + CharSelect char_select = {}; +}; + +template<> +struct Packet_Fixed<0x006e> +{ + static const uint16_t PACKET_ID = 0x006e; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t code = {}; +}; + +template<> +struct Packet_Fixed<0x006f> +{ + static const uint16_t PACKET_ID = 0x006f; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x0070> +{ + static const uint16_t PACKET_ID = 0x0070; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t code = {}; +}; + +template<> +struct Packet_Fixed<0x0071> +{ + static const uint16_t PACKET_ID = 0x0071; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + CharId char_id = {}; + MapName map_name = {}; + IP4Address ip = {}; + uint16_t port = {}; +}; + + +template<> +struct NetPacket_Fixed<0x0061> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountPass)> old_pass; + NetString<sizeof(AccountPass)> new_pass; +}; +static_assert(offsetof(NetPacket_Fixed<0x0061>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0061>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0061>, old_pass) == 2, "offsetof(NetPacket_Fixed<0x0061>, old_pass) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0061>, new_pass) == 26, "offsetof(NetPacket_Fixed<0x0061>, new_pass) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x0061>) == 50, "sizeof(NetPacket_Fixed<0x0061>) == 50"); +static_assert(alignof(NetPacket_Fixed<0x0061>) == 1, "alignof(NetPacket_Fixed<0x0061>) == 1"); + +template<> +struct NetPacket_Fixed<0x0062> +{ + Little16 magic_packet_id; + Byte status; +}; +static_assert(offsetof(NetPacket_Fixed<0x0062>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0062>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0062>, status) == 2, "offsetof(NetPacket_Fixed<0x0062>, status) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x0062>) == 3, "sizeof(NetPacket_Fixed<0x0062>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x0062>) == 1, "alignof(NetPacket_Fixed<0x0062>) == 1"); + +template<> +struct NetPacket_Fixed<0x0065> +{ + Little16 magic_packet_id; + Little32 account_id; + Little32 login_id1; + Little32 login_id2; + Little16 packet_tmw_version; + Byte sex; +}; +static_assert(offsetof(NetPacket_Fixed<0x0065>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0065>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0065>, account_id) == 2, "offsetof(NetPacket_Fixed<0x0065>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0065>, login_id1) == 6, "offsetof(NetPacket_Fixed<0x0065>, login_id1) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0065>, login_id2) == 10, "offsetof(NetPacket_Fixed<0x0065>, login_id2) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x0065>, packet_tmw_version) == 14, "offsetof(NetPacket_Fixed<0x0065>, packet_tmw_version) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x0065>, sex) == 16, "offsetof(NetPacket_Fixed<0x0065>, sex) == 16"); +static_assert(sizeof(NetPacket_Fixed<0x0065>) == 17, "sizeof(NetPacket_Fixed<0x0065>) == 17"); +static_assert(alignof(NetPacket_Fixed<0x0065>) == 1, "alignof(NetPacket_Fixed<0x0065>) == 1"); + +template<> +struct NetPacket_Fixed<0x0066> +{ + Little16 magic_packet_id; + Byte code; +}; +static_assert(offsetof(NetPacket_Fixed<0x0066>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0066>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0066>, code) == 2, "offsetof(NetPacket_Fixed<0x0066>, code) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x0066>) == 3, "sizeof(NetPacket_Fixed<0x0066>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x0066>) == 1, "alignof(NetPacket_Fixed<0x0066>) == 1"); + +template<> +struct NetPacket_Fixed<0x0067> +{ + Little16 magic_packet_id; + NetString<sizeof(CharName)> char_name; + NetStats6 stats; + Byte slot; + Little16 hair_color; + Little16 hair_style; +}; +static_assert(offsetof(NetPacket_Fixed<0x0067>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0067>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0067>, char_name) == 2, "offsetof(NetPacket_Fixed<0x0067>, char_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0067>, stats) == 26, "offsetof(NetPacket_Fixed<0x0067>, stats) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x0067>, slot) == 32, "offsetof(NetPacket_Fixed<0x0067>, slot) == 32"); +static_assert(offsetof(NetPacket_Fixed<0x0067>, hair_color) == 33, "offsetof(NetPacket_Fixed<0x0067>, hair_color) == 33"); +static_assert(offsetof(NetPacket_Fixed<0x0067>, hair_style) == 35, "offsetof(NetPacket_Fixed<0x0067>, hair_style) == 35"); +static_assert(sizeof(NetPacket_Fixed<0x0067>) == 37, "sizeof(NetPacket_Fixed<0x0067>) == 37"); +static_assert(alignof(NetPacket_Fixed<0x0067>) == 1, "alignof(NetPacket_Fixed<0x0067>) == 1"); + +template<> +struct NetPacket_Fixed<0x0068> +{ + Little16 magic_packet_id; + Little32 char_id; + NetString<sizeof(AccountEmail)> email; +}; +static_assert(offsetof(NetPacket_Fixed<0x0068>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0068>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0068>, char_id) == 2, "offsetof(NetPacket_Fixed<0x0068>, char_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0068>, email) == 6, "offsetof(NetPacket_Fixed<0x0068>, email) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x0068>) == 46, "sizeof(NetPacket_Fixed<0x0068>) == 46"); +static_assert(alignof(NetPacket_Fixed<0x0068>) == 1, "alignof(NetPacket_Fixed<0x0068>) == 1"); + +template<> +struct NetPacket_Head<0x006b> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + NetString<sizeof(VString<19>)> unused; +}; +static_assert(offsetof(NetPacket_Head<0x006b>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x006b>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x006b>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x006b>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x006b>, unused) == 4, "offsetof(NetPacket_Head<0x006b>, unused) == 4"); +static_assert(sizeof(NetPacket_Head<0x006b>) == 24, "sizeof(NetPacket_Head<0x006b>) == 24"); +static_assert(alignof(NetPacket_Head<0x006b>) == 1, "alignof(NetPacket_Head<0x006b>) == 1"); +template<> +struct NetPacket_Repeat<0x006b> +{ + NetCharSelect char_select; +}; +static_assert(offsetof(NetPacket_Repeat<0x006b>, char_select) == 0, "offsetof(NetPacket_Repeat<0x006b>, char_select) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x006b>) == 106, "sizeof(NetPacket_Repeat<0x006b>) == 106"); +static_assert(alignof(NetPacket_Repeat<0x006b>) == 1, "alignof(NetPacket_Repeat<0x006b>) == 1"); + +template<> +struct NetPacket_Fixed<0x006c> +{ + Little16 magic_packet_id; + Byte code; +}; +static_assert(offsetof(NetPacket_Fixed<0x006c>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x006c>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x006c>, code) == 2, "offsetof(NetPacket_Fixed<0x006c>, code) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x006c>) == 3, "sizeof(NetPacket_Fixed<0x006c>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x006c>) == 1, "alignof(NetPacket_Fixed<0x006c>) == 1"); + +template<> +struct NetPacket_Fixed<0x006d> +{ + Little16 magic_packet_id; + NetCharSelect char_select; +}; +static_assert(offsetof(NetPacket_Fixed<0x006d>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x006d>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x006d>, char_select) == 2, "offsetof(NetPacket_Fixed<0x006d>, char_select) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x006d>) == 108, "sizeof(NetPacket_Fixed<0x006d>) == 108"); +static_assert(alignof(NetPacket_Fixed<0x006d>) == 1, "alignof(NetPacket_Fixed<0x006d>) == 1"); + +template<> +struct NetPacket_Fixed<0x006e> +{ + Little16 magic_packet_id; + Byte code; +}; +static_assert(offsetof(NetPacket_Fixed<0x006e>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x006e>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x006e>, code) == 2, "offsetof(NetPacket_Fixed<0x006e>, code) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x006e>) == 3, "sizeof(NetPacket_Fixed<0x006e>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x006e>) == 1, "alignof(NetPacket_Fixed<0x006e>) == 1"); + +template<> +struct NetPacket_Fixed<0x006f> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x006f>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x006f>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x006f>) == 2, "sizeof(NetPacket_Fixed<0x006f>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x006f>) == 1, "alignof(NetPacket_Fixed<0x006f>) == 1"); + +template<> +struct NetPacket_Fixed<0x0070> +{ + Little16 magic_packet_id; + Byte code; +}; +static_assert(offsetof(NetPacket_Fixed<0x0070>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0070>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0070>, code) == 2, "offsetof(NetPacket_Fixed<0x0070>, code) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x0070>) == 3, "sizeof(NetPacket_Fixed<0x0070>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x0070>) == 1, "alignof(NetPacket_Fixed<0x0070>) == 1"); + +template<> +struct NetPacket_Fixed<0x0071> +{ + Little16 magic_packet_id; + Little32 char_id; + NetString<sizeof(MapName)> map_name; + IP4Address ip; + Little16 port; +}; +static_assert(offsetof(NetPacket_Fixed<0x0071>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0071>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0071>, char_id) == 2, "offsetof(NetPacket_Fixed<0x0071>, char_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0071>, map_name) == 6, "offsetof(NetPacket_Fixed<0x0071>, map_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0071>, ip) == 22, "offsetof(NetPacket_Fixed<0x0071>, ip) == 22"); +static_assert(offsetof(NetPacket_Fixed<0x0071>, port) == 26, "offsetof(NetPacket_Fixed<0x0071>, port) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x0071>) == 28, "sizeof(NetPacket_Fixed<0x0071>) == 28"); +static_assert(alignof(NetPacket_Fixed<0x0071>) == 1, "alignof(NetPacket_Fixed<0x0071>) == 1"); + + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0061> *network, Packet_Fixed<0x0061> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->old_pass, native.old_pass); + rv &= native_to_network(&network->new_pass, native.new_pass); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0061> *native, NetPacket_Fixed<0x0061> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->old_pass, network.old_pass); + rv &= network_to_native(&native->new_pass, network.new_pass); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0062> *network, Packet_Fixed<0x0062> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->status, native.status); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0062> *native, NetPacket_Fixed<0x0062> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->status, network.status); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0065> *network, Packet_Fixed<0x0065> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->login_id1, native.login_id1); + rv &= native_to_network(&network->login_id2, native.login_id2); + rv &= native_to_network(&network->packet_tmw_version, native.packet_tmw_version); + rv &= native_to_network(&network->sex, native.sex); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0065> *native, NetPacket_Fixed<0x0065> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->login_id1, network.login_id1); + rv &= network_to_native(&native->login_id2, network.login_id2); + rv &= network_to_native(&native->packet_tmw_version, network.packet_tmw_version); + rv &= network_to_native(&native->sex, network.sex); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0066> *network, Packet_Fixed<0x0066> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->code, native.code); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0066> *native, NetPacket_Fixed<0x0066> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->code, network.code); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0067> *network, Packet_Fixed<0x0067> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->char_name, native.char_name); + rv &= native_to_network(&network->stats, native.stats); + rv &= native_to_network(&network->slot, native.slot); + rv &= native_to_network(&network->hair_color, native.hair_color); + rv &= native_to_network(&network->hair_style, native.hair_style); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0067> *native, NetPacket_Fixed<0x0067> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->char_name, network.char_name); + rv &= network_to_native(&native->stats, network.stats); + rv &= network_to_native(&native->slot, network.slot); + rv &= network_to_native(&native->hair_color, network.hair_color); + rv &= network_to_native(&native->hair_style, network.hair_style); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0068> *network, Packet_Fixed<0x0068> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->char_id, native.char_id); + rv &= native_to_network(&network->email, native.email); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0068> *native, NetPacket_Fixed<0x0068> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->char_id, network.char_id); + rv &= network_to_native(&native->email, network.email); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x006b> *network, Packet_Head<0x006b> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->unused, native.unused); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x006b> *native, NetPacket_Head<0x006b> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->unused, network.unused); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x006b> *network, Packet_Repeat<0x006b> native) +{ + bool rv = true; + rv &= native_to_network(&network->char_select, native.char_select); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x006b> *native, NetPacket_Repeat<0x006b> network) +{ + bool rv = true; + rv &= network_to_native(&native->char_select, network.char_select); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x006c> *network, Packet_Fixed<0x006c> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->code, native.code); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x006c> *native, NetPacket_Fixed<0x006c> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->code, network.code); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x006d> *network, Packet_Fixed<0x006d> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->char_select, native.char_select); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x006d> *native, NetPacket_Fixed<0x006d> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->char_select, network.char_select); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x006e> *network, Packet_Fixed<0x006e> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->code, native.code); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x006e> *native, NetPacket_Fixed<0x006e> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->code, network.code); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x006f> *network, Packet_Fixed<0x006f> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x006f> *native, NetPacket_Fixed<0x006f> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0070> *network, Packet_Fixed<0x0070> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->code, native.code); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0070> *native, NetPacket_Fixed<0x0070> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->code, network.code); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0071> *network, Packet_Fixed<0x0071> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->char_id, native.char_id); + rv &= native_to_network(&network->map_name, native.map_name); + rv &= native_to_network(&network->ip, native.ip); + rv &= native_to_network(&network->port, native.port); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0071> *native, NetPacket_Fixed<0x0071> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->char_id, network.char_id); + rv &= network_to_native(&native->map_name, network.map_name); + rv &= network_to_native(&native->ip, network.ip); + rv &= network_to_native(&native->port, network.port); + return rv; +} + +} // namespace tmwa diff --git a/src/proto2/char-user_test.cpp b/src/proto2/char-user_test.cpp new file mode 100644 index 0000000..ade1843 --- /dev/null +++ b/src/proto2/char-user_test.cpp @@ -0,0 +1,27 @@ +#include "char-user.hpp" +// char-user_test.cpp - TMWA network protocol: char/user +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "../poison.hpp" + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/proto2/fwd.hpp b/src/proto2/fwd.hpp new file mode 100644 index 0000000..e1e0161 --- /dev/null +++ b/src/proto2/fwd.hpp @@ -0,0 +1,1713 @@ +#pragma once +// proto2/fwd.hpp - Forward declarations of network packets +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + +#include <cstdint> + +namespace tmwa +{ +template<uint16_t PACKET_ID> class Packet_Fixed; +template<uint16_t PACKET_ID> class NetPacket_Fixed; +template<uint16_t PACKET_ID> class Packet_Payload; +template<uint16_t PACKET_ID> class NetPacket_Payload; +template<uint16_t PACKET_ID> class Packet_Head; +template<uint16_t PACKET_ID> class NetPacket_Head; +template<uint16_t PACKET_ID> class Packet_Repeat; +template<uint16_t PACKET_ID> class NetPacket_Repeat; +template<uint16_t PACKET_ID> class Packet_Option; +template<uint16_t PACKET_ID> class NetPacket_Option; + +template<> +struct Packet_Fixed<0x2709>; +template<> +struct NetPacket_Fixed<0x2709>; + +template<> +struct Packet_Fixed<0x2710>; +template<> +struct NetPacket_Fixed<0x2710>; + +template<> +struct Packet_Fixed<0x2711>; +template<> +struct NetPacket_Fixed<0x2711>; + +template<> +struct Packet_Fixed<0x2712>; +template<> +struct NetPacket_Fixed<0x2712>; + +template<> +struct Packet_Fixed<0x2713>; +template<> +struct NetPacket_Fixed<0x2713>; + +template<> +struct Packet_Fixed<0x2714>; +template<> +struct NetPacket_Fixed<0x2714>; + +template<> +struct Packet_Fixed<0x2716>; +template<> +struct NetPacket_Fixed<0x2716>; + +template<> +struct Packet_Fixed<0x2717>; +template<> +struct NetPacket_Fixed<0x2717>; + +template<> +struct Packet_Head<0x2720>; +template<> +struct NetPacket_Head<0x2720>; +template<> +struct Packet_Repeat<0x2720>; +template<> +struct NetPacket_Repeat<0x2720>; + +template<> +struct Packet_Fixed<0x2721>; +template<> +struct NetPacket_Fixed<0x2721>; + +template<> +struct Packet_Fixed<0x2722>; +template<> +struct NetPacket_Fixed<0x2722>; + +template<> +struct Packet_Fixed<0x2723>; +template<> +struct NetPacket_Fixed<0x2723>; + +template<> +struct Packet_Fixed<0x2724>; +template<> +struct NetPacket_Fixed<0x2724>; + +template<> +struct Packet_Fixed<0x2725>; +template<> +struct NetPacket_Fixed<0x2725>; + +template<> +struct Packet_Fixed<0x2727>; +template<> +struct NetPacket_Fixed<0x2727>; + +template<> +struct Packet_Head<0x2728>; +template<> +struct NetPacket_Head<0x2728>; +template<> +struct Packet_Repeat<0x2728>; +template<> +struct NetPacket_Repeat<0x2728>; + +template<> +struct Packet_Head<0x2729>; +template<> +struct NetPacket_Head<0x2729>; +template<> +struct Packet_Repeat<0x2729>; +template<> +struct NetPacket_Repeat<0x2729>; + +template<> +struct Packet_Fixed<0x272a>; +template<> +struct NetPacket_Fixed<0x272a>; + +template<> +struct Packet_Fixed<0x2730>; +template<> +struct NetPacket_Fixed<0x2730>; + +template<> +struct Packet_Fixed<0x2731>; +template<> +struct NetPacket_Fixed<0x2731>; + +template<> +struct Packet_Head<0x2732>; +template<> +struct NetPacket_Head<0x2732>; +template<> +struct Packet_Repeat<0x2732>; +template<> +struct NetPacket_Repeat<0x2732>; + +template<> +struct Packet_Fixed<0x2740>; +template<> +struct NetPacket_Fixed<0x2740>; + +template<> +struct Packet_Fixed<0x2741>; +template<> +struct NetPacket_Fixed<0x2741>; + + +template<> +struct Packet_Head<0x2726>; +template<> +struct NetPacket_Head<0x2726>; +template<> +struct Packet_Repeat<0x2726>; +template<> +struct NetPacket_Repeat<0x2726>; + +template<> +struct Packet_Fixed<0x7918>; +template<> +struct NetPacket_Fixed<0x7918>; + +template<> +struct Packet_Fixed<0x7919>; +template<> +struct NetPacket_Fixed<0x7919>; + +template<> +struct Packet_Fixed<0x7920>; +template<> +struct NetPacket_Fixed<0x7920>; + +template<> +struct Packet_Head<0x7921>; +template<> +struct NetPacket_Head<0x7921>; +template<> +struct Packet_Repeat<0x7921>; +template<> +struct NetPacket_Repeat<0x7921>; + +template<> +struct Packet_Fixed<0x7924>; +template<> +struct NetPacket_Fixed<0x7924>; + +template<> +struct Packet_Fixed<0x7925>; +template<> +struct NetPacket_Fixed<0x7925>; + +template<> +struct Packet_Fixed<0x7930>; +template<> +struct NetPacket_Fixed<0x7930>; + +template<> +struct Packet_Fixed<0x7931>; +template<> +struct NetPacket_Fixed<0x7931>; + +template<> +struct Packet_Fixed<0x7932>; +template<> +struct NetPacket_Fixed<0x7932>; + +template<> +struct Packet_Fixed<0x7933>; +template<> +struct NetPacket_Fixed<0x7933>; + +template<> +struct Packet_Fixed<0x7934>; +template<> +struct NetPacket_Fixed<0x7934>; + +template<> +struct Packet_Fixed<0x7935>; +template<> +struct NetPacket_Fixed<0x7935>; + +template<> +struct Packet_Fixed<0x7936>; +template<> +struct NetPacket_Fixed<0x7936>; + +template<> +struct Packet_Fixed<0x7937>; +template<> +struct NetPacket_Fixed<0x7937>; + +template<> +struct Packet_Fixed<0x7938>; +template<> +struct NetPacket_Fixed<0x7938>; + +template<> +struct Packet_Head<0x7939>; +template<> +struct NetPacket_Head<0x7939>; +template<> +struct Packet_Repeat<0x7939>; +template<> +struct NetPacket_Repeat<0x7939>; + +template<> +struct Packet_Fixed<0x793a>; +template<> +struct NetPacket_Fixed<0x793a>; + +template<> +struct Packet_Fixed<0x793b>; +template<> +struct NetPacket_Fixed<0x793b>; + +template<> +struct Packet_Fixed<0x793c>; +template<> +struct NetPacket_Fixed<0x793c>; + +template<> +struct Packet_Fixed<0x793d>; +template<> +struct NetPacket_Fixed<0x793d>; + +template<> +struct Packet_Fixed<0x793e>; +template<> +struct NetPacket_Fixed<0x793e>; + +template<> +struct Packet_Fixed<0x793f>; +template<> +struct NetPacket_Fixed<0x793f>; + +template<> +struct Packet_Fixed<0x7940>; +template<> +struct NetPacket_Fixed<0x7940>; + +template<> +struct Packet_Fixed<0x7941>; +template<> +struct NetPacket_Fixed<0x7941>; + +template<> +struct Packet_Head<0x7942>; +template<> +struct NetPacket_Head<0x7942>; +template<> +struct Packet_Repeat<0x7942>; +template<> +struct NetPacket_Repeat<0x7942>; + +template<> +struct Packet_Fixed<0x7943>; +template<> +struct NetPacket_Fixed<0x7943>; + +template<> +struct Packet_Fixed<0x7944>; +template<> +struct NetPacket_Fixed<0x7944>; + +template<> +struct Packet_Fixed<0x7945>; +template<> +struct NetPacket_Fixed<0x7945>; + +template<> +struct Packet_Fixed<0x7946>; +template<> +struct NetPacket_Fixed<0x7946>; + +template<> +struct Packet_Fixed<0x7947>; +template<> +struct NetPacket_Fixed<0x7947>; + +template<> +struct Packet_Fixed<0x7948>; +template<> +struct NetPacket_Fixed<0x7948>; + +template<> +struct Packet_Fixed<0x7949>; +template<> +struct NetPacket_Fixed<0x7949>; + +template<> +struct Packet_Fixed<0x794a>; +template<> +struct NetPacket_Fixed<0x794a>; + +template<> +struct Packet_Fixed<0x794b>; +template<> +struct NetPacket_Fixed<0x794b>; + +template<> +struct Packet_Fixed<0x794c>; +template<> +struct NetPacket_Fixed<0x794c>; + +template<> +struct Packet_Fixed<0x794d>; +template<> +struct NetPacket_Fixed<0x794d>; + +template<> +struct Packet_Head<0x794e>; +template<> +struct NetPacket_Head<0x794e>; +template<> +struct Packet_Repeat<0x794e>; +template<> +struct NetPacket_Repeat<0x794e>; + +template<> +struct Packet_Fixed<0x794f>; +template<> +struct NetPacket_Fixed<0x794f>; + +template<> +struct Packet_Fixed<0x7950>; +template<> +struct NetPacket_Fixed<0x7950>; + +template<> +struct Packet_Fixed<0x7951>; +template<> +struct NetPacket_Fixed<0x7951>; + +template<> +struct Packet_Fixed<0x7952>; +template<> +struct NetPacket_Fixed<0x7952>; + +template<> +struct Packet_Head<0x7953>; +template<> +struct NetPacket_Head<0x7953>; +template<> +struct Packet_Repeat<0x7953>; +template<> +struct NetPacket_Repeat<0x7953>; + +template<> +struct Packet_Fixed<0x7954>; +template<> +struct NetPacket_Fixed<0x7954>; + +template<> +struct Packet_Fixed<0x7955>; +template<> +struct NetPacket_Fixed<0x7955>; + + +template<> +struct Packet_Head<0x0063>; +template<> +struct NetPacket_Head<0x0063>; +template<> +struct Packet_Repeat<0x0063>; +template<> +struct NetPacket_Repeat<0x0063>; + +template<> +struct Packet_Fixed<0x0064>; +template<> +struct NetPacket_Fixed<0x0064>; + +template<> +struct Packet_Head<0x0069>; +template<> +struct NetPacket_Head<0x0069>; +template<> +struct Packet_Repeat<0x0069>; +template<> +struct NetPacket_Repeat<0x0069>; + +template<> +struct Packet_Fixed<0x006a>; +template<> +struct NetPacket_Fixed<0x006a>; + + +template<> +struct Packet_Fixed<0x2af7>; +template<> +struct NetPacket_Fixed<0x2af7>; + +template<> +struct Packet_Fixed<0x2af8>; +template<> +struct NetPacket_Fixed<0x2af8>; + +template<> +struct Packet_Fixed<0x2af9>; +template<> +struct NetPacket_Fixed<0x2af9>; + +template<> +struct Packet_Head<0x2afa>; +template<> +struct NetPacket_Head<0x2afa>; +template<> +struct Packet_Repeat<0x2afa>; +template<> +struct NetPacket_Repeat<0x2afa>; + +template<> +struct Packet_Fixed<0x2afa>; +template<> +struct NetPacket_Fixed<0x2afa>; + +template<> +struct Packet_Fixed<0x2afb>; +template<> +struct NetPacket_Fixed<0x2afb>; + +template<> +struct Packet_Fixed<0x2afc>; +template<> +struct NetPacket_Fixed<0x2afc>; + +template<> +struct Packet_Payload<0x2afd>; +template<> +struct NetPacket_Payload<0x2afd>; + +template<> +struct Packet_Fixed<0x2afe>; +template<> +struct NetPacket_Fixed<0x2afe>; + +template<> +struct Packet_Head<0x2aff>; +template<> +struct NetPacket_Head<0x2aff>; +template<> +struct Packet_Repeat<0x2aff>; +template<> +struct NetPacket_Repeat<0x2aff>; + +template<> +struct Packet_Fixed<0x2b00>; +template<> +struct NetPacket_Fixed<0x2b00>; + +template<> +struct Packet_Payload<0x2b01>; +template<> +struct NetPacket_Payload<0x2b01>; + +template<> +struct Packet_Fixed<0x2b02>; +template<> +struct NetPacket_Fixed<0x2b02>; + +template<> +struct Packet_Fixed<0x2b03>; +template<> +struct NetPacket_Fixed<0x2b03>; + +template<> +struct Packet_Head<0x2b04>; +template<> +struct NetPacket_Head<0x2b04>; +template<> +struct Packet_Repeat<0x2b04>; +template<> +struct NetPacket_Repeat<0x2b04>; + +template<> +struct Packet_Fixed<0x2b05>; +template<> +struct NetPacket_Fixed<0x2b05>; + +template<> +struct Packet_Fixed<0x2b06>; +template<> +struct NetPacket_Fixed<0x2b06>; + +template<> +struct Packet_Head<0x2b0a>; +template<> +struct NetPacket_Head<0x2b0a>; +template<> +struct Packet_Repeat<0x2b0a>; +template<> +struct NetPacket_Repeat<0x2b0a>; + +template<> +struct Packet_Fixed<0x2b0b>; +template<> +struct NetPacket_Fixed<0x2b0b>; + +template<> +struct Packet_Fixed<0x2b0c>; +template<> +struct NetPacket_Fixed<0x2b0c>; + +template<> +struct Packet_Fixed<0x2b0d>; +template<> +struct NetPacket_Fixed<0x2b0d>; + +template<> +struct Packet_Fixed<0x2b0e>; +template<> +struct NetPacket_Fixed<0x2b0e>; + +template<> +struct Packet_Fixed<0x2b0f>; +template<> +struct NetPacket_Fixed<0x2b0f>; + +template<> +struct Packet_Head<0x2b10>; +template<> +struct NetPacket_Head<0x2b10>; +template<> +struct Packet_Repeat<0x2b10>; +template<> +struct NetPacket_Repeat<0x2b10>; + +template<> +struct Packet_Head<0x2b11>; +template<> +struct NetPacket_Head<0x2b11>; +template<> +struct Packet_Repeat<0x2b11>; +template<> +struct NetPacket_Repeat<0x2b11>; + +template<> +struct Packet_Fixed<0x2b12>; +template<> +struct NetPacket_Fixed<0x2b12>; + +template<> +struct Packet_Fixed<0x2b13>; +template<> +struct NetPacket_Fixed<0x2b13>; + +template<> +struct Packet_Fixed<0x2b14>; +template<> +struct NetPacket_Fixed<0x2b14>; + +template<> +struct Packet_Head<0x2b15>; +template<> +struct NetPacket_Head<0x2b15>; +template<> +struct Packet_Repeat<0x2b15>; +template<> +struct NetPacket_Repeat<0x2b15>; + +template<> +struct Packet_Fixed<0x2b16>; +template<> +struct NetPacket_Fixed<0x2b16>; + +template<> +struct Packet_Head<0x3000>; +template<> +struct NetPacket_Head<0x3000>; +template<> +struct Packet_Repeat<0x3000>; +template<> +struct NetPacket_Repeat<0x3000>; + +template<> +struct Packet_Head<0x3001>; +template<> +struct NetPacket_Head<0x3001>; +template<> +struct Packet_Repeat<0x3001>; +template<> +struct NetPacket_Repeat<0x3001>; + +template<> +struct Packet_Fixed<0x3002>; +template<> +struct NetPacket_Fixed<0x3002>; + +template<> +struct Packet_Head<0x3003>; +template<> +struct NetPacket_Head<0x3003>; +template<> +struct Packet_Repeat<0x3003>; +template<> +struct NetPacket_Repeat<0x3003>; + +template<> +struct Packet_Head<0x3004>; +template<> +struct NetPacket_Head<0x3004>; +template<> +struct Packet_Repeat<0x3004>; +template<> +struct NetPacket_Repeat<0x3004>; + +template<> +struct Packet_Fixed<0x3005>; +template<> +struct NetPacket_Fixed<0x3005>; + +template<> +struct Packet_Fixed<0x3010>; +template<> +struct NetPacket_Fixed<0x3010>; + +template<> +struct Packet_Payload<0x3011>; +template<> +struct NetPacket_Payload<0x3011>; + +template<> +struct Packet_Fixed<0x3020>; +template<> +struct NetPacket_Fixed<0x3020>; + +template<> +struct Packet_Fixed<0x3021>; +template<> +struct NetPacket_Fixed<0x3021>; + +template<> +struct Packet_Fixed<0x3022>; +template<> +struct NetPacket_Fixed<0x3022>; + +template<> +struct Packet_Fixed<0x3023>; +template<> +struct NetPacket_Fixed<0x3023>; + +template<> +struct Packet_Fixed<0x3024>; +template<> +struct NetPacket_Fixed<0x3024>; + +template<> +struct Packet_Fixed<0x3025>; +template<> +struct NetPacket_Fixed<0x3025>; + +template<> +struct Packet_Head<0x3027>; +template<> +struct NetPacket_Head<0x3027>; +template<> +struct Packet_Repeat<0x3027>; +template<> +struct NetPacket_Repeat<0x3027>; + +template<> +struct Packet_Fixed<0x3028>; +template<> +struct NetPacket_Fixed<0x3028>; + +template<> +struct Packet_Head<0x3800>; +template<> +struct NetPacket_Head<0x3800>; +template<> +struct Packet_Repeat<0x3800>; +template<> +struct NetPacket_Repeat<0x3800>; + +template<> +struct Packet_Head<0x3801>; +template<> +struct NetPacket_Head<0x3801>; +template<> +struct Packet_Repeat<0x3801>; +template<> +struct NetPacket_Repeat<0x3801>; + +template<> +struct Packet_Fixed<0x3802>; +template<> +struct NetPacket_Fixed<0x3802>; + +template<> +struct Packet_Head<0x3803>; +template<> +struct NetPacket_Head<0x3803>; +template<> +struct Packet_Repeat<0x3803>; +template<> +struct NetPacket_Repeat<0x3803>; + +template<> +struct Packet_Head<0x3804>; +template<> +struct NetPacket_Head<0x3804>; +template<> +struct Packet_Repeat<0x3804>; +template<> +struct NetPacket_Repeat<0x3804>; + +template<> +struct Packet_Payload<0x3810>; +template<> +struct NetPacket_Payload<0x3810>; + +template<> +struct Packet_Fixed<0x3811>; +template<> +struct NetPacket_Fixed<0x3811>; + +template<> +struct Packet_Fixed<0x3820>; +template<> +struct NetPacket_Fixed<0x3820>; + +template<> +struct Packet_Head<0x3821>; +template<> +struct NetPacket_Head<0x3821>; +template<> +struct Packet_Option<0x3821>; +template<> +struct NetPacket_Option<0x3821>; + +template<> +struct Packet_Fixed<0x3822>; +template<> +struct NetPacket_Fixed<0x3822>; + +template<> +struct Packet_Fixed<0x3823>; +template<> +struct NetPacket_Fixed<0x3823>; + +template<> +struct Packet_Fixed<0x3824>; +template<> +struct NetPacket_Fixed<0x3824>; + +template<> +struct Packet_Fixed<0x3825>; +template<> +struct NetPacket_Fixed<0x3825>; + +template<> +struct Packet_Fixed<0x3826>; +template<> +struct NetPacket_Fixed<0x3826>; + +template<> +struct Packet_Head<0x3827>; +template<> +struct NetPacket_Head<0x3827>; +template<> +struct Packet_Repeat<0x3827>; +template<> +struct NetPacket_Repeat<0x3827>; + + +template<> +struct Packet_Fixed<0x0061>; +template<> +struct NetPacket_Fixed<0x0061>; + +template<> +struct Packet_Fixed<0x0062>; +template<> +struct NetPacket_Fixed<0x0062>; + +template<> +struct Packet_Fixed<0x0065>; +template<> +struct NetPacket_Fixed<0x0065>; + +template<> +struct Packet_Fixed<0x0066>; +template<> +struct NetPacket_Fixed<0x0066>; + +template<> +struct Packet_Fixed<0x0067>; +template<> +struct NetPacket_Fixed<0x0067>; + +template<> +struct Packet_Fixed<0x0068>; +template<> +struct NetPacket_Fixed<0x0068>; + +template<> +struct Packet_Head<0x006b>; +template<> +struct NetPacket_Head<0x006b>; +template<> +struct Packet_Repeat<0x006b>; +template<> +struct NetPacket_Repeat<0x006b>; + +template<> +struct Packet_Fixed<0x006c>; +template<> +struct NetPacket_Fixed<0x006c>; + +template<> +struct Packet_Fixed<0x006d>; +template<> +struct NetPacket_Fixed<0x006d>; + +template<> +struct Packet_Fixed<0x006e>; +template<> +struct NetPacket_Fixed<0x006e>; + +template<> +struct Packet_Fixed<0x006f>; +template<> +struct NetPacket_Fixed<0x006f>; + +template<> +struct Packet_Fixed<0x0070>; +template<> +struct NetPacket_Fixed<0x0070>; + +template<> +struct Packet_Fixed<0x0071>; +template<> +struct NetPacket_Fixed<0x0071>; + + +template<> +struct Packet_Fixed<0x0072>; +template<> +struct NetPacket_Fixed<0x0072>; + +template<> +struct Packet_Fixed<0x0073>; +template<> +struct NetPacket_Fixed<0x0073>; + +template<> +struct Packet_Fixed<0x0078>; +template<> +struct NetPacket_Fixed<0x0078>; + +template<> +struct Packet_Fixed<0x007b>; +template<> +struct NetPacket_Fixed<0x007b>; + +template<> +struct Packet_Fixed<0x007c>; +template<> +struct NetPacket_Fixed<0x007c>; + +template<> +struct Packet_Fixed<0x007d>; +template<> +struct NetPacket_Fixed<0x007d>; + +template<> +struct Packet_Fixed<0x007e>; +template<> +struct NetPacket_Fixed<0x007e>; + +template<> +struct Packet_Fixed<0x007f>; +template<> +struct NetPacket_Fixed<0x007f>; + +template<> +struct Packet_Fixed<0x0080>; +template<> +struct NetPacket_Fixed<0x0080>; + +template<> +struct Packet_Fixed<0x0085>; +template<> +struct NetPacket_Fixed<0x0085>; + +template<> +struct Packet_Fixed<0x0087>; +template<> +struct NetPacket_Fixed<0x0087>; + +template<> +struct Packet_Fixed<0x0088>; +template<> +struct NetPacket_Fixed<0x0088>; + +template<> +struct Packet_Fixed<0x0089>; +template<> +struct NetPacket_Fixed<0x0089>; + +template<> +struct Packet_Fixed<0x008a>; +template<> +struct NetPacket_Fixed<0x008a>; + +template<> +struct Packet_Head<0x008c>; +template<> +struct NetPacket_Head<0x008c>; +template<> +struct Packet_Repeat<0x008c>; +template<> +struct NetPacket_Repeat<0x008c>; + +template<> +struct Packet_Head<0x008d>; +template<> +struct NetPacket_Head<0x008d>; +template<> +struct Packet_Repeat<0x008d>; +template<> +struct NetPacket_Repeat<0x008d>; + +template<> +struct Packet_Head<0x008e>; +template<> +struct NetPacket_Head<0x008e>; +template<> +struct Packet_Repeat<0x008e>; +template<> +struct NetPacket_Repeat<0x008e>; + +template<> +struct Packet_Fixed<0x0090>; +template<> +struct NetPacket_Fixed<0x0090>; + +template<> +struct Packet_Fixed<0x0091>; +template<> +struct NetPacket_Fixed<0x0091>; + +template<> +struct Packet_Fixed<0x0092>; +template<> +struct NetPacket_Fixed<0x0092>; + +template<> +struct Packet_Fixed<0x0094>; +template<> +struct NetPacket_Fixed<0x0094>; + +template<> +struct Packet_Fixed<0x0095>; +template<> +struct NetPacket_Fixed<0x0095>; + +template<> +struct Packet_Head<0x0096>; +template<> +struct NetPacket_Head<0x0096>; +template<> +struct Packet_Repeat<0x0096>; +template<> +struct NetPacket_Repeat<0x0096>; + +template<> +struct Packet_Head<0x0097>; +template<> +struct NetPacket_Head<0x0097>; +template<> +struct Packet_Repeat<0x0097>; +template<> +struct NetPacket_Repeat<0x0097>; + +template<> +struct Packet_Fixed<0x0098>; +template<> +struct NetPacket_Fixed<0x0098>; + +template<> +struct Packet_Head<0x009a>; +template<> +struct NetPacket_Head<0x009a>; +template<> +struct Packet_Repeat<0x009a>; +template<> +struct NetPacket_Repeat<0x009a>; + +template<> +struct Packet_Fixed<0x009b>; +template<> +struct NetPacket_Fixed<0x009b>; + +template<> +struct Packet_Fixed<0x009c>; +template<> +struct NetPacket_Fixed<0x009c>; + +template<> +struct Packet_Fixed<0x009d>; +template<> +struct NetPacket_Fixed<0x009d>; + +template<> +struct Packet_Fixed<0x009e>; +template<> +struct NetPacket_Fixed<0x009e>; + +template<> +struct Packet_Fixed<0x009f>; +template<> +struct NetPacket_Fixed<0x009f>; + +template<> +struct Packet_Fixed<0x00a0>; +template<> +struct NetPacket_Fixed<0x00a0>; + +template<> +struct Packet_Fixed<0x00a1>; +template<> +struct NetPacket_Fixed<0x00a1>; + +template<> +struct Packet_Fixed<0x00a2>; +template<> +struct NetPacket_Fixed<0x00a2>; + +template<> +struct Packet_Head<0x00a4>; +template<> +struct NetPacket_Head<0x00a4>; +template<> +struct Packet_Repeat<0x00a4>; +template<> +struct NetPacket_Repeat<0x00a4>; + +template<> +struct Packet_Head<0x00a6>; +template<> +struct NetPacket_Head<0x00a6>; +template<> +struct Packet_Repeat<0x00a6>; +template<> +struct NetPacket_Repeat<0x00a6>; + +template<> +struct Packet_Fixed<0x00a7>; +template<> +struct NetPacket_Fixed<0x00a7>; + +template<> +struct Packet_Fixed<0x00a8>; +template<> +struct NetPacket_Fixed<0x00a8>; + +template<> +struct Packet_Fixed<0x00a9>; +template<> +struct NetPacket_Fixed<0x00a9>; + +template<> +struct Packet_Fixed<0x00aa>; +template<> +struct NetPacket_Fixed<0x00aa>; + +template<> +struct Packet_Fixed<0x00ab>; +template<> +struct NetPacket_Fixed<0x00ab>; + +template<> +struct Packet_Fixed<0x00ac>; +template<> +struct NetPacket_Fixed<0x00ac>; + +template<> +struct Packet_Fixed<0x00af>; +template<> +struct NetPacket_Fixed<0x00af>; + +template<> +struct Packet_Fixed<0x00b0>; +template<> +struct NetPacket_Fixed<0x00b0>; + +template<> +struct Packet_Fixed<0x00b1>; +template<> +struct NetPacket_Fixed<0x00b1>; + +template<> +struct Packet_Fixed<0x00b2>; +template<> +struct NetPacket_Fixed<0x00b2>; + +template<> +struct Packet_Fixed<0x00b3>; +template<> +struct NetPacket_Fixed<0x00b3>; + +template<> +struct Packet_Head<0x00b4>; +template<> +struct NetPacket_Head<0x00b4>; +template<> +struct Packet_Repeat<0x00b4>; +template<> +struct NetPacket_Repeat<0x00b4>; + +template<> +struct Packet_Fixed<0x00b5>; +template<> +struct NetPacket_Fixed<0x00b5>; + +template<> +struct Packet_Fixed<0x00b6>; +template<> +struct NetPacket_Fixed<0x00b6>; + +template<> +struct Packet_Head<0x00b7>; +template<> +struct NetPacket_Head<0x00b7>; +template<> +struct Packet_Repeat<0x00b7>; +template<> +struct NetPacket_Repeat<0x00b7>; + +template<> +struct Packet_Fixed<0x00b8>; +template<> +struct NetPacket_Fixed<0x00b8>; + +template<> +struct Packet_Fixed<0x00b9>; +template<> +struct NetPacket_Fixed<0x00b9>; + +template<> +struct Packet_Fixed<0x00bb>; +template<> +struct NetPacket_Fixed<0x00bb>; + +template<> +struct Packet_Fixed<0x00bc>; +template<> +struct NetPacket_Fixed<0x00bc>; + +template<> +struct Packet_Fixed<0x00bd>; +template<> +struct NetPacket_Fixed<0x00bd>; + +template<> +struct Packet_Fixed<0x00be>; +template<> +struct NetPacket_Fixed<0x00be>; + +template<> +struct Packet_Fixed<0x00bf>; +template<> +struct NetPacket_Fixed<0x00bf>; + +template<> +struct Packet_Fixed<0x00c0>; +template<> +struct NetPacket_Fixed<0x00c0>; + +template<> +struct Packet_Fixed<0x00c1>; +template<> +struct NetPacket_Fixed<0x00c1>; + +template<> +struct Packet_Fixed<0x00c2>; +template<> +struct NetPacket_Fixed<0x00c2>; + +template<> +struct Packet_Fixed<0x00c4>; +template<> +struct NetPacket_Fixed<0x00c4>; + +template<> +struct Packet_Fixed<0x00c5>; +template<> +struct NetPacket_Fixed<0x00c5>; + +template<> +struct Packet_Head<0x00c6>; +template<> +struct NetPacket_Head<0x00c6>; +template<> +struct Packet_Repeat<0x00c6>; +template<> +struct NetPacket_Repeat<0x00c6>; + +template<> +struct Packet_Head<0x00c7>; +template<> +struct NetPacket_Head<0x00c7>; +template<> +struct Packet_Repeat<0x00c7>; +template<> +struct NetPacket_Repeat<0x00c7>; + +template<> +struct Packet_Head<0x00c8>; +template<> +struct NetPacket_Head<0x00c8>; +template<> +struct Packet_Repeat<0x00c8>; +template<> +struct NetPacket_Repeat<0x00c8>; + +template<> +struct Packet_Head<0x00c9>; +template<> +struct NetPacket_Head<0x00c9>; +template<> +struct Packet_Repeat<0x00c9>; +template<> +struct NetPacket_Repeat<0x00c9>; + +template<> +struct Packet_Fixed<0x00ca>; +template<> +struct NetPacket_Fixed<0x00ca>; + +template<> +struct Packet_Fixed<0x00cb>; +template<> +struct NetPacket_Fixed<0x00cb>; + +template<> +struct Packet_Fixed<0x00cd>; +template<> +struct NetPacket_Fixed<0x00cd>; + +template<> +struct Packet_Fixed<0x00e4>; +template<> +struct NetPacket_Fixed<0x00e4>; + +template<> +struct Packet_Fixed<0x00e5>; +template<> +struct NetPacket_Fixed<0x00e5>; + +template<> +struct Packet_Fixed<0x00e6>; +template<> +struct NetPacket_Fixed<0x00e6>; + +template<> +struct Packet_Fixed<0x00e7>; +template<> +struct NetPacket_Fixed<0x00e7>; + +template<> +struct Packet_Fixed<0x00e8>; +template<> +struct NetPacket_Fixed<0x00e8>; + +template<> +struct Packet_Fixed<0x00e9>; +template<> +struct NetPacket_Fixed<0x00e9>; + +template<> +struct Packet_Fixed<0x00eb>; +template<> +struct NetPacket_Fixed<0x00eb>; + +template<> +struct Packet_Fixed<0x00ec>; +template<> +struct NetPacket_Fixed<0x00ec>; + +template<> +struct Packet_Fixed<0x00ed>; +template<> +struct NetPacket_Fixed<0x00ed>; + +template<> +struct Packet_Fixed<0x00ee>; +template<> +struct NetPacket_Fixed<0x00ee>; + +template<> +struct Packet_Fixed<0x00ef>; +template<> +struct NetPacket_Fixed<0x00ef>; + +template<> +struct Packet_Fixed<0x00f0>; +template<> +struct NetPacket_Fixed<0x00f0>; + +template<> +struct Packet_Fixed<0x00f2>; +template<> +struct NetPacket_Fixed<0x00f2>; + +template<> +struct Packet_Fixed<0x00f3>; +template<> +struct NetPacket_Fixed<0x00f3>; + +template<> +struct Packet_Fixed<0x00f4>; +template<> +struct NetPacket_Fixed<0x00f4>; + +template<> +struct Packet_Fixed<0x00f5>; +template<> +struct NetPacket_Fixed<0x00f5>; + +template<> +struct Packet_Fixed<0x00f6>; +template<> +struct NetPacket_Fixed<0x00f6>; + +template<> +struct Packet_Fixed<0x00f7>; +template<> +struct NetPacket_Fixed<0x00f7>; + +template<> +struct Packet_Fixed<0x00f8>; +template<> +struct NetPacket_Fixed<0x00f8>; + +template<> +struct Packet_Fixed<0x00f9>; +template<> +struct NetPacket_Fixed<0x00f9>; + +template<> +struct Packet_Fixed<0x00fa>; +template<> +struct NetPacket_Fixed<0x00fa>; + +template<> +struct Packet_Head<0x00fb>; +template<> +struct NetPacket_Head<0x00fb>; +template<> +struct Packet_Repeat<0x00fb>; +template<> +struct NetPacket_Repeat<0x00fb>; + +template<> +struct Packet_Fixed<0x00fc>; +template<> +struct NetPacket_Fixed<0x00fc>; + +template<> +struct Packet_Fixed<0x00fd>; +template<> +struct NetPacket_Fixed<0x00fd>; + +template<> +struct Packet_Fixed<0x00fe>; +template<> +struct NetPacket_Fixed<0x00fe>; + +template<> +struct Packet_Fixed<0x00ff>; +template<> +struct NetPacket_Fixed<0x00ff>; + +template<> +struct Packet_Fixed<0x0100>; +template<> +struct NetPacket_Fixed<0x0100>; + +template<> +struct Packet_Fixed<0x0101>; +template<> +struct NetPacket_Fixed<0x0101>; + +template<> +struct Packet_Fixed<0x0102>; +template<> +struct NetPacket_Fixed<0x0102>; + +template<> +struct Packet_Fixed<0x0103>; +template<> +struct NetPacket_Fixed<0x0103>; + +template<> +struct Packet_Fixed<0x0105>; +template<> +struct NetPacket_Fixed<0x0105>; + +template<> +struct Packet_Fixed<0x0106>; +template<> +struct NetPacket_Fixed<0x0106>; + +template<> +struct Packet_Fixed<0x0107>; +template<> +struct NetPacket_Fixed<0x0107>; + +template<> +struct Packet_Head<0x0108>; +template<> +struct NetPacket_Head<0x0108>; +template<> +struct Packet_Repeat<0x0108>; +template<> +struct NetPacket_Repeat<0x0108>; + +template<> +struct Packet_Head<0x0109>; +template<> +struct NetPacket_Head<0x0109>; +template<> +struct Packet_Repeat<0x0109>; +template<> +struct NetPacket_Repeat<0x0109>; + +template<> +struct Packet_Fixed<0x010c>; +template<> +struct NetPacket_Fixed<0x010c>; + +template<> +struct Packet_Fixed<0x010e>; +template<> +struct NetPacket_Fixed<0x010e>; + +template<> +struct Packet_Head<0x010f>; +template<> +struct NetPacket_Head<0x010f>; +template<> +struct Packet_Repeat<0x010f>; +template<> +struct NetPacket_Repeat<0x010f>; + +template<> +struct Packet_Fixed<0x0110>; +template<> +struct NetPacket_Fixed<0x0110>; + +template<> +struct Packet_Fixed<0x0112>; +template<> +struct NetPacket_Fixed<0x0112>; + +template<> +struct Packet_Fixed<0x0118>; +template<> +struct NetPacket_Fixed<0x0118>; + +template<> +struct Packet_Fixed<0x0119>; +template<> +struct NetPacket_Fixed<0x0119>; + +template<> +struct Packet_Fixed<0x0139>; +template<> +struct NetPacket_Fixed<0x0139>; + +template<> +struct Packet_Fixed<0x013a>; +template<> +struct NetPacket_Fixed<0x013a>; + +template<> +struct Packet_Fixed<0x013b>; +template<> +struct NetPacket_Fixed<0x013b>; + +template<> +struct Packet_Fixed<0x013c>; +template<> +struct NetPacket_Fixed<0x013c>; + +template<> +struct Packet_Fixed<0x0141>; +template<> +struct NetPacket_Fixed<0x0141>; + +template<> +struct Packet_Fixed<0x0142>; +template<> +struct NetPacket_Fixed<0x0142>; + +template<> +struct Packet_Fixed<0x0143>; +template<> +struct NetPacket_Fixed<0x0143>; + +template<> +struct Packet_Fixed<0x0146>; +template<> +struct NetPacket_Fixed<0x0146>; + +template<> +struct Packet_Fixed<0x0147>; +template<> +struct NetPacket_Fixed<0x0147>; + +template<> +struct Packet_Fixed<0x0148>; +template<> +struct NetPacket_Fixed<0x0148>; + +template<> +struct Packet_Fixed<0x014d>; +template<> +struct NetPacket_Fixed<0x014d>; + +template<> +struct Packet_Fixed<0x018a>; +template<> +struct NetPacket_Fixed<0x018a>; + +template<> +struct Packet_Fixed<0x018b>; +template<> +struct NetPacket_Fixed<0x018b>; + +template<> +struct Packet_Fixed<0x0195>; +template<> +struct NetPacket_Fixed<0x0195>; + +template<> +struct Packet_Fixed<0x0196>; +template<> +struct NetPacket_Fixed<0x0196>; + +template<> +struct Packet_Fixed<0x019b>; +template<> +struct NetPacket_Fixed<0x019b>; + +template<> +struct Packet_Fixed<0x01b1>; +template<> +struct NetPacket_Fixed<0x01b1>; + +template<> +struct Packet_Fixed<0x01c8>; +template<> +struct NetPacket_Fixed<0x01c8>; + +template<> +struct Packet_Fixed<0x01d4>; +template<> +struct NetPacket_Fixed<0x01d4>; + +template<> +struct Packet_Head<0x01d5>; +template<> +struct NetPacket_Head<0x01d5>; +template<> +struct Packet_Repeat<0x01d5>; +template<> +struct NetPacket_Repeat<0x01d5>; + +template<> +struct Packet_Fixed<0x01d7>; +template<> +struct NetPacket_Fixed<0x01d7>; + +template<> +struct Packet_Fixed<0x01d8>; +template<> +struct NetPacket_Fixed<0x01d8>; + +template<> +struct Packet_Fixed<0x01d9>; +template<> +struct NetPacket_Fixed<0x01d9>; + +template<> +struct Packet_Fixed<0x01da>; +template<> +struct NetPacket_Fixed<0x01da>; + +template<> +struct Packet_Fixed<0x01de>; +template<> +struct NetPacket_Fixed<0x01de>; + +template<> +struct Packet_Head<0x01ee>; +template<> +struct NetPacket_Head<0x01ee>; +template<> +struct Packet_Repeat<0x01ee>; +template<> +struct NetPacket_Repeat<0x01ee>; + +template<> +struct Packet_Head<0x01f0>; +template<> +struct NetPacket_Head<0x01f0>; +template<> +struct Packet_Repeat<0x01f0>; +template<> +struct NetPacket_Repeat<0x01f0>; + +template<> +struct Packet_Fixed<0x020c>; +template<> +struct NetPacket_Fixed<0x020c>; + +template<> +struct Packet_Fixed<0x0212>; +template<> +struct NetPacket_Fixed<0x0212>; + + +template<> +struct Packet_Fixed<0x0081>; +template<> +struct NetPacket_Fixed<0x0081>; + +template<> +struct Packet_Fixed<0x7530>; +template<> +struct NetPacket_Fixed<0x7530>; + +template<> +struct Packet_Fixed<0x7531>; +template<> +struct NetPacket_Fixed<0x7531>; + +template<> +struct Packet_Fixed<0x7532>; +template<> +struct NetPacket_Fixed<0x7532>; + +template<> +struct Packet_Payload<0x8000>; +template<> +struct NetPacket_Payload<0x8000>; + + +} // namespace tmwa diff --git a/src/proto2/include_clif_t_test.cpp b/src/proto2/include_clif_t_test.cpp new file mode 100644 index 0000000..f0125fe --- /dev/null +++ b/src/proto2/include_clif_t_test.cpp @@ -0,0 +1,41 @@ +#include "../map/clif.t.hpp" +// include_clif_t_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_Position1 = Position1; +using Test_NetPosition1 = NetPosition1; +using Test_Position2 = Position2; +using Test_NetPosition2 = NetPosition2; +using Test_BeingRemoveWhy = BeingRemoveWhy; +using Test_DIR = DIR; +using Test_Opt1 = Opt1; +using Test_Opt2 = Opt2; +using Test_Opt3 = Opt3; +using Test_ItemType = ItemType; +using Test_PickupFail = PickupFail; +using Test_DamageType = DamageType; +using Test_SP = SP; +using Test_LOOK = LOOK; +using Test_IOff2 = IOff2; +using Test_SOff1 = SOff1; +} // namespace tmwa diff --git a/src/proto2/include_consts_test.cpp b/src/proto2/include_consts_test.cpp new file mode 100644 index 0000000..634c0e9 --- /dev/null +++ b/src/proto2/include_consts_test.cpp @@ -0,0 +1,26 @@ +#include "../mmo/consts.hpp" +// include_consts_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_PartyMember = PartyMember; +} // namespace tmwa diff --git a/src/proto2/include_cstdint_test.cpp b/src/proto2/include_cstdint_test.cpp new file mode 100644 index 0000000..85bab61 --- /dev/null +++ b/src/proto2/include_cstdint_test.cpp @@ -0,0 +1,33 @@ +#include <cstdint> +// include_cstdint_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_uint8_t = uint8_t; +using Test_uint16_t = uint16_t; +using Test_uint32_t = uint32_t; +using Test_uint64_t = uint64_t; +using Test_int8_t = int8_t; +using Test_int16_t = int16_t; +using Test_int32_t = int32_t; +using Test_int64_t = int64_t; +} // namespace tmwa diff --git a/src/proto2/include_enums_test.cpp b/src/proto2/include_enums_test.cpp new file mode 100644 index 0000000..f409d28 --- /dev/null +++ b/src/proto2/include_enums_test.cpp @@ -0,0 +1,29 @@ +#include "../mmo/enums.hpp" +// include_enums_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_SEX = SEX; +using Test_Option = Option; +using Test_EPOS = EPOS; +using Test_ItemLook = ItemLook; +} // namespace tmwa diff --git a/src/proto2/include_human_time_diff_test.cpp b/src/proto2/include_human_time_diff_test.cpp new file mode 100644 index 0000000..2e16c99 --- /dev/null +++ b/src/proto2/include_human_time_diff_test.cpp @@ -0,0 +1,26 @@ +#include "../mmo/human_time_diff.hpp" +// include_human_time_diff_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_HumanTimeDiff = HumanTimeDiff; +} // namespace tmwa diff --git a/src/proto2/include_ids_test.cpp b/src/proto2/include_ids_test.cpp new file mode 100644 index 0000000..1c1eeca --- /dev/null +++ b/src/proto2/include_ids_test.cpp @@ -0,0 +1,32 @@ +#include "../mmo/ids.hpp" +// include_ids_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_Species = Species; +using Test_AccountId = AccountId; +using Test_CharId = CharId; +using Test_PartyId = PartyId; +using Test_ItemNameId = ItemNameId; +using Test_BlockId = BlockId; +using Test_GmLevel = GmLevel; +} // namespace tmwa diff --git a/src/proto2/include_ip_test.cpp b/src/proto2/include_ip_test.cpp new file mode 100644 index 0000000..d380651 --- /dev/null +++ b/src/proto2/include_ip_test.cpp @@ -0,0 +1,26 @@ +#include "../net/ip.hpp" +// include_ip_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_IP4Address = IP4Address; +} // namespace tmwa diff --git a/src/proto2/include_little_test.cpp b/src/proto2/include_little_test.cpp new file mode 100644 index 0000000..08a4fbd --- /dev/null +++ b/src/proto2/include_little_test.cpp @@ -0,0 +1,29 @@ +#include "../ints/little.hpp" +// include_little_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_Byte = Byte; +using Test_Little16 = Little16; +using Test_Little32 = Little32; +using Test_Little64 = Little64; +} // namespace tmwa diff --git a/src/proto2/include_login_t_test.cpp b/src/proto2/include_login_t_test.cpp new file mode 100644 index 0000000..808e02e --- /dev/null +++ b/src/proto2/include_login_t_test.cpp @@ -0,0 +1,26 @@ +#include "../login/login.t.hpp" +// include_login_t_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_VERSION_2 = VERSION_2; +} // namespace tmwa diff --git a/src/proto2/include_skill_t_test.cpp b/src/proto2/include_skill_t_test.cpp new file mode 100644 index 0000000..4bd944f --- /dev/null +++ b/src/proto2/include_skill_t_test.cpp @@ -0,0 +1,28 @@ +#include "../map/skill.t.hpp" +// include_skill_t_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_SkillID = SkillID; +using Test_StatusChange = StatusChange; +using Test_SkillFlags = SkillFlags; +} // namespace tmwa diff --git a/src/proto2/include_strs_test.cpp b/src/proto2/include_strs_test.cpp new file mode 100644 index 0000000..67b41f4 --- /dev/null +++ b/src/proto2/include_strs_test.cpp @@ -0,0 +1,33 @@ +#include "../mmo/strs.hpp" +// include_strs_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_AccountName = AccountName; +using Test_AccountPass = AccountPass; +using Test_AccountEmail = AccountEmail; +using Test_ServerName = ServerName; +using Test_PartyName = PartyName; +using Test_VarName = VarName; +using Test_CharName = CharName; +using Test_MapName = MapName; +} // namespace tmwa diff --git a/src/proto2/include_timer_t_test.cpp b/src/proto2/include_timer_t_test.cpp new file mode 100644 index 0000000..a936021 --- /dev/null +++ b/src/proto2/include_timer_t_test.cpp @@ -0,0 +1,27 @@ +#include "../net/timer.t.hpp" +// include_timer_t_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_tick_t = tick_t; +using Test_interval_t = interval_t; +} // namespace tmwa diff --git a/src/proto2/include_utils_test.cpp b/src/proto2/include_utils_test.cpp new file mode 100644 index 0000000..5b6c92d --- /dev/null +++ b/src/proto2/include_utils_test.cpp @@ -0,0 +1,28 @@ +#include "../mmo/utils.hpp" +// include_utils_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_TimeT = TimeT; +using Test_timestamp_seconds_buffer = timestamp_seconds_buffer; +using Test_timestamp_milliseconds_buffer = timestamp_milliseconds_buffer; +} // namespace tmwa diff --git a/src/proto2/include_version_test.cpp b/src/proto2/include_version_test.cpp new file mode 100644 index 0000000..13856b9 --- /dev/null +++ b/src/proto2/include_version_test.cpp @@ -0,0 +1,26 @@ +#include "../mmo/version.hpp" +// include_version_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_Version = Version; +} // namespace tmwa diff --git a/src/proto2/include_vstring_test.cpp b/src/proto2/include_vstring_test.cpp new file mode 100644 index 0000000..3570a29 --- /dev/null +++ b/src/proto2/include_vstring_test.cpp @@ -0,0 +1,30 @@ +#include "../strings/vstring.hpp" +// include_vstring_test.cpp - testsuite for protocol includes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + +namespace tmwa +{ +using Test_VString_15_ = VString<15>; +using Test_VString_19_ = VString<19>; +using Test_VString_23_ = VString<23>; +using Test_VString_31_ = VString<31>; +using Test_VString_39_ = VString<39>; +} // namespace tmwa diff --git a/src/proto2/login-admin.hpp b/src/proto2/login-admin.hpp new file mode 100644 index 0000000..9d5fb5e --- /dev/null +++ b/src/proto2/login-admin.hpp @@ -0,0 +1,2218 @@ +#pragma once +// login-admin.hpp - TMWA network protocol: login/admin +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "fwd.hpp" + +#include "types.hpp" + +namespace tmwa +{ +// This is an internal protocol, and can be changed without notice + +template<> +struct Packet_Head<0x2726> +{ + static const uint16_t PACKET_ID = 0x2726; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t unused = {}; + // TODO remove this + uint32_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x2726> +{ + static const uint16_t PACKET_ID = 0x2726; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x7918> +{ + static const uint16_t PACKET_ID = 0x7918; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t encryption_zero = {}; + AccountPass account_pass = {}; +}; + +template<> +struct Packet_Fixed<0x7919> +{ + static const uint16_t PACKET_ID = 0x7919; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t error = {}; +}; + +template<> +struct Packet_Fixed<0x7920> +{ + static const uint16_t PACKET_ID = 0x7920; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId start_account_id = {}; + AccountId end_account_id = {}; +}; + +template<> +struct Packet_Head<0x7921> +{ + static const uint16_t PACKET_ID = 0x7921; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x7921> +{ + static const uint16_t PACKET_ID = 0x7921; + + AccountId account_id = {}; + GmLevel gm_level = {}; + AccountName account_name = {}; + SEX sex = {}; + uint32_t login_count = {}; + uint32_t status = {}; +}; + +template<> +struct Packet_Fixed<0x7924> +{ + static const uint16_t PACKET_ID = 0x7924; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + ItemNameId source_item_id = {}; + ItemNameId dest_item_id = {}; +}; + +template<> +struct Packet_Fixed<0x7925> +{ + static const uint16_t PACKET_ID = 0x7925; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x7930> +{ + static const uint16_t PACKET_ID = 0x7930; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + AccountPass password = {}; + SEX sex = {}; + AccountEmail email = {}; +}; + +template<> +struct Packet_Fixed<0x7931> +{ + static const uint16_t PACKET_ID = 0x7931; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; +}; + +template<> +struct Packet_Fixed<0x7932> +{ + static const uint16_t PACKET_ID = 0x7932; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; +}; + +template<> +struct Packet_Fixed<0x7933> +{ + static const uint16_t PACKET_ID = 0x7933; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; +}; + +template<> +struct Packet_Fixed<0x7934> +{ + static const uint16_t PACKET_ID = 0x7934; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + AccountPass password = {}; +}; + +template<> +struct Packet_Fixed<0x7935> +{ + static const uint16_t PACKET_ID = 0x7935; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; +}; + +template<> +struct Packet_Fixed<0x7936> +{ + static const uint16_t PACKET_ID = 0x7936; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + uint32_t status = {}; + timestamp_seconds_buffer error_message = {}; +}; + +template<> +struct Packet_Fixed<0x7937> +{ + static const uint16_t PACKET_ID = 0x7937; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; + uint32_t status = {}; +}; + +template<> +struct Packet_Fixed<0x7938> +{ + static const uint16_t PACKET_ID = 0x7938; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Head<0x7939> +{ + static const uint16_t PACKET_ID = 0x7939; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x7939> +{ + static const uint16_t PACKET_ID = 0x7939; + + IP4Address ip = {}; + uint16_t port = {}; + ServerName name = {}; + uint16_t users = {}; + uint16_t maintenance = {}; + uint16_t is_new = {}; +}; + +template<> +struct Packet_Fixed<0x793a> +{ + static const uint16_t PACKET_ID = 0x793a; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + AccountPass password = {}; +}; + +template<> +struct Packet_Fixed<0x793b> +{ + static const uint16_t PACKET_ID = 0x793b; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; +}; + +template<> +struct Packet_Fixed<0x793c> +{ + static const uint16_t PACKET_ID = 0x793c; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + SEX sex = {}; +}; + +template<> +struct Packet_Fixed<0x793d> +{ + static const uint16_t PACKET_ID = 0x793d; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; +}; + +template<> +struct Packet_Fixed<0x793e> +{ + static const uint16_t PACKET_ID = 0x793e; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + GmLevel gm_level = {}; +}; + +template<> +struct Packet_Fixed<0x793f> +{ + static const uint16_t PACKET_ID = 0x793f; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; +}; + +template<> +struct Packet_Fixed<0x7940> +{ + static const uint16_t PACKET_ID = 0x7940; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + AccountEmail email = {}; +}; + +template<> +struct Packet_Fixed<0x7941> +{ + static const uint16_t PACKET_ID = 0x7941; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; +}; + +template<> +struct Packet_Head<0x7942> +{ + static const uint16_t PACKET_ID = 0x7942; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x7942> +{ + static const uint16_t PACKET_ID = 0x7942; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x7943> +{ + static const uint16_t PACKET_ID = 0x7943; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; +}; + +template<> +struct Packet_Fixed<0x7944> +{ + static const uint16_t PACKET_ID = 0x7944; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; +}; + +template<> +struct Packet_Fixed<0x7945> +{ + static const uint16_t PACKET_ID = 0x7945; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; +}; + +template<> +struct Packet_Fixed<0x7946> +{ + static const uint16_t PACKET_ID = 0x7946; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Fixed<0x7947> +{ + static const uint16_t PACKET_ID = 0x7947; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; +}; + +template<> +struct Packet_Fixed<0x7948> +{ + static const uint16_t PACKET_ID = 0x7948; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + TimeT valid_until = {}; +}; + +template<> +struct Packet_Fixed<0x7949> +{ + static const uint16_t PACKET_ID = 0x7949; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; + TimeT valid_until = {}; +}; + +template<> +struct Packet_Fixed<0x794a> +{ + static const uint16_t PACKET_ID = 0x794a; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + TimeT ban_until = {}; +}; + +template<> +struct Packet_Fixed<0x794b> +{ + static const uint16_t PACKET_ID = 0x794b; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; + TimeT ban_until = {}; +}; + +template<> +struct Packet_Fixed<0x794c> +{ + static const uint16_t PACKET_ID = 0x794c; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + HumanTimeDiff ban_add = {}; +}; + +template<> +struct Packet_Fixed<0x794d> +{ + static const uint16_t PACKET_ID = 0x794d; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; + TimeT ban_until = {}; +}; + +template<> +struct Packet_Head<0x794e> +{ + static const uint16_t PACKET_ID = 0x794e; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t unused = {}; + // TODO remove this + uint32_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x794e> +{ + static const uint16_t PACKET_ID = 0x794e; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x794f> +{ + static const uint16_t PACKET_ID = 0x794f; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t error = {}; +}; + +template<> +struct Packet_Fixed<0x7950> +{ + static const uint16_t PACKET_ID = 0x7950; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + HumanTimeDiff valid_add = {}; +}; + +template<> +struct Packet_Fixed<0x7951> +{ + static const uint16_t PACKET_ID = 0x7951; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountName account_name = {}; + TimeT valid_until = {}; +}; + +template<> +struct Packet_Fixed<0x7952> +{ + static const uint16_t PACKET_ID = 0x7952; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; +}; + +template<> +struct Packet_Head<0x7953> +{ + static const uint16_t PACKET_ID = 0x7953; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + GmLevel gm_level = {}; + AccountName account_name = {}; + SEX sex = {}; + uint32_t login_count = {}; + uint32_t state = {}; + timestamp_seconds_buffer error_message = {}; + timestamp_milliseconds_buffer last_login_string = {}; + VString<15> ip_string = {}; + AccountEmail email = {}; + TimeT connect_until = {}; + TimeT ban_until = {}; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x7953> +{ + static const uint16_t PACKET_ID = 0x7953; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x7954> +{ + static const uint16_t PACKET_ID = 0x7954; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Fixed<0x7955> +{ + static const uint16_t PACKET_ID = 0x7955; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + + +template<> +struct NetPacket_Head<0x2726> +{ + Little16 magic_packet_id; + Little16 unused; + SkewedLength<Little32, 8> magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x2726>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2726>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2726>, unused) == 2, "offsetof(NetPacket_Head<0x2726>, unused) == 2"); +static_assert(offsetof(NetPacket_Head<0x2726>, magic_packet_length) == 4, "offsetof(NetPacket_Head<0x2726>, magic_packet_length) == 4"); +static_assert(sizeof(NetPacket_Head<0x2726>) == 8, "sizeof(NetPacket_Head<0x2726>) == 8"); +static_assert(alignof(NetPacket_Head<0x2726>) == 1, "alignof(NetPacket_Head<0x2726>) == 1"); +template<> +struct NetPacket_Repeat<0x2726> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x2726>, c) == 0, "offsetof(NetPacket_Repeat<0x2726>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x2726>) == 1, "sizeof(NetPacket_Repeat<0x2726>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x2726>) == 1, "alignof(NetPacket_Repeat<0x2726>) == 1"); + +template<> +struct NetPacket_Fixed<0x7918> +{ + Little16 magic_packet_id; + Little16 encryption_zero; + NetString<sizeof(AccountPass)> account_pass; +}; +static_assert(offsetof(NetPacket_Fixed<0x7918>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7918>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7918>, encryption_zero) == 2, "offsetof(NetPacket_Fixed<0x7918>, encryption_zero) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7918>, account_pass) == 4, "offsetof(NetPacket_Fixed<0x7918>, account_pass) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x7918>) == 28, "sizeof(NetPacket_Fixed<0x7918>) == 28"); +static_assert(alignof(NetPacket_Fixed<0x7918>) == 1, "alignof(NetPacket_Fixed<0x7918>) == 1"); + +template<> +struct NetPacket_Fixed<0x7919> +{ + Little16 magic_packet_id; + Byte error; +}; +static_assert(offsetof(NetPacket_Fixed<0x7919>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7919>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7919>, error) == 2, "offsetof(NetPacket_Fixed<0x7919>, error) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x7919>) == 3, "sizeof(NetPacket_Fixed<0x7919>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x7919>) == 1, "alignof(NetPacket_Fixed<0x7919>) == 1"); + +template<> +struct NetPacket_Fixed<0x7920> +{ + Little16 magic_packet_id; + Little32 start_account_id; + Little32 end_account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x7920>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7920>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7920>, start_account_id) == 2, "offsetof(NetPacket_Fixed<0x7920>, start_account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7920>, end_account_id) == 6, "offsetof(NetPacket_Fixed<0x7920>, end_account_id) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x7920>) == 10, "sizeof(NetPacket_Fixed<0x7920>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x7920>) == 1, "alignof(NetPacket_Fixed<0x7920>) == 1"); + +template<> +struct NetPacket_Head<0x7921> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x7921>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x7921>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x7921>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x7921>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x7921>) == 4, "sizeof(NetPacket_Head<0x7921>) == 4"); +static_assert(alignof(NetPacket_Head<0x7921>) == 1, "alignof(NetPacket_Head<0x7921>) == 1"); +template<> +struct NetPacket_Repeat<0x7921> +{ + Little32 account_id; + Byte gm_level; + NetString<sizeof(AccountName)> account_name; + Byte sex; + Little32 login_count; + Little32 status; +}; +static_assert(offsetof(NetPacket_Repeat<0x7921>, account_id) == 0, "offsetof(NetPacket_Repeat<0x7921>, account_id) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x7921>, gm_level) == 4, "offsetof(NetPacket_Repeat<0x7921>, gm_level) == 4"); +static_assert(offsetof(NetPacket_Repeat<0x7921>, account_name) == 5, "offsetof(NetPacket_Repeat<0x7921>, account_name) == 5"); +static_assert(offsetof(NetPacket_Repeat<0x7921>, sex) == 29, "offsetof(NetPacket_Repeat<0x7921>, sex) == 29"); +static_assert(offsetof(NetPacket_Repeat<0x7921>, login_count) == 30, "offsetof(NetPacket_Repeat<0x7921>, login_count) == 30"); +static_assert(offsetof(NetPacket_Repeat<0x7921>, status) == 34, "offsetof(NetPacket_Repeat<0x7921>, status) == 34"); +static_assert(sizeof(NetPacket_Repeat<0x7921>) == 38, "sizeof(NetPacket_Repeat<0x7921>) == 38"); +static_assert(alignof(NetPacket_Repeat<0x7921>) == 1, "alignof(NetPacket_Repeat<0x7921>) == 1"); + +template<> +struct NetPacket_Fixed<0x7924> +{ + Little16 magic_packet_id; + Little32 source_item_id; + Little32 dest_item_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x7924>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7924>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7924>, source_item_id) == 2, "offsetof(NetPacket_Fixed<0x7924>, source_item_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7924>, dest_item_id) == 6, "offsetof(NetPacket_Fixed<0x7924>, dest_item_id) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x7924>) == 10, "sizeof(NetPacket_Fixed<0x7924>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x7924>) == 1, "alignof(NetPacket_Fixed<0x7924>) == 1"); + +template<> +struct NetPacket_Fixed<0x7925> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x7925>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7925>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x7925>) == 2, "sizeof(NetPacket_Fixed<0x7925>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x7925>) == 1, "alignof(NetPacket_Fixed<0x7925>) == 1"); + +template<> +struct NetPacket_Fixed<0x7930> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + NetString<sizeof(AccountPass)> password; + char sex; + NetString<sizeof(AccountEmail)> email; +}; +static_assert(offsetof(NetPacket_Fixed<0x7930>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7930>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7930>, account_name) == 2, "offsetof(NetPacket_Fixed<0x7930>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7930>, password) == 26, "offsetof(NetPacket_Fixed<0x7930>, password) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x7930>, sex) == 50, "offsetof(NetPacket_Fixed<0x7930>, sex) == 50"); +static_assert(offsetof(NetPacket_Fixed<0x7930>, email) == 51, "offsetof(NetPacket_Fixed<0x7930>, email) == 51"); +static_assert(sizeof(NetPacket_Fixed<0x7930>) == 91, "sizeof(NetPacket_Fixed<0x7930>) == 91"); +static_assert(alignof(NetPacket_Fixed<0x7930>) == 1, "alignof(NetPacket_Fixed<0x7930>) == 1"); + +template<> +struct NetPacket_Fixed<0x7931> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x7931>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7931>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7931>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7931>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7931>, account_name) == 6, "offsetof(NetPacket_Fixed<0x7931>, account_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x7931>) == 30, "sizeof(NetPacket_Fixed<0x7931>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x7931>) == 1, "alignof(NetPacket_Fixed<0x7931>) == 1"); + +template<> +struct NetPacket_Fixed<0x7932> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x7932>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7932>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7932>, account_name) == 2, "offsetof(NetPacket_Fixed<0x7932>, account_name) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x7932>) == 26, "sizeof(NetPacket_Fixed<0x7932>) == 26"); +static_assert(alignof(NetPacket_Fixed<0x7932>) == 1, "alignof(NetPacket_Fixed<0x7932>) == 1"); + +template<> +struct NetPacket_Fixed<0x7933> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x7933>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7933>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7933>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7933>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7933>, account_name) == 6, "offsetof(NetPacket_Fixed<0x7933>, account_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x7933>) == 30, "sizeof(NetPacket_Fixed<0x7933>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x7933>) == 1, "alignof(NetPacket_Fixed<0x7933>) == 1"); + +template<> +struct NetPacket_Fixed<0x7934> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + NetString<sizeof(AccountPass)> password; +}; +static_assert(offsetof(NetPacket_Fixed<0x7934>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7934>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7934>, account_name) == 2, "offsetof(NetPacket_Fixed<0x7934>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7934>, password) == 26, "offsetof(NetPacket_Fixed<0x7934>, password) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x7934>) == 50, "sizeof(NetPacket_Fixed<0x7934>) == 50"); +static_assert(alignof(NetPacket_Fixed<0x7934>) == 1, "alignof(NetPacket_Fixed<0x7934>) == 1"); + +template<> +struct NetPacket_Fixed<0x7935> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x7935>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7935>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7935>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7935>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7935>, account_name) == 6, "offsetof(NetPacket_Fixed<0x7935>, account_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x7935>) == 30, "sizeof(NetPacket_Fixed<0x7935>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x7935>) == 1, "alignof(NetPacket_Fixed<0x7935>) == 1"); + +template<> +struct NetPacket_Fixed<0x7936> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + Little32 status; + NetString<sizeof(timestamp_seconds_buffer)> error_message; +}; +static_assert(offsetof(NetPacket_Fixed<0x7936>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7936>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7936>, account_name) == 2, "offsetof(NetPacket_Fixed<0x7936>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7936>, status) == 26, "offsetof(NetPacket_Fixed<0x7936>, status) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x7936>, error_message) == 30, "offsetof(NetPacket_Fixed<0x7936>, error_message) == 30"); +static_assert(sizeof(NetPacket_Fixed<0x7936>) == 50, "sizeof(NetPacket_Fixed<0x7936>) == 50"); +static_assert(alignof(NetPacket_Fixed<0x7936>) == 1, "alignof(NetPacket_Fixed<0x7936>) == 1"); + +template<> +struct NetPacket_Fixed<0x7937> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; + Little32 status; +}; +static_assert(offsetof(NetPacket_Fixed<0x7937>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7937>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7937>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7937>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7937>, account_name) == 6, "offsetof(NetPacket_Fixed<0x7937>, account_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x7937>, status) == 30, "offsetof(NetPacket_Fixed<0x7937>, status) == 30"); +static_assert(sizeof(NetPacket_Fixed<0x7937>) == 34, "sizeof(NetPacket_Fixed<0x7937>) == 34"); +static_assert(alignof(NetPacket_Fixed<0x7937>) == 1, "alignof(NetPacket_Fixed<0x7937>) == 1"); + +template<> +struct NetPacket_Fixed<0x7938> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x7938>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7938>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x7938>) == 2, "sizeof(NetPacket_Fixed<0x7938>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x7938>) == 1, "alignof(NetPacket_Fixed<0x7938>) == 1"); + +template<> +struct NetPacket_Head<0x7939> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x7939>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x7939>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x7939>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x7939>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x7939>) == 4, "sizeof(NetPacket_Head<0x7939>) == 4"); +static_assert(alignof(NetPacket_Head<0x7939>) == 1, "alignof(NetPacket_Head<0x7939>) == 1"); +template<> +struct NetPacket_Repeat<0x7939> +{ + IP4Address ip; + Little16 port; + NetString<sizeof(ServerName)> name; + Little16 users; + Little16 maintenance; + Little16 is_new; +}; +static_assert(offsetof(NetPacket_Repeat<0x7939>, ip) == 0, "offsetof(NetPacket_Repeat<0x7939>, ip) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x7939>, port) == 4, "offsetof(NetPacket_Repeat<0x7939>, port) == 4"); +static_assert(offsetof(NetPacket_Repeat<0x7939>, name) == 6, "offsetof(NetPacket_Repeat<0x7939>, name) == 6"); +static_assert(offsetof(NetPacket_Repeat<0x7939>, users) == 26, "offsetof(NetPacket_Repeat<0x7939>, users) == 26"); +static_assert(offsetof(NetPacket_Repeat<0x7939>, maintenance) == 28, "offsetof(NetPacket_Repeat<0x7939>, maintenance) == 28"); +static_assert(offsetof(NetPacket_Repeat<0x7939>, is_new) == 30, "offsetof(NetPacket_Repeat<0x7939>, is_new) == 30"); +static_assert(sizeof(NetPacket_Repeat<0x7939>) == 32, "sizeof(NetPacket_Repeat<0x7939>) == 32"); +static_assert(alignof(NetPacket_Repeat<0x7939>) == 1, "alignof(NetPacket_Repeat<0x7939>) == 1"); + +template<> +struct NetPacket_Fixed<0x793a> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + NetString<sizeof(AccountPass)> password; +}; +static_assert(offsetof(NetPacket_Fixed<0x793a>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x793a>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x793a>, account_name) == 2, "offsetof(NetPacket_Fixed<0x793a>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x793a>, password) == 26, "offsetof(NetPacket_Fixed<0x793a>, password) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x793a>) == 50, "sizeof(NetPacket_Fixed<0x793a>) == 50"); +static_assert(alignof(NetPacket_Fixed<0x793a>) == 1, "alignof(NetPacket_Fixed<0x793a>) == 1"); + +template<> +struct NetPacket_Fixed<0x793b> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x793b>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x793b>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x793b>, account_id) == 2, "offsetof(NetPacket_Fixed<0x793b>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x793b>, account_name) == 6, "offsetof(NetPacket_Fixed<0x793b>, account_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x793b>) == 30, "sizeof(NetPacket_Fixed<0x793b>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x793b>) == 1, "alignof(NetPacket_Fixed<0x793b>) == 1"); + +template<> +struct NetPacket_Fixed<0x793c> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + char sex; +}; +static_assert(offsetof(NetPacket_Fixed<0x793c>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x793c>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x793c>, account_name) == 2, "offsetof(NetPacket_Fixed<0x793c>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x793c>, sex) == 26, "offsetof(NetPacket_Fixed<0x793c>, sex) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x793c>) == 27, "sizeof(NetPacket_Fixed<0x793c>) == 27"); +static_assert(alignof(NetPacket_Fixed<0x793c>) == 1, "alignof(NetPacket_Fixed<0x793c>) == 1"); + +template<> +struct NetPacket_Fixed<0x793d> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x793d>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x793d>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x793d>, account_id) == 2, "offsetof(NetPacket_Fixed<0x793d>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x793d>, account_name) == 6, "offsetof(NetPacket_Fixed<0x793d>, account_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x793d>) == 30, "sizeof(NetPacket_Fixed<0x793d>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x793d>) == 1, "alignof(NetPacket_Fixed<0x793d>) == 1"); + +template<> +struct NetPacket_Fixed<0x793e> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + Byte gm_level; +}; +static_assert(offsetof(NetPacket_Fixed<0x793e>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x793e>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x793e>, account_name) == 2, "offsetof(NetPacket_Fixed<0x793e>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x793e>, gm_level) == 26, "offsetof(NetPacket_Fixed<0x793e>, gm_level) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x793e>) == 27, "sizeof(NetPacket_Fixed<0x793e>) == 27"); +static_assert(alignof(NetPacket_Fixed<0x793e>) == 1, "alignof(NetPacket_Fixed<0x793e>) == 1"); + +template<> +struct NetPacket_Fixed<0x793f> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x793f>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x793f>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x793f>, account_id) == 2, "offsetof(NetPacket_Fixed<0x793f>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x793f>, account_name) == 6, "offsetof(NetPacket_Fixed<0x793f>, account_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x793f>) == 30, "sizeof(NetPacket_Fixed<0x793f>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x793f>) == 1, "alignof(NetPacket_Fixed<0x793f>) == 1"); + +template<> +struct NetPacket_Fixed<0x7940> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + NetString<sizeof(AccountEmail)> email; +}; +static_assert(offsetof(NetPacket_Fixed<0x7940>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7940>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7940>, account_name) == 2, "offsetof(NetPacket_Fixed<0x7940>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7940>, email) == 26, "offsetof(NetPacket_Fixed<0x7940>, email) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x7940>) == 66, "sizeof(NetPacket_Fixed<0x7940>) == 66"); +static_assert(alignof(NetPacket_Fixed<0x7940>) == 1, "alignof(NetPacket_Fixed<0x7940>) == 1"); + +template<> +struct NetPacket_Fixed<0x7941> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x7941>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7941>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7941>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7941>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7941>, account_name) == 6, "offsetof(NetPacket_Fixed<0x7941>, account_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x7941>) == 30, "sizeof(NetPacket_Fixed<0x7941>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x7941>) == 1, "alignof(NetPacket_Fixed<0x7941>) == 1"); + +template<> +struct NetPacket_Head<0x7942> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + SkewedLength<Little16, 28> magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x7942>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x7942>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x7942>, account_name) == 2, "offsetof(NetPacket_Head<0x7942>, account_name) == 2"); +static_assert(offsetof(NetPacket_Head<0x7942>, magic_packet_length) == 26, "offsetof(NetPacket_Head<0x7942>, magic_packet_length) == 26"); +static_assert(sizeof(NetPacket_Head<0x7942>) == 28, "sizeof(NetPacket_Head<0x7942>) == 28"); +static_assert(alignof(NetPacket_Head<0x7942>) == 1, "alignof(NetPacket_Head<0x7942>) == 1"); +template<> +struct NetPacket_Repeat<0x7942> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x7942>, c) == 0, "offsetof(NetPacket_Repeat<0x7942>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x7942>) == 1, "sizeof(NetPacket_Repeat<0x7942>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x7942>) == 1, "alignof(NetPacket_Repeat<0x7942>) == 1"); + +template<> +struct NetPacket_Fixed<0x7943> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x7943>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7943>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7943>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7943>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7943>, account_name) == 6, "offsetof(NetPacket_Fixed<0x7943>, account_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x7943>) == 30, "sizeof(NetPacket_Fixed<0x7943>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x7943>) == 1, "alignof(NetPacket_Fixed<0x7943>) == 1"); + +template<> +struct NetPacket_Fixed<0x7944> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x7944>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7944>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7944>, account_name) == 2, "offsetof(NetPacket_Fixed<0x7944>, account_name) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x7944>) == 26, "sizeof(NetPacket_Fixed<0x7944>) == 26"); +static_assert(alignof(NetPacket_Fixed<0x7944>) == 1, "alignof(NetPacket_Fixed<0x7944>) == 1"); + +template<> +struct NetPacket_Fixed<0x7945> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x7945>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7945>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7945>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7945>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7945>, account_name) == 6, "offsetof(NetPacket_Fixed<0x7945>, account_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x7945>) == 30, "sizeof(NetPacket_Fixed<0x7945>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x7945>) == 1, "alignof(NetPacket_Fixed<0x7945>) == 1"); + +template<> +struct NetPacket_Fixed<0x7946> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x7946>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7946>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7946>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7946>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x7946>) == 6, "sizeof(NetPacket_Fixed<0x7946>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x7946>) == 1, "alignof(NetPacket_Fixed<0x7946>) == 1"); + +template<> +struct NetPacket_Fixed<0x7947> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x7947>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7947>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7947>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7947>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7947>, account_name) == 6, "offsetof(NetPacket_Fixed<0x7947>, account_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x7947>) == 30, "sizeof(NetPacket_Fixed<0x7947>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x7947>) == 1, "alignof(NetPacket_Fixed<0x7947>) == 1"); + +template<> +struct NetPacket_Fixed<0x7948> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + Little32 valid_until; +}; +static_assert(offsetof(NetPacket_Fixed<0x7948>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7948>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7948>, account_name) == 2, "offsetof(NetPacket_Fixed<0x7948>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7948>, valid_until) == 26, "offsetof(NetPacket_Fixed<0x7948>, valid_until) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x7948>) == 30, "sizeof(NetPacket_Fixed<0x7948>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x7948>) == 1, "alignof(NetPacket_Fixed<0x7948>) == 1"); + +template<> +struct NetPacket_Fixed<0x7949> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; + Little32 valid_until; +}; +static_assert(offsetof(NetPacket_Fixed<0x7949>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7949>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7949>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7949>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7949>, account_name) == 6, "offsetof(NetPacket_Fixed<0x7949>, account_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x7949>, valid_until) == 30, "offsetof(NetPacket_Fixed<0x7949>, valid_until) == 30"); +static_assert(sizeof(NetPacket_Fixed<0x7949>) == 34, "sizeof(NetPacket_Fixed<0x7949>) == 34"); +static_assert(alignof(NetPacket_Fixed<0x7949>) == 1, "alignof(NetPacket_Fixed<0x7949>) == 1"); + +template<> +struct NetPacket_Fixed<0x794a> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + Little32 ban_until; +}; +static_assert(offsetof(NetPacket_Fixed<0x794a>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x794a>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x794a>, account_name) == 2, "offsetof(NetPacket_Fixed<0x794a>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x794a>, ban_until) == 26, "offsetof(NetPacket_Fixed<0x794a>, ban_until) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x794a>) == 30, "sizeof(NetPacket_Fixed<0x794a>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x794a>) == 1, "alignof(NetPacket_Fixed<0x794a>) == 1"); + +template<> +struct NetPacket_Fixed<0x794b> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; + Little32 ban_until; +}; +static_assert(offsetof(NetPacket_Fixed<0x794b>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x794b>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x794b>, account_id) == 2, "offsetof(NetPacket_Fixed<0x794b>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x794b>, account_name) == 6, "offsetof(NetPacket_Fixed<0x794b>, account_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x794b>, ban_until) == 30, "offsetof(NetPacket_Fixed<0x794b>, ban_until) == 30"); +static_assert(sizeof(NetPacket_Fixed<0x794b>) == 34, "sizeof(NetPacket_Fixed<0x794b>) == 34"); +static_assert(alignof(NetPacket_Fixed<0x794b>) == 1, "alignof(NetPacket_Fixed<0x794b>) == 1"); + +template<> +struct NetPacket_Fixed<0x794c> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + NetHumanTimeDiff ban_add; +}; +static_assert(offsetof(NetPacket_Fixed<0x794c>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x794c>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x794c>, account_name) == 2, "offsetof(NetPacket_Fixed<0x794c>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x794c>, ban_add) == 26, "offsetof(NetPacket_Fixed<0x794c>, ban_add) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x794c>) == 38, "sizeof(NetPacket_Fixed<0x794c>) == 38"); +static_assert(alignof(NetPacket_Fixed<0x794c>) == 1, "alignof(NetPacket_Fixed<0x794c>) == 1"); + +template<> +struct NetPacket_Fixed<0x794d> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; + Little32 ban_until; +}; +static_assert(offsetof(NetPacket_Fixed<0x794d>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x794d>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x794d>, account_id) == 2, "offsetof(NetPacket_Fixed<0x794d>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x794d>, account_name) == 6, "offsetof(NetPacket_Fixed<0x794d>, account_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x794d>, ban_until) == 30, "offsetof(NetPacket_Fixed<0x794d>, ban_until) == 30"); +static_assert(sizeof(NetPacket_Fixed<0x794d>) == 34, "sizeof(NetPacket_Fixed<0x794d>) == 34"); +static_assert(alignof(NetPacket_Fixed<0x794d>) == 1, "alignof(NetPacket_Fixed<0x794d>) == 1"); + +template<> +struct NetPacket_Head<0x794e> +{ + Little16 magic_packet_id; + Little16 unused; + SkewedLength<Little32, 8> magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x794e>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x794e>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x794e>, unused) == 2, "offsetof(NetPacket_Head<0x794e>, unused) == 2"); +static_assert(offsetof(NetPacket_Head<0x794e>, magic_packet_length) == 4, "offsetof(NetPacket_Head<0x794e>, magic_packet_length) == 4"); +static_assert(sizeof(NetPacket_Head<0x794e>) == 8, "sizeof(NetPacket_Head<0x794e>) == 8"); +static_assert(alignof(NetPacket_Head<0x794e>) == 1, "alignof(NetPacket_Head<0x794e>) == 1"); +template<> +struct NetPacket_Repeat<0x794e> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x794e>, c) == 0, "offsetof(NetPacket_Repeat<0x794e>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x794e>) == 1, "sizeof(NetPacket_Repeat<0x794e>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x794e>) == 1, "alignof(NetPacket_Repeat<0x794e>) == 1"); + +template<> +struct NetPacket_Fixed<0x794f> +{ + Little16 magic_packet_id; + Little16 error; +}; +static_assert(offsetof(NetPacket_Fixed<0x794f>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x794f>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x794f>, error) == 2, "offsetof(NetPacket_Fixed<0x794f>, error) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x794f>) == 4, "sizeof(NetPacket_Fixed<0x794f>) == 4"); +static_assert(alignof(NetPacket_Fixed<0x794f>) == 1, "alignof(NetPacket_Fixed<0x794f>) == 1"); + +template<> +struct NetPacket_Fixed<0x7950> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + NetHumanTimeDiff valid_add; +}; +static_assert(offsetof(NetPacket_Fixed<0x7950>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7950>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7950>, account_name) == 2, "offsetof(NetPacket_Fixed<0x7950>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7950>, valid_add) == 26, "offsetof(NetPacket_Fixed<0x7950>, valid_add) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x7950>) == 38, "sizeof(NetPacket_Fixed<0x7950>) == 38"); +static_assert(alignof(NetPacket_Fixed<0x7950>) == 1, "alignof(NetPacket_Fixed<0x7950>) == 1"); + +template<> +struct NetPacket_Fixed<0x7951> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountName)> account_name; + Little32 valid_until; +}; +static_assert(offsetof(NetPacket_Fixed<0x7951>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7951>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7951>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7951>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x7951>, account_name) == 6, "offsetof(NetPacket_Fixed<0x7951>, account_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x7951>, valid_until) == 30, "offsetof(NetPacket_Fixed<0x7951>, valid_until) == 30"); +static_assert(sizeof(NetPacket_Fixed<0x7951>) == 34, "sizeof(NetPacket_Fixed<0x7951>) == 34"); +static_assert(alignof(NetPacket_Fixed<0x7951>) == 1, "alignof(NetPacket_Fixed<0x7951>) == 1"); + +template<> +struct NetPacket_Fixed<0x7952> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x7952>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7952>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7952>, account_name) == 2, "offsetof(NetPacket_Fixed<0x7952>, account_name) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x7952>) == 26, "sizeof(NetPacket_Fixed<0x7952>) == 26"); +static_assert(alignof(NetPacket_Fixed<0x7952>) == 1, "alignof(NetPacket_Fixed<0x7952>) == 1"); + +template<> +struct NetPacket_Head<0x7953> +{ + Little16 magic_packet_id; + Little32 account_id; + Byte gm_level; + NetString<sizeof(AccountName)> account_name; + Byte sex; + Little32 login_count; + Little32 state; + NetString<sizeof(timestamp_seconds_buffer)> error_message; + NetString<sizeof(timestamp_milliseconds_buffer)> last_login_string; + NetString<sizeof(VString<15>)> ip_string; + NetString<sizeof(AccountEmail)> email; + Little32 connect_until; + Little32 ban_until; + SkewedLength<Little16, 150> magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x7953>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x7953>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x7953>, account_id) == 2, "offsetof(NetPacket_Head<0x7953>, account_id) == 2"); +static_assert(offsetof(NetPacket_Head<0x7953>, gm_level) == 6, "offsetof(NetPacket_Head<0x7953>, gm_level) == 6"); +static_assert(offsetof(NetPacket_Head<0x7953>, account_name) == 7, "offsetof(NetPacket_Head<0x7953>, account_name) == 7"); +static_assert(offsetof(NetPacket_Head<0x7953>, sex) == 31, "offsetof(NetPacket_Head<0x7953>, sex) == 31"); +static_assert(offsetof(NetPacket_Head<0x7953>, login_count) == 32, "offsetof(NetPacket_Head<0x7953>, login_count) == 32"); +static_assert(offsetof(NetPacket_Head<0x7953>, state) == 36, "offsetof(NetPacket_Head<0x7953>, state) == 36"); +static_assert(offsetof(NetPacket_Head<0x7953>, error_message) == 40, "offsetof(NetPacket_Head<0x7953>, error_message) == 40"); +static_assert(offsetof(NetPacket_Head<0x7953>, last_login_string) == 60, "offsetof(NetPacket_Head<0x7953>, last_login_string) == 60"); +static_assert(offsetof(NetPacket_Head<0x7953>, ip_string) == 84, "offsetof(NetPacket_Head<0x7953>, ip_string) == 84"); +static_assert(offsetof(NetPacket_Head<0x7953>, email) == 100, "offsetof(NetPacket_Head<0x7953>, email) == 100"); +static_assert(offsetof(NetPacket_Head<0x7953>, connect_until) == 140, "offsetof(NetPacket_Head<0x7953>, connect_until) == 140"); +static_assert(offsetof(NetPacket_Head<0x7953>, ban_until) == 144, "offsetof(NetPacket_Head<0x7953>, ban_until) == 144"); +static_assert(offsetof(NetPacket_Head<0x7953>, magic_packet_length) == 148, "offsetof(NetPacket_Head<0x7953>, magic_packet_length) == 148"); +static_assert(sizeof(NetPacket_Head<0x7953>) == 150, "sizeof(NetPacket_Head<0x7953>) == 150"); +static_assert(alignof(NetPacket_Head<0x7953>) == 1, "alignof(NetPacket_Head<0x7953>) == 1"); +template<> +struct NetPacket_Repeat<0x7953> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x7953>, c) == 0, "offsetof(NetPacket_Repeat<0x7953>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x7953>) == 1, "sizeof(NetPacket_Repeat<0x7953>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x7953>) == 1, "alignof(NetPacket_Repeat<0x7953>) == 1"); + +template<> +struct NetPacket_Fixed<0x7954> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x7954>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7954>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x7954>, account_id) == 2, "offsetof(NetPacket_Fixed<0x7954>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x7954>) == 6, "sizeof(NetPacket_Fixed<0x7954>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x7954>) == 1, "alignof(NetPacket_Fixed<0x7954>) == 1"); + +template<> +struct NetPacket_Fixed<0x7955> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x7955>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x7955>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x7955>) == 2, "sizeof(NetPacket_Fixed<0x7955>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x7955>) == 1, "alignof(NetPacket_Fixed<0x7955>) == 1"); + + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2726> *network, Packet_Head<0x2726> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->unused, native.unused); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2726> *native, NetPacket_Head<0x2726> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->unused, network.unused); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2726> *network, Packet_Repeat<0x2726> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2726> *native, NetPacket_Repeat<0x2726> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7918> *network, Packet_Fixed<0x7918> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->encryption_zero, native.encryption_zero); + rv &= native_to_network(&network->account_pass, native.account_pass); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7918> *native, NetPacket_Fixed<0x7918> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->encryption_zero, network.encryption_zero); + rv &= network_to_native(&native->account_pass, network.account_pass); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7919> *network, Packet_Fixed<0x7919> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->error, native.error); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7919> *native, NetPacket_Fixed<0x7919> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->error, network.error); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7920> *network, Packet_Fixed<0x7920> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->start_account_id, native.start_account_id); + rv &= native_to_network(&network->end_account_id, native.end_account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7920> *native, NetPacket_Fixed<0x7920> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->start_account_id, network.start_account_id); + rv &= network_to_native(&native->end_account_id, network.end_account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x7921> *network, Packet_Head<0x7921> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x7921> *native, NetPacket_Head<0x7921> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x7921> *network, Packet_Repeat<0x7921> native) +{ + bool rv = true; + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->gm_level, native.gm_level); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->sex, native.sex); + rv &= native_to_network(&network->login_count, native.login_count); + rv &= native_to_network(&network->status, native.status); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x7921> *native, NetPacket_Repeat<0x7921> network) +{ + bool rv = true; + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->gm_level, network.gm_level); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->sex, network.sex); + rv &= network_to_native(&native->login_count, network.login_count); + rv &= network_to_native(&native->status, network.status); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7924> *network, Packet_Fixed<0x7924> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->source_item_id, native.source_item_id); + rv &= native_to_network(&network->dest_item_id, native.dest_item_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7924> *native, NetPacket_Fixed<0x7924> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->source_item_id, network.source_item_id); + rv &= network_to_native(&native->dest_item_id, network.dest_item_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7925> *network, Packet_Fixed<0x7925> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7925> *native, NetPacket_Fixed<0x7925> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7930> *network, Packet_Fixed<0x7930> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->password, native.password); + rv &= native_to_network(&network->sex, native.sex); + rv &= native_to_network(&network->email, native.email); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7930> *native, NetPacket_Fixed<0x7930> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->password, network.password); + rv &= network_to_native(&native->sex, network.sex); + rv &= network_to_native(&native->email, network.email); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7931> *network, Packet_Fixed<0x7931> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7931> *native, NetPacket_Fixed<0x7931> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7932> *network, Packet_Fixed<0x7932> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7932> *native, NetPacket_Fixed<0x7932> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7933> *network, Packet_Fixed<0x7933> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7933> *native, NetPacket_Fixed<0x7933> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7934> *network, Packet_Fixed<0x7934> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->password, native.password); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7934> *native, NetPacket_Fixed<0x7934> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->password, network.password); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7935> *network, Packet_Fixed<0x7935> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7935> *native, NetPacket_Fixed<0x7935> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7936> *network, Packet_Fixed<0x7936> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->status, native.status); + rv &= native_to_network(&network->error_message, native.error_message); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7936> *native, NetPacket_Fixed<0x7936> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->status, network.status); + rv &= network_to_native(&native->error_message, network.error_message); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7937> *network, Packet_Fixed<0x7937> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->status, native.status); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7937> *native, NetPacket_Fixed<0x7937> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->status, network.status); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7938> *network, Packet_Fixed<0x7938> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7938> *native, NetPacket_Fixed<0x7938> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x7939> *network, Packet_Head<0x7939> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x7939> *native, NetPacket_Head<0x7939> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x7939> *network, Packet_Repeat<0x7939> native) +{ + bool rv = true; + rv &= native_to_network(&network->ip, native.ip); + rv &= native_to_network(&network->port, native.port); + rv &= native_to_network(&network->name, native.name); + rv &= native_to_network(&network->users, native.users); + rv &= native_to_network(&network->maintenance, native.maintenance); + rv &= native_to_network(&network->is_new, native.is_new); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x7939> *native, NetPacket_Repeat<0x7939> network) +{ + bool rv = true; + rv &= network_to_native(&native->ip, network.ip); + rv &= network_to_native(&native->port, network.port); + rv &= network_to_native(&native->name, network.name); + rv &= network_to_native(&native->users, network.users); + rv &= network_to_native(&native->maintenance, network.maintenance); + rv &= network_to_native(&native->is_new, network.is_new); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x793a> *network, Packet_Fixed<0x793a> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->password, native.password); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x793a> *native, NetPacket_Fixed<0x793a> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->password, network.password); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x793b> *network, Packet_Fixed<0x793b> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x793b> *native, NetPacket_Fixed<0x793b> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x793c> *network, Packet_Fixed<0x793c> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->sex, native.sex); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x793c> *native, NetPacket_Fixed<0x793c> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->sex, network.sex); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x793d> *network, Packet_Fixed<0x793d> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x793d> *native, NetPacket_Fixed<0x793d> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x793e> *network, Packet_Fixed<0x793e> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->gm_level, native.gm_level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x793e> *native, NetPacket_Fixed<0x793e> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->gm_level, network.gm_level); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x793f> *network, Packet_Fixed<0x793f> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x793f> *native, NetPacket_Fixed<0x793f> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7940> *network, Packet_Fixed<0x7940> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->email, native.email); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7940> *native, NetPacket_Fixed<0x7940> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->email, network.email); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7941> *network, Packet_Fixed<0x7941> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7941> *native, NetPacket_Fixed<0x7941> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x7942> *network, Packet_Head<0x7942> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x7942> *native, NetPacket_Head<0x7942> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x7942> *network, Packet_Repeat<0x7942> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x7942> *native, NetPacket_Repeat<0x7942> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7943> *network, Packet_Fixed<0x7943> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7943> *native, NetPacket_Fixed<0x7943> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7944> *network, Packet_Fixed<0x7944> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7944> *native, NetPacket_Fixed<0x7944> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7945> *network, Packet_Fixed<0x7945> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7945> *native, NetPacket_Fixed<0x7945> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7946> *network, Packet_Fixed<0x7946> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7946> *native, NetPacket_Fixed<0x7946> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7947> *network, Packet_Fixed<0x7947> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7947> *native, NetPacket_Fixed<0x7947> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7948> *network, Packet_Fixed<0x7948> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->valid_until, native.valid_until); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7948> *native, NetPacket_Fixed<0x7948> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->valid_until, network.valid_until); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7949> *network, Packet_Fixed<0x7949> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->valid_until, native.valid_until); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7949> *native, NetPacket_Fixed<0x7949> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->valid_until, network.valid_until); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x794a> *network, Packet_Fixed<0x794a> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->ban_until, native.ban_until); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x794a> *native, NetPacket_Fixed<0x794a> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->ban_until, network.ban_until); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x794b> *network, Packet_Fixed<0x794b> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->ban_until, native.ban_until); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x794b> *native, NetPacket_Fixed<0x794b> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->ban_until, network.ban_until); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x794c> *network, Packet_Fixed<0x794c> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->ban_add, native.ban_add); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x794c> *native, NetPacket_Fixed<0x794c> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->ban_add, network.ban_add); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x794d> *network, Packet_Fixed<0x794d> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->ban_until, native.ban_until); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x794d> *native, NetPacket_Fixed<0x794d> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->ban_until, network.ban_until); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x794e> *network, Packet_Head<0x794e> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->unused, native.unused); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x794e> *native, NetPacket_Head<0x794e> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->unused, network.unused); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x794e> *network, Packet_Repeat<0x794e> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x794e> *native, NetPacket_Repeat<0x794e> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x794f> *network, Packet_Fixed<0x794f> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->error, native.error); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x794f> *native, NetPacket_Fixed<0x794f> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->error, network.error); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7950> *network, Packet_Fixed<0x7950> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->valid_add, native.valid_add); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7950> *native, NetPacket_Fixed<0x7950> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->valid_add, network.valid_add); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7951> *network, Packet_Fixed<0x7951> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->valid_until, native.valid_until); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7951> *native, NetPacket_Fixed<0x7951> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->valid_until, network.valid_until); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7952> *network, Packet_Fixed<0x7952> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7952> *native, NetPacket_Fixed<0x7952> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x7953> *network, Packet_Head<0x7953> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->gm_level, native.gm_level); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->sex, native.sex); + rv &= native_to_network(&network->login_count, native.login_count); + rv &= native_to_network(&network->state, native.state); + rv &= native_to_network(&network->error_message, native.error_message); + rv &= native_to_network(&network->last_login_string, native.last_login_string); + rv &= native_to_network(&network->ip_string, native.ip_string); + rv &= native_to_network(&network->email, native.email); + rv &= native_to_network(&network->connect_until, native.connect_until); + rv &= native_to_network(&network->ban_until, native.ban_until); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x7953> *native, NetPacket_Head<0x7953> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->gm_level, network.gm_level); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->sex, network.sex); + rv &= network_to_native(&native->login_count, network.login_count); + rv &= network_to_native(&native->state, network.state); + rv &= network_to_native(&native->error_message, network.error_message); + rv &= network_to_native(&native->last_login_string, network.last_login_string); + rv &= network_to_native(&native->ip_string, network.ip_string); + rv &= network_to_native(&native->email, network.email); + rv &= network_to_native(&native->connect_until, network.connect_until); + rv &= network_to_native(&native->ban_until, network.ban_until); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x7953> *network, Packet_Repeat<0x7953> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x7953> *native, NetPacket_Repeat<0x7953> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7954> *network, Packet_Fixed<0x7954> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7954> *native, NetPacket_Fixed<0x7954> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x7955> *network, Packet_Fixed<0x7955> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x7955> *native, NetPacket_Fixed<0x7955> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +} // namespace tmwa diff --git a/src/proto2/login-admin_test.cpp b/src/proto2/login-admin_test.cpp new file mode 100644 index 0000000..1bc322d --- /dev/null +++ b/src/proto2/login-admin_test.cpp @@ -0,0 +1,27 @@ +#include "login-admin.hpp" +// login-admin_test.cpp - TMWA network protocol: login/admin +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "../poison.hpp" + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/proto2/login-char.hpp b/src/proto2/login-char.hpp new file mode 100644 index 0000000..00fe2ac --- /dev/null +++ b/src/proto2/login-char.hpp @@ -0,0 +1,1192 @@ +#pragma once +// login-char.hpp - TMWA network protocol: login/char +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "fwd.hpp" + +#include "types.hpp" + +namespace tmwa +{ +// This is an internal protocol, and can be changed without notice + +template<> +struct Packet_Fixed<0x2709> +{ + static const uint16_t PACKET_ID = 0x2709; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x2710> +{ + static const uint16_t PACKET_ID = 0x2710; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountName account_name = {}; + AccountPass account_pass = {}; + uint32_t unknown = {}; + IP4Address ip = {}; + uint16_t port = {}; + ServerName server_name = {}; + uint16_t unknown2 = {}; + uint16_t maintenance = {}; + uint16_t is_new = {}; +}; + +template<> +struct Packet_Fixed<0x2711> +{ + static const uint16_t PACKET_ID = 0x2711; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t code = {}; +}; + +template<> +struct Packet_Fixed<0x2712> +{ + static const uint16_t PACKET_ID = 0x2712; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint32_t login_id1 = {}; + uint32_t login_id2 = {}; + SEX sex = {}; + IP4Address ip = {}; +}; + +template<> +struct Packet_Fixed<0x2713> +{ + static const uint16_t PACKET_ID = 0x2713; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint8_t invalid = {}; + AccountEmail email = {}; + TimeT connect_until = {}; +}; + +template<> +struct Packet_Fixed<0x2714> +{ + static const uint16_t PACKET_ID = 0x2714; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint32_t users = {}; +}; + +template<> +struct Packet_Fixed<0x2716> +{ + static const uint16_t PACKET_ID = 0x2716; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Fixed<0x2717> +{ + static const uint16_t PACKET_ID = 0x2717; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountEmail email = {}; + TimeT connect_until = {}; +}; + +template<> +struct Packet_Head<0x2720> +{ + static const uint16_t PACKET_ID = 0x2720; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; +}; +template<> +struct Packet_Repeat<0x2720> +{ + static const uint16_t PACKET_ID = 0x2720; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x2721> +{ + static const uint16_t PACKET_ID = 0x2721; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + GmLevel gm_level = {}; +}; + +template<> +struct Packet_Fixed<0x2722> +{ + static const uint16_t PACKET_ID = 0x2722; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountEmail old_email = {}; + AccountEmail new_email = {}; +}; + +template<> +struct Packet_Fixed<0x2723> +{ + static const uint16_t PACKET_ID = 0x2723; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + SEX sex = {}; +}; + +template<> +struct Packet_Fixed<0x2724> +{ + static const uint16_t PACKET_ID = 0x2724; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint32_t status = {}; +}; + +template<> +struct Packet_Fixed<0x2725> +{ + static const uint16_t PACKET_ID = 0x2725; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + HumanTimeDiff ban_add = {}; +}; + +template<> +struct Packet_Fixed<0x2727> +{ + static const uint16_t PACKET_ID = 0x2727; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Head<0x2728> +{ + static const uint16_t PACKET_ID = 0x2728; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; +}; +template<> +struct Packet_Repeat<0x2728> +{ + static const uint16_t PACKET_ID = 0x2728; + + VarName name = {}; + uint32_t value = {}; +}; + +template<> +struct Packet_Head<0x2729> +{ + static const uint16_t PACKET_ID = 0x2729; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; +}; +template<> +struct Packet_Repeat<0x2729> +{ + static const uint16_t PACKET_ID = 0x2729; + + VarName name = {}; + uint32_t value = {}; +}; + +template<> +struct Packet_Fixed<0x272a> +{ + static const uint16_t PACKET_ID = 0x272a; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Fixed<0x2730> +{ + static const uint16_t PACKET_ID = 0x2730; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Fixed<0x2731> +{ + static const uint16_t PACKET_ID = 0x2731; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint8_t ban_not_status = {}; + TimeT status_or_ban_until = {}; +}; + +template<> +struct Packet_Head<0x2732> +{ + static const uint16_t PACKET_ID = 0x2732; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x2732> +{ + static const uint16_t PACKET_ID = 0x2732; + + AccountId account_id = {}; + GmLevel gm_level = {}; +}; + +template<> +struct Packet_Fixed<0x2740> +{ + static const uint16_t PACKET_ID = 0x2740; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + AccountPass old_pass = {}; + AccountPass new_pass = {}; +}; + +template<> +struct Packet_Fixed<0x2741> +{ + static const uint16_t PACKET_ID = 0x2741; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint8_t status = {}; +}; + + +template<> +struct NetPacket_Fixed<0x2709> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x2709>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2709>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x2709>) == 2, "sizeof(NetPacket_Fixed<0x2709>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x2709>) == 1, "alignof(NetPacket_Fixed<0x2709>) == 1"); + +template<> +struct NetPacket_Fixed<0x2710> +{ + Little16 magic_packet_id; + NetString<sizeof(AccountName)> account_name; + NetString<sizeof(AccountPass)> account_pass; + Little32 unknown; + IP4Address ip; + Little16 port; + NetString<sizeof(ServerName)> server_name; + Little16 unknown2; + Little16 maintenance; + Little16 is_new; +}; +static_assert(offsetof(NetPacket_Fixed<0x2710>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2710>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2710>, account_name) == 2, "offsetof(NetPacket_Fixed<0x2710>, account_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2710>, account_pass) == 26, "offsetof(NetPacket_Fixed<0x2710>, account_pass) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x2710>, unknown) == 50, "offsetof(NetPacket_Fixed<0x2710>, unknown) == 50"); +static_assert(offsetof(NetPacket_Fixed<0x2710>, ip) == 54, "offsetof(NetPacket_Fixed<0x2710>, ip) == 54"); +static_assert(offsetof(NetPacket_Fixed<0x2710>, port) == 58, "offsetof(NetPacket_Fixed<0x2710>, port) == 58"); +static_assert(offsetof(NetPacket_Fixed<0x2710>, server_name) == 60, "offsetof(NetPacket_Fixed<0x2710>, server_name) == 60"); +static_assert(offsetof(NetPacket_Fixed<0x2710>, unknown2) == 80, "offsetof(NetPacket_Fixed<0x2710>, unknown2) == 80"); +static_assert(offsetof(NetPacket_Fixed<0x2710>, maintenance) == 82, "offsetof(NetPacket_Fixed<0x2710>, maintenance) == 82"); +static_assert(offsetof(NetPacket_Fixed<0x2710>, is_new) == 84, "offsetof(NetPacket_Fixed<0x2710>, is_new) == 84"); +static_assert(sizeof(NetPacket_Fixed<0x2710>) == 86, "sizeof(NetPacket_Fixed<0x2710>) == 86"); +static_assert(alignof(NetPacket_Fixed<0x2710>) == 1, "alignof(NetPacket_Fixed<0x2710>) == 1"); + +template<> +struct NetPacket_Fixed<0x2711> +{ + Little16 magic_packet_id; + Byte code; +}; +static_assert(offsetof(NetPacket_Fixed<0x2711>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2711>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2711>, code) == 2, "offsetof(NetPacket_Fixed<0x2711>, code) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x2711>) == 3, "sizeof(NetPacket_Fixed<0x2711>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x2711>) == 1, "alignof(NetPacket_Fixed<0x2711>) == 1"); + +template<> +struct NetPacket_Fixed<0x2712> +{ + Little16 magic_packet_id; + Little32 account_id; + Little32 login_id1; + Little32 login_id2; + Byte sex; + IP4Address ip; +}; +static_assert(offsetof(NetPacket_Fixed<0x2712>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2712>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2712>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2712>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2712>, login_id1) == 6, "offsetof(NetPacket_Fixed<0x2712>, login_id1) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2712>, login_id2) == 10, "offsetof(NetPacket_Fixed<0x2712>, login_id2) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x2712>, sex) == 14, "offsetof(NetPacket_Fixed<0x2712>, sex) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x2712>, ip) == 15, "offsetof(NetPacket_Fixed<0x2712>, ip) == 15"); +static_assert(sizeof(NetPacket_Fixed<0x2712>) == 19, "sizeof(NetPacket_Fixed<0x2712>) == 19"); +static_assert(alignof(NetPacket_Fixed<0x2712>) == 1, "alignof(NetPacket_Fixed<0x2712>) == 1"); + +template<> +struct NetPacket_Fixed<0x2713> +{ + Little16 magic_packet_id; + Little32 account_id; + Byte invalid; + NetString<sizeof(AccountEmail)> email; + Little32 connect_until; +}; +static_assert(offsetof(NetPacket_Fixed<0x2713>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2713>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2713>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2713>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2713>, invalid) == 6, "offsetof(NetPacket_Fixed<0x2713>, invalid) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2713>, email) == 7, "offsetof(NetPacket_Fixed<0x2713>, email) == 7"); +static_assert(offsetof(NetPacket_Fixed<0x2713>, connect_until) == 47, "offsetof(NetPacket_Fixed<0x2713>, connect_until) == 47"); +static_assert(sizeof(NetPacket_Fixed<0x2713>) == 51, "sizeof(NetPacket_Fixed<0x2713>) == 51"); +static_assert(alignof(NetPacket_Fixed<0x2713>) == 1, "alignof(NetPacket_Fixed<0x2713>) == 1"); + +template<> +struct NetPacket_Fixed<0x2714> +{ + Little16 magic_packet_id; + Little32 users; +}; +static_assert(offsetof(NetPacket_Fixed<0x2714>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2714>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2714>, users) == 2, "offsetof(NetPacket_Fixed<0x2714>, users) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x2714>) == 6, "sizeof(NetPacket_Fixed<0x2714>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x2714>) == 1, "alignof(NetPacket_Fixed<0x2714>) == 1"); + +template<> +struct NetPacket_Fixed<0x2716> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x2716>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2716>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2716>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2716>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x2716>) == 6, "sizeof(NetPacket_Fixed<0x2716>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x2716>) == 1, "alignof(NetPacket_Fixed<0x2716>) == 1"); + +template<> +struct NetPacket_Fixed<0x2717> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountEmail)> email; + Little32 connect_until; +}; +static_assert(offsetof(NetPacket_Fixed<0x2717>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2717>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2717>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2717>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2717>, email) == 6, "offsetof(NetPacket_Fixed<0x2717>, email) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2717>, connect_until) == 46, "offsetof(NetPacket_Fixed<0x2717>, connect_until) == 46"); +static_assert(sizeof(NetPacket_Fixed<0x2717>) == 50, "sizeof(NetPacket_Fixed<0x2717>) == 50"); +static_assert(alignof(NetPacket_Fixed<0x2717>) == 1, "alignof(NetPacket_Fixed<0x2717>) == 1"); + +template<> +struct NetPacket_Head<0x2720> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Head<0x2720>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2720>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2720>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x2720>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x2720>, account_id) == 4, "offsetof(NetPacket_Head<0x2720>, account_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x2720>) == 8, "sizeof(NetPacket_Head<0x2720>) == 8"); +static_assert(alignof(NetPacket_Head<0x2720>) == 1, "alignof(NetPacket_Head<0x2720>) == 1"); +template<> +struct NetPacket_Repeat<0x2720> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x2720>, c) == 0, "offsetof(NetPacket_Repeat<0x2720>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x2720>) == 1, "sizeof(NetPacket_Repeat<0x2720>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x2720>) == 1, "alignof(NetPacket_Repeat<0x2720>) == 1"); + +template<> +struct NetPacket_Fixed<0x2721> +{ + Little16 magic_packet_id; + Little32 account_id; + Little32 gm_level; +}; +static_assert(offsetof(NetPacket_Fixed<0x2721>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2721>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2721>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2721>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2721>, gm_level) == 6, "offsetof(NetPacket_Fixed<0x2721>, gm_level) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x2721>) == 10, "sizeof(NetPacket_Fixed<0x2721>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x2721>) == 1, "alignof(NetPacket_Fixed<0x2721>) == 1"); + +template<> +struct NetPacket_Fixed<0x2722> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountEmail)> old_email; + NetString<sizeof(AccountEmail)> new_email; +}; +static_assert(offsetof(NetPacket_Fixed<0x2722>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2722>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2722>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2722>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2722>, old_email) == 6, "offsetof(NetPacket_Fixed<0x2722>, old_email) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2722>, new_email) == 46, "offsetof(NetPacket_Fixed<0x2722>, new_email) == 46"); +static_assert(sizeof(NetPacket_Fixed<0x2722>) == 86, "sizeof(NetPacket_Fixed<0x2722>) == 86"); +static_assert(alignof(NetPacket_Fixed<0x2722>) == 1, "alignof(NetPacket_Fixed<0x2722>) == 1"); + +template<> +struct NetPacket_Fixed<0x2723> +{ + Little16 magic_packet_id; + Little32 account_id; + Byte sex; +}; +static_assert(offsetof(NetPacket_Fixed<0x2723>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2723>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2723>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2723>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2723>, sex) == 6, "offsetof(NetPacket_Fixed<0x2723>, sex) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x2723>) == 7, "sizeof(NetPacket_Fixed<0x2723>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x2723>) == 1, "alignof(NetPacket_Fixed<0x2723>) == 1"); + +template<> +struct NetPacket_Fixed<0x2724> +{ + Little16 magic_packet_id; + Little32 account_id; + Little32 status; +}; +static_assert(offsetof(NetPacket_Fixed<0x2724>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2724>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2724>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2724>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2724>, status) == 6, "offsetof(NetPacket_Fixed<0x2724>, status) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x2724>) == 10, "sizeof(NetPacket_Fixed<0x2724>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x2724>) == 1, "alignof(NetPacket_Fixed<0x2724>) == 1"); + +template<> +struct NetPacket_Fixed<0x2725> +{ + Little16 magic_packet_id; + Little32 account_id; + NetHumanTimeDiff ban_add; +}; +static_assert(offsetof(NetPacket_Fixed<0x2725>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2725>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2725>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2725>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2725>, ban_add) == 6, "offsetof(NetPacket_Fixed<0x2725>, ban_add) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x2725>) == 18, "sizeof(NetPacket_Fixed<0x2725>) == 18"); +static_assert(alignof(NetPacket_Fixed<0x2725>) == 1, "alignof(NetPacket_Fixed<0x2725>) == 1"); + +template<> +struct NetPacket_Fixed<0x2727> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x2727>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2727>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2727>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2727>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x2727>) == 6, "sizeof(NetPacket_Fixed<0x2727>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x2727>) == 1, "alignof(NetPacket_Fixed<0x2727>) == 1"); + +template<> +struct NetPacket_Head<0x2728> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Head<0x2728>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2728>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2728>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x2728>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x2728>, account_id) == 4, "offsetof(NetPacket_Head<0x2728>, account_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x2728>) == 8, "sizeof(NetPacket_Head<0x2728>) == 8"); +static_assert(alignof(NetPacket_Head<0x2728>) == 1, "alignof(NetPacket_Head<0x2728>) == 1"); +template<> +struct NetPacket_Repeat<0x2728> +{ + NetString<sizeof(VarName)> name; + Little32 value; +}; +static_assert(offsetof(NetPacket_Repeat<0x2728>, name) == 0, "offsetof(NetPacket_Repeat<0x2728>, name) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x2728>, value) == 32, "offsetof(NetPacket_Repeat<0x2728>, value) == 32"); +static_assert(sizeof(NetPacket_Repeat<0x2728>) == 36, "sizeof(NetPacket_Repeat<0x2728>) == 36"); +static_assert(alignof(NetPacket_Repeat<0x2728>) == 1, "alignof(NetPacket_Repeat<0x2728>) == 1"); + +template<> +struct NetPacket_Head<0x2729> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Head<0x2729>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2729>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2729>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x2729>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x2729>, account_id) == 4, "offsetof(NetPacket_Head<0x2729>, account_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x2729>) == 8, "sizeof(NetPacket_Head<0x2729>) == 8"); +static_assert(alignof(NetPacket_Head<0x2729>) == 1, "alignof(NetPacket_Head<0x2729>) == 1"); +template<> +struct NetPacket_Repeat<0x2729> +{ + NetString<sizeof(VarName)> name; + Little32 value; +}; +static_assert(offsetof(NetPacket_Repeat<0x2729>, name) == 0, "offsetof(NetPacket_Repeat<0x2729>, name) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x2729>, value) == 32, "offsetof(NetPacket_Repeat<0x2729>, value) == 32"); +static_assert(sizeof(NetPacket_Repeat<0x2729>) == 36, "sizeof(NetPacket_Repeat<0x2729>) == 36"); +static_assert(alignof(NetPacket_Repeat<0x2729>) == 1, "alignof(NetPacket_Repeat<0x2729>) == 1"); + +template<> +struct NetPacket_Fixed<0x272a> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x272a>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x272a>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x272a>, account_id) == 2, "offsetof(NetPacket_Fixed<0x272a>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x272a>) == 6, "sizeof(NetPacket_Fixed<0x272a>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x272a>) == 1, "alignof(NetPacket_Fixed<0x272a>) == 1"); + +template<> +struct NetPacket_Fixed<0x2730> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x2730>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2730>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2730>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2730>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x2730>) == 6, "sizeof(NetPacket_Fixed<0x2730>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x2730>) == 1, "alignof(NetPacket_Fixed<0x2730>) == 1"); + +template<> +struct NetPacket_Fixed<0x2731> +{ + Little16 magic_packet_id; + Little32 account_id; + Byte ban_not_status; + Little32 status_or_ban_until; +}; +static_assert(offsetof(NetPacket_Fixed<0x2731>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2731>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2731>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2731>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2731>, ban_not_status) == 6, "offsetof(NetPacket_Fixed<0x2731>, ban_not_status) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2731>, status_or_ban_until) == 7, "offsetof(NetPacket_Fixed<0x2731>, status_or_ban_until) == 7"); +static_assert(sizeof(NetPacket_Fixed<0x2731>) == 11, "sizeof(NetPacket_Fixed<0x2731>) == 11"); +static_assert(alignof(NetPacket_Fixed<0x2731>) == 1, "alignof(NetPacket_Fixed<0x2731>) == 1"); + +template<> +struct NetPacket_Head<0x2732> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x2732>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x2732>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x2732>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x2732>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x2732>) == 4, "sizeof(NetPacket_Head<0x2732>) == 4"); +static_assert(alignof(NetPacket_Head<0x2732>) == 1, "alignof(NetPacket_Head<0x2732>) == 1"); +template<> +struct NetPacket_Repeat<0x2732> +{ + Little32 account_id; + Byte gm_level; +}; +static_assert(offsetof(NetPacket_Repeat<0x2732>, account_id) == 0, "offsetof(NetPacket_Repeat<0x2732>, account_id) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x2732>, gm_level) == 4, "offsetof(NetPacket_Repeat<0x2732>, gm_level) == 4"); +static_assert(sizeof(NetPacket_Repeat<0x2732>) == 5, "sizeof(NetPacket_Repeat<0x2732>) == 5"); +static_assert(alignof(NetPacket_Repeat<0x2732>) == 1, "alignof(NetPacket_Repeat<0x2732>) == 1"); + +template<> +struct NetPacket_Fixed<0x2740> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(AccountPass)> old_pass; + NetString<sizeof(AccountPass)> new_pass; +}; +static_assert(offsetof(NetPacket_Fixed<0x2740>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2740>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2740>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2740>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2740>, old_pass) == 6, "offsetof(NetPacket_Fixed<0x2740>, old_pass) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x2740>, new_pass) == 30, "offsetof(NetPacket_Fixed<0x2740>, new_pass) == 30"); +static_assert(sizeof(NetPacket_Fixed<0x2740>) == 54, "sizeof(NetPacket_Fixed<0x2740>) == 54"); +static_assert(alignof(NetPacket_Fixed<0x2740>) == 1, "alignof(NetPacket_Fixed<0x2740>) == 1"); + +template<> +struct NetPacket_Fixed<0x2741> +{ + Little16 magic_packet_id; + Little32 account_id; + Byte status; +}; +static_assert(offsetof(NetPacket_Fixed<0x2741>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x2741>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x2741>, account_id) == 2, "offsetof(NetPacket_Fixed<0x2741>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x2741>, status) == 6, "offsetof(NetPacket_Fixed<0x2741>, status) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x2741>) == 7, "sizeof(NetPacket_Fixed<0x2741>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x2741>) == 1, "alignof(NetPacket_Fixed<0x2741>) == 1"); + + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2709> *network, Packet_Fixed<0x2709> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2709> *native, NetPacket_Fixed<0x2709> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2710> *network, Packet_Fixed<0x2710> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->account_pass, native.account_pass); + rv &= native_to_network(&network->unknown, native.unknown); + rv &= native_to_network(&network->ip, native.ip); + rv &= native_to_network(&network->port, native.port); + rv &= native_to_network(&network->server_name, native.server_name); + rv &= native_to_network(&network->unknown2, native.unknown2); + rv &= native_to_network(&network->maintenance, native.maintenance); + rv &= native_to_network(&network->is_new, native.is_new); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2710> *native, NetPacket_Fixed<0x2710> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->account_pass, network.account_pass); + rv &= network_to_native(&native->unknown, network.unknown); + rv &= network_to_native(&native->ip, network.ip); + rv &= network_to_native(&native->port, network.port); + rv &= network_to_native(&native->server_name, network.server_name); + rv &= network_to_native(&native->unknown2, network.unknown2); + rv &= network_to_native(&native->maintenance, network.maintenance); + rv &= network_to_native(&native->is_new, network.is_new); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2711> *network, Packet_Fixed<0x2711> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->code, native.code); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2711> *native, NetPacket_Fixed<0x2711> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->code, network.code); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2712> *network, Packet_Fixed<0x2712> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->login_id1, native.login_id1); + rv &= native_to_network(&network->login_id2, native.login_id2); + rv &= native_to_network(&network->sex, native.sex); + rv &= native_to_network(&network->ip, native.ip); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2712> *native, NetPacket_Fixed<0x2712> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->login_id1, network.login_id1); + rv &= network_to_native(&native->login_id2, network.login_id2); + rv &= network_to_native(&native->sex, network.sex); + rv &= network_to_native(&native->ip, network.ip); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2713> *network, Packet_Fixed<0x2713> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->invalid, native.invalid); + rv &= native_to_network(&network->email, native.email); + rv &= native_to_network(&network->connect_until, native.connect_until); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2713> *native, NetPacket_Fixed<0x2713> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->invalid, network.invalid); + rv &= network_to_native(&native->email, network.email); + rv &= network_to_native(&native->connect_until, network.connect_until); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2714> *network, Packet_Fixed<0x2714> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->users, native.users); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2714> *native, NetPacket_Fixed<0x2714> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->users, network.users); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2716> *network, Packet_Fixed<0x2716> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2716> *native, NetPacket_Fixed<0x2716> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2717> *network, Packet_Fixed<0x2717> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->email, native.email); + rv &= native_to_network(&network->connect_until, native.connect_until); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2717> *native, NetPacket_Fixed<0x2717> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->email, network.email); + rv &= network_to_native(&native->connect_until, network.connect_until); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2720> *network, Packet_Head<0x2720> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2720> *native, NetPacket_Head<0x2720> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2720> *network, Packet_Repeat<0x2720> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2720> *native, NetPacket_Repeat<0x2720> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2721> *network, Packet_Fixed<0x2721> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->gm_level, native.gm_level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2721> *native, NetPacket_Fixed<0x2721> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->gm_level, network.gm_level); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2722> *network, Packet_Fixed<0x2722> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->old_email, native.old_email); + rv &= native_to_network(&network->new_email, native.new_email); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2722> *native, NetPacket_Fixed<0x2722> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->old_email, network.old_email); + rv &= network_to_native(&native->new_email, network.new_email); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2723> *network, Packet_Fixed<0x2723> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->sex, native.sex); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2723> *native, NetPacket_Fixed<0x2723> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->sex, network.sex); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2724> *network, Packet_Fixed<0x2724> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->status, native.status); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2724> *native, NetPacket_Fixed<0x2724> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->status, network.status); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2725> *network, Packet_Fixed<0x2725> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->ban_add, native.ban_add); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2725> *native, NetPacket_Fixed<0x2725> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->ban_add, network.ban_add); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2727> *network, Packet_Fixed<0x2727> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2727> *native, NetPacket_Fixed<0x2727> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2728> *network, Packet_Head<0x2728> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2728> *native, NetPacket_Head<0x2728> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2728> *network, Packet_Repeat<0x2728> native) +{ + bool rv = true; + rv &= native_to_network(&network->name, native.name); + rv &= native_to_network(&network->value, native.value); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2728> *native, NetPacket_Repeat<0x2728> network) +{ + bool rv = true; + rv &= network_to_native(&native->name, network.name); + rv &= network_to_native(&native->value, network.value); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2729> *network, Packet_Head<0x2729> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2729> *native, NetPacket_Head<0x2729> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2729> *network, Packet_Repeat<0x2729> native) +{ + bool rv = true; + rv &= native_to_network(&network->name, native.name); + rv &= native_to_network(&network->value, native.value); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2729> *native, NetPacket_Repeat<0x2729> network) +{ + bool rv = true; + rv &= network_to_native(&native->name, network.name); + rv &= network_to_native(&native->value, network.value); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x272a> *network, Packet_Fixed<0x272a> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x272a> *native, NetPacket_Fixed<0x272a> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2730> *network, Packet_Fixed<0x2730> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2730> *native, NetPacket_Fixed<0x2730> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2731> *network, Packet_Fixed<0x2731> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->ban_not_status, native.ban_not_status); + rv &= native_to_network(&network->status_or_ban_until, native.status_or_ban_until); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2731> *native, NetPacket_Fixed<0x2731> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->ban_not_status, network.ban_not_status); + rv &= network_to_native(&native->status_or_ban_until, network.status_or_ban_until); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x2732> *network, Packet_Head<0x2732> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x2732> *native, NetPacket_Head<0x2732> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x2732> *network, Packet_Repeat<0x2732> native) +{ + bool rv = true; + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->gm_level, native.gm_level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x2732> *native, NetPacket_Repeat<0x2732> network) +{ + bool rv = true; + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->gm_level, network.gm_level); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2740> *network, Packet_Fixed<0x2740> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->old_pass, native.old_pass); + rv &= native_to_network(&network->new_pass, native.new_pass); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2740> *native, NetPacket_Fixed<0x2740> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->old_pass, network.old_pass); + rv &= network_to_native(&native->new_pass, network.new_pass); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x2741> *network, Packet_Fixed<0x2741> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->status, native.status); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x2741> *native, NetPacket_Fixed<0x2741> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->status, network.status); + return rv; +} + +} // namespace tmwa diff --git a/src/proto2/login-char_test.cpp b/src/proto2/login-char_test.cpp new file mode 100644 index 0000000..0b61645 --- /dev/null +++ b/src/proto2/login-char_test.cpp @@ -0,0 +1,27 @@ +#include "login-char.hpp" +// login-char_test.cpp - TMWA network protocol: login/char +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "../poison.hpp" + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/proto2/login-user.hpp b/src/proto2/login-user.hpp new file mode 100644 index 0000000..fb6fcc7 --- /dev/null +++ b/src/proto2/login-user.hpp @@ -0,0 +1,325 @@ +#pragma once +// login-user.hpp - TMWA network protocol: login/user +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "fwd.hpp" + +#include "types.hpp" + +namespace tmwa +{ +// This is a public protocol, and changes require client cooperation + +template<> +struct Packet_Head<0x0063> +{ + static const uint16_t PACKET_ID = 0x0063; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x0063> +{ + static const uint16_t PACKET_ID = 0x0063; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x0064> +{ + static const uint16_t PACKET_ID = 0x0064; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint32_t unknown = {}; + AccountName account_name = {}; + AccountPass account_pass = {}; + VERSION_2 version_2_flags = {}; +}; + +template<> +struct Packet_Head<0x0069> +{ + static const uint16_t PACKET_ID = 0x0069; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + uint32_t login_id1 = {}; + AccountId account_id = {}; + uint32_t login_id2 = {}; + uint32_t unused = {}; + timestamp_milliseconds_buffer last_login_string = {}; + uint16_t unused2 = {}; + SEX sex = {}; +}; +template<> +struct Packet_Repeat<0x0069> +{ + static const uint16_t PACKET_ID = 0x0069; + + IP4Address ip = {}; + uint16_t port = {}; + ServerName server_name = {}; + uint16_t users = {}; + uint16_t maintenance = {}; + uint16_t is_new = {}; +}; + +template<> +struct Packet_Fixed<0x006a> +{ + static const uint16_t PACKET_ID = 0x006a; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t error_code = {}; + timestamp_seconds_buffer error_message = {}; +}; + + +template<> +struct NetPacket_Head<0x0063> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x0063>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x0063>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x0063>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x0063>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x0063>) == 4, "sizeof(NetPacket_Head<0x0063>) == 4"); +static_assert(alignof(NetPacket_Head<0x0063>) == 1, "alignof(NetPacket_Head<0x0063>) == 1"); +template<> +struct NetPacket_Repeat<0x0063> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x0063>, c) == 0, "offsetof(NetPacket_Repeat<0x0063>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x0063>) == 1, "sizeof(NetPacket_Repeat<0x0063>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x0063>) == 1, "alignof(NetPacket_Repeat<0x0063>) == 1"); + +template<> +struct NetPacket_Fixed<0x0064> +{ + Little16 magic_packet_id; + Little32 unknown; + NetString<sizeof(AccountName)> account_name; + NetString<sizeof(AccountPass)> account_pass; + Byte version_2_flags; +}; +static_assert(offsetof(NetPacket_Fixed<0x0064>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0064>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0064>, unknown) == 2, "offsetof(NetPacket_Fixed<0x0064>, unknown) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0064>, account_name) == 6, "offsetof(NetPacket_Fixed<0x0064>, account_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0064>, account_pass) == 30, "offsetof(NetPacket_Fixed<0x0064>, account_pass) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x0064>, version_2_flags) == 54, "offsetof(NetPacket_Fixed<0x0064>, version_2_flags) == 54"); +static_assert(sizeof(NetPacket_Fixed<0x0064>) == 55, "sizeof(NetPacket_Fixed<0x0064>) == 55"); +static_assert(alignof(NetPacket_Fixed<0x0064>) == 1, "alignof(NetPacket_Fixed<0x0064>) == 1"); + +template<> +struct NetPacket_Head<0x0069> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 login_id1; + Little32 account_id; + Little32 login_id2; + Little32 unused; + NetString<sizeof(timestamp_milliseconds_buffer)> last_login_string; + Little16 unused2; + Byte sex; +}; +static_assert(offsetof(NetPacket_Head<0x0069>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x0069>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x0069>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x0069>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x0069>, login_id1) == 4, "offsetof(NetPacket_Head<0x0069>, login_id1) == 4"); +static_assert(offsetof(NetPacket_Head<0x0069>, account_id) == 8, "offsetof(NetPacket_Head<0x0069>, account_id) == 8"); +static_assert(offsetof(NetPacket_Head<0x0069>, login_id2) == 12, "offsetof(NetPacket_Head<0x0069>, login_id2) == 12"); +static_assert(offsetof(NetPacket_Head<0x0069>, unused) == 16, "offsetof(NetPacket_Head<0x0069>, unused) == 16"); +static_assert(offsetof(NetPacket_Head<0x0069>, last_login_string) == 20, "offsetof(NetPacket_Head<0x0069>, last_login_string) == 20"); +static_assert(offsetof(NetPacket_Head<0x0069>, unused2) == 44, "offsetof(NetPacket_Head<0x0069>, unused2) == 44"); +static_assert(offsetof(NetPacket_Head<0x0069>, sex) == 46, "offsetof(NetPacket_Head<0x0069>, sex) == 46"); +static_assert(sizeof(NetPacket_Head<0x0069>) == 47, "sizeof(NetPacket_Head<0x0069>) == 47"); +static_assert(alignof(NetPacket_Head<0x0069>) == 1, "alignof(NetPacket_Head<0x0069>) == 1"); +template<> +struct NetPacket_Repeat<0x0069> +{ + IP4Address ip; + Little16 port; + NetString<sizeof(ServerName)> server_name; + Little16 users; + Little16 maintenance; + Little16 is_new; +}; +static_assert(offsetof(NetPacket_Repeat<0x0069>, ip) == 0, "offsetof(NetPacket_Repeat<0x0069>, ip) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x0069>, port) == 4, "offsetof(NetPacket_Repeat<0x0069>, port) == 4"); +static_assert(offsetof(NetPacket_Repeat<0x0069>, server_name) == 6, "offsetof(NetPacket_Repeat<0x0069>, server_name) == 6"); +static_assert(offsetof(NetPacket_Repeat<0x0069>, users) == 26, "offsetof(NetPacket_Repeat<0x0069>, users) == 26"); +static_assert(offsetof(NetPacket_Repeat<0x0069>, maintenance) == 28, "offsetof(NetPacket_Repeat<0x0069>, maintenance) == 28"); +static_assert(offsetof(NetPacket_Repeat<0x0069>, is_new) == 30, "offsetof(NetPacket_Repeat<0x0069>, is_new) == 30"); +static_assert(sizeof(NetPacket_Repeat<0x0069>) == 32, "sizeof(NetPacket_Repeat<0x0069>) == 32"); +static_assert(alignof(NetPacket_Repeat<0x0069>) == 1, "alignof(NetPacket_Repeat<0x0069>) == 1"); + +template<> +struct NetPacket_Fixed<0x006a> +{ + Little16 magic_packet_id; + Byte error_code; + NetString<sizeof(timestamp_seconds_buffer)> error_message; +}; +static_assert(offsetof(NetPacket_Fixed<0x006a>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x006a>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x006a>, error_code) == 2, "offsetof(NetPacket_Fixed<0x006a>, error_code) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x006a>, error_message) == 3, "offsetof(NetPacket_Fixed<0x006a>, error_message) == 3"); +static_assert(sizeof(NetPacket_Fixed<0x006a>) == 23, "sizeof(NetPacket_Fixed<0x006a>) == 23"); +static_assert(alignof(NetPacket_Fixed<0x006a>) == 1, "alignof(NetPacket_Fixed<0x006a>) == 1"); + + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x0063> *network, Packet_Head<0x0063> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x0063> *native, NetPacket_Head<0x0063> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x0063> *network, Packet_Repeat<0x0063> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x0063> *native, NetPacket_Repeat<0x0063> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0064> *network, Packet_Fixed<0x0064> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->unknown, native.unknown); + rv &= native_to_network(&network->account_name, native.account_name); + rv &= native_to_network(&network->account_pass, native.account_pass); + rv &= native_to_network(&network->version_2_flags, native.version_2_flags); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0064> *native, NetPacket_Fixed<0x0064> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->unknown, network.unknown); + rv &= network_to_native(&native->account_name, network.account_name); + rv &= network_to_native(&native->account_pass, network.account_pass); + rv &= network_to_native(&native->version_2_flags, network.version_2_flags); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x0069> *network, Packet_Head<0x0069> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->login_id1, native.login_id1); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->login_id2, native.login_id2); + rv &= native_to_network(&network->unused, native.unused); + rv &= native_to_network(&network->last_login_string, native.last_login_string); + rv &= native_to_network(&network->unused2, native.unused2); + rv &= native_to_network(&network->sex, native.sex); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x0069> *native, NetPacket_Head<0x0069> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->login_id1, network.login_id1); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->login_id2, network.login_id2); + rv &= network_to_native(&native->unused, network.unused); + rv &= network_to_native(&native->last_login_string, network.last_login_string); + rv &= network_to_native(&native->unused2, network.unused2); + rv &= network_to_native(&native->sex, network.sex); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x0069> *network, Packet_Repeat<0x0069> native) +{ + bool rv = true; + rv &= native_to_network(&network->ip, native.ip); + rv &= native_to_network(&network->port, native.port); + rv &= native_to_network(&network->server_name, native.server_name); + rv &= native_to_network(&network->users, native.users); + rv &= native_to_network(&network->maintenance, native.maintenance); + rv &= native_to_network(&network->is_new, native.is_new); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x0069> *native, NetPacket_Repeat<0x0069> network) +{ + bool rv = true; + rv &= network_to_native(&native->ip, network.ip); + rv &= network_to_native(&native->port, network.port); + rv &= network_to_native(&native->server_name, network.server_name); + rv &= network_to_native(&native->users, network.users); + rv &= network_to_native(&native->maintenance, network.maintenance); + rv &= network_to_native(&native->is_new, network.is_new); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x006a> *network, Packet_Fixed<0x006a> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->error_code, native.error_code); + rv &= native_to_network(&network->error_message, native.error_message); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x006a> *native, NetPacket_Fixed<0x006a> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->error_code, network.error_code); + rv &= network_to_native(&native->error_message, network.error_message); + return rv; +} + +} // namespace tmwa diff --git a/src/proto2/login-user_test.cpp b/src/proto2/login-user_test.cpp new file mode 100644 index 0000000..fa2128a --- /dev/null +++ b/src/proto2/login-user_test.cpp @@ -0,0 +1,27 @@ +#include "login-user.hpp" +// login-user_test.cpp - TMWA network protocol: login/user +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "../poison.hpp" + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/proto2/map-user.hpp b/src/proto2/map-user.hpp new file mode 100644 index 0000000..630c4f2 --- /dev/null +++ b/src/proto2/map-user.hpp @@ -0,0 +1,7931 @@ +#pragma once +// map-user.hpp - TMWA network protocol: map/user +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "fwd.hpp" + +#include "types.hpp" + +namespace tmwa +{ +// This is a public protocol, and changes require client cooperation + +template<> +struct Packet_Fixed<0x0072> +{ + static const uint16_t PACKET_ID = 0x0072; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + CharId char_id = {}; + uint32_t login_id1 = {}; + uint32_t client_tick = {}; + SEX sex = {}; +}; + +template<> +struct Packet_Fixed<0x0073> +{ + static const uint16_t PACKET_ID = 0x0073; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + tick_t tick = {}; + Position1 pos = {}; + uint8_t five1 = {}; + uint8_t five2 = {}; +}; + +template<> +struct Packet_Fixed<0x0078> +{ + static const uint16_t PACKET_ID = 0x0078; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + interval_t speed = {}; + Opt1 opt1 = {}; + Opt2 opt2 = {}; + Option option = {}; + Species species = {}; + uint16_t unused_hair_style = {}; + uint16_t unused_weapon = {}; + uint16_t unused_head_bottom_or_species_again = {}; + uint16_t unused_shield_or_part_of_guild_emblem = {}; + uint16_t unused_head_top_or_unused_part_of_guild_emblem = {}; + uint16_t unused_head_mid_or_part_of_guild_id = {}; + uint16_t unused_hair_color_or_part_of_guild_id = {}; + uint16_t unused_clothes_color = {}; + uint16_t unused_1 = {}; + uint16_t unused_2 = {}; + Position1 unused_pos_again = {}; + uint8_t unused_4b = {}; + uint16_t unused_5 = {}; + uint16_t unused_zero_1 = {}; + uint8_t unused_zero_2 = {}; + uint8_t unused_sex = {}; + Position1 pos = {}; + uint8_t five1 = {}; + uint8_t five2 = {}; + uint8_t zero = {}; + uint16_t level = {}; +}; + +template<> +struct Packet_Fixed<0x007b> +{ + static const uint16_t PACKET_ID = 0x007b; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + interval_t speed = {}; + Opt1 opt1 = {}; + Opt2 opt2 = {}; + Option option = {}; + Species mob_class = {}; + uint16_t unused_hair_style = {}; + uint16_t unused_weapon = {}; + uint16_t unused_head_bottom = {}; + tick_t tick_and_maybe_part_of_guild_emblem = {}; + uint16_t unused_shield_or_maybe_part_of_guild_emblem = {}; + uint16_t unused_head_top_or_maybe_part_of_guild_id = {}; + uint16_t unused_head_mid_or_maybe_part_of_guild_id = {}; + uint16_t unused_hair_color = {}; + uint16_t unused_clothes_color = {}; + uint16_t unused_1 = {}; + uint16_t unused_2 = {}; + uint16_t unused_3 = {}; + uint16_t unused_4 = {}; + uint16_t unused_5 = {}; + uint16_t unused_zero_1 = {}; + uint8_t unused_zero_2 = {}; + uint8_t unused_sex = {}; + Position2 pos2 = {}; + uint8_t zero = {}; + uint8_t five1 = {}; + uint8_t five2 = {}; + uint16_t level = {}; +}; + +template<> +struct Packet_Fixed<0x007c> +{ + static const uint16_t PACKET_ID = 0x007c; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + interval_t speed = {}; + Opt1 opt1 = {}; + Opt2 opt2 = {}; + Option option = {}; + uint16_t unknown_1 = {}; + uint16_t unknown_2 = {}; + uint16_t unknown_3 = {}; + Species species = {}; + uint16_t unknown_4 = {}; + uint16_t unknown_5 = {}; + uint16_t unknown_6 = {}; + uint16_t unknown_7 = {}; + uint16_t unknown_8 = {}; + uint16_t unknown_9 = {}; + uint16_t unknown_10 = {}; + Position1 pos = {}; + uint16_t unknown_11 = {}; +}; + +template<> +struct Packet_Fixed<0x007d> +{ + static const uint16_t PACKET_ID = 0x007d; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x007e> +{ + static const uint16_t PACKET_ID = 0x007e; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint32_t client_tick = {}; +}; + +template<> +struct Packet_Fixed<0x007f> +{ + static const uint16_t PACKET_ID = 0x007f; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + tick_t tick = {}; +}; + +template<> +struct Packet_Fixed<0x0080> +{ + static const uint16_t PACKET_ID = 0x0080; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + BeingRemoveWhy type = {}; +}; + +template<> +struct Packet_Fixed<0x0085> +{ + static const uint16_t PACKET_ID = 0x0085; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + Position1 pos = {}; +}; + +template<> +struct Packet_Fixed<0x0087> +{ + static const uint16_t PACKET_ID = 0x0087; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + tick_t tick = {}; + Position2 pos2 = {}; + uint8_t zero = {}; +}; + +template<> +struct Packet_Fixed<0x0088> +{ + static const uint16_t PACKET_ID = 0x0088; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + uint16_t x = {}; + uint16_t y = {}; +}; + +template<> +struct Packet_Fixed<0x0089> +{ + static const uint16_t PACKET_ID = 0x0089; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId target_id = {}; + DamageType action = {}; +}; + +template<> +struct Packet_Fixed<0x008a> +{ + static const uint16_t PACKET_ID = 0x008a; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId src_id = {}; + BlockId dst_id = {}; + tick_t tick = {}; + interval_t sdelay = {}; + interval_t ddelay = {}; + uint16_t damage = {}; + uint16_t div = {}; + DamageType damage_type = {}; + uint16_t damage2 = {}; +}; + +template<> +struct Packet_Head<0x008c> +{ + static const uint16_t PACKET_ID = 0x008c; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x008c> +{ + static const uint16_t PACKET_ID = 0x008c; + + uint8_t c = {}; +}; + +template<> +struct Packet_Head<0x008d> +{ + static const uint16_t PACKET_ID = 0x008d; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + BlockId block_id = {}; +}; +template<> +struct Packet_Repeat<0x008d> +{ + static const uint16_t PACKET_ID = 0x008d; + + uint8_t c = {}; +}; + +template<> +struct Packet_Head<0x008e> +{ + static const uint16_t PACKET_ID = 0x008e; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x008e> +{ + static const uint16_t PACKET_ID = 0x008e; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x0090> +{ + static const uint16_t PACKET_ID = 0x0090; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + uint8_t unused = {}; +}; + +template<> +struct Packet_Fixed<0x0091> +{ + static const uint16_t PACKET_ID = 0x0091; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + MapName map_name = {}; + uint16_t x = {}; + uint16_t y = {}; +}; + +template<> +struct Packet_Fixed<0x0092> +{ + static const uint16_t PACKET_ID = 0x0092; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + MapName map_name = {}; + uint16_t x = {}; + uint16_t y = {}; + IP4Address ip = {}; + uint16_t port = {}; +}; + +template<> +struct Packet_Fixed<0x0094> +{ + static const uint16_t PACKET_ID = 0x0094; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; +}; + +template<> +struct Packet_Fixed<0x0095> +{ + static const uint16_t PACKET_ID = 0x0095; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + CharName char_name = {}; +}; + +template<> +struct Packet_Head<0x0096> +{ + static const uint16_t PACKET_ID = 0x0096; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + CharName target_name = {}; +}; +template<> +struct Packet_Repeat<0x0096> +{ + static const uint16_t PACKET_ID = 0x0096; + + uint8_t c = {}; +}; + +template<> +struct Packet_Head<0x0097> +{ + static const uint16_t PACKET_ID = 0x0097; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + CharName char_name = {}; +}; +template<> +struct Packet_Repeat<0x0097> +{ + static const uint16_t PACKET_ID = 0x0097; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x0098> +{ + static const uint16_t PACKET_ID = 0x0098; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t flag = {}; +}; + +template<> +struct Packet_Head<0x009a> +{ + static const uint16_t PACKET_ID = 0x009a; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x009a> +{ + static const uint16_t PACKET_ID = 0x009a; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x009b> +{ + static const uint16_t PACKET_ID = 0x009b; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t unused = {}; + uint8_t client_dir = {}; +}; + +template<> +struct Packet_Fixed<0x009c> +{ + static const uint16_t PACKET_ID = 0x009c; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + uint16_t zero = {}; + uint8_t client_dir = {}; +}; + +template<> +struct Packet_Fixed<0x009d> +{ + static const uint16_t PACKET_ID = 0x009d; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + ItemNameId name_id = {}; + uint8_t identify = {}; + uint16_t x = {}; + uint16_t y = {}; + uint16_t amount = {}; + uint8_t subx = {}; + uint8_t suby = {}; +}; + +template<> +struct Packet_Fixed<0x009e> +{ + static const uint16_t PACKET_ID = 0x009e; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + ItemNameId name_id = {}; + uint8_t identify = {}; + uint16_t x = {}; + uint16_t y = {}; + uint8_t subx = {}; + uint8_t suby = {}; + uint16_t amount = {}; +}; + +template<> +struct Packet_Fixed<0x009f> +{ + static const uint16_t PACKET_ID = 0x009f; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId object_id = {}; +}; + +template<> +struct Packet_Fixed<0x00a0> +{ + static const uint16_t PACKET_ID = 0x00a0; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; + uint16_t amount = {}; + ItemNameId name_id = {}; + uint8_t identify = {}; + uint8_t broken_or_attribute = {}; + uint8_t refine = {}; + uint16_t card0 = {}; + uint16_t card1 = {}; + uint16_t card2 = {}; + uint16_t card3 = {}; + EPOS epos = {}; + ItemType item_type = {}; + PickupFail pickup_fail = {}; +}; + +template<> +struct Packet_Fixed<0x00a1> +{ + static const uint16_t PACKET_ID = 0x00a1; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; +}; + +template<> +struct Packet_Fixed<0x00a2> +{ + static const uint16_t PACKET_ID = 0x00a2; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; + uint16_t amount = {}; +}; + +template<> +struct Packet_Head<0x00a4> +{ + static const uint16_t PACKET_ID = 0x00a4; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x00a4> +{ + static const uint16_t PACKET_ID = 0x00a4; + + IOff2 ioff2 = {}; + ItemNameId name_id = {}; + ItemType item_type = {}; + uint8_t identify = {}; + EPOS epos_pc = {}; + EPOS epos_inv = {}; + uint8_t broken_or_attribute = {}; + uint8_t refine = {}; + uint16_t card0 = {}; + uint16_t card1 = {}; + uint16_t card2 = {}; + uint16_t card3 = {}; +}; + +template<> +struct Packet_Head<0x00a6> +{ + static const uint16_t PACKET_ID = 0x00a6; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x00a6> +{ + static const uint16_t PACKET_ID = 0x00a6; + + SOff1 soff1 = {}; + ItemNameId name_id = {}; + ItemType item_type = {}; + uint8_t identify = {}; + EPOS epos_id = {}; + EPOS epos_stor = {}; + uint8_t broken_or_attribute = {}; + uint8_t refine = {}; + uint16_t card0 = {}; + uint16_t card1 = {}; + uint16_t card2 = {}; + uint16_t card3 = {}; +}; + +template<> +struct Packet_Fixed<0x00a7> +{ + static const uint16_t PACKET_ID = 0x00a7; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; + uint32_t unused_id = {}; +}; + +template<> +struct Packet_Fixed<0x00a8> +{ + static const uint16_t PACKET_ID = 0x00a8; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; + uint16_t amount = {}; + uint8_t ok = {}; +}; + +template<> +struct Packet_Fixed<0x00a9> +{ + static const uint16_t PACKET_ID = 0x00a9; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; + EPOS epos_ignored = {}; +}; + +template<> +struct Packet_Fixed<0x00aa> +{ + static const uint16_t PACKET_ID = 0x00aa; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; + EPOS epos = {}; + uint8_t ok = {}; +}; + +template<> +struct Packet_Fixed<0x00ab> +{ + static const uint16_t PACKET_ID = 0x00ab; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; +}; + +template<> +struct Packet_Fixed<0x00ac> +{ + static const uint16_t PACKET_ID = 0x00ac; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; + EPOS epos = {}; + uint8_t ok = {}; +}; + +template<> +struct Packet_Fixed<0x00af> +{ + static const uint16_t PACKET_ID = 0x00af; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; + uint16_t amount = {}; +}; + +template<> +struct Packet_Fixed<0x00b0> +{ + static const uint16_t PACKET_ID = 0x00b0; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SP sp_type = {}; + uint32_t value = {}; +}; + +template<> +struct Packet_Fixed<0x00b1> +{ + static const uint16_t PACKET_ID = 0x00b1; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SP sp_type = {}; + uint32_t value = {}; +}; + +template<> +struct Packet_Fixed<0x00b2> +{ + static const uint16_t PACKET_ID = 0x00b2; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t flag = {}; +}; + +template<> +struct Packet_Fixed<0x00b3> +{ + static const uint16_t PACKET_ID = 0x00b3; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t one = {}; +}; + +template<> +struct Packet_Head<0x00b4> +{ + static const uint16_t PACKET_ID = 0x00b4; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + BlockId block_id = {}; +}; +template<> +struct Packet_Repeat<0x00b4> +{ + static const uint16_t PACKET_ID = 0x00b4; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x00b5> +{ + static const uint16_t PACKET_ID = 0x00b5; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; +}; + +template<> +struct Packet_Fixed<0x00b6> +{ + static const uint16_t PACKET_ID = 0x00b6; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; +}; + +template<> +struct Packet_Head<0x00b7> +{ + static const uint16_t PACKET_ID = 0x00b7; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + BlockId block_id = {}; +}; +template<> +struct Packet_Repeat<0x00b7> +{ + static const uint16_t PACKET_ID = 0x00b7; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x00b8> +{ + static const uint16_t PACKET_ID = 0x00b8; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId npc_id = {}; + uint8_t menu_entry = {}; +}; + +template<> +struct Packet_Fixed<0x00b9> +{ + static const uint16_t PACKET_ID = 0x00b9; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId npc_id = {}; +}; + +template<> +struct Packet_Fixed<0x00bb> +{ + static const uint16_t PACKET_ID = 0x00bb; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SP asp = {}; + uint8_t unused = {}; +}; + +template<> +struct Packet_Fixed<0x00bc> +{ + static const uint16_t PACKET_ID = 0x00bc; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SP sp_type = {}; + uint8_t ok = {}; + uint8_t val = {}; +}; + +template<> +struct Packet_Fixed<0x00bd> +{ + static const uint16_t PACKET_ID = 0x00bd; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t status_point = {}; + uint8_t str_attr = {}; + uint8_t str_upd = {}; + uint8_t agi_attr = {}; + uint8_t agi_upd = {}; + uint8_t vit_attr = {}; + uint8_t vit_upd = {}; + uint8_t int_attr = {}; + uint8_t int_upd = {}; + uint8_t dex_attr = {}; + uint8_t dex_upd = {}; + uint8_t luk_attr = {}; + uint8_t luk_upd = {}; + uint16_t atk_sum = {}; + uint16_t watk2 = {}; + uint16_t matk1 = {}; + uint16_t matk2 = {}; + uint16_t def = {}; + uint16_t def2 = {}; + uint16_t mdef = {}; + uint16_t mdef2 = {}; + uint16_t hit = {}; + uint16_t flee = {}; + uint16_t flee2 = {}; + uint16_t critical = {}; + uint16_t karma = {}; + uint16_t manner = {}; +}; + +template<> +struct Packet_Fixed<0x00be> +{ + static const uint16_t PACKET_ID = 0x00be; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SP sp_type = {}; + uint8_t value = {}; +}; + +template<> +struct Packet_Fixed<0x00bf> +{ + static const uint16_t PACKET_ID = 0x00bf; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t emote = {}; +}; + +template<> +struct Packet_Fixed<0x00c0> +{ + static const uint16_t PACKET_ID = 0x00c0; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + uint8_t type = {}; +}; + +template<> +struct Packet_Fixed<0x00c1> +{ + static const uint16_t PACKET_ID = 0x00c1; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x00c2> +{ + static const uint16_t PACKET_ID = 0x00c2; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint32_t users = {}; +}; + +template<> +struct Packet_Fixed<0x00c4> +{ + static const uint16_t PACKET_ID = 0x00c4; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; +}; + +template<> +struct Packet_Fixed<0x00c5> +{ + static const uint16_t PACKET_ID = 0x00c5; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + uint8_t type = {}; +}; + +template<> +struct Packet_Head<0x00c6> +{ + static const uint16_t PACKET_ID = 0x00c6; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x00c6> +{ + static const uint16_t PACKET_ID = 0x00c6; + + uint32_t base_price = {}; + uint32_t actual_price = {}; + ItemType type = {}; + ItemNameId name_id = {}; +}; + +template<> +struct Packet_Head<0x00c7> +{ + static const uint16_t PACKET_ID = 0x00c7; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x00c7> +{ + static const uint16_t PACKET_ID = 0x00c7; + + IOff2 ioff2 = {}; + uint32_t base_price = {}; + uint32_t actual_price = {}; +}; + +template<> +struct Packet_Head<0x00c8> +{ + static const uint16_t PACKET_ID = 0x00c8; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x00c8> +{ + static const uint16_t PACKET_ID = 0x00c8; + + uint16_t count = {}; + ItemNameId name_id = {}; +}; + +template<> +struct Packet_Head<0x00c9> +{ + static const uint16_t PACKET_ID = 0x00c9; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x00c9> +{ + static const uint16_t PACKET_ID = 0x00c9; + + IOff2 ioff2 = {}; + uint16_t count = {}; +}; + +template<> +struct Packet_Fixed<0x00ca> +{ + static const uint16_t PACKET_ID = 0x00ca; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t fail = {}; +}; + +template<> +struct Packet_Fixed<0x00cb> +{ + static const uint16_t PACKET_ID = 0x00cb; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t fail = {}; +}; + +template<> +struct Packet_Fixed<0x00cd> +{ + static const uint16_t PACKET_ID = 0x00cd; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Fixed<0x00e4> +{ + static const uint16_t PACKET_ID = 0x00e4; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; +}; + +template<> +struct Packet_Fixed<0x00e5> +{ + static const uint16_t PACKET_ID = 0x00e5; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + CharName char_name = {}; +}; + +template<> +struct Packet_Fixed<0x00e6> +{ + static const uint16_t PACKET_ID = 0x00e6; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t type = {}; +}; + +template<> +struct Packet_Fixed<0x00e7> +{ + static const uint16_t PACKET_ID = 0x00e7; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t type = {}; +}; + +template<> +struct Packet_Fixed<0x00e8> +{ + static const uint16_t PACKET_ID = 0x00e8; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 zeny_or_ioff2 = {}; + uint32_t amount = {}; +}; + +template<> +struct Packet_Fixed<0x00e9> +{ + static const uint16_t PACKET_ID = 0x00e9; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint32_t amount = {}; + ItemNameId name_id = {}; + uint8_t identify = {}; + uint8_t broken_or_attribute = {}; + uint8_t refine = {}; + uint16_t card0 = {}; + uint16_t card1 = {}; + uint16_t card2 = {}; + uint16_t card3 = {}; +}; + +template<> +struct Packet_Fixed<0x00eb> +{ + static const uint16_t PACKET_ID = 0x00eb; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x00ec> +{ + static const uint16_t PACKET_ID = 0x00ec; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t fail = {}; +}; + +template<> +struct Packet_Fixed<0x00ed> +{ + static const uint16_t PACKET_ID = 0x00ed; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x00ee> +{ + static const uint16_t PACKET_ID = 0x00ee; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x00ef> +{ + static const uint16_t PACKET_ID = 0x00ef; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x00f0> +{ + static const uint16_t PACKET_ID = 0x00f0; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t fail = {}; +}; + +template<> +struct Packet_Fixed<0x00f2> +{ + static const uint16_t PACKET_ID = 0x00f2; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t current_slots = {}; + uint16_t max_slots = {}; +}; + +template<> +struct Packet_Fixed<0x00f3> +{ + static const uint16_t PACKET_ID = 0x00f3; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; + uint32_t amount = {}; +}; + +template<> +struct Packet_Fixed<0x00f4> +{ + static const uint16_t PACKET_ID = 0x00f4; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SOff1 soff1 = {}; + uint32_t amount = {}; + ItemNameId name_id = {}; + uint8_t identify = {}; + uint8_t broken_or_attribute = {}; + uint8_t refine = {}; + uint16_t card0 = {}; + uint16_t card1 = {}; + uint16_t card2 = {}; + uint16_t card3 = {}; +}; + +template<> +struct Packet_Fixed<0x00f5> +{ + static const uint16_t PACKET_ID = 0x00f5; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SOff1 soff1 = {}; + uint32_t amount = {}; +}; + +template<> +struct Packet_Fixed<0x00f6> +{ + static const uint16_t PACKET_ID = 0x00f6; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SOff1 soff1 = {}; + uint32_t amount = {}; +}; + +template<> +struct Packet_Fixed<0x00f7> +{ + static const uint16_t PACKET_ID = 0x00f7; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x00f8> +{ + static const uint16_t PACKET_ID = 0x00f8; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x00f9> +{ + static const uint16_t PACKET_ID = 0x00f9; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + PartyName party_name = {}; +}; + +template<> +struct Packet_Fixed<0x00fa> +{ + static const uint16_t PACKET_ID = 0x00fa; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint8_t flag = {}; +}; + +template<> +struct Packet_Head<0x00fb> +{ + static const uint16_t PACKET_ID = 0x00fb; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + PartyName party_name = {}; +}; +template<> +struct Packet_Repeat<0x00fb> +{ + static const uint16_t PACKET_ID = 0x00fb; + + AccountId account_id = {}; + CharName char_name = {}; + MapName map_name = {}; + uint8_t leader = {}; + uint8_t online = {}; +}; + +template<> +struct Packet_Fixed<0x00fc> +{ + static const uint16_t PACKET_ID = 0x00fc; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; +}; + +template<> +struct Packet_Fixed<0x00fd> +{ + static const uint16_t PACKET_ID = 0x00fd; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + CharName char_name = {}; + uint8_t flag = {}; +}; + +template<> +struct Packet_Fixed<0x00fe> +{ + static const uint16_t PACKET_ID = 0x00fe; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + PartyName party_name = {}; +}; + +template<> +struct Packet_Fixed<0x00ff> +{ + static const uint16_t PACKET_ID = 0x00ff; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint32_t flag = {}; +}; + +template<> +struct Packet_Fixed<0x0100> +{ + static const uint16_t PACKET_ID = 0x0100; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x0101> +{ + static const uint16_t PACKET_ID = 0x0101; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t exp = {}; + uint16_t item = {}; +}; + +template<> +struct Packet_Fixed<0x0102> +{ + static const uint16_t PACKET_ID = 0x0102; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t exp = {}; + uint16_t item = {}; +}; + +template<> +struct Packet_Fixed<0x0103> +{ + static const uint16_t PACKET_ID = 0x0103; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + CharName unused_char_name = {}; +}; + +template<> +struct Packet_Fixed<0x0105> +{ + static const uint16_t PACKET_ID = 0x0105; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + CharName char_name = {}; + uint8_t flag = {}; +}; + +template<> +struct Packet_Fixed<0x0106> +{ + static const uint16_t PACKET_ID = 0x0106; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint16_t hp = {}; + uint16_t max_hp = {}; +}; + +template<> +struct Packet_Fixed<0x0107> +{ + static const uint16_t PACKET_ID = 0x0107; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + AccountId account_id = {}; + uint16_t x = {}; + uint16_t y = {}; +}; + +template<> +struct Packet_Head<0x0108> +{ + static const uint16_t PACKET_ID = 0x0108; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x0108> +{ + static const uint16_t PACKET_ID = 0x0108; + + uint8_t c = {}; +}; + +template<> +struct Packet_Head<0x0109> +{ + static const uint16_t PACKET_ID = 0x0109; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + AccountId account_id = {}; +}; +template<> +struct Packet_Repeat<0x0109> +{ + static const uint16_t PACKET_ID = 0x0109; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x010c> +{ + static const uint16_t PACKET_ID = 0x010c; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; +}; + +template<> +struct Packet_Fixed<0x010e> +{ + static const uint16_t PACKET_ID = 0x010e; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SkillID skill_id = {}; + uint16_t level = {}; + uint16_t sp = {}; + uint16_t range = {}; + uint8_t can_raise = {}; +}; + +template<> +struct Packet_Head<0x010f> +{ + static const uint16_t PACKET_ID = 0x010f; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x010f> +{ + static const uint16_t PACKET_ID = 0x010f; + + SkillInfo info = {}; +}; + +template<> +struct Packet_Fixed<0x0110> +{ + static const uint16_t PACKET_ID = 0x0110; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SkillID skill_id = {}; + uint16_t btype = {}; + uint16_t zero1 = {}; + uint8_t zero2 = {}; + uint8_t type = {}; +}; + +template<> +struct Packet_Fixed<0x0112> +{ + static const uint16_t PACKET_ID = 0x0112; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SkillID skill_id = {}; +}; + +template<> +struct Packet_Fixed<0x0118> +{ + static const uint16_t PACKET_ID = 0x0118; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x0119> +{ + static const uint16_t PACKET_ID = 0x0119; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + Opt1 opt1 = {}; + Opt2 opt2 = {}; + Option option = {}; + uint8_t zero = {}; +}; + +template<> +struct Packet_Fixed<0x0139> +{ + static const uint16_t PACKET_ID = 0x0139; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + uint16_t bl_x = {}; + uint16_t bl_y = {}; + uint16_t sd_x = {}; + uint16_t sd_y = {}; + uint16_t range = {}; +}; + +template<> +struct Packet_Fixed<0x013a> +{ + static const uint16_t PACKET_ID = 0x013a; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t attack_range = {}; +}; + +template<> +struct Packet_Fixed<0x013b> +{ + static const uint16_t PACKET_ID = 0x013b; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t type = {}; +}; + +template<> +struct Packet_Fixed<0x013c> +{ + static const uint16_t PACKET_ID = 0x013c; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; +}; + +template<> +struct Packet_Fixed<0x0141> +{ + static const uint16_t PACKET_ID = 0x0141; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SP sp_type = {}; + uint16_t zero = {}; + uint32_t value_status = {}; + uint32_t value_b_e = {}; +}; + +template<> +struct Packet_Fixed<0x0142> +{ + static const uint16_t PACKET_ID = 0x0142; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; +}; + +template<> +struct Packet_Fixed<0x0143> +{ + static const uint16_t PACKET_ID = 0x0143; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + uint32_t input_int_value = {}; +}; + +template<> +struct Packet_Fixed<0x0146> +{ + static const uint16_t PACKET_ID = 0x0146; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; +}; + +template<> +struct Packet_Fixed<0x0147> +{ + static const uint16_t PACKET_ID = 0x0147; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SkillInfo info = {}; +}; + +template<> +struct Packet_Fixed<0x0148> +{ + static const uint16_t PACKET_ID = 0x0148; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + uint16_t type = {}; +}; + +template<> +struct Packet_Fixed<0x014d> +{ + static const uint16_t PACKET_ID = 0x014d; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; +}; + +template<> +struct Packet_Fixed<0x018a> +{ + static const uint16_t PACKET_ID = 0x018a; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t unused = {}; +}; + +template<> +struct Packet_Fixed<0x018b> +{ + static const uint16_t PACKET_ID = 0x018b; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + uint16_t okay = {}; +}; + +template<> +struct Packet_Fixed<0x0195> +{ + static const uint16_t PACKET_ID = 0x0195; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + PartyName party_name = {}; + VString<23> guild_name = {}; + VString<23> guild_pos = {}; + VString<23> guild_pos_again = {}; +}; + +template<> +struct Packet_Fixed<0x0196> +{ + static const uint16_t PACKET_ID = 0x0196; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + StatusChange sc_type = {}; + BlockId block_id = {}; + uint8_t flag = {}; +}; + +template<> +struct Packet_Fixed<0x019b> +{ + static const uint16_t PACKET_ID = 0x019b; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + uint32_t type = {}; +}; + +template<> +struct Packet_Fixed<0x01b1> +{ + static const uint16_t PACKET_ID = 0x01b1; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; + uint16_t amount = {}; + uint8_t fail = {}; +}; + +template<> +struct Packet_Fixed<0x01c8> +{ + static const uint16_t PACKET_ID = 0x01c8; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + IOff2 ioff2 = {}; + ItemNameId name_id = {}; + BlockId block_id = {}; + uint16_t amount = {}; + uint8_t ok = {}; +}; + +template<> +struct Packet_Fixed<0x01d4> +{ + static const uint16_t PACKET_ID = 0x01d4; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; +}; + +template<> +struct Packet_Head<0x01d5> +{ + static const uint16_t PACKET_ID = 0x01d5; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; + BlockId block_id = {}; +}; +template<> +struct Packet_Repeat<0x01d5> +{ + static const uint16_t PACKET_ID = 0x01d5; + + uint8_t c = {}; +}; + +template<> +struct Packet_Fixed<0x01d7> +{ + static const uint16_t PACKET_ID = 0x01d7; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + LOOK look_type = {}; + uint16_t weapon_or_name_id_or_value = {}; + ItemNameId shield = {}; +}; + +template<> +struct Packet_Fixed<0x01d8> +{ + static const uint16_t PACKET_ID = 0x01d8; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + interval_t speed = {}; + Opt1 opt1 = {}; + Opt2 opt2 = {}; + Option option = {}; + Species species = {}; + uint16_t hair_style = {}; + ItemNameId weapon = {}; + ItemNameId shield = {}; + ItemNameId head_bottom = {}; + ItemNameId head_top = {}; + ItemNameId head_mid = {}; + uint16_t hair_color = {}; + uint16_t clothes_color = {}; + DIR head_dir = {}; + uint8_t unused2 = {}; + uint32_t guild_id = {}; + uint16_t guild_emblem_id = {}; + uint16_t manner = {}; + Opt3 opt3 = {}; + uint8_t karma = {}; + SEX sex = {}; + Position1 pos = {}; + uint16_t gm_bits = {}; + uint8_t dead_sit = {}; + uint16_t unused = {}; +}; + +template<> +struct Packet_Fixed<0x01d9> +{ + static const uint16_t PACKET_ID = 0x01d9; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + interval_t speed = {}; + Opt1 opt1 = {}; + Opt2 opt2 = {}; + Option option = {}; + Species species = {}; + uint16_t hair_style = {}; + ItemNameId weapon = {}; + ItemNameId shield = {}; + ItemNameId head_bottom = {}; + ItemNameId head_top = {}; + ItemNameId head_mid = {}; + uint16_t hair_color = {}; + uint16_t clothes_color = {}; + DIR head_dir = {}; + uint8_t unused2 = {}; + uint32_t guild_id = {}; + uint16_t guild_emblem_id = {}; + uint16_t manner = {}; + Opt3 opt3 = {}; + uint8_t karma = {}; + SEX sex = {}; + Position1 pos = {}; + uint16_t gm_bits = {}; + uint16_t unused = {}; +}; + +template<> +struct Packet_Fixed<0x01da> +{ + static const uint16_t PACKET_ID = 0x01da; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + interval_t speed = {}; + Opt1 opt1 = {}; + Opt2 opt2 = {}; + Option option = {}; + Species species = {}; + uint16_t hair_style = {}; + ItemNameId weapon = {}; + ItemNameId shield = {}; + ItemNameId head_bottom = {}; + tick_t tick = {}; + ItemNameId head_top = {}; + ItemNameId head_mid = {}; + uint16_t hair_color = {}; + uint16_t clothes_color = {}; + DIR head_dir = {}; + uint8_t unused2 = {}; + uint32_t guild_id = {}; + uint16_t guild_emblem_id = {}; + uint16_t manner = {}; + Opt3 opt3 = {}; + uint8_t karma = {}; + SEX sex = {}; + Position2 pos2 = {}; + uint16_t gm_bits = {}; + uint8_t five = {}; + uint16_t unused = {}; +}; + +template<> +struct Packet_Fixed<0x01de> +{ + static const uint16_t PACKET_ID = 0x01de; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + SkillID skill_id = {}; + BlockId src_id = {}; + BlockId dst_id = {}; + tick_t tick = {}; + interval_t sdelay = {}; + interval_t ddelay = {}; + uint32_t damage = {}; + uint16_t skill_level = {}; + uint16_t div = {}; + uint8_t type_or_hit = {}; +}; + +template<> +struct Packet_Head<0x01ee> +{ + static const uint16_t PACKET_ID = 0x01ee; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x01ee> +{ + static const uint16_t PACKET_ID = 0x01ee; + + IOff2 ioff2 = {}; + ItemNameId name_id = {}; + ItemType item_type = {}; + uint8_t identify = {}; + uint16_t amount = {}; + EPOS epos = {}; + uint16_t card0 = {}; + uint16_t card1 = {}; + uint16_t card2 = {}; + uint16_t card3 = {}; +}; + +template<> +struct Packet_Head<0x01f0> +{ + static const uint16_t PACKET_ID = 0x01f0; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + // TODO remove this + uint16_t magic_packet_length = {}; +}; +template<> +struct Packet_Repeat<0x01f0> +{ + static const uint16_t PACKET_ID = 0x01f0; + + SOff1 soff1 = {}; + ItemNameId name_id = {}; + ItemType item_type = {}; + uint8_t identify = {}; + uint16_t amount = {}; + EPOS epos_zero = {}; + uint16_t card0 = {}; + uint16_t card1 = {}; + uint16_t card2 = {}; + uint16_t card3 = {}; +}; + +template<> +struct Packet_Fixed<0x020c> +{ + static const uint16_t PACKET_ID = 0x020c; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId block_id = {}; + IP4Address ip = {}; +}; + +template<> +struct Packet_Fixed<0x0212> +{ + static const uint16_t PACKET_ID = 0x0212; + + // TODO remove this + uint16_t magic_packet_id = PACKET_ID; + BlockId npc_id = {}; + uint16_t command = {}; + BlockId id = {}; + uint16_t x = {}; + uint16_t y = {}; +}; + + +template<> +struct NetPacket_Fixed<0x0072> +{ + Little16 magic_packet_id; + Little32 account_id; + Little32 char_id; + Little32 login_id1; + Little32 client_tick; + Byte sex; +}; +static_assert(offsetof(NetPacket_Fixed<0x0072>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0072>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0072>, account_id) == 2, "offsetof(NetPacket_Fixed<0x0072>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0072>, char_id) == 6, "offsetof(NetPacket_Fixed<0x0072>, char_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0072>, login_id1) == 10, "offsetof(NetPacket_Fixed<0x0072>, login_id1) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x0072>, client_tick) == 14, "offsetof(NetPacket_Fixed<0x0072>, client_tick) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x0072>, sex) == 18, "offsetof(NetPacket_Fixed<0x0072>, sex) == 18"); +static_assert(sizeof(NetPacket_Fixed<0x0072>) == 19, "sizeof(NetPacket_Fixed<0x0072>) == 19"); +static_assert(alignof(NetPacket_Fixed<0x0072>) == 1, "alignof(NetPacket_Fixed<0x0072>) == 1"); + +template<> +struct NetPacket_Fixed<0x0073> +{ + Little16 magic_packet_id; + Little32 tick; + NetPosition1 pos; + Byte five1; + Byte five2; +}; +static_assert(offsetof(NetPacket_Fixed<0x0073>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0073>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0073>, tick) == 2, "offsetof(NetPacket_Fixed<0x0073>, tick) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0073>, pos) == 6, "offsetof(NetPacket_Fixed<0x0073>, pos) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0073>, five1) == 9, "offsetof(NetPacket_Fixed<0x0073>, five1) == 9"); +static_assert(offsetof(NetPacket_Fixed<0x0073>, five2) == 10, "offsetof(NetPacket_Fixed<0x0073>, five2) == 10"); +static_assert(sizeof(NetPacket_Fixed<0x0073>) == 11, "sizeof(NetPacket_Fixed<0x0073>) == 11"); +static_assert(alignof(NetPacket_Fixed<0x0073>) == 1, "alignof(NetPacket_Fixed<0x0073>) == 1"); + +template<> +struct NetPacket_Fixed<0x0078> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 speed; + Little16 opt1; + Little16 opt2; + Little16 option; + Little16 species; + Little16 unused_hair_style; + Little16 unused_weapon; + Little16 unused_head_bottom_or_species_again; + Little16 unused_shield_or_part_of_guild_emblem; + Little16 unused_head_top_or_unused_part_of_guild_emblem; + Little16 unused_head_mid_or_part_of_guild_id; + Little16 unused_hair_color_or_part_of_guild_id; + Little16 unused_clothes_color; + Little16 unused_1; + Little16 unused_2; + NetPosition1 unused_pos_again; + Byte unused_4b; + Little16 unused_5; + Little16 unused_zero_1; + Byte unused_zero_2; + Byte unused_sex; + NetPosition1 pos; + Byte five1; + Byte five2; + Byte zero; + Little16 level; +}; +static_assert(offsetof(NetPacket_Fixed<0x0078>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0078>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0078>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, speed) == 6, "offsetof(NetPacket_Fixed<0x0078>, speed) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, opt1) == 8, "offsetof(NetPacket_Fixed<0x0078>, opt1) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, opt2) == 10, "offsetof(NetPacket_Fixed<0x0078>, opt2) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, option) == 12, "offsetof(NetPacket_Fixed<0x0078>, option) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, species) == 14, "offsetof(NetPacket_Fixed<0x0078>, species) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_hair_style) == 16, "offsetof(NetPacket_Fixed<0x0078>, unused_hair_style) == 16"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_weapon) == 18, "offsetof(NetPacket_Fixed<0x0078>, unused_weapon) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_head_bottom_or_species_again) == 20, "offsetof(NetPacket_Fixed<0x0078>, unused_head_bottom_or_species_again) == 20"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_shield_or_part_of_guild_emblem) == 22, "offsetof(NetPacket_Fixed<0x0078>, unused_shield_or_part_of_guild_emblem) == 22"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_head_top_or_unused_part_of_guild_emblem) == 24, "offsetof(NetPacket_Fixed<0x0078>, unused_head_top_or_unused_part_of_guild_emblem) == 24"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_head_mid_or_part_of_guild_id) == 26, "offsetof(NetPacket_Fixed<0x0078>, unused_head_mid_or_part_of_guild_id) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_hair_color_or_part_of_guild_id) == 28, "offsetof(NetPacket_Fixed<0x0078>, unused_hair_color_or_part_of_guild_id) == 28"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_clothes_color) == 30, "offsetof(NetPacket_Fixed<0x0078>, unused_clothes_color) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_1) == 32, "offsetof(NetPacket_Fixed<0x0078>, unused_1) == 32"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_2) == 34, "offsetof(NetPacket_Fixed<0x0078>, unused_2) == 34"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_pos_again) == 36, "offsetof(NetPacket_Fixed<0x0078>, unused_pos_again) == 36"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_4b) == 39, "offsetof(NetPacket_Fixed<0x0078>, unused_4b) == 39"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_5) == 40, "offsetof(NetPacket_Fixed<0x0078>, unused_5) == 40"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_zero_1) == 42, "offsetof(NetPacket_Fixed<0x0078>, unused_zero_1) == 42"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_zero_2) == 44, "offsetof(NetPacket_Fixed<0x0078>, unused_zero_2) == 44"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, unused_sex) == 45, "offsetof(NetPacket_Fixed<0x0078>, unused_sex) == 45"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, pos) == 46, "offsetof(NetPacket_Fixed<0x0078>, pos) == 46"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, five1) == 49, "offsetof(NetPacket_Fixed<0x0078>, five1) == 49"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, five2) == 50, "offsetof(NetPacket_Fixed<0x0078>, five2) == 50"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, zero) == 51, "offsetof(NetPacket_Fixed<0x0078>, zero) == 51"); +static_assert(offsetof(NetPacket_Fixed<0x0078>, level) == 52, "offsetof(NetPacket_Fixed<0x0078>, level) == 52"); +static_assert(sizeof(NetPacket_Fixed<0x0078>) == 54, "sizeof(NetPacket_Fixed<0x0078>) == 54"); +static_assert(alignof(NetPacket_Fixed<0x0078>) == 1, "alignof(NetPacket_Fixed<0x0078>) == 1"); + +template<> +struct NetPacket_Fixed<0x007b> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 speed; + Little16 opt1; + Little16 opt2; + Little16 option; + Little16 mob_class; + Little16 unused_hair_style; + Little16 unused_weapon; + Little16 unused_head_bottom; + Little32 tick_and_maybe_part_of_guild_emblem; + Little16 unused_shield_or_maybe_part_of_guild_emblem; + Little16 unused_head_top_or_maybe_part_of_guild_id; + Little16 unused_head_mid_or_maybe_part_of_guild_id; + Little16 unused_hair_color; + Little16 unused_clothes_color; + Little16 unused_1; + Little16 unused_2; + Little16 unused_3; + Little16 unused_4; + Little16 unused_5; + Little16 unused_zero_1; + Byte unused_zero_2; + Byte unused_sex; + NetPosition2 pos2; + Byte zero; + Byte five1; + Byte five2; + Little16 level; +}; +static_assert(offsetof(NetPacket_Fixed<0x007b>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x007b>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, block_id) == 2, "offsetof(NetPacket_Fixed<0x007b>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, speed) == 6, "offsetof(NetPacket_Fixed<0x007b>, speed) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, opt1) == 8, "offsetof(NetPacket_Fixed<0x007b>, opt1) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, opt2) == 10, "offsetof(NetPacket_Fixed<0x007b>, opt2) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, option) == 12, "offsetof(NetPacket_Fixed<0x007b>, option) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, mob_class) == 14, "offsetof(NetPacket_Fixed<0x007b>, mob_class) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_hair_style) == 16, "offsetof(NetPacket_Fixed<0x007b>, unused_hair_style) == 16"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_weapon) == 18, "offsetof(NetPacket_Fixed<0x007b>, unused_weapon) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_head_bottom) == 20, "offsetof(NetPacket_Fixed<0x007b>, unused_head_bottom) == 20"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, tick_and_maybe_part_of_guild_emblem) == 22, "offsetof(NetPacket_Fixed<0x007b>, tick_and_maybe_part_of_guild_emblem) == 22"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_shield_or_maybe_part_of_guild_emblem) == 26, "offsetof(NetPacket_Fixed<0x007b>, unused_shield_or_maybe_part_of_guild_emblem) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_head_top_or_maybe_part_of_guild_id) == 28, "offsetof(NetPacket_Fixed<0x007b>, unused_head_top_or_maybe_part_of_guild_id) == 28"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_head_mid_or_maybe_part_of_guild_id) == 30, "offsetof(NetPacket_Fixed<0x007b>, unused_head_mid_or_maybe_part_of_guild_id) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_hair_color) == 32, "offsetof(NetPacket_Fixed<0x007b>, unused_hair_color) == 32"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_clothes_color) == 34, "offsetof(NetPacket_Fixed<0x007b>, unused_clothes_color) == 34"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_1) == 36, "offsetof(NetPacket_Fixed<0x007b>, unused_1) == 36"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_2) == 38, "offsetof(NetPacket_Fixed<0x007b>, unused_2) == 38"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_3) == 40, "offsetof(NetPacket_Fixed<0x007b>, unused_3) == 40"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_4) == 42, "offsetof(NetPacket_Fixed<0x007b>, unused_4) == 42"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_5) == 44, "offsetof(NetPacket_Fixed<0x007b>, unused_5) == 44"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_zero_1) == 46, "offsetof(NetPacket_Fixed<0x007b>, unused_zero_1) == 46"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_zero_2) == 48, "offsetof(NetPacket_Fixed<0x007b>, unused_zero_2) == 48"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, unused_sex) == 49, "offsetof(NetPacket_Fixed<0x007b>, unused_sex) == 49"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, pos2) == 50, "offsetof(NetPacket_Fixed<0x007b>, pos2) == 50"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, zero) == 55, "offsetof(NetPacket_Fixed<0x007b>, zero) == 55"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, five1) == 56, "offsetof(NetPacket_Fixed<0x007b>, five1) == 56"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, five2) == 57, "offsetof(NetPacket_Fixed<0x007b>, five2) == 57"); +static_assert(offsetof(NetPacket_Fixed<0x007b>, level) == 58, "offsetof(NetPacket_Fixed<0x007b>, level) == 58"); +static_assert(sizeof(NetPacket_Fixed<0x007b>) == 60, "sizeof(NetPacket_Fixed<0x007b>) == 60"); +static_assert(alignof(NetPacket_Fixed<0x007b>) == 1, "alignof(NetPacket_Fixed<0x007b>) == 1"); + +template<> +struct NetPacket_Fixed<0x007c> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 speed; + Little16 opt1; + Little16 opt2; + Little16 option; + Little16 unknown_1; + Little16 unknown_2; + Little16 unknown_3; + Little16 species; + Little16 unknown_4; + Little16 unknown_5; + Little16 unknown_6; + Little16 unknown_7; + Little16 unknown_8; + Little16 unknown_9; + Little16 unknown_10; + NetPosition1 pos; + Little16 unknown_11; +}; +static_assert(offsetof(NetPacket_Fixed<0x007c>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x007c>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, block_id) == 2, "offsetof(NetPacket_Fixed<0x007c>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, speed) == 6, "offsetof(NetPacket_Fixed<0x007c>, speed) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, opt1) == 8, "offsetof(NetPacket_Fixed<0x007c>, opt1) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, opt2) == 10, "offsetof(NetPacket_Fixed<0x007c>, opt2) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, option) == 12, "offsetof(NetPacket_Fixed<0x007c>, option) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, unknown_1) == 14, "offsetof(NetPacket_Fixed<0x007c>, unknown_1) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, unknown_2) == 16, "offsetof(NetPacket_Fixed<0x007c>, unknown_2) == 16"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, unknown_3) == 18, "offsetof(NetPacket_Fixed<0x007c>, unknown_3) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, species) == 20, "offsetof(NetPacket_Fixed<0x007c>, species) == 20"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, unknown_4) == 22, "offsetof(NetPacket_Fixed<0x007c>, unknown_4) == 22"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, unknown_5) == 24, "offsetof(NetPacket_Fixed<0x007c>, unknown_5) == 24"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, unknown_6) == 26, "offsetof(NetPacket_Fixed<0x007c>, unknown_6) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, unknown_7) == 28, "offsetof(NetPacket_Fixed<0x007c>, unknown_7) == 28"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, unknown_8) == 30, "offsetof(NetPacket_Fixed<0x007c>, unknown_8) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, unknown_9) == 32, "offsetof(NetPacket_Fixed<0x007c>, unknown_9) == 32"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, unknown_10) == 34, "offsetof(NetPacket_Fixed<0x007c>, unknown_10) == 34"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, pos) == 36, "offsetof(NetPacket_Fixed<0x007c>, pos) == 36"); +static_assert(offsetof(NetPacket_Fixed<0x007c>, unknown_11) == 39, "offsetof(NetPacket_Fixed<0x007c>, unknown_11) == 39"); +static_assert(sizeof(NetPacket_Fixed<0x007c>) == 41, "sizeof(NetPacket_Fixed<0x007c>) == 41"); +static_assert(alignof(NetPacket_Fixed<0x007c>) == 1, "alignof(NetPacket_Fixed<0x007c>) == 1"); + +template<> +struct NetPacket_Fixed<0x007d> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x007d>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x007d>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x007d>) == 2, "sizeof(NetPacket_Fixed<0x007d>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x007d>) == 1, "alignof(NetPacket_Fixed<0x007d>) == 1"); + +template<> +struct NetPacket_Fixed<0x007e> +{ + Little16 magic_packet_id; + Little32 client_tick; +}; +static_assert(offsetof(NetPacket_Fixed<0x007e>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x007e>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x007e>, client_tick) == 2, "offsetof(NetPacket_Fixed<0x007e>, client_tick) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x007e>) == 6, "sizeof(NetPacket_Fixed<0x007e>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x007e>) == 1, "alignof(NetPacket_Fixed<0x007e>) == 1"); + +template<> +struct NetPacket_Fixed<0x007f> +{ + Little16 magic_packet_id; + Little32 tick; +}; +static_assert(offsetof(NetPacket_Fixed<0x007f>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x007f>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x007f>, tick) == 2, "offsetof(NetPacket_Fixed<0x007f>, tick) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x007f>) == 6, "sizeof(NetPacket_Fixed<0x007f>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x007f>) == 1, "alignof(NetPacket_Fixed<0x007f>) == 1"); + +template<> +struct NetPacket_Fixed<0x0080> +{ + Little16 magic_packet_id; + Little32 block_id; + Byte type; +}; +static_assert(offsetof(NetPacket_Fixed<0x0080>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0080>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0080>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0080>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0080>, type) == 6, "offsetof(NetPacket_Fixed<0x0080>, type) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x0080>) == 7, "sizeof(NetPacket_Fixed<0x0080>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x0080>) == 1, "alignof(NetPacket_Fixed<0x0080>) == 1"); + +template<> +struct NetPacket_Fixed<0x0085> +{ + Little16 magic_packet_id; + NetPosition1 pos; +}; +static_assert(offsetof(NetPacket_Fixed<0x0085>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0085>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0085>, pos) == 2, "offsetof(NetPacket_Fixed<0x0085>, pos) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x0085>) == 5, "sizeof(NetPacket_Fixed<0x0085>) == 5"); +static_assert(alignof(NetPacket_Fixed<0x0085>) == 1, "alignof(NetPacket_Fixed<0x0085>) == 1"); + +template<> +struct NetPacket_Fixed<0x0087> +{ + Little16 magic_packet_id; + Little32 tick; + NetPosition2 pos2; + Byte zero; +}; +static_assert(offsetof(NetPacket_Fixed<0x0087>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0087>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0087>, tick) == 2, "offsetof(NetPacket_Fixed<0x0087>, tick) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0087>, pos2) == 6, "offsetof(NetPacket_Fixed<0x0087>, pos2) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0087>, zero) == 11, "offsetof(NetPacket_Fixed<0x0087>, zero) == 11"); +static_assert(sizeof(NetPacket_Fixed<0x0087>) == 12, "sizeof(NetPacket_Fixed<0x0087>) == 12"); +static_assert(alignof(NetPacket_Fixed<0x0087>) == 1, "alignof(NetPacket_Fixed<0x0087>) == 1"); + +template<> +struct NetPacket_Fixed<0x0088> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 x; + Little16 y; +}; +static_assert(offsetof(NetPacket_Fixed<0x0088>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0088>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0088>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0088>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0088>, x) == 6, "offsetof(NetPacket_Fixed<0x0088>, x) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0088>, y) == 8, "offsetof(NetPacket_Fixed<0x0088>, y) == 8"); +static_assert(sizeof(NetPacket_Fixed<0x0088>) == 10, "sizeof(NetPacket_Fixed<0x0088>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x0088>) == 1, "alignof(NetPacket_Fixed<0x0088>) == 1"); + +template<> +struct NetPacket_Fixed<0x0089> +{ + Little16 magic_packet_id; + Little32 target_id; + Byte action; +}; +static_assert(offsetof(NetPacket_Fixed<0x0089>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0089>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0089>, target_id) == 2, "offsetof(NetPacket_Fixed<0x0089>, target_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0089>, action) == 6, "offsetof(NetPacket_Fixed<0x0089>, action) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x0089>) == 7, "sizeof(NetPacket_Fixed<0x0089>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x0089>) == 1, "alignof(NetPacket_Fixed<0x0089>) == 1"); + +template<> +struct NetPacket_Fixed<0x008a> +{ + Little16 magic_packet_id; + Little32 src_id; + Little32 dst_id; + Little32 tick; + Little32 sdelay; + Little32 ddelay; + Little16 damage; + Little16 div; + Byte damage_type; + Little16 damage2; +}; +static_assert(offsetof(NetPacket_Fixed<0x008a>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x008a>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x008a>, src_id) == 2, "offsetof(NetPacket_Fixed<0x008a>, src_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x008a>, dst_id) == 6, "offsetof(NetPacket_Fixed<0x008a>, dst_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x008a>, tick) == 10, "offsetof(NetPacket_Fixed<0x008a>, tick) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x008a>, sdelay) == 14, "offsetof(NetPacket_Fixed<0x008a>, sdelay) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x008a>, ddelay) == 18, "offsetof(NetPacket_Fixed<0x008a>, ddelay) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x008a>, damage) == 22, "offsetof(NetPacket_Fixed<0x008a>, damage) == 22"); +static_assert(offsetof(NetPacket_Fixed<0x008a>, div) == 24, "offsetof(NetPacket_Fixed<0x008a>, div) == 24"); +static_assert(offsetof(NetPacket_Fixed<0x008a>, damage_type) == 26, "offsetof(NetPacket_Fixed<0x008a>, damage_type) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x008a>, damage2) == 27, "offsetof(NetPacket_Fixed<0x008a>, damage2) == 27"); +static_assert(sizeof(NetPacket_Fixed<0x008a>) == 29, "sizeof(NetPacket_Fixed<0x008a>) == 29"); +static_assert(alignof(NetPacket_Fixed<0x008a>) == 1, "alignof(NetPacket_Fixed<0x008a>) == 1"); + +template<> +struct NetPacket_Head<0x008c> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x008c>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x008c>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x008c>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x008c>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x008c>) == 4, "sizeof(NetPacket_Head<0x008c>) == 4"); +static_assert(alignof(NetPacket_Head<0x008c>) == 1, "alignof(NetPacket_Head<0x008c>) == 1"); +template<> +struct NetPacket_Repeat<0x008c> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x008c>, c) == 0, "offsetof(NetPacket_Repeat<0x008c>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x008c>) == 1, "sizeof(NetPacket_Repeat<0x008c>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x008c>) == 1, "alignof(NetPacket_Repeat<0x008c>) == 1"); + +template<> +struct NetPacket_Head<0x008d> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Head<0x008d>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x008d>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x008d>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x008d>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x008d>, block_id) == 4, "offsetof(NetPacket_Head<0x008d>, block_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x008d>) == 8, "sizeof(NetPacket_Head<0x008d>) == 8"); +static_assert(alignof(NetPacket_Head<0x008d>) == 1, "alignof(NetPacket_Head<0x008d>) == 1"); +template<> +struct NetPacket_Repeat<0x008d> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x008d>, c) == 0, "offsetof(NetPacket_Repeat<0x008d>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x008d>) == 1, "sizeof(NetPacket_Repeat<0x008d>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x008d>) == 1, "alignof(NetPacket_Repeat<0x008d>) == 1"); + +template<> +struct NetPacket_Head<0x008e> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x008e>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x008e>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x008e>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x008e>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x008e>) == 4, "sizeof(NetPacket_Head<0x008e>) == 4"); +static_assert(alignof(NetPacket_Head<0x008e>) == 1, "alignof(NetPacket_Head<0x008e>) == 1"); +template<> +struct NetPacket_Repeat<0x008e> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x008e>, c) == 0, "offsetof(NetPacket_Repeat<0x008e>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x008e>) == 1, "sizeof(NetPacket_Repeat<0x008e>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x008e>) == 1, "alignof(NetPacket_Repeat<0x008e>) == 1"); + +template<> +struct NetPacket_Fixed<0x0090> +{ + Little16 magic_packet_id; + Little32 block_id; + Byte unused; +}; +static_assert(offsetof(NetPacket_Fixed<0x0090>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0090>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0090>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0090>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0090>, unused) == 6, "offsetof(NetPacket_Fixed<0x0090>, unused) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x0090>) == 7, "sizeof(NetPacket_Fixed<0x0090>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x0090>) == 1, "alignof(NetPacket_Fixed<0x0090>) == 1"); + +template<> +struct NetPacket_Fixed<0x0091> +{ + Little16 magic_packet_id; + NetString<sizeof(MapName)> map_name; + Little16 x; + Little16 y; +}; +static_assert(offsetof(NetPacket_Fixed<0x0091>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0091>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0091>, map_name) == 2, "offsetof(NetPacket_Fixed<0x0091>, map_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0091>, x) == 18, "offsetof(NetPacket_Fixed<0x0091>, x) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x0091>, y) == 20, "offsetof(NetPacket_Fixed<0x0091>, y) == 20"); +static_assert(sizeof(NetPacket_Fixed<0x0091>) == 22, "sizeof(NetPacket_Fixed<0x0091>) == 22"); +static_assert(alignof(NetPacket_Fixed<0x0091>) == 1, "alignof(NetPacket_Fixed<0x0091>) == 1"); + +template<> +struct NetPacket_Fixed<0x0092> +{ + Little16 magic_packet_id; + NetString<sizeof(MapName)> map_name; + Little16 x; + Little16 y; + IP4Address ip; + Little16 port; +}; +static_assert(offsetof(NetPacket_Fixed<0x0092>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0092>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0092>, map_name) == 2, "offsetof(NetPacket_Fixed<0x0092>, map_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0092>, x) == 18, "offsetof(NetPacket_Fixed<0x0092>, x) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x0092>, y) == 20, "offsetof(NetPacket_Fixed<0x0092>, y) == 20"); +static_assert(offsetof(NetPacket_Fixed<0x0092>, ip) == 22, "offsetof(NetPacket_Fixed<0x0092>, ip) == 22"); +static_assert(offsetof(NetPacket_Fixed<0x0092>, port) == 26, "offsetof(NetPacket_Fixed<0x0092>, port) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x0092>) == 28, "sizeof(NetPacket_Fixed<0x0092>) == 28"); +static_assert(alignof(NetPacket_Fixed<0x0092>) == 1, "alignof(NetPacket_Fixed<0x0092>) == 1"); + +template<> +struct NetPacket_Fixed<0x0094> +{ + Little16 magic_packet_id; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x0094>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0094>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0094>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0094>, block_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x0094>) == 6, "sizeof(NetPacket_Fixed<0x0094>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x0094>) == 1, "alignof(NetPacket_Fixed<0x0094>) == 1"); + +template<> +struct NetPacket_Fixed<0x0095> +{ + Little16 magic_packet_id; + Little32 block_id; + NetString<sizeof(CharName)> char_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x0095>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0095>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0095>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0095>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0095>, char_name) == 6, "offsetof(NetPacket_Fixed<0x0095>, char_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x0095>) == 30, "sizeof(NetPacket_Fixed<0x0095>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x0095>) == 1, "alignof(NetPacket_Fixed<0x0095>) == 1"); + +template<> +struct NetPacket_Head<0x0096> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + NetString<sizeof(CharName)> target_name; +}; +static_assert(offsetof(NetPacket_Head<0x0096>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x0096>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x0096>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x0096>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x0096>, target_name) == 4, "offsetof(NetPacket_Head<0x0096>, target_name) == 4"); +static_assert(sizeof(NetPacket_Head<0x0096>) == 28, "sizeof(NetPacket_Head<0x0096>) == 28"); +static_assert(alignof(NetPacket_Head<0x0096>) == 1, "alignof(NetPacket_Head<0x0096>) == 1"); +template<> +struct NetPacket_Repeat<0x0096> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x0096>, c) == 0, "offsetof(NetPacket_Repeat<0x0096>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x0096>) == 1, "sizeof(NetPacket_Repeat<0x0096>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x0096>) == 1, "alignof(NetPacket_Repeat<0x0096>) == 1"); + +template<> +struct NetPacket_Head<0x0097> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + NetString<sizeof(CharName)> char_name; +}; +static_assert(offsetof(NetPacket_Head<0x0097>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x0097>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x0097>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x0097>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x0097>, char_name) == 4, "offsetof(NetPacket_Head<0x0097>, char_name) == 4"); +static_assert(sizeof(NetPacket_Head<0x0097>) == 28, "sizeof(NetPacket_Head<0x0097>) == 28"); +static_assert(alignof(NetPacket_Head<0x0097>) == 1, "alignof(NetPacket_Head<0x0097>) == 1"); +template<> +struct NetPacket_Repeat<0x0097> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x0097>, c) == 0, "offsetof(NetPacket_Repeat<0x0097>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x0097>) == 1, "sizeof(NetPacket_Repeat<0x0097>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x0097>) == 1, "alignof(NetPacket_Repeat<0x0097>) == 1"); + +template<> +struct NetPacket_Fixed<0x0098> +{ + Little16 magic_packet_id; + Byte flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x0098>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0098>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0098>, flag) == 2, "offsetof(NetPacket_Fixed<0x0098>, flag) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x0098>) == 3, "sizeof(NetPacket_Fixed<0x0098>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x0098>) == 1, "alignof(NetPacket_Fixed<0x0098>) == 1"); + +template<> +struct NetPacket_Head<0x009a> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x009a>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x009a>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x009a>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x009a>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x009a>) == 4, "sizeof(NetPacket_Head<0x009a>) == 4"); +static_assert(alignof(NetPacket_Head<0x009a>) == 1, "alignof(NetPacket_Head<0x009a>) == 1"); +template<> +struct NetPacket_Repeat<0x009a> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x009a>, c) == 0, "offsetof(NetPacket_Repeat<0x009a>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x009a>) == 1, "sizeof(NetPacket_Repeat<0x009a>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x009a>) == 1, "alignof(NetPacket_Repeat<0x009a>) == 1"); + +template<> +struct NetPacket_Fixed<0x009b> +{ + Little16 magic_packet_id; + Little16 unused; + Byte client_dir; +}; +static_assert(offsetof(NetPacket_Fixed<0x009b>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x009b>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x009b>, unused) == 2, "offsetof(NetPacket_Fixed<0x009b>, unused) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x009b>, client_dir) == 4, "offsetof(NetPacket_Fixed<0x009b>, client_dir) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x009b>) == 5, "sizeof(NetPacket_Fixed<0x009b>) == 5"); +static_assert(alignof(NetPacket_Fixed<0x009b>) == 1, "alignof(NetPacket_Fixed<0x009b>) == 1"); + +template<> +struct NetPacket_Fixed<0x009c> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 zero; + Byte client_dir; +}; +static_assert(offsetof(NetPacket_Fixed<0x009c>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x009c>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x009c>, block_id) == 2, "offsetof(NetPacket_Fixed<0x009c>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x009c>, zero) == 6, "offsetof(NetPacket_Fixed<0x009c>, zero) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x009c>, client_dir) == 8, "offsetof(NetPacket_Fixed<0x009c>, client_dir) == 8"); +static_assert(sizeof(NetPacket_Fixed<0x009c>) == 9, "sizeof(NetPacket_Fixed<0x009c>) == 9"); +static_assert(alignof(NetPacket_Fixed<0x009c>) == 1, "alignof(NetPacket_Fixed<0x009c>) == 1"); + +template<> +struct NetPacket_Fixed<0x009d> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 name_id; + Byte identify; + Little16 x; + Little16 y; + Little16 amount; + Byte subx; + Byte suby; +}; +static_assert(offsetof(NetPacket_Fixed<0x009d>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x009d>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x009d>, block_id) == 2, "offsetof(NetPacket_Fixed<0x009d>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x009d>, name_id) == 6, "offsetof(NetPacket_Fixed<0x009d>, name_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x009d>, identify) == 8, "offsetof(NetPacket_Fixed<0x009d>, identify) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x009d>, x) == 9, "offsetof(NetPacket_Fixed<0x009d>, x) == 9"); +static_assert(offsetof(NetPacket_Fixed<0x009d>, y) == 11, "offsetof(NetPacket_Fixed<0x009d>, y) == 11"); +static_assert(offsetof(NetPacket_Fixed<0x009d>, amount) == 13, "offsetof(NetPacket_Fixed<0x009d>, amount) == 13"); +static_assert(offsetof(NetPacket_Fixed<0x009d>, subx) == 15, "offsetof(NetPacket_Fixed<0x009d>, subx) == 15"); +static_assert(offsetof(NetPacket_Fixed<0x009d>, suby) == 16, "offsetof(NetPacket_Fixed<0x009d>, suby) == 16"); +static_assert(sizeof(NetPacket_Fixed<0x009d>) == 17, "sizeof(NetPacket_Fixed<0x009d>) == 17"); +static_assert(alignof(NetPacket_Fixed<0x009d>) == 1, "alignof(NetPacket_Fixed<0x009d>) == 1"); + +template<> +struct NetPacket_Fixed<0x009e> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 name_id; + Byte identify; + Little16 x; + Little16 y; + Byte subx; + Byte suby; + Little16 amount; +}; +static_assert(offsetof(NetPacket_Fixed<0x009e>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x009e>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x009e>, block_id) == 2, "offsetof(NetPacket_Fixed<0x009e>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x009e>, name_id) == 6, "offsetof(NetPacket_Fixed<0x009e>, name_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x009e>, identify) == 8, "offsetof(NetPacket_Fixed<0x009e>, identify) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x009e>, x) == 9, "offsetof(NetPacket_Fixed<0x009e>, x) == 9"); +static_assert(offsetof(NetPacket_Fixed<0x009e>, y) == 11, "offsetof(NetPacket_Fixed<0x009e>, y) == 11"); +static_assert(offsetof(NetPacket_Fixed<0x009e>, subx) == 13, "offsetof(NetPacket_Fixed<0x009e>, subx) == 13"); +static_assert(offsetof(NetPacket_Fixed<0x009e>, suby) == 14, "offsetof(NetPacket_Fixed<0x009e>, suby) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x009e>, amount) == 15, "offsetof(NetPacket_Fixed<0x009e>, amount) == 15"); +static_assert(sizeof(NetPacket_Fixed<0x009e>) == 17, "sizeof(NetPacket_Fixed<0x009e>) == 17"); +static_assert(alignof(NetPacket_Fixed<0x009e>) == 1, "alignof(NetPacket_Fixed<0x009e>) == 1"); + +template<> +struct NetPacket_Fixed<0x009f> +{ + Little16 magic_packet_id; + Little32 object_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x009f>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x009f>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x009f>, object_id) == 2, "offsetof(NetPacket_Fixed<0x009f>, object_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x009f>) == 6, "sizeof(NetPacket_Fixed<0x009f>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x009f>) == 1, "alignof(NetPacket_Fixed<0x009f>) == 1"); + +template<> +struct NetPacket_Fixed<0x00a0> +{ + Little16 magic_packet_id; + Little16 ioff2; + Little16 amount; + Little16 name_id; + Byte identify; + Byte broken_or_attribute; + Byte refine; + Little16 card0; + Little16 card1; + Little16 card2; + Little16 card3; + Little16 epos; + Byte item_type; + Byte pickup_fail; +}; +static_assert(offsetof(NetPacket_Fixed<0x00a0>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00a0>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x00a0>, ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, amount) == 4, "offsetof(NetPacket_Fixed<0x00a0>, amount) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, name_id) == 6, "offsetof(NetPacket_Fixed<0x00a0>, name_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, identify) == 8, "offsetof(NetPacket_Fixed<0x00a0>, identify) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, broken_or_attribute) == 9, "offsetof(NetPacket_Fixed<0x00a0>, broken_or_attribute) == 9"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, refine) == 10, "offsetof(NetPacket_Fixed<0x00a0>, refine) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, card0) == 11, "offsetof(NetPacket_Fixed<0x00a0>, card0) == 11"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, card1) == 13, "offsetof(NetPacket_Fixed<0x00a0>, card1) == 13"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, card2) == 15, "offsetof(NetPacket_Fixed<0x00a0>, card2) == 15"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, card3) == 17, "offsetof(NetPacket_Fixed<0x00a0>, card3) == 17"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, epos) == 19, "offsetof(NetPacket_Fixed<0x00a0>, epos) == 19"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, item_type) == 21, "offsetof(NetPacket_Fixed<0x00a0>, item_type) == 21"); +static_assert(offsetof(NetPacket_Fixed<0x00a0>, pickup_fail) == 22, "offsetof(NetPacket_Fixed<0x00a0>, pickup_fail) == 22"); +static_assert(sizeof(NetPacket_Fixed<0x00a0>) == 23, "sizeof(NetPacket_Fixed<0x00a0>) == 23"); +static_assert(alignof(NetPacket_Fixed<0x00a0>) == 1, "alignof(NetPacket_Fixed<0x00a0>) == 1"); + +template<> +struct NetPacket_Fixed<0x00a1> +{ + Little16 magic_packet_id; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00a1>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00a1>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00a1>, block_id) == 2, "offsetof(NetPacket_Fixed<0x00a1>, block_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00a1>) == 6, "sizeof(NetPacket_Fixed<0x00a1>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00a1>) == 1, "alignof(NetPacket_Fixed<0x00a1>) == 1"); + +template<> +struct NetPacket_Fixed<0x00a2> +{ + Little16 magic_packet_id; + Little16 ioff2; + Little16 amount; +}; +static_assert(offsetof(NetPacket_Fixed<0x00a2>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00a2>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00a2>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x00a2>, ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00a2>, amount) == 4, "offsetof(NetPacket_Fixed<0x00a2>, amount) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00a2>) == 6, "sizeof(NetPacket_Fixed<0x00a2>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00a2>) == 1, "alignof(NetPacket_Fixed<0x00a2>) == 1"); + +template<> +struct NetPacket_Head<0x00a4> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x00a4>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x00a4>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x00a4>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x00a4>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x00a4>) == 4, "sizeof(NetPacket_Head<0x00a4>) == 4"); +static_assert(alignof(NetPacket_Head<0x00a4>) == 1, "alignof(NetPacket_Head<0x00a4>) == 1"); +template<> +struct NetPacket_Repeat<0x00a4> +{ + Little16 ioff2; + Little16 name_id; + Byte item_type; + Byte identify; + Little16 epos_pc; + Little16 epos_inv; + Byte broken_or_attribute; + Byte refine; + Little16 card0; + Little16 card1; + Little16 card2; + Little16 card3; +}; +static_assert(offsetof(NetPacket_Repeat<0x00a4>, ioff2) == 0, "offsetof(NetPacket_Repeat<0x00a4>, ioff2) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x00a4>, name_id) == 2, "offsetof(NetPacket_Repeat<0x00a4>, name_id) == 2"); +static_assert(offsetof(NetPacket_Repeat<0x00a4>, item_type) == 4, "offsetof(NetPacket_Repeat<0x00a4>, item_type) == 4"); +static_assert(offsetof(NetPacket_Repeat<0x00a4>, identify) == 5, "offsetof(NetPacket_Repeat<0x00a4>, identify) == 5"); +static_assert(offsetof(NetPacket_Repeat<0x00a4>, epos_pc) == 6, "offsetof(NetPacket_Repeat<0x00a4>, epos_pc) == 6"); +static_assert(offsetof(NetPacket_Repeat<0x00a4>, epos_inv) == 8, "offsetof(NetPacket_Repeat<0x00a4>, epos_inv) == 8"); +static_assert(offsetof(NetPacket_Repeat<0x00a4>, broken_or_attribute) == 10, "offsetof(NetPacket_Repeat<0x00a4>, broken_or_attribute) == 10"); +static_assert(offsetof(NetPacket_Repeat<0x00a4>, refine) == 11, "offsetof(NetPacket_Repeat<0x00a4>, refine) == 11"); +static_assert(offsetof(NetPacket_Repeat<0x00a4>, card0) == 12, "offsetof(NetPacket_Repeat<0x00a4>, card0) == 12"); +static_assert(offsetof(NetPacket_Repeat<0x00a4>, card1) == 14, "offsetof(NetPacket_Repeat<0x00a4>, card1) == 14"); +static_assert(offsetof(NetPacket_Repeat<0x00a4>, card2) == 16, "offsetof(NetPacket_Repeat<0x00a4>, card2) == 16"); +static_assert(offsetof(NetPacket_Repeat<0x00a4>, card3) == 18, "offsetof(NetPacket_Repeat<0x00a4>, card3) == 18"); +static_assert(sizeof(NetPacket_Repeat<0x00a4>) == 20, "sizeof(NetPacket_Repeat<0x00a4>) == 20"); +static_assert(alignof(NetPacket_Repeat<0x00a4>) == 1, "alignof(NetPacket_Repeat<0x00a4>) == 1"); + +template<> +struct NetPacket_Head<0x00a6> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x00a6>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x00a6>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x00a6>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x00a6>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x00a6>) == 4, "sizeof(NetPacket_Head<0x00a6>) == 4"); +static_assert(alignof(NetPacket_Head<0x00a6>) == 1, "alignof(NetPacket_Head<0x00a6>) == 1"); +template<> +struct NetPacket_Repeat<0x00a6> +{ + Little16 soff1; + Little16 name_id; + Byte item_type; + Byte identify; + Little16 epos_id; + Little16 epos_stor; + Byte broken_or_attribute; + Byte refine; + Little16 card0; + Little16 card1; + Little16 card2; + Little16 card3; +}; +static_assert(offsetof(NetPacket_Repeat<0x00a6>, soff1) == 0, "offsetof(NetPacket_Repeat<0x00a6>, soff1) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x00a6>, name_id) == 2, "offsetof(NetPacket_Repeat<0x00a6>, name_id) == 2"); +static_assert(offsetof(NetPacket_Repeat<0x00a6>, item_type) == 4, "offsetof(NetPacket_Repeat<0x00a6>, item_type) == 4"); +static_assert(offsetof(NetPacket_Repeat<0x00a6>, identify) == 5, "offsetof(NetPacket_Repeat<0x00a6>, identify) == 5"); +static_assert(offsetof(NetPacket_Repeat<0x00a6>, epos_id) == 6, "offsetof(NetPacket_Repeat<0x00a6>, epos_id) == 6"); +static_assert(offsetof(NetPacket_Repeat<0x00a6>, epos_stor) == 8, "offsetof(NetPacket_Repeat<0x00a6>, epos_stor) == 8"); +static_assert(offsetof(NetPacket_Repeat<0x00a6>, broken_or_attribute) == 10, "offsetof(NetPacket_Repeat<0x00a6>, broken_or_attribute) == 10"); +static_assert(offsetof(NetPacket_Repeat<0x00a6>, refine) == 11, "offsetof(NetPacket_Repeat<0x00a6>, refine) == 11"); +static_assert(offsetof(NetPacket_Repeat<0x00a6>, card0) == 12, "offsetof(NetPacket_Repeat<0x00a6>, card0) == 12"); +static_assert(offsetof(NetPacket_Repeat<0x00a6>, card1) == 14, "offsetof(NetPacket_Repeat<0x00a6>, card1) == 14"); +static_assert(offsetof(NetPacket_Repeat<0x00a6>, card2) == 16, "offsetof(NetPacket_Repeat<0x00a6>, card2) == 16"); +static_assert(offsetof(NetPacket_Repeat<0x00a6>, card3) == 18, "offsetof(NetPacket_Repeat<0x00a6>, card3) == 18"); +static_assert(sizeof(NetPacket_Repeat<0x00a6>) == 20, "sizeof(NetPacket_Repeat<0x00a6>) == 20"); +static_assert(alignof(NetPacket_Repeat<0x00a6>) == 1, "alignof(NetPacket_Repeat<0x00a6>) == 1"); + +template<> +struct NetPacket_Fixed<0x00a7> +{ + Little16 magic_packet_id; + Little16 ioff2; + Little32 unused_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00a7>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00a7>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00a7>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x00a7>, ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00a7>, unused_id) == 4, "offsetof(NetPacket_Fixed<0x00a7>, unused_id) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00a7>) == 8, "sizeof(NetPacket_Fixed<0x00a7>) == 8"); +static_assert(alignof(NetPacket_Fixed<0x00a7>) == 1, "alignof(NetPacket_Fixed<0x00a7>) == 1"); + +template<> +struct NetPacket_Fixed<0x00a8> +{ + Little16 magic_packet_id; + Little16 ioff2; + Little16 amount; + Byte ok; +}; +static_assert(offsetof(NetPacket_Fixed<0x00a8>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00a8>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00a8>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x00a8>, ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00a8>, amount) == 4, "offsetof(NetPacket_Fixed<0x00a8>, amount) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x00a8>, ok) == 6, "offsetof(NetPacket_Fixed<0x00a8>, ok) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x00a8>) == 7, "sizeof(NetPacket_Fixed<0x00a8>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x00a8>) == 1, "alignof(NetPacket_Fixed<0x00a8>) == 1"); + +template<> +struct NetPacket_Fixed<0x00a9> +{ + Little16 magic_packet_id; + Little16 ioff2; + Little16 epos_ignored; +}; +static_assert(offsetof(NetPacket_Fixed<0x00a9>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00a9>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00a9>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x00a9>, ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00a9>, epos_ignored) == 4, "offsetof(NetPacket_Fixed<0x00a9>, epos_ignored) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00a9>) == 6, "sizeof(NetPacket_Fixed<0x00a9>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00a9>) == 1, "alignof(NetPacket_Fixed<0x00a9>) == 1"); + +template<> +struct NetPacket_Fixed<0x00aa> +{ + Little16 magic_packet_id; + Little16 ioff2; + Little16 epos; + Byte ok; +}; +static_assert(offsetof(NetPacket_Fixed<0x00aa>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00aa>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00aa>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x00aa>, ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00aa>, epos) == 4, "offsetof(NetPacket_Fixed<0x00aa>, epos) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x00aa>, ok) == 6, "offsetof(NetPacket_Fixed<0x00aa>, ok) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x00aa>) == 7, "sizeof(NetPacket_Fixed<0x00aa>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x00aa>) == 1, "alignof(NetPacket_Fixed<0x00aa>) == 1"); + +template<> +struct NetPacket_Fixed<0x00ab> +{ + Little16 magic_packet_id; + Little16 ioff2; +}; +static_assert(offsetof(NetPacket_Fixed<0x00ab>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00ab>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00ab>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x00ab>, ioff2) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00ab>) == 4, "sizeof(NetPacket_Fixed<0x00ab>) == 4"); +static_assert(alignof(NetPacket_Fixed<0x00ab>) == 1, "alignof(NetPacket_Fixed<0x00ab>) == 1"); + +template<> +struct NetPacket_Fixed<0x00ac> +{ + Little16 magic_packet_id; + Little16 ioff2; + Little16 epos; + Byte ok; +}; +static_assert(offsetof(NetPacket_Fixed<0x00ac>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00ac>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00ac>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x00ac>, ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00ac>, epos) == 4, "offsetof(NetPacket_Fixed<0x00ac>, epos) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x00ac>, ok) == 6, "offsetof(NetPacket_Fixed<0x00ac>, ok) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x00ac>) == 7, "sizeof(NetPacket_Fixed<0x00ac>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x00ac>) == 1, "alignof(NetPacket_Fixed<0x00ac>) == 1"); + +template<> +struct NetPacket_Fixed<0x00af> +{ + Little16 magic_packet_id; + Little16 ioff2; + Little16 amount; +}; +static_assert(offsetof(NetPacket_Fixed<0x00af>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00af>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00af>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x00af>, ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00af>, amount) == 4, "offsetof(NetPacket_Fixed<0x00af>, amount) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00af>) == 6, "sizeof(NetPacket_Fixed<0x00af>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00af>) == 1, "alignof(NetPacket_Fixed<0x00af>) == 1"); + +template<> +struct NetPacket_Fixed<0x00b0> +{ + Little16 magic_packet_id; + Little16 sp_type; + Little32 value; +}; +static_assert(offsetof(NetPacket_Fixed<0x00b0>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00b0>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00b0>, sp_type) == 2, "offsetof(NetPacket_Fixed<0x00b0>, sp_type) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00b0>, value) == 4, "offsetof(NetPacket_Fixed<0x00b0>, value) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00b0>) == 8, "sizeof(NetPacket_Fixed<0x00b0>) == 8"); +static_assert(alignof(NetPacket_Fixed<0x00b0>) == 1, "alignof(NetPacket_Fixed<0x00b0>) == 1"); + +template<> +struct NetPacket_Fixed<0x00b1> +{ + Little16 magic_packet_id; + Little16 sp_type; + Little32 value; +}; +static_assert(offsetof(NetPacket_Fixed<0x00b1>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00b1>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00b1>, sp_type) == 2, "offsetof(NetPacket_Fixed<0x00b1>, sp_type) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00b1>, value) == 4, "offsetof(NetPacket_Fixed<0x00b1>, value) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00b1>) == 8, "sizeof(NetPacket_Fixed<0x00b1>) == 8"); +static_assert(alignof(NetPacket_Fixed<0x00b1>) == 1, "alignof(NetPacket_Fixed<0x00b1>) == 1"); + +template<> +struct NetPacket_Fixed<0x00b2> +{ + Little16 magic_packet_id; + Byte flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x00b2>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00b2>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00b2>, flag) == 2, "offsetof(NetPacket_Fixed<0x00b2>, flag) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00b2>) == 3, "sizeof(NetPacket_Fixed<0x00b2>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x00b2>) == 1, "alignof(NetPacket_Fixed<0x00b2>) == 1"); + +template<> +struct NetPacket_Fixed<0x00b3> +{ + Little16 magic_packet_id; + Byte one; +}; +static_assert(offsetof(NetPacket_Fixed<0x00b3>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00b3>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00b3>, one) == 2, "offsetof(NetPacket_Fixed<0x00b3>, one) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00b3>) == 3, "sizeof(NetPacket_Fixed<0x00b3>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x00b3>) == 1, "alignof(NetPacket_Fixed<0x00b3>) == 1"); + +template<> +struct NetPacket_Head<0x00b4> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Head<0x00b4>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x00b4>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x00b4>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x00b4>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x00b4>, block_id) == 4, "offsetof(NetPacket_Head<0x00b4>, block_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x00b4>) == 8, "sizeof(NetPacket_Head<0x00b4>) == 8"); +static_assert(alignof(NetPacket_Head<0x00b4>) == 1, "alignof(NetPacket_Head<0x00b4>) == 1"); +template<> +struct NetPacket_Repeat<0x00b4> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x00b4>, c) == 0, "offsetof(NetPacket_Repeat<0x00b4>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x00b4>) == 1, "sizeof(NetPacket_Repeat<0x00b4>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x00b4>) == 1, "alignof(NetPacket_Repeat<0x00b4>) == 1"); + +template<> +struct NetPacket_Fixed<0x00b5> +{ + Little16 magic_packet_id; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00b5>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00b5>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00b5>, block_id) == 2, "offsetof(NetPacket_Fixed<0x00b5>, block_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00b5>) == 6, "sizeof(NetPacket_Fixed<0x00b5>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00b5>) == 1, "alignof(NetPacket_Fixed<0x00b5>) == 1"); + +template<> +struct NetPacket_Fixed<0x00b6> +{ + Little16 magic_packet_id; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00b6>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00b6>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00b6>, block_id) == 2, "offsetof(NetPacket_Fixed<0x00b6>, block_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00b6>) == 6, "sizeof(NetPacket_Fixed<0x00b6>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00b6>) == 1, "alignof(NetPacket_Fixed<0x00b6>) == 1"); + +template<> +struct NetPacket_Head<0x00b7> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Head<0x00b7>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x00b7>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x00b7>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x00b7>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x00b7>, block_id) == 4, "offsetof(NetPacket_Head<0x00b7>, block_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x00b7>) == 8, "sizeof(NetPacket_Head<0x00b7>) == 8"); +static_assert(alignof(NetPacket_Head<0x00b7>) == 1, "alignof(NetPacket_Head<0x00b7>) == 1"); +template<> +struct NetPacket_Repeat<0x00b7> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x00b7>, c) == 0, "offsetof(NetPacket_Repeat<0x00b7>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x00b7>) == 1, "sizeof(NetPacket_Repeat<0x00b7>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x00b7>) == 1, "alignof(NetPacket_Repeat<0x00b7>) == 1"); + +template<> +struct NetPacket_Fixed<0x00b8> +{ + Little16 magic_packet_id; + Little32 npc_id; + Byte menu_entry; +}; +static_assert(offsetof(NetPacket_Fixed<0x00b8>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00b8>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00b8>, npc_id) == 2, "offsetof(NetPacket_Fixed<0x00b8>, npc_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00b8>, menu_entry) == 6, "offsetof(NetPacket_Fixed<0x00b8>, menu_entry) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x00b8>) == 7, "sizeof(NetPacket_Fixed<0x00b8>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x00b8>) == 1, "alignof(NetPacket_Fixed<0x00b8>) == 1"); + +template<> +struct NetPacket_Fixed<0x00b9> +{ + Little16 magic_packet_id; + Little32 npc_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00b9>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00b9>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00b9>, npc_id) == 2, "offsetof(NetPacket_Fixed<0x00b9>, npc_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00b9>) == 6, "sizeof(NetPacket_Fixed<0x00b9>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00b9>) == 1, "alignof(NetPacket_Fixed<0x00b9>) == 1"); + +template<> +struct NetPacket_Fixed<0x00bb> +{ + Little16 magic_packet_id; + Little16 asp; + Byte unused; +}; +static_assert(offsetof(NetPacket_Fixed<0x00bb>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00bb>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00bb>, asp) == 2, "offsetof(NetPacket_Fixed<0x00bb>, asp) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00bb>, unused) == 4, "offsetof(NetPacket_Fixed<0x00bb>, unused) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00bb>) == 5, "sizeof(NetPacket_Fixed<0x00bb>) == 5"); +static_assert(alignof(NetPacket_Fixed<0x00bb>) == 1, "alignof(NetPacket_Fixed<0x00bb>) == 1"); + +template<> +struct NetPacket_Fixed<0x00bc> +{ + Little16 magic_packet_id; + Little16 sp_type; + Byte ok; + Byte val; +}; +static_assert(offsetof(NetPacket_Fixed<0x00bc>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00bc>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00bc>, sp_type) == 2, "offsetof(NetPacket_Fixed<0x00bc>, sp_type) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00bc>, ok) == 4, "offsetof(NetPacket_Fixed<0x00bc>, ok) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x00bc>, val) == 5, "offsetof(NetPacket_Fixed<0x00bc>, val) == 5"); +static_assert(sizeof(NetPacket_Fixed<0x00bc>) == 6, "sizeof(NetPacket_Fixed<0x00bc>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00bc>) == 1, "alignof(NetPacket_Fixed<0x00bc>) == 1"); + +template<> +struct NetPacket_Fixed<0x00bd> +{ + Little16 magic_packet_id; + Little16 status_point; + Byte str_attr; + Byte str_upd; + Byte agi_attr; + Byte agi_upd; + Byte vit_attr; + Byte vit_upd; + Byte int_attr; + Byte int_upd; + Byte dex_attr; + Byte dex_upd; + Byte luk_attr; + Byte luk_upd; + Little16 atk_sum; + Little16 watk2; + Little16 matk1; + Little16 matk2; + Little16 def; + Little16 def2; + Little16 mdef; + Little16 mdef2; + Little16 hit; + Little16 flee; + Little16 flee2; + Little16 critical; + Little16 karma; + Little16 manner; +}; +static_assert(offsetof(NetPacket_Fixed<0x00bd>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00bd>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, status_point) == 2, "offsetof(NetPacket_Fixed<0x00bd>, status_point) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, str_attr) == 4, "offsetof(NetPacket_Fixed<0x00bd>, str_attr) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, str_upd) == 5, "offsetof(NetPacket_Fixed<0x00bd>, str_upd) == 5"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, agi_attr) == 6, "offsetof(NetPacket_Fixed<0x00bd>, agi_attr) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, agi_upd) == 7, "offsetof(NetPacket_Fixed<0x00bd>, agi_upd) == 7"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, vit_attr) == 8, "offsetof(NetPacket_Fixed<0x00bd>, vit_attr) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, vit_upd) == 9, "offsetof(NetPacket_Fixed<0x00bd>, vit_upd) == 9"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, int_attr) == 10, "offsetof(NetPacket_Fixed<0x00bd>, int_attr) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, int_upd) == 11, "offsetof(NetPacket_Fixed<0x00bd>, int_upd) == 11"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, dex_attr) == 12, "offsetof(NetPacket_Fixed<0x00bd>, dex_attr) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, dex_upd) == 13, "offsetof(NetPacket_Fixed<0x00bd>, dex_upd) == 13"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, luk_attr) == 14, "offsetof(NetPacket_Fixed<0x00bd>, luk_attr) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, luk_upd) == 15, "offsetof(NetPacket_Fixed<0x00bd>, luk_upd) == 15"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, atk_sum) == 16, "offsetof(NetPacket_Fixed<0x00bd>, atk_sum) == 16"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, watk2) == 18, "offsetof(NetPacket_Fixed<0x00bd>, watk2) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, matk1) == 20, "offsetof(NetPacket_Fixed<0x00bd>, matk1) == 20"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, matk2) == 22, "offsetof(NetPacket_Fixed<0x00bd>, matk2) == 22"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, def) == 24, "offsetof(NetPacket_Fixed<0x00bd>, def) == 24"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, def2) == 26, "offsetof(NetPacket_Fixed<0x00bd>, def2) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, mdef) == 28, "offsetof(NetPacket_Fixed<0x00bd>, mdef) == 28"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, mdef2) == 30, "offsetof(NetPacket_Fixed<0x00bd>, mdef2) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, hit) == 32, "offsetof(NetPacket_Fixed<0x00bd>, hit) == 32"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, flee) == 34, "offsetof(NetPacket_Fixed<0x00bd>, flee) == 34"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, flee2) == 36, "offsetof(NetPacket_Fixed<0x00bd>, flee2) == 36"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, critical) == 38, "offsetof(NetPacket_Fixed<0x00bd>, critical) == 38"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, karma) == 40, "offsetof(NetPacket_Fixed<0x00bd>, karma) == 40"); +static_assert(offsetof(NetPacket_Fixed<0x00bd>, manner) == 42, "offsetof(NetPacket_Fixed<0x00bd>, manner) == 42"); +static_assert(sizeof(NetPacket_Fixed<0x00bd>) == 44, "sizeof(NetPacket_Fixed<0x00bd>) == 44"); +static_assert(alignof(NetPacket_Fixed<0x00bd>) == 1, "alignof(NetPacket_Fixed<0x00bd>) == 1"); + +template<> +struct NetPacket_Fixed<0x00be> +{ + Little16 magic_packet_id; + Little16 sp_type; + Byte value; +}; +static_assert(offsetof(NetPacket_Fixed<0x00be>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00be>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00be>, sp_type) == 2, "offsetof(NetPacket_Fixed<0x00be>, sp_type) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00be>, value) == 4, "offsetof(NetPacket_Fixed<0x00be>, value) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00be>) == 5, "sizeof(NetPacket_Fixed<0x00be>) == 5"); +static_assert(alignof(NetPacket_Fixed<0x00be>) == 1, "alignof(NetPacket_Fixed<0x00be>) == 1"); + +template<> +struct NetPacket_Fixed<0x00bf> +{ + Little16 magic_packet_id; + Byte emote; +}; +static_assert(offsetof(NetPacket_Fixed<0x00bf>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00bf>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00bf>, emote) == 2, "offsetof(NetPacket_Fixed<0x00bf>, emote) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00bf>) == 3, "sizeof(NetPacket_Fixed<0x00bf>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x00bf>) == 1, "alignof(NetPacket_Fixed<0x00bf>) == 1"); + +template<> +struct NetPacket_Fixed<0x00c0> +{ + Little16 magic_packet_id; + Little32 block_id; + Byte type; +}; +static_assert(offsetof(NetPacket_Fixed<0x00c0>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00c0>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00c0>, block_id) == 2, "offsetof(NetPacket_Fixed<0x00c0>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00c0>, type) == 6, "offsetof(NetPacket_Fixed<0x00c0>, type) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x00c0>) == 7, "sizeof(NetPacket_Fixed<0x00c0>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x00c0>) == 1, "alignof(NetPacket_Fixed<0x00c0>) == 1"); + +template<> +struct NetPacket_Fixed<0x00c1> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00c1>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00c1>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x00c1>) == 2, "sizeof(NetPacket_Fixed<0x00c1>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x00c1>) == 1, "alignof(NetPacket_Fixed<0x00c1>) == 1"); + +template<> +struct NetPacket_Fixed<0x00c2> +{ + Little16 magic_packet_id; + Little32 users; +}; +static_assert(offsetof(NetPacket_Fixed<0x00c2>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00c2>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00c2>, users) == 2, "offsetof(NetPacket_Fixed<0x00c2>, users) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00c2>) == 6, "sizeof(NetPacket_Fixed<0x00c2>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00c2>) == 1, "alignof(NetPacket_Fixed<0x00c2>) == 1"); + +template<> +struct NetPacket_Fixed<0x00c4> +{ + Little16 magic_packet_id; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00c4>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00c4>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00c4>, block_id) == 2, "offsetof(NetPacket_Fixed<0x00c4>, block_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00c4>) == 6, "sizeof(NetPacket_Fixed<0x00c4>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00c4>) == 1, "alignof(NetPacket_Fixed<0x00c4>) == 1"); + +template<> +struct NetPacket_Fixed<0x00c5> +{ + Little16 magic_packet_id; + Little32 block_id; + Byte type; +}; +static_assert(offsetof(NetPacket_Fixed<0x00c5>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00c5>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00c5>, block_id) == 2, "offsetof(NetPacket_Fixed<0x00c5>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00c5>, type) == 6, "offsetof(NetPacket_Fixed<0x00c5>, type) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x00c5>) == 7, "sizeof(NetPacket_Fixed<0x00c5>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x00c5>) == 1, "alignof(NetPacket_Fixed<0x00c5>) == 1"); + +template<> +struct NetPacket_Head<0x00c6> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x00c6>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x00c6>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x00c6>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x00c6>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x00c6>) == 4, "sizeof(NetPacket_Head<0x00c6>) == 4"); +static_assert(alignof(NetPacket_Head<0x00c6>) == 1, "alignof(NetPacket_Head<0x00c6>) == 1"); +template<> +struct NetPacket_Repeat<0x00c6> +{ + Little32 base_price; + Little32 actual_price; + Byte type; + Little16 name_id; +}; +static_assert(offsetof(NetPacket_Repeat<0x00c6>, base_price) == 0, "offsetof(NetPacket_Repeat<0x00c6>, base_price) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x00c6>, actual_price) == 4, "offsetof(NetPacket_Repeat<0x00c6>, actual_price) == 4"); +static_assert(offsetof(NetPacket_Repeat<0x00c6>, type) == 8, "offsetof(NetPacket_Repeat<0x00c6>, type) == 8"); +static_assert(offsetof(NetPacket_Repeat<0x00c6>, name_id) == 9, "offsetof(NetPacket_Repeat<0x00c6>, name_id) == 9"); +static_assert(sizeof(NetPacket_Repeat<0x00c6>) == 11, "sizeof(NetPacket_Repeat<0x00c6>) == 11"); +static_assert(alignof(NetPacket_Repeat<0x00c6>) == 1, "alignof(NetPacket_Repeat<0x00c6>) == 1"); + +template<> +struct NetPacket_Head<0x00c7> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x00c7>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x00c7>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x00c7>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x00c7>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x00c7>) == 4, "sizeof(NetPacket_Head<0x00c7>) == 4"); +static_assert(alignof(NetPacket_Head<0x00c7>) == 1, "alignof(NetPacket_Head<0x00c7>) == 1"); +template<> +struct NetPacket_Repeat<0x00c7> +{ + Little16 ioff2; + Little32 base_price; + Little32 actual_price; +}; +static_assert(offsetof(NetPacket_Repeat<0x00c7>, ioff2) == 0, "offsetof(NetPacket_Repeat<0x00c7>, ioff2) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x00c7>, base_price) == 2, "offsetof(NetPacket_Repeat<0x00c7>, base_price) == 2"); +static_assert(offsetof(NetPacket_Repeat<0x00c7>, actual_price) == 6, "offsetof(NetPacket_Repeat<0x00c7>, actual_price) == 6"); +static_assert(sizeof(NetPacket_Repeat<0x00c7>) == 10, "sizeof(NetPacket_Repeat<0x00c7>) == 10"); +static_assert(alignof(NetPacket_Repeat<0x00c7>) == 1, "alignof(NetPacket_Repeat<0x00c7>) == 1"); + +template<> +struct NetPacket_Head<0x00c8> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x00c8>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x00c8>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x00c8>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x00c8>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x00c8>) == 4, "sizeof(NetPacket_Head<0x00c8>) == 4"); +static_assert(alignof(NetPacket_Head<0x00c8>) == 1, "alignof(NetPacket_Head<0x00c8>) == 1"); +template<> +struct NetPacket_Repeat<0x00c8> +{ + Little16 count; + Little16 name_id; +}; +static_assert(offsetof(NetPacket_Repeat<0x00c8>, count) == 0, "offsetof(NetPacket_Repeat<0x00c8>, count) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x00c8>, name_id) == 2, "offsetof(NetPacket_Repeat<0x00c8>, name_id) == 2"); +static_assert(sizeof(NetPacket_Repeat<0x00c8>) == 4, "sizeof(NetPacket_Repeat<0x00c8>) == 4"); +static_assert(alignof(NetPacket_Repeat<0x00c8>) == 1, "alignof(NetPacket_Repeat<0x00c8>) == 1"); + +template<> +struct NetPacket_Head<0x00c9> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x00c9>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x00c9>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x00c9>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x00c9>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x00c9>) == 4, "sizeof(NetPacket_Head<0x00c9>) == 4"); +static_assert(alignof(NetPacket_Head<0x00c9>) == 1, "alignof(NetPacket_Head<0x00c9>) == 1"); +template<> +struct NetPacket_Repeat<0x00c9> +{ + Little16 ioff2; + Little16 count; +}; +static_assert(offsetof(NetPacket_Repeat<0x00c9>, ioff2) == 0, "offsetof(NetPacket_Repeat<0x00c9>, ioff2) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x00c9>, count) == 2, "offsetof(NetPacket_Repeat<0x00c9>, count) == 2"); +static_assert(sizeof(NetPacket_Repeat<0x00c9>) == 4, "sizeof(NetPacket_Repeat<0x00c9>) == 4"); +static_assert(alignof(NetPacket_Repeat<0x00c9>) == 1, "alignof(NetPacket_Repeat<0x00c9>) == 1"); + +template<> +struct NetPacket_Fixed<0x00ca> +{ + Little16 magic_packet_id; + Byte fail; +}; +static_assert(offsetof(NetPacket_Fixed<0x00ca>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00ca>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00ca>, fail) == 2, "offsetof(NetPacket_Fixed<0x00ca>, fail) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00ca>) == 3, "sizeof(NetPacket_Fixed<0x00ca>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x00ca>) == 1, "alignof(NetPacket_Fixed<0x00ca>) == 1"); + +template<> +struct NetPacket_Fixed<0x00cb> +{ + Little16 magic_packet_id; + Byte fail; +}; +static_assert(offsetof(NetPacket_Fixed<0x00cb>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00cb>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00cb>, fail) == 2, "offsetof(NetPacket_Fixed<0x00cb>, fail) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00cb>) == 3, "sizeof(NetPacket_Fixed<0x00cb>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x00cb>) == 1, "alignof(NetPacket_Fixed<0x00cb>) == 1"); + +template<> +struct NetPacket_Fixed<0x00cd> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00cd>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00cd>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00cd>, account_id) == 2, "offsetof(NetPacket_Fixed<0x00cd>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00cd>) == 6, "sizeof(NetPacket_Fixed<0x00cd>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00cd>) == 1, "alignof(NetPacket_Fixed<0x00cd>) == 1"); + +template<> +struct NetPacket_Fixed<0x00e4> +{ + Little16 magic_packet_id; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00e4>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00e4>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00e4>, block_id) == 2, "offsetof(NetPacket_Fixed<0x00e4>, block_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00e4>) == 6, "sizeof(NetPacket_Fixed<0x00e4>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00e4>) == 1, "alignof(NetPacket_Fixed<0x00e4>) == 1"); + +template<> +struct NetPacket_Fixed<0x00e5> +{ + Little16 magic_packet_id; + NetString<sizeof(CharName)> char_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x00e5>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00e5>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00e5>, char_name) == 2, "offsetof(NetPacket_Fixed<0x00e5>, char_name) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00e5>) == 26, "sizeof(NetPacket_Fixed<0x00e5>) == 26"); +static_assert(alignof(NetPacket_Fixed<0x00e5>) == 1, "alignof(NetPacket_Fixed<0x00e5>) == 1"); + +template<> +struct NetPacket_Fixed<0x00e6> +{ + Little16 magic_packet_id; + Byte type; +}; +static_assert(offsetof(NetPacket_Fixed<0x00e6>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00e6>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00e6>, type) == 2, "offsetof(NetPacket_Fixed<0x00e6>, type) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00e6>) == 3, "sizeof(NetPacket_Fixed<0x00e6>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x00e6>) == 1, "alignof(NetPacket_Fixed<0x00e6>) == 1"); + +template<> +struct NetPacket_Fixed<0x00e7> +{ + Little16 magic_packet_id; + Byte type; +}; +static_assert(offsetof(NetPacket_Fixed<0x00e7>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00e7>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00e7>, type) == 2, "offsetof(NetPacket_Fixed<0x00e7>, type) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00e7>) == 3, "sizeof(NetPacket_Fixed<0x00e7>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x00e7>) == 1, "alignof(NetPacket_Fixed<0x00e7>) == 1"); + +template<> +struct NetPacket_Fixed<0x00e8> +{ + Little16 magic_packet_id; + Little16 zeny_or_ioff2; + Little32 amount; +}; +static_assert(offsetof(NetPacket_Fixed<0x00e8>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00e8>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00e8>, zeny_or_ioff2) == 2, "offsetof(NetPacket_Fixed<0x00e8>, zeny_or_ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00e8>, amount) == 4, "offsetof(NetPacket_Fixed<0x00e8>, amount) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00e8>) == 8, "sizeof(NetPacket_Fixed<0x00e8>) == 8"); +static_assert(alignof(NetPacket_Fixed<0x00e8>) == 1, "alignof(NetPacket_Fixed<0x00e8>) == 1"); + +template<> +struct NetPacket_Fixed<0x00e9> +{ + Little16 magic_packet_id; + Little32 amount; + Little16 name_id; + Byte identify; + Byte broken_or_attribute; + Byte refine; + Little16 card0; + Little16 card1; + Little16 card2; + Little16 card3; +}; +static_assert(offsetof(NetPacket_Fixed<0x00e9>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00e9>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00e9>, amount) == 2, "offsetof(NetPacket_Fixed<0x00e9>, amount) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00e9>, name_id) == 6, "offsetof(NetPacket_Fixed<0x00e9>, name_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x00e9>, identify) == 8, "offsetof(NetPacket_Fixed<0x00e9>, identify) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x00e9>, broken_or_attribute) == 9, "offsetof(NetPacket_Fixed<0x00e9>, broken_or_attribute) == 9"); +static_assert(offsetof(NetPacket_Fixed<0x00e9>, refine) == 10, "offsetof(NetPacket_Fixed<0x00e9>, refine) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x00e9>, card0) == 11, "offsetof(NetPacket_Fixed<0x00e9>, card0) == 11"); +static_assert(offsetof(NetPacket_Fixed<0x00e9>, card1) == 13, "offsetof(NetPacket_Fixed<0x00e9>, card1) == 13"); +static_assert(offsetof(NetPacket_Fixed<0x00e9>, card2) == 15, "offsetof(NetPacket_Fixed<0x00e9>, card2) == 15"); +static_assert(offsetof(NetPacket_Fixed<0x00e9>, card3) == 17, "offsetof(NetPacket_Fixed<0x00e9>, card3) == 17"); +static_assert(sizeof(NetPacket_Fixed<0x00e9>) == 19, "sizeof(NetPacket_Fixed<0x00e9>) == 19"); +static_assert(alignof(NetPacket_Fixed<0x00e9>) == 1, "alignof(NetPacket_Fixed<0x00e9>) == 1"); + +template<> +struct NetPacket_Fixed<0x00eb> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00eb>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00eb>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x00eb>) == 2, "sizeof(NetPacket_Fixed<0x00eb>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x00eb>) == 1, "alignof(NetPacket_Fixed<0x00eb>) == 1"); + +template<> +struct NetPacket_Fixed<0x00ec> +{ + Little16 magic_packet_id; + Byte fail; +}; +static_assert(offsetof(NetPacket_Fixed<0x00ec>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00ec>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00ec>, fail) == 2, "offsetof(NetPacket_Fixed<0x00ec>, fail) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00ec>) == 3, "sizeof(NetPacket_Fixed<0x00ec>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x00ec>) == 1, "alignof(NetPacket_Fixed<0x00ec>) == 1"); + +template<> +struct NetPacket_Fixed<0x00ed> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00ed>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00ed>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x00ed>) == 2, "sizeof(NetPacket_Fixed<0x00ed>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x00ed>) == 1, "alignof(NetPacket_Fixed<0x00ed>) == 1"); + +template<> +struct NetPacket_Fixed<0x00ee> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00ee>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00ee>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x00ee>) == 2, "sizeof(NetPacket_Fixed<0x00ee>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x00ee>) == 1, "alignof(NetPacket_Fixed<0x00ee>) == 1"); + +template<> +struct NetPacket_Fixed<0x00ef> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00ef>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00ef>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x00ef>) == 2, "sizeof(NetPacket_Fixed<0x00ef>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x00ef>) == 1, "alignof(NetPacket_Fixed<0x00ef>) == 1"); + +template<> +struct NetPacket_Fixed<0x00f0> +{ + Little16 magic_packet_id; + Byte fail; +}; +static_assert(offsetof(NetPacket_Fixed<0x00f0>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00f0>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00f0>, fail) == 2, "offsetof(NetPacket_Fixed<0x00f0>, fail) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00f0>) == 3, "sizeof(NetPacket_Fixed<0x00f0>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x00f0>) == 1, "alignof(NetPacket_Fixed<0x00f0>) == 1"); + +template<> +struct NetPacket_Fixed<0x00f2> +{ + Little16 magic_packet_id; + Little16 current_slots; + Little16 max_slots; +}; +static_assert(offsetof(NetPacket_Fixed<0x00f2>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00f2>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00f2>, current_slots) == 2, "offsetof(NetPacket_Fixed<0x00f2>, current_slots) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00f2>, max_slots) == 4, "offsetof(NetPacket_Fixed<0x00f2>, max_slots) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00f2>) == 6, "sizeof(NetPacket_Fixed<0x00f2>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00f2>) == 1, "alignof(NetPacket_Fixed<0x00f2>) == 1"); + +template<> +struct NetPacket_Fixed<0x00f3> +{ + Little16 magic_packet_id; + Little16 ioff2; + Little32 amount; +}; +static_assert(offsetof(NetPacket_Fixed<0x00f3>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00f3>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00f3>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x00f3>, ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00f3>, amount) == 4, "offsetof(NetPacket_Fixed<0x00f3>, amount) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00f3>) == 8, "sizeof(NetPacket_Fixed<0x00f3>) == 8"); +static_assert(alignof(NetPacket_Fixed<0x00f3>) == 1, "alignof(NetPacket_Fixed<0x00f3>) == 1"); + +template<> +struct NetPacket_Fixed<0x00f4> +{ + Little16 magic_packet_id; + Little16 soff1; + Little32 amount; + Little16 name_id; + Byte identify; + Byte broken_or_attribute; + Byte refine; + Little16 card0; + Little16 card1; + Little16 card2; + Little16 card3; +}; +static_assert(offsetof(NetPacket_Fixed<0x00f4>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00f4>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00f4>, soff1) == 2, "offsetof(NetPacket_Fixed<0x00f4>, soff1) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00f4>, amount) == 4, "offsetof(NetPacket_Fixed<0x00f4>, amount) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x00f4>, name_id) == 8, "offsetof(NetPacket_Fixed<0x00f4>, name_id) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x00f4>, identify) == 10, "offsetof(NetPacket_Fixed<0x00f4>, identify) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x00f4>, broken_or_attribute) == 11, "offsetof(NetPacket_Fixed<0x00f4>, broken_or_attribute) == 11"); +static_assert(offsetof(NetPacket_Fixed<0x00f4>, refine) == 12, "offsetof(NetPacket_Fixed<0x00f4>, refine) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x00f4>, card0) == 13, "offsetof(NetPacket_Fixed<0x00f4>, card0) == 13"); +static_assert(offsetof(NetPacket_Fixed<0x00f4>, card1) == 15, "offsetof(NetPacket_Fixed<0x00f4>, card1) == 15"); +static_assert(offsetof(NetPacket_Fixed<0x00f4>, card2) == 17, "offsetof(NetPacket_Fixed<0x00f4>, card2) == 17"); +static_assert(offsetof(NetPacket_Fixed<0x00f4>, card3) == 19, "offsetof(NetPacket_Fixed<0x00f4>, card3) == 19"); +static_assert(sizeof(NetPacket_Fixed<0x00f4>) == 21, "sizeof(NetPacket_Fixed<0x00f4>) == 21"); +static_assert(alignof(NetPacket_Fixed<0x00f4>) == 1, "alignof(NetPacket_Fixed<0x00f4>) == 1"); + +template<> +struct NetPacket_Fixed<0x00f5> +{ + Little16 magic_packet_id; + Little16 soff1; + Little32 amount; +}; +static_assert(offsetof(NetPacket_Fixed<0x00f5>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00f5>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00f5>, soff1) == 2, "offsetof(NetPacket_Fixed<0x00f5>, soff1) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00f5>, amount) == 4, "offsetof(NetPacket_Fixed<0x00f5>, amount) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00f5>) == 8, "sizeof(NetPacket_Fixed<0x00f5>) == 8"); +static_assert(alignof(NetPacket_Fixed<0x00f5>) == 1, "alignof(NetPacket_Fixed<0x00f5>) == 1"); + +template<> +struct NetPacket_Fixed<0x00f6> +{ + Little16 magic_packet_id; + Little16 soff1; + Little32 amount; +}; +static_assert(offsetof(NetPacket_Fixed<0x00f6>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00f6>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00f6>, soff1) == 2, "offsetof(NetPacket_Fixed<0x00f6>, soff1) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00f6>, amount) == 4, "offsetof(NetPacket_Fixed<0x00f6>, amount) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x00f6>) == 8, "sizeof(NetPacket_Fixed<0x00f6>) == 8"); +static_assert(alignof(NetPacket_Fixed<0x00f6>) == 1, "alignof(NetPacket_Fixed<0x00f6>) == 1"); + +template<> +struct NetPacket_Fixed<0x00f7> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00f7>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00f7>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x00f7>) == 2, "sizeof(NetPacket_Fixed<0x00f7>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x00f7>) == 1, "alignof(NetPacket_Fixed<0x00f7>) == 1"); + +template<> +struct NetPacket_Fixed<0x00f8> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00f8>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00f8>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x00f8>) == 2, "sizeof(NetPacket_Fixed<0x00f8>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x00f8>) == 1, "alignof(NetPacket_Fixed<0x00f8>) == 1"); + +template<> +struct NetPacket_Fixed<0x00f9> +{ + Little16 magic_packet_id; + NetString<sizeof(PartyName)> party_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x00f9>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00f9>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00f9>, party_name) == 2, "offsetof(NetPacket_Fixed<0x00f9>, party_name) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00f9>) == 26, "sizeof(NetPacket_Fixed<0x00f9>) == 26"); +static_assert(alignof(NetPacket_Fixed<0x00f9>) == 1, "alignof(NetPacket_Fixed<0x00f9>) == 1"); + +template<> +struct NetPacket_Fixed<0x00fa> +{ + Little16 magic_packet_id; + Byte flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x00fa>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00fa>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00fa>, flag) == 2, "offsetof(NetPacket_Fixed<0x00fa>, flag) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00fa>) == 3, "sizeof(NetPacket_Fixed<0x00fa>) == 3"); +static_assert(alignof(NetPacket_Fixed<0x00fa>) == 1, "alignof(NetPacket_Fixed<0x00fa>) == 1"); + +template<> +struct NetPacket_Head<0x00fb> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + NetString<sizeof(PartyName)> party_name; +}; +static_assert(offsetof(NetPacket_Head<0x00fb>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x00fb>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x00fb>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x00fb>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x00fb>, party_name) == 4, "offsetof(NetPacket_Head<0x00fb>, party_name) == 4"); +static_assert(sizeof(NetPacket_Head<0x00fb>) == 28, "sizeof(NetPacket_Head<0x00fb>) == 28"); +static_assert(alignof(NetPacket_Head<0x00fb>) == 1, "alignof(NetPacket_Head<0x00fb>) == 1"); +template<> +struct NetPacket_Repeat<0x00fb> +{ + Little32 account_id; + NetString<sizeof(CharName)> char_name; + NetString<sizeof(MapName)> map_name; + Byte leader; + Byte online; +}; +static_assert(offsetof(NetPacket_Repeat<0x00fb>, account_id) == 0, "offsetof(NetPacket_Repeat<0x00fb>, account_id) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x00fb>, char_name) == 4, "offsetof(NetPacket_Repeat<0x00fb>, char_name) == 4"); +static_assert(offsetof(NetPacket_Repeat<0x00fb>, map_name) == 28, "offsetof(NetPacket_Repeat<0x00fb>, map_name) == 28"); +static_assert(offsetof(NetPacket_Repeat<0x00fb>, leader) == 44, "offsetof(NetPacket_Repeat<0x00fb>, leader) == 44"); +static_assert(offsetof(NetPacket_Repeat<0x00fb>, online) == 45, "offsetof(NetPacket_Repeat<0x00fb>, online) == 45"); +static_assert(sizeof(NetPacket_Repeat<0x00fb>) == 46, "sizeof(NetPacket_Repeat<0x00fb>) == 46"); +static_assert(alignof(NetPacket_Repeat<0x00fb>) == 1, "alignof(NetPacket_Repeat<0x00fb>) == 1"); + +template<> +struct NetPacket_Fixed<0x00fc> +{ + Little16 magic_packet_id; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x00fc>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00fc>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00fc>, account_id) == 2, "offsetof(NetPacket_Fixed<0x00fc>, account_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x00fc>) == 6, "sizeof(NetPacket_Fixed<0x00fc>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x00fc>) == 1, "alignof(NetPacket_Fixed<0x00fc>) == 1"); + +template<> +struct NetPacket_Fixed<0x00fd> +{ + Little16 magic_packet_id; + NetString<sizeof(CharName)> char_name; + Byte flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x00fd>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00fd>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00fd>, char_name) == 2, "offsetof(NetPacket_Fixed<0x00fd>, char_name) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00fd>, flag) == 26, "offsetof(NetPacket_Fixed<0x00fd>, flag) == 26"); +static_assert(sizeof(NetPacket_Fixed<0x00fd>) == 27, "sizeof(NetPacket_Fixed<0x00fd>) == 27"); +static_assert(alignof(NetPacket_Fixed<0x00fd>) == 1, "alignof(NetPacket_Fixed<0x00fd>) == 1"); + +template<> +struct NetPacket_Fixed<0x00fe> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(PartyName)> party_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x00fe>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00fe>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00fe>, account_id) == 2, "offsetof(NetPacket_Fixed<0x00fe>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00fe>, party_name) == 6, "offsetof(NetPacket_Fixed<0x00fe>, party_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x00fe>) == 30, "sizeof(NetPacket_Fixed<0x00fe>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x00fe>) == 1, "alignof(NetPacket_Fixed<0x00fe>) == 1"); + +template<> +struct NetPacket_Fixed<0x00ff> +{ + Little16 magic_packet_id; + Little32 account_id; + Little32 flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x00ff>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x00ff>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x00ff>, account_id) == 2, "offsetof(NetPacket_Fixed<0x00ff>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x00ff>, flag) == 6, "offsetof(NetPacket_Fixed<0x00ff>, flag) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x00ff>) == 10, "sizeof(NetPacket_Fixed<0x00ff>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x00ff>) == 1, "alignof(NetPacket_Fixed<0x00ff>) == 1"); + +template<> +struct NetPacket_Fixed<0x0100> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x0100>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0100>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x0100>) == 2, "sizeof(NetPacket_Fixed<0x0100>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x0100>) == 1, "alignof(NetPacket_Fixed<0x0100>) == 1"); + +template<> +struct NetPacket_Fixed<0x0101> +{ + Little16 magic_packet_id; + Little16 exp; + Little16 item; +}; +static_assert(offsetof(NetPacket_Fixed<0x0101>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0101>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0101>, exp) == 2, "offsetof(NetPacket_Fixed<0x0101>, exp) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0101>, item) == 4, "offsetof(NetPacket_Fixed<0x0101>, item) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x0101>) == 6, "sizeof(NetPacket_Fixed<0x0101>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x0101>) == 1, "alignof(NetPacket_Fixed<0x0101>) == 1"); + +template<> +struct NetPacket_Fixed<0x0102> +{ + Little16 magic_packet_id; + Little16 exp; + Little16 item; +}; +static_assert(offsetof(NetPacket_Fixed<0x0102>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0102>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0102>, exp) == 2, "offsetof(NetPacket_Fixed<0x0102>, exp) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0102>, item) == 4, "offsetof(NetPacket_Fixed<0x0102>, item) == 4"); +static_assert(sizeof(NetPacket_Fixed<0x0102>) == 6, "sizeof(NetPacket_Fixed<0x0102>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x0102>) == 1, "alignof(NetPacket_Fixed<0x0102>) == 1"); + +template<> +struct NetPacket_Fixed<0x0103> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(CharName)> unused_char_name; +}; +static_assert(offsetof(NetPacket_Fixed<0x0103>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0103>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0103>, account_id) == 2, "offsetof(NetPacket_Fixed<0x0103>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0103>, unused_char_name) == 6, "offsetof(NetPacket_Fixed<0x0103>, unused_char_name) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x0103>) == 30, "sizeof(NetPacket_Fixed<0x0103>) == 30"); +static_assert(alignof(NetPacket_Fixed<0x0103>) == 1, "alignof(NetPacket_Fixed<0x0103>) == 1"); + +template<> +struct NetPacket_Fixed<0x0105> +{ + Little16 magic_packet_id; + Little32 account_id; + NetString<sizeof(CharName)> char_name; + Byte flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x0105>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0105>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0105>, account_id) == 2, "offsetof(NetPacket_Fixed<0x0105>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0105>, char_name) == 6, "offsetof(NetPacket_Fixed<0x0105>, char_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0105>, flag) == 30, "offsetof(NetPacket_Fixed<0x0105>, flag) == 30"); +static_assert(sizeof(NetPacket_Fixed<0x0105>) == 31, "sizeof(NetPacket_Fixed<0x0105>) == 31"); +static_assert(alignof(NetPacket_Fixed<0x0105>) == 1, "alignof(NetPacket_Fixed<0x0105>) == 1"); + +template<> +struct NetPacket_Fixed<0x0106> +{ + Little16 magic_packet_id; + Little32 account_id; + Little16 hp; + Little16 max_hp; +}; +static_assert(offsetof(NetPacket_Fixed<0x0106>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0106>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0106>, account_id) == 2, "offsetof(NetPacket_Fixed<0x0106>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0106>, hp) == 6, "offsetof(NetPacket_Fixed<0x0106>, hp) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0106>, max_hp) == 8, "offsetof(NetPacket_Fixed<0x0106>, max_hp) == 8"); +static_assert(sizeof(NetPacket_Fixed<0x0106>) == 10, "sizeof(NetPacket_Fixed<0x0106>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x0106>) == 1, "alignof(NetPacket_Fixed<0x0106>) == 1"); + +template<> +struct NetPacket_Fixed<0x0107> +{ + Little16 magic_packet_id; + Little32 account_id; + Little16 x; + Little16 y; +}; +static_assert(offsetof(NetPacket_Fixed<0x0107>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0107>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0107>, account_id) == 2, "offsetof(NetPacket_Fixed<0x0107>, account_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0107>, x) == 6, "offsetof(NetPacket_Fixed<0x0107>, x) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0107>, y) == 8, "offsetof(NetPacket_Fixed<0x0107>, y) == 8"); +static_assert(sizeof(NetPacket_Fixed<0x0107>) == 10, "sizeof(NetPacket_Fixed<0x0107>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x0107>) == 1, "alignof(NetPacket_Fixed<0x0107>) == 1"); + +template<> +struct NetPacket_Head<0x0108> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x0108>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x0108>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x0108>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x0108>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x0108>) == 4, "sizeof(NetPacket_Head<0x0108>) == 4"); +static_assert(alignof(NetPacket_Head<0x0108>) == 1, "alignof(NetPacket_Head<0x0108>) == 1"); +template<> +struct NetPacket_Repeat<0x0108> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x0108>, c) == 0, "offsetof(NetPacket_Repeat<0x0108>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x0108>) == 1, "sizeof(NetPacket_Repeat<0x0108>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x0108>) == 1, "alignof(NetPacket_Repeat<0x0108>) == 1"); + +template<> +struct NetPacket_Head<0x0109> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 account_id; +}; +static_assert(offsetof(NetPacket_Head<0x0109>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x0109>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x0109>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x0109>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x0109>, account_id) == 4, "offsetof(NetPacket_Head<0x0109>, account_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x0109>) == 8, "sizeof(NetPacket_Head<0x0109>) == 8"); +static_assert(alignof(NetPacket_Head<0x0109>) == 1, "alignof(NetPacket_Head<0x0109>) == 1"); +template<> +struct NetPacket_Repeat<0x0109> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x0109>, c) == 0, "offsetof(NetPacket_Repeat<0x0109>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x0109>) == 1, "sizeof(NetPacket_Repeat<0x0109>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x0109>) == 1, "alignof(NetPacket_Repeat<0x0109>) == 1"); + +template<> +struct NetPacket_Fixed<0x010c> +{ + Little16 magic_packet_id; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x010c>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x010c>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x010c>, block_id) == 2, "offsetof(NetPacket_Fixed<0x010c>, block_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x010c>) == 6, "sizeof(NetPacket_Fixed<0x010c>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x010c>) == 1, "alignof(NetPacket_Fixed<0x010c>) == 1"); + +template<> +struct NetPacket_Fixed<0x010e> +{ + Little16 magic_packet_id; + Little16 skill_id; + Little16 level; + Little16 sp; + Little16 range; + Byte can_raise; +}; +static_assert(offsetof(NetPacket_Fixed<0x010e>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x010e>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x010e>, skill_id) == 2, "offsetof(NetPacket_Fixed<0x010e>, skill_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x010e>, level) == 4, "offsetof(NetPacket_Fixed<0x010e>, level) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x010e>, sp) == 6, "offsetof(NetPacket_Fixed<0x010e>, sp) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x010e>, range) == 8, "offsetof(NetPacket_Fixed<0x010e>, range) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x010e>, can_raise) == 10, "offsetof(NetPacket_Fixed<0x010e>, can_raise) == 10"); +static_assert(sizeof(NetPacket_Fixed<0x010e>) == 11, "sizeof(NetPacket_Fixed<0x010e>) == 11"); +static_assert(alignof(NetPacket_Fixed<0x010e>) == 1, "alignof(NetPacket_Fixed<0x010e>) == 1"); + +template<> +struct NetPacket_Head<0x010f> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x010f>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x010f>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x010f>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x010f>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x010f>) == 4, "sizeof(NetPacket_Head<0x010f>) == 4"); +static_assert(alignof(NetPacket_Head<0x010f>) == 1, "alignof(NetPacket_Head<0x010f>) == 1"); +template<> +struct NetPacket_Repeat<0x010f> +{ + NetSkillInfo info; +}; +static_assert(offsetof(NetPacket_Repeat<0x010f>, info) == 0, "offsetof(NetPacket_Repeat<0x010f>, info) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x010f>) == 37, "sizeof(NetPacket_Repeat<0x010f>) == 37"); +static_assert(alignof(NetPacket_Repeat<0x010f>) == 1, "alignof(NetPacket_Repeat<0x010f>) == 1"); + +template<> +struct NetPacket_Fixed<0x0110> +{ + Little16 magic_packet_id; + Little16 skill_id; + Little16 btype; + Little16 zero1; + Byte zero2; + Byte type; +}; +static_assert(offsetof(NetPacket_Fixed<0x0110>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0110>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0110>, skill_id) == 2, "offsetof(NetPacket_Fixed<0x0110>, skill_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0110>, btype) == 4, "offsetof(NetPacket_Fixed<0x0110>, btype) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x0110>, zero1) == 6, "offsetof(NetPacket_Fixed<0x0110>, zero1) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0110>, zero2) == 8, "offsetof(NetPacket_Fixed<0x0110>, zero2) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x0110>, type) == 9, "offsetof(NetPacket_Fixed<0x0110>, type) == 9"); +static_assert(sizeof(NetPacket_Fixed<0x0110>) == 10, "sizeof(NetPacket_Fixed<0x0110>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x0110>) == 1, "alignof(NetPacket_Fixed<0x0110>) == 1"); + +template<> +struct NetPacket_Fixed<0x0112> +{ + Little16 magic_packet_id; + Little16 skill_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x0112>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0112>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0112>, skill_id) == 2, "offsetof(NetPacket_Fixed<0x0112>, skill_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x0112>) == 4, "sizeof(NetPacket_Fixed<0x0112>) == 4"); +static_assert(alignof(NetPacket_Fixed<0x0112>) == 1, "alignof(NetPacket_Fixed<0x0112>) == 1"); + +template<> +struct NetPacket_Fixed<0x0118> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x0118>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0118>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x0118>) == 2, "sizeof(NetPacket_Fixed<0x0118>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x0118>) == 1, "alignof(NetPacket_Fixed<0x0118>) == 1"); + +template<> +struct NetPacket_Fixed<0x0119> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 opt1; + Little16 opt2; + Little16 option; + Byte zero; +}; +static_assert(offsetof(NetPacket_Fixed<0x0119>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0119>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0119>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0119>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0119>, opt1) == 6, "offsetof(NetPacket_Fixed<0x0119>, opt1) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0119>, opt2) == 8, "offsetof(NetPacket_Fixed<0x0119>, opt2) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x0119>, option) == 10, "offsetof(NetPacket_Fixed<0x0119>, option) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x0119>, zero) == 12, "offsetof(NetPacket_Fixed<0x0119>, zero) == 12"); +static_assert(sizeof(NetPacket_Fixed<0x0119>) == 13, "sizeof(NetPacket_Fixed<0x0119>) == 13"); +static_assert(alignof(NetPacket_Fixed<0x0119>) == 1, "alignof(NetPacket_Fixed<0x0119>) == 1"); + +template<> +struct NetPacket_Fixed<0x0139> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 bl_x; + Little16 bl_y; + Little16 sd_x; + Little16 sd_y; + Little16 range; +}; +static_assert(offsetof(NetPacket_Fixed<0x0139>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0139>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0139>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0139>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0139>, bl_x) == 6, "offsetof(NetPacket_Fixed<0x0139>, bl_x) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0139>, bl_y) == 8, "offsetof(NetPacket_Fixed<0x0139>, bl_y) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x0139>, sd_x) == 10, "offsetof(NetPacket_Fixed<0x0139>, sd_x) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x0139>, sd_y) == 12, "offsetof(NetPacket_Fixed<0x0139>, sd_y) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x0139>, range) == 14, "offsetof(NetPacket_Fixed<0x0139>, range) == 14"); +static_assert(sizeof(NetPacket_Fixed<0x0139>) == 16, "sizeof(NetPacket_Fixed<0x0139>) == 16"); +static_assert(alignof(NetPacket_Fixed<0x0139>) == 1, "alignof(NetPacket_Fixed<0x0139>) == 1"); + +template<> +struct NetPacket_Fixed<0x013a> +{ + Little16 magic_packet_id; + Little16 attack_range; +}; +static_assert(offsetof(NetPacket_Fixed<0x013a>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x013a>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x013a>, attack_range) == 2, "offsetof(NetPacket_Fixed<0x013a>, attack_range) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x013a>) == 4, "sizeof(NetPacket_Fixed<0x013a>) == 4"); +static_assert(alignof(NetPacket_Fixed<0x013a>) == 1, "alignof(NetPacket_Fixed<0x013a>) == 1"); + +template<> +struct NetPacket_Fixed<0x013b> +{ + Little16 magic_packet_id; + Little16 type; +}; +static_assert(offsetof(NetPacket_Fixed<0x013b>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x013b>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x013b>, type) == 2, "offsetof(NetPacket_Fixed<0x013b>, type) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x013b>) == 4, "sizeof(NetPacket_Fixed<0x013b>) == 4"); +static_assert(alignof(NetPacket_Fixed<0x013b>) == 1, "alignof(NetPacket_Fixed<0x013b>) == 1"); + +template<> +struct NetPacket_Fixed<0x013c> +{ + Little16 magic_packet_id; + Little16 ioff2; +}; +static_assert(offsetof(NetPacket_Fixed<0x013c>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x013c>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x013c>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x013c>, ioff2) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x013c>) == 4, "sizeof(NetPacket_Fixed<0x013c>) == 4"); +static_assert(alignof(NetPacket_Fixed<0x013c>) == 1, "alignof(NetPacket_Fixed<0x013c>) == 1"); + +template<> +struct NetPacket_Fixed<0x0141> +{ + Little16 magic_packet_id; + Little16 sp_type; + Little16 zero; + Little32 value_status; + Little32 value_b_e; +}; +static_assert(offsetof(NetPacket_Fixed<0x0141>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0141>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0141>, sp_type) == 2, "offsetof(NetPacket_Fixed<0x0141>, sp_type) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0141>, zero) == 4, "offsetof(NetPacket_Fixed<0x0141>, zero) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x0141>, value_status) == 6, "offsetof(NetPacket_Fixed<0x0141>, value_status) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0141>, value_b_e) == 10, "offsetof(NetPacket_Fixed<0x0141>, value_b_e) == 10"); +static_assert(sizeof(NetPacket_Fixed<0x0141>) == 14, "sizeof(NetPacket_Fixed<0x0141>) == 14"); +static_assert(alignof(NetPacket_Fixed<0x0141>) == 1, "alignof(NetPacket_Fixed<0x0141>) == 1"); + +template<> +struct NetPacket_Fixed<0x0142> +{ + Little16 magic_packet_id; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x0142>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0142>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0142>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0142>, block_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x0142>) == 6, "sizeof(NetPacket_Fixed<0x0142>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x0142>) == 1, "alignof(NetPacket_Fixed<0x0142>) == 1"); + +template<> +struct NetPacket_Fixed<0x0143> +{ + Little16 magic_packet_id; + Little32 block_id; + Little32 input_int_value; +}; +static_assert(offsetof(NetPacket_Fixed<0x0143>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0143>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0143>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0143>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0143>, input_int_value) == 6, "offsetof(NetPacket_Fixed<0x0143>, input_int_value) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x0143>) == 10, "sizeof(NetPacket_Fixed<0x0143>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x0143>) == 1, "alignof(NetPacket_Fixed<0x0143>) == 1"); + +template<> +struct NetPacket_Fixed<0x0146> +{ + Little16 magic_packet_id; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x0146>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0146>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0146>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0146>, block_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x0146>) == 6, "sizeof(NetPacket_Fixed<0x0146>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x0146>) == 1, "alignof(NetPacket_Fixed<0x0146>) == 1"); + +template<> +struct NetPacket_Fixed<0x0147> +{ + Little16 magic_packet_id; + NetSkillInfo info; +}; +static_assert(offsetof(NetPacket_Fixed<0x0147>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0147>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0147>, info) == 2, "offsetof(NetPacket_Fixed<0x0147>, info) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x0147>) == 39, "sizeof(NetPacket_Fixed<0x0147>) == 39"); +static_assert(alignof(NetPacket_Fixed<0x0147>) == 1, "alignof(NetPacket_Fixed<0x0147>) == 1"); + +template<> +struct NetPacket_Fixed<0x0148> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 type; +}; +static_assert(offsetof(NetPacket_Fixed<0x0148>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0148>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0148>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0148>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0148>, type) == 6, "offsetof(NetPacket_Fixed<0x0148>, type) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x0148>) == 8, "sizeof(NetPacket_Fixed<0x0148>) == 8"); +static_assert(alignof(NetPacket_Fixed<0x0148>) == 1, "alignof(NetPacket_Fixed<0x0148>) == 1"); + +template<> +struct NetPacket_Fixed<0x014d> +{ + Little16 magic_packet_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x014d>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x014d>, magic_packet_id) == 0"); +static_assert(sizeof(NetPacket_Fixed<0x014d>) == 2, "sizeof(NetPacket_Fixed<0x014d>) == 2"); +static_assert(alignof(NetPacket_Fixed<0x014d>) == 1, "alignof(NetPacket_Fixed<0x014d>) == 1"); + +template<> +struct NetPacket_Fixed<0x018a> +{ + Little16 magic_packet_id; + Little16 unused; +}; +static_assert(offsetof(NetPacket_Fixed<0x018a>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x018a>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x018a>, unused) == 2, "offsetof(NetPacket_Fixed<0x018a>, unused) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x018a>) == 4, "sizeof(NetPacket_Fixed<0x018a>) == 4"); +static_assert(alignof(NetPacket_Fixed<0x018a>) == 1, "alignof(NetPacket_Fixed<0x018a>) == 1"); + +template<> +struct NetPacket_Fixed<0x018b> +{ + Little16 magic_packet_id; + Little16 okay; +}; +static_assert(offsetof(NetPacket_Fixed<0x018b>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x018b>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x018b>, okay) == 2, "offsetof(NetPacket_Fixed<0x018b>, okay) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x018b>) == 4, "sizeof(NetPacket_Fixed<0x018b>) == 4"); +static_assert(alignof(NetPacket_Fixed<0x018b>) == 1, "alignof(NetPacket_Fixed<0x018b>) == 1"); + +template<> +struct NetPacket_Fixed<0x0195> +{ + Little16 magic_packet_id; + Little32 block_id; + NetString<sizeof(PartyName)> party_name; + NetString<sizeof(VString<23>)> guild_name; + NetString<sizeof(VString<23>)> guild_pos; + NetString<sizeof(VString<23>)> guild_pos_again; +}; +static_assert(offsetof(NetPacket_Fixed<0x0195>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0195>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0195>, block_id) == 2, "offsetof(NetPacket_Fixed<0x0195>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0195>, party_name) == 6, "offsetof(NetPacket_Fixed<0x0195>, party_name) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0195>, guild_name) == 30, "offsetof(NetPacket_Fixed<0x0195>, guild_name) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x0195>, guild_pos) == 54, "offsetof(NetPacket_Fixed<0x0195>, guild_pos) == 54"); +static_assert(offsetof(NetPacket_Fixed<0x0195>, guild_pos_again) == 78, "offsetof(NetPacket_Fixed<0x0195>, guild_pos_again) == 78"); +static_assert(sizeof(NetPacket_Fixed<0x0195>) == 102, "sizeof(NetPacket_Fixed<0x0195>) == 102"); +static_assert(alignof(NetPacket_Fixed<0x0195>) == 1, "alignof(NetPacket_Fixed<0x0195>) == 1"); + +template<> +struct NetPacket_Fixed<0x0196> +{ + Little16 magic_packet_id; + Little16 sc_type; + Little32 block_id; + Byte flag; +}; +static_assert(offsetof(NetPacket_Fixed<0x0196>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0196>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0196>, sc_type) == 2, "offsetof(NetPacket_Fixed<0x0196>, sc_type) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0196>, block_id) == 4, "offsetof(NetPacket_Fixed<0x0196>, block_id) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x0196>, flag) == 8, "offsetof(NetPacket_Fixed<0x0196>, flag) == 8"); +static_assert(sizeof(NetPacket_Fixed<0x0196>) == 9, "sizeof(NetPacket_Fixed<0x0196>) == 9"); +static_assert(alignof(NetPacket_Fixed<0x0196>) == 1, "alignof(NetPacket_Fixed<0x0196>) == 1"); + +template<> +struct NetPacket_Fixed<0x019b> +{ + Little16 magic_packet_id; + Little32 block_id; + Little32 type; +}; +static_assert(offsetof(NetPacket_Fixed<0x019b>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x019b>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x019b>, block_id) == 2, "offsetof(NetPacket_Fixed<0x019b>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x019b>, type) == 6, "offsetof(NetPacket_Fixed<0x019b>, type) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x019b>) == 10, "sizeof(NetPacket_Fixed<0x019b>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x019b>) == 1, "alignof(NetPacket_Fixed<0x019b>) == 1"); + +template<> +struct NetPacket_Fixed<0x01b1> +{ + Little16 magic_packet_id; + Little16 ioff2; + Little16 amount; + Byte fail; +}; +static_assert(offsetof(NetPacket_Fixed<0x01b1>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x01b1>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x01b1>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x01b1>, ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x01b1>, amount) == 4, "offsetof(NetPacket_Fixed<0x01b1>, amount) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x01b1>, fail) == 6, "offsetof(NetPacket_Fixed<0x01b1>, fail) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x01b1>) == 7, "sizeof(NetPacket_Fixed<0x01b1>) == 7"); +static_assert(alignof(NetPacket_Fixed<0x01b1>) == 1, "alignof(NetPacket_Fixed<0x01b1>) == 1"); + +template<> +struct NetPacket_Fixed<0x01c8> +{ + Little16 magic_packet_id; + Little16 ioff2; + Little16 name_id; + Little32 block_id; + Little16 amount; + Byte ok; +}; +static_assert(offsetof(NetPacket_Fixed<0x01c8>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x01c8>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x01c8>, ioff2) == 2, "offsetof(NetPacket_Fixed<0x01c8>, ioff2) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x01c8>, name_id) == 4, "offsetof(NetPacket_Fixed<0x01c8>, name_id) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x01c8>, block_id) == 6, "offsetof(NetPacket_Fixed<0x01c8>, block_id) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x01c8>, amount) == 10, "offsetof(NetPacket_Fixed<0x01c8>, amount) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x01c8>, ok) == 12, "offsetof(NetPacket_Fixed<0x01c8>, ok) == 12"); +static_assert(sizeof(NetPacket_Fixed<0x01c8>) == 13, "sizeof(NetPacket_Fixed<0x01c8>) == 13"); +static_assert(alignof(NetPacket_Fixed<0x01c8>) == 1, "alignof(NetPacket_Fixed<0x01c8>) == 1"); + +template<> +struct NetPacket_Fixed<0x01d4> +{ + Little16 magic_packet_id; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Fixed<0x01d4>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x01d4>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x01d4>, block_id) == 2, "offsetof(NetPacket_Fixed<0x01d4>, block_id) == 2"); +static_assert(sizeof(NetPacket_Fixed<0x01d4>) == 6, "sizeof(NetPacket_Fixed<0x01d4>) == 6"); +static_assert(alignof(NetPacket_Fixed<0x01d4>) == 1, "alignof(NetPacket_Fixed<0x01d4>) == 1"); + +template<> +struct NetPacket_Head<0x01d5> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; + Little32 block_id; +}; +static_assert(offsetof(NetPacket_Head<0x01d5>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x01d5>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x01d5>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x01d5>, magic_packet_length) == 2"); +static_assert(offsetof(NetPacket_Head<0x01d5>, block_id) == 4, "offsetof(NetPacket_Head<0x01d5>, block_id) == 4"); +static_assert(sizeof(NetPacket_Head<0x01d5>) == 8, "sizeof(NetPacket_Head<0x01d5>) == 8"); +static_assert(alignof(NetPacket_Head<0x01d5>) == 1, "alignof(NetPacket_Head<0x01d5>) == 1"); +template<> +struct NetPacket_Repeat<0x01d5> +{ + Byte c; +}; +static_assert(offsetof(NetPacket_Repeat<0x01d5>, c) == 0, "offsetof(NetPacket_Repeat<0x01d5>, c) == 0"); +static_assert(sizeof(NetPacket_Repeat<0x01d5>) == 1, "sizeof(NetPacket_Repeat<0x01d5>) == 1"); +static_assert(alignof(NetPacket_Repeat<0x01d5>) == 1, "alignof(NetPacket_Repeat<0x01d5>) == 1"); + +template<> +struct NetPacket_Fixed<0x01d7> +{ + Little16 magic_packet_id; + Little32 block_id; + Byte look_type; + Little16 weapon_or_name_id_or_value; + Little16 shield; +}; +static_assert(offsetof(NetPacket_Fixed<0x01d7>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x01d7>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x01d7>, block_id) == 2, "offsetof(NetPacket_Fixed<0x01d7>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x01d7>, look_type) == 6, "offsetof(NetPacket_Fixed<0x01d7>, look_type) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x01d7>, weapon_or_name_id_or_value) == 7, "offsetof(NetPacket_Fixed<0x01d7>, weapon_or_name_id_or_value) == 7"); +static_assert(offsetof(NetPacket_Fixed<0x01d7>, shield) == 9, "offsetof(NetPacket_Fixed<0x01d7>, shield) == 9"); +static_assert(sizeof(NetPacket_Fixed<0x01d7>) == 11, "sizeof(NetPacket_Fixed<0x01d7>) == 11"); +static_assert(alignof(NetPacket_Fixed<0x01d7>) == 1, "alignof(NetPacket_Fixed<0x01d7>) == 1"); + +template<> +struct NetPacket_Fixed<0x01d8> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 speed; + Little16 opt1; + Little16 opt2; + Little16 option; + Little16 species; + Little16 hair_style; + Little16 weapon; + Little16 shield; + Little16 head_bottom; + Little16 head_top; + Little16 head_mid; + Little16 hair_color; + Little16 clothes_color; + Byte head_dir; + Byte unused2; + Little32 guild_id; + Little16 guild_emblem_id; + Little16 manner; + Little16 opt3; + Byte karma; + Byte sex; + NetPosition1 pos; + Little16 gm_bits; + Byte dead_sit; + Little16 unused; +}; +static_assert(offsetof(NetPacket_Fixed<0x01d8>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x01d8>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, block_id) == 2, "offsetof(NetPacket_Fixed<0x01d8>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, speed) == 6, "offsetof(NetPacket_Fixed<0x01d8>, speed) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, opt1) == 8, "offsetof(NetPacket_Fixed<0x01d8>, opt1) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, opt2) == 10, "offsetof(NetPacket_Fixed<0x01d8>, opt2) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, option) == 12, "offsetof(NetPacket_Fixed<0x01d8>, option) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, species) == 14, "offsetof(NetPacket_Fixed<0x01d8>, species) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, hair_style) == 16, "offsetof(NetPacket_Fixed<0x01d8>, hair_style) == 16"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, weapon) == 18, "offsetof(NetPacket_Fixed<0x01d8>, weapon) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, shield) == 20, "offsetof(NetPacket_Fixed<0x01d8>, shield) == 20"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, head_bottom) == 22, "offsetof(NetPacket_Fixed<0x01d8>, head_bottom) == 22"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, head_top) == 24, "offsetof(NetPacket_Fixed<0x01d8>, head_top) == 24"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, head_mid) == 26, "offsetof(NetPacket_Fixed<0x01d8>, head_mid) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, hair_color) == 28, "offsetof(NetPacket_Fixed<0x01d8>, hair_color) == 28"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, clothes_color) == 30, "offsetof(NetPacket_Fixed<0x01d8>, clothes_color) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, head_dir) == 32, "offsetof(NetPacket_Fixed<0x01d8>, head_dir) == 32"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, unused2) == 33, "offsetof(NetPacket_Fixed<0x01d8>, unused2) == 33"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, guild_id) == 34, "offsetof(NetPacket_Fixed<0x01d8>, guild_id) == 34"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, guild_emblem_id) == 38, "offsetof(NetPacket_Fixed<0x01d8>, guild_emblem_id) == 38"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, manner) == 40, "offsetof(NetPacket_Fixed<0x01d8>, manner) == 40"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, opt3) == 42, "offsetof(NetPacket_Fixed<0x01d8>, opt3) == 42"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, karma) == 44, "offsetof(NetPacket_Fixed<0x01d8>, karma) == 44"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, sex) == 45, "offsetof(NetPacket_Fixed<0x01d8>, sex) == 45"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, pos) == 46, "offsetof(NetPacket_Fixed<0x01d8>, pos) == 46"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, gm_bits) == 49, "offsetof(NetPacket_Fixed<0x01d8>, gm_bits) == 49"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, dead_sit) == 51, "offsetof(NetPacket_Fixed<0x01d8>, dead_sit) == 51"); +static_assert(offsetof(NetPacket_Fixed<0x01d8>, unused) == 52, "offsetof(NetPacket_Fixed<0x01d8>, unused) == 52"); +static_assert(sizeof(NetPacket_Fixed<0x01d8>) == 54, "sizeof(NetPacket_Fixed<0x01d8>) == 54"); +static_assert(alignof(NetPacket_Fixed<0x01d8>) == 1, "alignof(NetPacket_Fixed<0x01d8>) == 1"); + +template<> +struct NetPacket_Fixed<0x01d9> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 speed; + Little16 opt1; + Little16 opt2; + Little16 option; + Little16 species; + Little16 hair_style; + Little16 weapon; + Little16 shield; + Little16 head_bottom; + Little16 head_top; + Little16 head_mid; + Little16 hair_color; + Little16 clothes_color; + Byte head_dir; + Byte unused2; + Little32 guild_id; + Little16 guild_emblem_id; + Little16 manner; + Little16 opt3; + Byte karma; + Byte sex; + NetPosition1 pos; + Little16 gm_bits; + Little16 unused; +}; +static_assert(offsetof(NetPacket_Fixed<0x01d9>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x01d9>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, block_id) == 2, "offsetof(NetPacket_Fixed<0x01d9>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, speed) == 6, "offsetof(NetPacket_Fixed<0x01d9>, speed) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, opt1) == 8, "offsetof(NetPacket_Fixed<0x01d9>, opt1) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, opt2) == 10, "offsetof(NetPacket_Fixed<0x01d9>, opt2) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, option) == 12, "offsetof(NetPacket_Fixed<0x01d9>, option) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, species) == 14, "offsetof(NetPacket_Fixed<0x01d9>, species) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, hair_style) == 16, "offsetof(NetPacket_Fixed<0x01d9>, hair_style) == 16"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, weapon) == 18, "offsetof(NetPacket_Fixed<0x01d9>, weapon) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, shield) == 20, "offsetof(NetPacket_Fixed<0x01d9>, shield) == 20"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, head_bottom) == 22, "offsetof(NetPacket_Fixed<0x01d9>, head_bottom) == 22"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, head_top) == 24, "offsetof(NetPacket_Fixed<0x01d9>, head_top) == 24"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, head_mid) == 26, "offsetof(NetPacket_Fixed<0x01d9>, head_mid) == 26"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, hair_color) == 28, "offsetof(NetPacket_Fixed<0x01d9>, hair_color) == 28"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, clothes_color) == 30, "offsetof(NetPacket_Fixed<0x01d9>, clothes_color) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, head_dir) == 32, "offsetof(NetPacket_Fixed<0x01d9>, head_dir) == 32"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, unused2) == 33, "offsetof(NetPacket_Fixed<0x01d9>, unused2) == 33"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, guild_id) == 34, "offsetof(NetPacket_Fixed<0x01d9>, guild_id) == 34"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, guild_emblem_id) == 38, "offsetof(NetPacket_Fixed<0x01d9>, guild_emblem_id) == 38"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, manner) == 40, "offsetof(NetPacket_Fixed<0x01d9>, manner) == 40"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, opt3) == 42, "offsetof(NetPacket_Fixed<0x01d9>, opt3) == 42"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, karma) == 44, "offsetof(NetPacket_Fixed<0x01d9>, karma) == 44"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, sex) == 45, "offsetof(NetPacket_Fixed<0x01d9>, sex) == 45"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, pos) == 46, "offsetof(NetPacket_Fixed<0x01d9>, pos) == 46"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, gm_bits) == 49, "offsetof(NetPacket_Fixed<0x01d9>, gm_bits) == 49"); +static_assert(offsetof(NetPacket_Fixed<0x01d9>, unused) == 51, "offsetof(NetPacket_Fixed<0x01d9>, unused) == 51"); +static_assert(sizeof(NetPacket_Fixed<0x01d9>) == 53, "sizeof(NetPacket_Fixed<0x01d9>) == 53"); +static_assert(alignof(NetPacket_Fixed<0x01d9>) == 1, "alignof(NetPacket_Fixed<0x01d9>) == 1"); + +template<> +struct NetPacket_Fixed<0x01da> +{ + Little16 magic_packet_id; + Little32 block_id; + Little16 speed; + Little16 opt1; + Little16 opt2; + Little16 option; + Little16 species; + Little16 hair_style; + Little16 weapon; + Little16 shield; + Little16 head_bottom; + Little32 tick; + Little16 head_top; + Little16 head_mid; + Little16 hair_color; + Little16 clothes_color; + Byte head_dir; + Byte unused2; + Little32 guild_id; + Little16 guild_emblem_id; + Little16 manner; + Little16 opt3; + Byte karma; + Byte sex; + NetPosition2 pos2; + Little16 gm_bits; + Byte five; + Little16 unused; +}; +static_assert(offsetof(NetPacket_Fixed<0x01da>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x01da>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, block_id) == 2, "offsetof(NetPacket_Fixed<0x01da>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, speed) == 6, "offsetof(NetPacket_Fixed<0x01da>, speed) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, opt1) == 8, "offsetof(NetPacket_Fixed<0x01da>, opt1) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, opt2) == 10, "offsetof(NetPacket_Fixed<0x01da>, opt2) == 10"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, option) == 12, "offsetof(NetPacket_Fixed<0x01da>, option) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, species) == 14, "offsetof(NetPacket_Fixed<0x01da>, species) == 14"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, hair_style) == 16, "offsetof(NetPacket_Fixed<0x01da>, hair_style) == 16"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, weapon) == 18, "offsetof(NetPacket_Fixed<0x01da>, weapon) == 18"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, shield) == 20, "offsetof(NetPacket_Fixed<0x01da>, shield) == 20"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, head_bottom) == 22, "offsetof(NetPacket_Fixed<0x01da>, head_bottom) == 22"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, tick) == 24, "offsetof(NetPacket_Fixed<0x01da>, tick) == 24"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, head_top) == 28, "offsetof(NetPacket_Fixed<0x01da>, head_top) == 28"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, head_mid) == 30, "offsetof(NetPacket_Fixed<0x01da>, head_mid) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, hair_color) == 32, "offsetof(NetPacket_Fixed<0x01da>, hair_color) == 32"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, clothes_color) == 34, "offsetof(NetPacket_Fixed<0x01da>, clothes_color) == 34"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, head_dir) == 36, "offsetof(NetPacket_Fixed<0x01da>, head_dir) == 36"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, unused2) == 37, "offsetof(NetPacket_Fixed<0x01da>, unused2) == 37"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, guild_id) == 38, "offsetof(NetPacket_Fixed<0x01da>, guild_id) == 38"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, guild_emblem_id) == 42, "offsetof(NetPacket_Fixed<0x01da>, guild_emblem_id) == 42"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, manner) == 44, "offsetof(NetPacket_Fixed<0x01da>, manner) == 44"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, opt3) == 46, "offsetof(NetPacket_Fixed<0x01da>, opt3) == 46"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, karma) == 48, "offsetof(NetPacket_Fixed<0x01da>, karma) == 48"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, sex) == 49, "offsetof(NetPacket_Fixed<0x01da>, sex) == 49"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, pos2) == 50, "offsetof(NetPacket_Fixed<0x01da>, pos2) == 50"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, gm_bits) == 55, "offsetof(NetPacket_Fixed<0x01da>, gm_bits) == 55"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, five) == 57, "offsetof(NetPacket_Fixed<0x01da>, five) == 57"); +static_assert(offsetof(NetPacket_Fixed<0x01da>, unused) == 58, "offsetof(NetPacket_Fixed<0x01da>, unused) == 58"); +static_assert(sizeof(NetPacket_Fixed<0x01da>) == 60, "sizeof(NetPacket_Fixed<0x01da>) == 60"); +static_assert(alignof(NetPacket_Fixed<0x01da>) == 1, "alignof(NetPacket_Fixed<0x01da>) == 1"); + +template<> +struct NetPacket_Fixed<0x01de> +{ + Little16 magic_packet_id; + Little16 skill_id; + Little32 src_id; + Little32 dst_id; + Little32 tick; + Little32 sdelay; + Little32 ddelay; + Little32 damage; + Little16 skill_level; + Little16 div; + Byte type_or_hit; +}; +static_assert(offsetof(NetPacket_Fixed<0x01de>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x01de>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x01de>, skill_id) == 2, "offsetof(NetPacket_Fixed<0x01de>, skill_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x01de>, src_id) == 4, "offsetof(NetPacket_Fixed<0x01de>, src_id) == 4"); +static_assert(offsetof(NetPacket_Fixed<0x01de>, dst_id) == 8, "offsetof(NetPacket_Fixed<0x01de>, dst_id) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x01de>, tick) == 12, "offsetof(NetPacket_Fixed<0x01de>, tick) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x01de>, sdelay) == 16, "offsetof(NetPacket_Fixed<0x01de>, sdelay) == 16"); +static_assert(offsetof(NetPacket_Fixed<0x01de>, ddelay) == 20, "offsetof(NetPacket_Fixed<0x01de>, ddelay) == 20"); +static_assert(offsetof(NetPacket_Fixed<0x01de>, damage) == 24, "offsetof(NetPacket_Fixed<0x01de>, damage) == 24"); +static_assert(offsetof(NetPacket_Fixed<0x01de>, skill_level) == 28, "offsetof(NetPacket_Fixed<0x01de>, skill_level) == 28"); +static_assert(offsetof(NetPacket_Fixed<0x01de>, div) == 30, "offsetof(NetPacket_Fixed<0x01de>, div) == 30"); +static_assert(offsetof(NetPacket_Fixed<0x01de>, type_or_hit) == 32, "offsetof(NetPacket_Fixed<0x01de>, type_or_hit) == 32"); +static_assert(sizeof(NetPacket_Fixed<0x01de>) == 33, "sizeof(NetPacket_Fixed<0x01de>) == 33"); +static_assert(alignof(NetPacket_Fixed<0x01de>) == 1, "alignof(NetPacket_Fixed<0x01de>) == 1"); + +template<> +struct NetPacket_Head<0x01ee> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x01ee>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x01ee>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x01ee>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x01ee>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x01ee>) == 4, "sizeof(NetPacket_Head<0x01ee>) == 4"); +static_assert(alignof(NetPacket_Head<0x01ee>) == 1, "alignof(NetPacket_Head<0x01ee>) == 1"); +template<> +struct NetPacket_Repeat<0x01ee> +{ + Little16 ioff2; + Little16 name_id; + Byte item_type; + Byte identify; + Little16 amount; + Little16 epos; + Little16 card0; + Little16 card1; + Little16 card2; + Little16 card3; +}; +static_assert(offsetof(NetPacket_Repeat<0x01ee>, ioff2) == 0, "offsetof(NetPacket_Repeat<0x01ee>, ioff2) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x01ee>, name_id) == 2, "offsetof(NetPacket_Repeat<0x01ee>, name_id) == 2"); +static_assert(offsetof(NetPacket_Repeat<0x01ee>, item_type) == 4, "offsetof(NetPacket_Repeat<0x01ee>, item_type) == 4"); +static_assert(offsetof(NetPacket_Repeat<0x01ee>, identify) == 5, "offsetof(NetPacket_Repeat<0x01ee>, identify) == 5"); +static_assert(offsetof(NetPacket_Repeat<0x01ee>, amount) == 6, "offsetof(NetPacket_Repeat<0x01ee>, amount) == 6"); +static_assert(offsetof(NetPacket_Repeat<0x01ee>, epos) == 8, "offsetof(NetPacket_Repeat<0x01ee>, epos) == 8"); +static_assert(offsetof(NetPacket_Repeat<0x01ee>, card0) == 10, "offsetof(NetPacket_Repeat<0x01ee>, card0) == 10"); +static_assert(offsetof(NetPacket_Repeat<0x01ee>, card1) == 12, "offsetof(NetPacket_Repeat<0x01ee>, card1) == 12"); +static_assert(offsetof(NetPacket_Repeat<0x01ee>, card2) == 14, "offsetof(NetPacket_Repeat<0x01ee>, card2) == 14"); +static_assert(offsetof(NetPacket_Repeat<0x01ee>, card3) == 16, "offsetof(NetPacket_Repeat<0x01ee>, card3) == 16"); +static_assert(sizeof(NetPacket_Repeat<0x01ee>) == 18, "sizeof(NetPacket_Repeat<0x01ee>) == 18"); +static_assert(alignof(NetPacket_Repeat<0x01ee>) == 1, "alignof(NetPacket_Repeat<0x01ee>) == 1"); + +template<> +struct NetPacket_Head<0x01f0> +{ + Little16 magic_packet_id; + Little16 magic_packet_length; +}; +static_assert(offsetof(NetPacket_Head<0x01f0>, magic_packet_id) == 0, "offsetof(NetPacket_Head<0x01f0>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Head<0x01f0>, magic_packet_length) == 2, "offsetof(NetPacket_Head<0x01f0>, magic_packet_length) == 2"); +static_assert(sizeof(NetPacket_Head<0x01f0>) == 4, "sizeof(NetPacket_Head<0x01f0>) == 4"); +static_assert(alignof(NetPacket_Head<0x01f0>) == 1, "alignof(NetPacket_Head<0x01f0>) == 1"); +template<> +struct NetPacket_Repeat<0x01f0> +{ + Little16 soff1; + Little16 name_id; + Byte item_type; + Byte identify; + Little16 amount; + Little16 epos_zero; + Little16 card0; + Little16 card1; + Little16 card2; + Little16 card3; +}; +static_assert(offsetof(NetPacket_Repeat<0x01f0>, soff1) == 0, "offsetof(NetPacket_Repeat<0x01f0>, soff1) == 0"); +static_assert(offsetof(NetPacket_Repeat<0x01f0>, name_id) == 2, "offsetof(NetPacket_Repeat<0x01f0>, name_id) == 2"); +static_assert(offsetof(NetPacket_Repeat<0x01f0>, item_type) == 4, "offsetof(NetPacket_Repeat<0x01f0>, item_type) == 4"); +static_assert(offsetof(NetPacket_Repeat<0x01f0>, identify) == 5, "offsetof(NetPacket_Repeat<0x01f0>, identify) == 5"); +static_assert(offsetof(NetPacket_Repeat<0x01f0>, amount) == 6, "offsetof(NetPacket_Repeat<0x01f0>, amount) == 6"); +static_assert(offsetof(NetPacket_Repeat<0x01f0>, epos_zero) == 8, "offsetof(NetPacket_Repeat<0x01f0>, epos_zero) == 8"); +static_assert(offsetof(NetPacket_Repeat<0x01f0>, card0) == 10, "offsetof(NetPacket_Repeat<0x01f0>, card0) == 10"); +static_assert(offsetof(NetPacket_Repeat<0x01f0>, card1) == 12, "offsetof(NetPacket_Repeat<0x01f0>, card1) == 12"); +static_assert(offsetof(NetPacket_Repeat<0x01f0>, card2) == 14, "offsetof(NetPacket_Repeat<0x01f0>, card2) == 14"); +static_assert(offsetof(NetPacket_Repeat<0x01f0>, card3) == 16, "offsetof(NetPacket_Repeat<0x01f0>, card3) == 16"); +static_assert(sizeof(NetPacket_Repeat<0x01f0>) == 18, "sizeof(NetPacket_Repeat<0x01f0>) == 18"); +static_assert(alignof(NetPacket_Repeat<0x01f0>) == 1, "alignof(NetPacket_Repeat<0x01f0>) == 1"); + +template<> +struct NetPacket_Fixed<0x020c> +{ + Little16 magic_packet_id; + Little32 block_id; + IP4Address ip; +}; +static_assert(offsetof(NetPacket_Fixed<0x020c>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x020c>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x020c>, block_id) == 2, "offsetof(NetPacket_Fixed<0x020c>, block_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x020c>, ip) == 6, "offsetof(NetPacket_Fixed<0x020c>, ip) == 6"); +static_assert(sizeof(NetPacket_Fixed<0x020c>) == 10, "sizeof(NetPacket_Fixed<0x020c>) == 10"); +static_assert(alignof(NetPacket_Fixed<0x020c>) == 1, "alignof(NetPacket_Fixed<0x020c>) == 1"); + +template<> +struct NetPacket_Fixed<0x0212> +{ + Little16 magic_packet_id; + Little32 npc_id; + Little16 command; + Little32 id; + Little16 x; + Little16 y; +}; +static_assert(offsetof(NetPacket_Fixed<0x0212>, magic_packet_id) == 0, "offsetof(NetPacket_Fixed<0x0212>, magic_packet_id) == 0"); +static_assert(offsetof(NetPacket_Fixed<0x0212>, npc_id) == 2, "offsetof(NetPacket_Fixed<0x0212>, npc_id) == 2"); +static_assert(offsetof(NetPacket_Fixed<0x0212>, command) == 6, "offsetof(NetPacket_Fixed<0x0212>, command) == 6"); +static_assert(offsetof(NetPacket_Fixed<0x0212>, id) == 8, "offsetof(NetPacket_Fixed<0x0212>, id) == 8"); +static_assert(offsetof(NetPacket_Fixed<0x0212>, x) == 12, "offsetof(NetPacket_Fixed<0x0212>, x) == 12"); +static_assert(offsetof(NetPacket_Fixed<0x0212>, y) == 14, "offsetof(NetPacket_Fixed<0x0212>, y) == 14"); +static_assert(sizeof(NetPacket_Fixed<0x0212>) == 16, "sizeof(NetPacket_Fixed<0x0212>) == 16"); +static_assert(alignof(NetPacket_Fixed<0x0212>) == 1, "alignof(NetPacket_Fixed<0x0212>) == 1"); + + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0072> *network, Packet_Fixed<0x0072> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->char_id, native.char_id); + rv &= native_to_network(&network->login_id1, native.login_id1); + rv &= native_to_network(&network->client_tick, native.client_tick); + rv &= native_to_network(&network->sex, native.sex); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0072> *native, NetPacket_Fixed<0x0072> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->char_id, network.char_id); + rv &= network_to_native(&native->login_id1, network.login_id1); + rv &= network_to_native(&native->client_tick, network.client_tick); + rv &= network_to_native(&native->sex, network.sex); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0073> *network, Packet_Fixed<0x0073> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->tick, native.tick); + rv &= native_to_network(&network->pos, native.pos); + rv &= native_to_network(&network->five1, native.five1); + rv &= native_to_network(&network->five2, native.five2); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0073> *native, NetPacket_Fixed<0x0073> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->tick, network.tick); + rv &= network_to_native(&native->pos, network.pos); + rv &= network_to_native(&native->five1, network.five1); + rv &= network_to_native(&native->five2, network.five2); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0078> *network, Packet_Fixed<0x0078> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->speed, native.speed); + rv &= native_to_network(&network->opt1, native.opt1); + rv &= native_to_network(&network->opt2, native.opt2); + rv &= native_to_network(&network->option, native.option); + rv &= native_to_network(&network->species, native.species); + rv &= native_to_network(&network->unused_hair_style, native.unused_hair_style); + rv &= native_to_network(&network->unused_weapon, native.unused_weapon); + rv &= native_to_network(&network->unused_head_bottom_or_species_again, native.unused_head_bottom_or_species_again); + rv &= native_to_network(&network->unused_shield_or_part_of_guild_emblem, native.unused_shield_or_part_of_guild_emblem); + rv &= native_to_network(&network->unused_head_top_or_unused_part_of_guild_emblem, native.unused_head_top_or_unused_part_of_guild_emblem); + rv &= native_to_network(&network->unused_head_mid_or_part_of_guild_id, native.unused_head_mid_or_part_of_guild_id); + rv &= native_to_network(&network->unused_hair_color_or_part_of_guild_id, native.unused_hair_color_or_part_of_guild_id); + rv &= native_to_network(&network->unused_clothes_color, native.unused_clothes_color); + rv &= native_to_network(&network->unused_1, native.unused_1); + rv &= native_to_network(&network->unused_2, native.unused_2); + rv &= native_to_network(&network->unused_pos_again, native.unused_pos_again); + rv &= native_to_network(&network->unused_4b, native.unused_4b); + rv &= native_to_network(&network->unused_5, native.unused_5); + rv &= native_to_network(&network->unused_zero_1, native.unused_zero_1); + rv &= native_to_network(&network->unused_zero_2, native.unused_zero_2); + rv &= native_to_network(&network->unused_sex, native.unused_sex); + rv &= native_to_network(&network->pos, native.pos); + rv &= native_to_network(&network->five1, native.five1); + rv &= native_to_network(&network->five2, native.five2); + rv &= native_to_network(&network->zero, native.zero); + rv &= native_to_network(&network->level, native.level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0078> *native, NetPacket_Fixed<0x0078> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->speed, network.speed); + rv &= network_to_native(&native->opt1, network.opt1); + rv &= network_to_native(&native->opt2, network.opt2); + rv &= network_to_native(&native->option, network.option); + rv &= network_to_native(&native->species, network.species); + rv &= network_to_native(&native->unused_hair_style, network.unused_hair_style); + rv &= network_to_native(&native->unused_weapon, network.unused_weapon); + rv &= network_to_native(&native->unused_head_bottom_or_species_again, network.unused_head_bottom_or_species_again); + rv &= network_to_native(&native->unused_shield_or_part_of_guild_emblem, network.unused_shield_or_part_of_guild_emblem); + rv &= network_to_native(&native->unused_head_top_or_unused_part_of_guild_emblem, network.unused_head_top_or_unused_part_of_guild_emblem); + rv &= network_to_native(&native->unused_head_mid_or_part_of_guild_id, network.unused_head_mid_or_part_of_guild_id); + rv &= network_to_native(&native->unused_hair_color_or_part_of_guild_id, network.unused_hair_color_or_part_of_guild_id); + rv &= network_to_native(&native->unused_clothes_color, network.unused_clothes_color); + rv &= network_to_native(&native->unused_1, network.unused_1); + rv &= network_to_native(&native->unused_2, network.unused_2); + rv &= network_to_native(&native->unused_pos_again, network.unused_pos_again); + rv &= network_to_native(&native->unused_4b, network.unused_4b); + rv &= network_to_native(&native->unused_5, network.unused_5); + rv &= network_to_native(&native->unused_zero_1, network.unused_zero_1); + rv &= network_to_native(&native->unused_zero_2, network.unused_zero_2); + rv &= network_to_native(&native->unused_sex, network.unused_sex); + rv &= network_to_native(&native->pos, network.pos); + rv &= network_to_native(&native->five1, network.five1); + rv &= network_to_native(&native->five2, network.five2); + rv &= network_to_native(&native->zero, network.zero); + rv &= network_to_native(&native->level, network.level); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x007b> *network, Packet_Fixed<0x007b> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->speed, native.speed); + rv &= native_to_network(&network->opt1, native.opt1); + rv &= native_to_network(&network->opt2, native.opt2); + rv &= native_to_network(&network->option, native.option); + rv &= native_to_network(&network->mob_class, native.mob_class); + rv &= native_to_network(&network->unused_hair_style, native.unused_hair_style); + rv &= native_to_network(&network->unused_weapon, native.unused_weapon); + rv &= native_to_network(&network->unused_head_bottom, native.unused_head_bottom); + rv &= native_to_network(&network->tick_and_maybe_part_of_guild_emblem, native.tick_and_maybe_part_of_guild_emblem); + rv &= native_to_network(&network->unused_shield_or_maybe_part_of_guild_emblem, native.unused_shield_or_maybe_part_of_guild_emblem); + rv &= native_to_network(&network->unused_head_top_or_maybe_part_of_guild_id, native.unused_head_top_or_maybe_part_of_guild_id); + rv &= native_to_network(&network->unused_head_mid_or_maybe_part_of_guild_id, native.unused_head_mid_or_maybe_part_of_guild_id); + rv &= native_to_network(&network->unused_hair_color, native.unused_hair_color); + rv &= native_to_network(&network->unused_clothes_color, native.unused_clothes_color); + rv &= native_to_network(&network->unused_1, native.unused_1); + rv &= native_to_network(&network->unused_2, native.unused_2); + rv &= native_to_network(&network->unused_3, native.unused_3); + rv &= native_to_network(&network->unused_4, native.unused_4); + rv &= native_to_network(&network->unused_5, native.unused_5); + rv &= native_to_network(&network->unused_zero_1, native.unused_zero_1); + rv &= native_to_network(&network->unused_zero_2, native.unused_zero_2); + rv &= native_to_network(&network->unused_sex, native.unused_sex); + rv &= native_to_network(&network->pos2, native.pos2); + rv &= native_to_network(&network->zero, native.zero); + rv &= native_to_network(&network->five1, native.five1); + rv &= native_to_network(&network->five2, native.five2); + rv &= native_to_network(&network->level, native.level); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x007b> *native, NetPacket_Fixed<0x007b> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->speed, network.speed); + rv &= network_to_native(&native->opt1, network.opt1); + rv &= network_to_native(&native->opt2, network.opt2); + rv &= network_to_native(&native->option, network.option); + rv &= network_to_native(&native->mob_class, network.mob_class); + rv &= network_to_native(&native->unused_hair_style, network.unused_hair_style); + rv &= network_to_native(&native->unused_weapon, network.unused_weapon); + rv &= network_to_native(&native->unused_head_bottom, network.unused_head_bottom); + rv &= network_to_native(&native->tick_and_maybe_part_of_guild_emblem, network.tick_and_maybe_part_of_guild_emblem); + rv &= network_to_native(&native->unused_shield_or_maybe_part_of_guild_emblem, network.unused_shield_or_maybe_part_of_guild_emblem); + rv &= network_to_native(&native->unused_head_top_or_maybe_part_of_guild_id, network.unused_head_top_or_maybe_part_of_guild_id); + rv &= network_to_native(&native->unused_head_mid_or_maybe_part_of_guild_id, network.unused_head_mid_or_maybe_part_of_guild_id); + rv &= network_to_native(&native->unused_hair_color, network.unused_hair_color); + rv &= network_to_native(&native->unused_clothes_color, network.unused_clothes_color); + rv &= network_to_native(&native->unused_1, network.unused_1); + rv &= network_to_native(&native->unused_2, network.unused_2); + rv &= network_to_native(&native->unused_3, network.unused_3); + rv &= network_to_native(&native->unused_4, network.unused_4); + rv &= network_to_native(&native->unused_5, network.unused_5); + rv &= network_to_native(&native->unused_zero_1, network.unused_zero_1); + rv &= network_to_native(&native->unused_zero_2, network.unused_zero_2); + rv &= network_to_native(&native->unused_sex, network.unused_sex); + rv &= network_to_native(&native->pos2, network.pos2); + rv &= network_to_native(&native->zero, network.zero); + rv &= network_to_native(&native->five1, network.five1); + rv &= network_to_native(&native->five2, network.five2); + rv &= network_to_native(&native->level, network.level); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x007c> *network, Packet_Fixed<0x007c> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->speed, native.speed); + rv &= native_to_network(&network->opt1, native.opt1); + rv &= native_to_network(&network->opt2, native.opt2); + rv &= native_to_network(&network->option, native.option); + rv &= native_to_network(&network->unknown_1, native.unknown_1); + rv &= native_to_network(&network->unknown_2, native.unknown_2); + rv &= native_to_network(&network->unknown_3, native.unknown_3); + rv &= native_to_network(&network->species, native.species); + rv &= native_to_network(&network->unknown_4, native.unknown_4); + rv &= native_to_network(&network->unknown_5, native.unknown_5); + rv &= native_to_network(&network->unknown_6, native.unknown_6); + rv &= native_to_network(&network->unknown_7, native.unknown_7); + rv &= native_to_network(&network->unknown_8, native.unknown_8); + rv &= native_to_network(&network->unknown_9, native.unknown_9); + rv &= native_to_network(&network->unknown_10, native.unknown_10); + rv &= native_to_network(&network->pos, native.pos); + rv &= native_to_network(&network->unknown_11, native.unknown_11); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x007c> *native, NetPacket_Fixed<0x007c> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->speed, network.speed); + rv &= network_to_native(&native->opt1, network.opt1); + rv &= network_to_native(&native->opt2, network.opt2); + rv &= network_to_native(&native->option, network.option); + rv &= network_to_native(&native->unknown_1, network.unknown_1); + rv &= network_to_native(&native->unknown_2, network.unknown_2); + rv &= network_to_native(&native->unknown_3, network.unknown_3); + rv &= network_to_native(&native->species, network.species); + rv &= network_to_native(&native->unknown_4, network.unknown_4); + rv &= network_to_native(&native->unknown_5, network.unknown_5); + rv &= network_to_native(&native->unknown_6, network.unknown_6); + rv &= network_to_native(&native->unknown_7, network.unknown_7); + rv &= network_to_native(&native->unknown_8, network.unknown_8); + rv &= network_to_native(&native->unknown_9, network.unknown_9); + rv &= network_to_native(&native->unknown_10, network.unknown_10); + rv &= network_to_native(&native->pos, network.pos); + rv &= network_to_native(&native->unknown_11, network.unknown_11); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x007d> *network, Packet_Fixed<0x007d> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x007d> *native, NetPacket_Fixed<0x007d> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x007e> *network, Packet_Fixed<0x007e> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->client_tick, native.client_tick); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x007e> *native, NetPacket_Fixed<0x007e> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->client_tick, network.client_tick); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x007f> *network, Packet_Fixed<0x007f> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->tick, native.tick); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x007f> *native, NetPacket_Fixed<0x007f> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->tick, network.tick); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0080> *network, Packet_Fixed<0x0080> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->type, native.type); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0080> *native, NetPacket_Fixed<0x0080> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->type, network.type); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0085> *network, Packet_Fixed<0x0085> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->pos, native.pos); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0085> *native, NetPacket_Fixed<0x0085> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->pos, network.pos); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0087> *network, Packet_Fixed<0x0087> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->tick, native.tick); + rv &= native_to_network(&network->pos2, native.pos2); + rv &= native_to_network(&network->zero, native.zero); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0087> *native, NetPacket_Fixed<0x0087> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->tick, network.tick); + rv &= network_to_native(&native->pos2, network.pos2); + rv &= network_to_native(&native->zero, network.zero); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0088> *network, Packet_Fixed<0x0088> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->x, native.x); + rv &= native_to_network(&network->y, native.y); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0088> *native, NetPacket_Fixed<0x0088> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->x, network.x); + rv &= network_to_native(&native->y, network.y); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0089> *network, Packet_Fixed<0x0089> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->target_id, native.target_id); + rv &= native_to_network(&network->action, native.action); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0089> *native, NetPacket_Fixed<0x0089> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->target_id, network.target_id); + rv &= network_to_native(&native->action, network.action); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x008a> *network, Packet_Fixed<0x008a> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->src_id, native.src_id); + rv &= native_to_network(&network->dst_id, native.dst_id); + rv &= native_to_network(&network->tick, native.tick); + rv &= native_to_network(&network->sdelay, native.sdelay); + rv &= native_to_network(&network->ddelay, native.ddelay); + rv &= native_to_network(&network->damage, native.damage); + rv &= native_to_network(&network->div, native.div); + rv &= native_to_network(&network->damage_type, native.damage_type); + rv &= native_to_network(&network->damage2, native.damage2); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x008a> *native, NetPacket_Fixed<0x008a> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->src_id, network.src_id); + rv &= network_to_native(&native->dst_id, network.dst_id); + rv &= network_to_native(&native->tick, network.tick); + rv &= network_to_native(&native->sdelay, network.sdelay); + rv &= network_to_native(&native->ddelay, network.ddelay); + rv &= network_to_native(&native->damage, network.damage); + rv &= network_to_native(&native->div, network.div); + rv &= network_to_native(&native->damage_type, network.damage_type); + rv &= network_to_native(&native->damage2, network.damage2); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x008c> *network, Packet_Head<0x008c> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x008c> *native, NetPacket_Head<0x008c> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x008c> *network, Packet_Repeat<0x008c> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x008c> *native, NetPacket_Repeat<0x008c> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x008d> *network, Packet_Head<0x008d> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x008d> *native, NetPacket_Head<0x008d> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x008d> *network, Packet_Repeat<0x008d> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x008d> *native, NetPacket_Repeat<0x008d> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x008e> *network, Packet_Head<0x008e> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x008e> *native, NetPacket_Head<0x008e> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x008e> *network, Packet_Repeat<0x008e> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x008e> *native, NetPacket_Repeat<0x008e> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0090> *network, Packet_Fixed<0x0090> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->unused, native.unused); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0090> *native, NetPacket_Fixed<0x0090> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->unused, network.unused); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0091> *network, Packet_Fixed<0x0091> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->map_name, native.map_name); + rv &= native_to_network(&network->x, native.x); + rv &= native_to_network(&network->y, native.y); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0091> *native, NetPacket_Fixed<0x0091> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->map_name, network.map_name); + rv &= network_to_native(&native->x, network.x); + rv &= network_to_native(&native->y, network.y); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0092> *network, Packet_Fixed<0x0092> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->map_name, native.map_name); + rv &= native_to_network(&network->x, native.x); + rv &= native_to_network(&network->y, native.y); + rv &= native_to_network(&network->ip, native.ip); + rv &= native_to_network(&network->port, native.port); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0092> *native, NetPacket_Fixed<0x0092> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->map_name, network.map_name); + rv &= network_to_native(&native->x, network.x); + rv &= network_to_native(&native->y, network.y); + rv &= network_to_native(&native->ip, network.ip); + rv &= network_to_native(&native->port, network.port); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0094> *network, Packet_Fixed<0x0094> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0094> *native, NetPacket_Fixed<0x0094> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0095> *network, Packet_Fixed<0x0095> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->char_name, native.char_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0095> *native, NetPacket_Fixed<0x0095> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->char_name, network.char_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x0096> *network, Packet_Head<0x0096> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->target_name, native.target_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x0096> *native, NetPacket_Head<0x0096> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->target_name, network.target_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x0096> *network, Packet_Repeat<0x0096> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x0096> *native, NetPacket_Repeat<0x0096> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x0097> *network, Packet_Head<0x0097> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->char_name, native.char_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x0097> *native, NetPacket_Head<0x0097> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->char_name, network.char_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x0097> *network, Packet_Repeat<0x0097> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x0097> *native, NetPacket_Repeat<0x0097> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0098> *network, Packet_Fixed<0x0098> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0098> *native, NetPacket_Fixed<0x0098> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x009a> *network, Packet_Head<0x009a> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x009a> *native, NetPacket_Head<0x009a> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x009a> *network, Packet_Repeat<0x009a> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x009a> *native, NetPacket_Repeat<0x009a> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x009b> *network, Packet_Fixed<0x009b> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->unused, native.unused); + rv &= native_to_network(&network->client_dir, native.client_dir); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x009b> *native, NetPacket_Fixed<0x009b> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->unused, network.unused); + rv &= network_to_native(&native->client_dir, network.client_dir); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x009c> *network, Packet_Fixed<0x009c> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->zero, native.zero); + rv &= native_to_network(&network->client_dir, native.client_dir); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x009c> *native, NetPacket_Fixed<0x009c> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->zero, network.zero); + rv &= network_to_native(&native->client_dir, network.client_dir); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x009d> *network, Packet_Fixed<0x009d> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->name_id, native.name_id); + rv &= native_to_network(&network->identify, native.identify); + rv &= native_to_network(&network->x, native.x); + rv &= native_to_network(&network->y, native.y); + rv &= native_to_network(&network->amount, native.amount); + rv &= native_to_network(&network->subx, native.subx); + rv &= native_to_network(&network->suby, native.suby); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x009d> *native, NetPacket_Fixed<0x009d> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->name_id, network.name_id); + rv &= network_to_native(&native->identify, network.identify); + rv &= network_to_native(&native->x, network.x); + rv &= network_to_native(&native->y, network.y); + rv &= network_to_native(&native->amount, network.amount); + rv &= network_to_native(&native->subx, network.subx); + rv &= network_to_native(&native->suby, network.suby); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x009e> *network, Packet_Fixed<0x009e> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->name_id, native.name_id); + rv &= native_to_network(&network->identify, native.identify); + rv &= native_to_network(&network->x, native.x); + rv &= native_to_network(&network->y, native.y); + rv &= native_to_network(&network->subx, native.subx); + rv &= native_to_network(&network->suby, native.suby); + rv &= native_to_network(&network->amount, native.amount); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x009e> *native, NetPacket_Fixed<0x009e> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->name_id, network.name_id); + rv &= network_to_native(&native->identify, network.identify); + rv &= network_to_native(&native->x, network.x); + rv &= network_to_native(&native->y, network.y); + rv &= network_to_native(&native->subx, network.subx); + rv &= network_to_native(&native->suby, network.suby); + rv &= network_to_native(&native->amount, network.amount); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x009f> *network, Packet_Fixed<0x009f> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->object_id, native.object_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x009f> *native, NetPacket_Fixed<0x009f> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->object_id, network.object_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00a0> *network, Packet_Fixed<0x00a0> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->amount, native.amount); + rv &= native_to_network(&network->name_id, native.name_id); + rv &= native_to_network(&network->identify, native.identify); + rv &= native_to_network(&network->broken_or_attribute, native.broken_or_attribute); + rv &= native_to_network(&network->refine, native.refine); + rv &= native_to_network(&network->card0, native.card0); + rv &= native_to_network(&network->card1, native.card1); + rv &= native_to_network(&network->card2, native.card2); + rv &= native_to_network(&network->card3, native.card3); + rv &= native_to_network(&network->epos, native.epos); + rv &= native_to_network(&network->item_type, native.item_type); + rv &= native_to_network(&network->pickup_fail, native.pickup_fail); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00a0> *native, NetPacket_Fixed<0x00a0> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->amount, network.amount); + rv &= network_to_native(&native->name_id, network.name_id); + rv &= network_to_native(&native->identify, network.identify); + rv &= network_to_native(&native->broken_or_attribute, network.broken_or_attribute); + rv &= network_to_native(&native->refine, network.refine); + rv &= network_to_native(&native->card0, network.card0); + rv &= network_to_native(&native->card1, network.card1); + rv &= network_to_native(&native->card2, network.card2); + rv &= network_to_native(&native->card3, network.card3); + rv &= network_to_native(&native->epos, network.epos); + rv &= network_to_native(&native->item_type, network.item_type); + rv &= network_to_native(&native->pickup_fail, network.pickup_fail); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00a1> *network, Packet_Fixed<0x00a1> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00a1> *native, NetPacket_Fixed<0x00a1> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00a2> *network, Packet_Fixed<0x00a2> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->amount, native.amount); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00a2> *native, NetPacket_Fixed<0x00a2> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->amount, network.amount); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x00a4> *network, Packet_Head<0x00a4> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x00a4> *native, NetPacket_Head<0x00a4> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x00a4> *network, Packet_Repeat<0x00a4> native) +{ + bool rv = true; + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->name_id, native.name_id); + rv &= native_to_network(&network->item_type, native.item_type); + rv &= native_to_network(&network->identify, native.identify); + rv &= native_to_network(&network->epos_pc, native.epos_pc); + rv &= native_to_network(&network->epos_inv, native.epos_inv); + rv &= native_to_network(&network->broken_or_attribute, native.broken_or_attribute); + rv &= native_to_network(&network->refine, native.refine); + rv &= native_to_network(&network->card0, native.card0); + rv &= native_to_network(&network->card1, native.card1); + rv &= native_to_network(&network->card2, native.card2); + rv &= native_to_network(&network->card3, native.card3); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x00a4> *native, NetPacket_Repeat<0x00a4> network) +{ + bool rv = true; + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->name_id, network.name_id); + rv &= network_to_native(&native->item_type, network.item_type); + rv &= network_to_native(&native->identify, network.identify); + rv &= network_to_native(&native->epos_pc, network.epos_pc); + rv &= network_to_native(&native->epos_inv, network.epos_inv); + rv &= network_to_native(&native->broken_or_attribute, network.broken_or_attribute); + rv &= network_to_native(&native->refine, network.refine); + rv &= network_to_native(&native->card0, network.card0); + rv &= network_to_native(&native->card1, network.card1); + rv &= network_to_native(&native->card2, network.card2); + rv &= network_to_native(&native->card3, network.card3); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x00a6> *network, Packet_Head<0x00a6> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x00a6> *native, NetPacket_Head<0x00a6> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x00a6> *network, Packet_Repeat<0x00a6> native) +{ + bool rv = true; + rv &= native_to_network(&network->soff1, native.soff1); + rv &= native_to_network(&network->name_id, native.name_id); + rv &= native_to_network(&network->item_type, native.item_type); + rv &= native_to_network(&network->identify, native.identify); + rv &= native_to_network(&network->epos_id, native.epos_id); + rv &= native_to_network(&network->epos_stor, native.epos_stor); + rv &= native_to_network(&network->broken_or_attribute, native.broken_or_attribute); + rv &= native_to_network(&network->refine, native.refine); + rv &= native_to_network(&network->card0, native.card0); + rv &= native_to_network(&network->card1, native.card1); + rv &= native_to_network(&network->card2, native.card2); + rv &= native_to_network(&network->card3, native.card3); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x00a6> *native, NetPacket_Repeat<0x00a6> network) +{ + bool rv = true; + rv &= network_to_native(&native->soff1, network.soff1); + rv &= network_to_native(&native->name_id, network.name_id); + rv &= network_to_native(&native->item_type, network.item_type); + rv &= network_to_native(&native->identify, network.identify); + rv &= network_to_native(&native->epos_id, network.epos_id); + rv &= network_to_native(&native->epos_stor, network.epos_stor); + rv &= network_to_native(&native->broken_or_attribute, network.broken_or_attribute); + rv &= network_to_native(&native->refine, network.refine); + rv &= network_to_native(&native->card0, network.card0); + rv &= network_to_native(&native->card1, network.card1); + rv &= network_to_native(&native->card2, network.card2); + rv &= network_to_native(&native->card3, network.card3); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00a7> *network, Packet_Fixed<0x00a7> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->unused_id, native.unused_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00a7> *native, NetPacket_Fixed<0x00a7> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->unused_id, network.unused_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00a8> *network, Packet_Fixed<0x00a8> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->amount, native.amount); + rv &= native_to_network(&network->ok, native.ok); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00a8> *native, NetPacket_Fixed<0x00a8> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->amount, network.amount); + rv &= network_to_native(&native->ok, network.ok); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00a9> *network, Packet_Fixed<0x00a9> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->epos_ignored, native.epos_ignored); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00a9> *native, NetPacket_Fixed<0x00a9> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->epos_ignored, network.epos_ignored); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00aa> *network, Packet_Fixed<0x00aa> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->epos, native.epos); + rv &= native_to_network(&network->ok, native.ok); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00aa> *native, NetPacket_Fixed<0x00aa> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->epos, network.epos); + rv &= network_to_native(&native->ok, network.ok); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00ab> *network, Packet_Fixed<0x00ab> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00ab> *native, NetPacket_Fixed<0x00ab> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00ac> *network, Packet_Fixed<0x00ac> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->epos, native.epos); + rv &= native_to_network(&network->ok, native.ok); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00ac> *native, NetPacket_Fixed<0x00ac> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->epos, network.epos); + rv &= network_to_native(&native->ok, network.ok); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00af> *network, Packet_Fixed<0x00af> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->amount, native.amount); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00af> *native, NetPacket_Fixed<0x00af> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->amount, network.amount); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00b0> *network, Packet_Fixed<0x00b0> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->sp_type, native.sp_type); + rv &= native_to_network(&network->value, native.value); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00b0> *native, NetPacket_Fixed<0x00b0> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->sp_type, network.sp_type); + rv &= network_to_native(&native->value, network.value); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00b1> *network, Packet_Fixed<0x00b1> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->sp_type, native.sp_type); + rv &= native_to_network(&network->value, native.value); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00b1> *native, NetPacket_Fixed<0x00b1> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->sp_type, network.sp_type); + rv &= network_to_native(&native->value, network.value); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00b2> *network, Packet_Fixed<0x00b2> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00b2> *native, NetPacket_Fixed<0x00b2> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00b3> *network, Packet_Fixed<0x00b3> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->one, native.one); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00b3> *native, NetPacket_Fixed<0x00b3> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->one, network.one); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x00b4> *network, Packet_Head<0x00b4> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x00b4> *native, NetPacket_Head<0x00b4> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x00b4> *network, Packet_Repeat<0x00b4> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x00b4> *native, NetPacket_Repeat<0x00b4> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00b5> *network, Packet_Fixed<0x00b5> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00b5> *native, NetPacket_Fixed<0x00b5> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00b6> *network, Packet_Fixed<0x00b6> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00b6> *native, NetPacket_Fixed<0x00b6> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x00b7> *network, Packet_Head<0x00b7> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x00b7> *native, NetPacket_Head<0x00b7> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x00b7> *network, Packet_Repeat<0x00b7> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x00b7> *native, NetPacket_Repeat<0x00b7> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00b8> *network, Packet_Fixed<0x00b8> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->npc_id, native.npc_id); + rv &= native_to_network(&network->menu_entry, native.menu_entry); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00b8> *native, NetPacket_Fixed<0x00b8> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->npc_id, network.npc_id); + rv &= network_to_native(&native->menu_entry, network.menu_entry); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00b9> *network, Packet_Fixed<0x00b9> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->npc_id, native.npc_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00b9> *native, NetPacket_Fixed<0x00b9> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->npc_id, network.npc_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00bb> *network, Packet_Fixed<0x00bb> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->asp, native.asp); + rv &= native_to_network(&network->unused, native.unused); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00bb> *native, NetPacket_Fixed<0x00bb> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->asp, network.asp); + rv &= network_to_native(&native->unused, network.unused); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00bc> *network, Packet_Fixed<0x00bc> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->sp_type, native.sp_type); + rv &= native_to_network(&network->ok, native.ok); + rv &= native_to_network(&network->val, native.val); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00bc> *native, NetPacket_Fixed<0x00bc> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->sp_type, network.sp_type); + rv &= network_to_native(&native->ok, network.ok); + rv &= network_to_native(&native->val, network.val); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00bd> *network, Packet_Fixed<0x00bd> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->status_point, native.status_point); + rv &= native_to_network(&network->str_attr, native.str_attr); + rv &= native_to_network(&network->str_upd, native.str_upd); + rv &= native_to_network(&network->agi_attr, native.agi_attr); + rv &= native_to_network(&network->agi_upd, native.agi_upd); + rv &= native_to_network(&network->vit_attr, native.vit_attr); + rv &= native_to_network(&network->vit_upd, native.vit_upd); + rv &= native_to_network(&network->int_attr, native.int_attr); + rv &= native_to_network(&network->int_upd, native.int_upd); + rv &= native_to_network(&network->dex_attr, native.dex_attr); + rv &= native_to_network(&network->dex_upd, native.dex_upd); + rv &= native_to_network(&network->luk_attr, native.luk_attr); + rv &= native_to_network(&network->luk_upd, native.luk_upd); + rv &= native_to_network(&network->atk_sum, native.atk_sum); + rv &= native_to_network(&network->watk2, native.watk2); + rv &= native_to_network(&network->matk1, native.matk1); + rv &= native_to_network(&network->matk2, native.matk2); + rv &= native_to_network(&network->def, native.def); + rv &= native_to_network(&network->def2, native.def2); + rv &= native_to_network(&network->mdef, native.mdef); + rv &= native_to_network(&network->mdef2, native.mdef2); + rv &= native_to_network(&network->hit, native.hit); + rv &= native_to_network(&network->flee, native.flee); + rv &= native_to_network(&network->flee2, native.flee2); + rv &= native_to_network(&network->critical, native.critical); + rv &= native_to_network(&network->karma, native.karma); + rv &= native_to_network(&network->manner, native.manner); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00bd> *native, NetPacket_Fixed<0x00bd> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->status_point, network.status_point); + rv &= network_to_native(&native->str_attr, network.str_attr); + rv &= network_to_native(&native->str_upd, network.str_upd); + rv &= network_to_native(&native->agi_attr, network.agi_attr); + rv &= network_to_native(&native->agi_upd, network.agi_upd); + rv &= network_to_native(&native->vit_attr, network.vit_attr); + rv &= network_to_native(&native->vit_upd, network.vit_upd); + rv &= network_to_native(&native->int_attr, network.int_attr); + rv &= network_to_native(&native->int_upd, network.int_upd); + rv &= network_to_native(&native->dex_attr, network.dex_attr); + rv &= network_to_native(&native->dex_upd, network.dex_upd); + rv &= network_to_native(&native->luk_attr, network.luk_attr); + rv &= network_to_native(&native->luk_upd, network.luk_upd); + rv &= network_to_native(&native->atk_sum, network.atk_sum); + rv &= network_to_native(&native->watk2, network.watk2); + rv &= network_to_native(&native->matk1, network.matk1); + rv &= network_to_native(&native->matk2, network.matk2); + rv &= network_to_native(&native->def, network.def); + rv &= network_to_native(&native->def2, network.def2); + rv &= network_to_native(&native->mdef, network.mdef); + rv &= network_to_native(&native->mdef2, network.mdef2); + rv &= network_to_native(&native->hit, network.hit); + rv &= network_to_native(&native->flee, network.flee); + rv &= network_to_native(&native->flee2, network.flee2); + rv &= network_to_native(&native->critical, network.critical); + rv &= network_to_native(&native->karma, network.karma); + rv &= network_to_native(&native->manner, network.manner); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00be> *network, Packet_Fixed<0x00be> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->sp_type, native.sp_type); + rv &= native_to_network(&network->value, native.value); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00be> *native, NetPacket_Fixed<0x00be> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->sp_type, network.sp_type); + rv &= network_to_native(&native->value, network.value); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00bf> *network, Packet_Fixed<0x00bf> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->emote, native.emote); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00bf> *native, NetPacket_Fixed<0x00bf> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->emote, network.emote); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00c0> *network, Packet_Fixed<0x00c0> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->type, native.type); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00c0> *native, NetPacket_Fixed<0x00c0> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->type, network.type); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00c1> *network, Packet_Fixed<0x00c1> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00c1> *native, NetPacket_Fixed<0x00c1> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00c2> *network, Packet_Fixed<0x00c2> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->users, native.users); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00c2> *native, NetPacket_Fixed<0x00c2> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->users, network.users); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00c4> *network, Packet_Fixed<0x00c4> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00c4> *native, NetPacket_Fixed<0x00c4> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00c5> *network, Packet_Fixed<0x00c5> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->type, native.type); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00c5> *native, NetPacket_Fixed<0x00c5> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->type, network.type); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x00c6> *network, Packet_Head<0x00c6> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x00c6> *native, NetPacket_Head<0x00c6> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x00c6> *network, Packet_Repeat<0x00c6> native) +{ + bool rv = true; + rv &= native_to_network(&network->base_price, native.base_price); + rv &= native_to_network(&network->actual_price, native.actual_price); + rv &= native_to_network(&network->type, native.type); + rv &= native_to_network(&network->name_id, native.name_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x00c6> *native, NetPacket_Repeat<0x00c6> network) +{ + bool rv = true; + rv &= network_to_native(&native->base_price, network.base_price); + rv &= network_to_native(&native->actual_price, network.actual_price); + rv &= network_to_native(&native->type, network.type); + rv &= network_to_native(&native->name_id, network.name_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x00c7> *network, Packet_Head<0x00c7> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x00c7> *native, NetPacket_Head<0x00c7> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x00c7> *network, Packet_Repeat<0x00c7> native) +{ + bool rv = true; + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->base_price, native.base_price); + rv &= native_to_network(&network->actual_price, native.actual_price); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x00c7> *native, NetPacket_Repeat<0x00c7> network) +{ + bool rv = true; + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->base_price, network.base_price); + rv &= network_to_native(&native->actual_price, network.actual_price); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x00c8> *network, Packet_Head<0x00c8> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x00c8> *native, NetPacket_Head<0x00c8> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x00c8> *network, Packet_Repeat<0x00c8> native) +{ + bool rv = true; + rv &= native_to_network(&network->count, native.count); + rv &= native_to_network(&network->name_id, native.name_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x00c8> *native, NetPacket_Repeat<0x00c8> network) +{ + bool rv = true; + rv &= network_to_native(&native->count, network.count); + rv &= network_to_native(&native->name_id, network.name_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x00c9> *network, Packet_Head<0x00c9> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x00c9> *native, NetPacket_Head<0x00c9> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x00c9> *network, Packet_Repeat<0x00c9> native) +{ + bool rv = true; + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->count, native.count); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x00c9> *native, NetPacket_Repeat<0x00c9> network) +{ + bool rv = true; + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->count, network.count); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00ca> *network, Packet_Fixed<0x00ca> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->fail, native.fail); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00ca> *native, NetPacket_Fixed<0x00ca> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->fail, network.fail); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00cb> *network, Packet_Fixed<0x00cb> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->fail, native.fail); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00cb> *native, NetPacket_Fixed<0x00cb> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->fail, network.fail); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00cd> *network, Packet_Fixed<0x00cd> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00cd> *native, NetPacket_Fixed<0x00cd> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00e4> *network, Packet_Fixed<0x00e4> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00e4> *native, NetPacket_Fixed<0x00e4> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00e5> *network, Packet_Fixed<0x00e5> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->char_name, native.char_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00e5> *native, NetPacket_Fixed<0x00e5> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->char_name, network.char_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00e6> *network, Packet_Fixed<0x00e6> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->type, native.type); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00e6> *native, NetPacket_Fixed<0x00e6> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->type, network.type); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00e7> *network, Packet_Fixed<0x00e7> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->type, native.type); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00e7> *native, NetPacket_Fixed<0x00e7> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->type, network.type); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00e8> *network, Packet_Fixed<0x00e8> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->zeny_or_ioff2, native.zeny_or_ioff2); + rv &= native_to_network(&network->amount, native.amount); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00e8> *native, NetPacket_Fixed<0x00e8> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->zeny_or_ioff2, network.zeny_or_ioff2); + rv &= network_to_native(&native->amount, network.amount); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00e9> *network, Packet_Fixed<0x00e9> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->amount, native.amount); + rv &= native_to_network(&network->name_id, native.name_id); + rv &= native_to_network(&network->identify, native.identify); + rv &= native_to_network(&network->broken_or_attribute, native.broken_or_attribute); + rv &= native_to_network(&network->refine, native.refine); + rv &= native_to_network(&network->card0, native.card0); + rv &= native_to_network(&network->card1, native.card1); + rv &= native_to_network(&network->card2, native.card2); + rv &= native_to_network(&network->card3, native.card3); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00e9> *native, NetPacket_Fixed<0x00e9> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->amount, network.amount); + rv &= network_to_native(&native->name_id, network.name_id); + rv &= network_to_native(&native->identify, network.identify); + rv &= network_to_native(&native->broken_or_attribute, network.broken_or_attribute); + rv &= network_to_native(&native->refine, network.refine); + rv &= network_to_native(&native->card0, network.card0); + rv &= network_to_native(&native->card1, network.card1); + rv &= network_to_native(&native->card2, network.card2); + rv &= network_to_native(&native->card3, network.card3); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00eb> *network, Packet_Fixed<0x00eb> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00eb> *native, NetPacket_Fixed<0x00eb> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00ec> *network, Packet_Fixed<0x00ec> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->fail, native.fail); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00ec> *native, NetPacket_Fixed<0x00ec> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->fail, network.fail); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00ed> *network, Packet_Fixed<0x00ed> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00ed> *native, NetPacket_Fixed<0x00ed> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00ee> *network, Packet_Fixed<0x00ee> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00ee> *native, NetPacket_Fixed<0x00ee> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00ef> *network, Packet_Fixed<0x00ef> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00ef> *native, NetPacket_Fixed<0x00ef> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00f0> *network, Packet_Fixed<0x00f0> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->fail, native.fail); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00f0> *native, NetPacket_Fixed<0x00f0> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->fail, network.fail); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00f2> *network, Packet_Fixed<0x00f2> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->current_slots, native.current_slots); + rv &= native_to_network(&network->max_slots, native.max_slots); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00f2> *native, NetPacket_Fixed<0x00f2> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->current_slots, network.current_slots); + rv &= network_to_native(&native->max_slots, network.max_slots); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00f3> *network, Packet_Fixed<0x00f3> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->amount, native.amount); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00f3> *native, NetPacket_Fixed<0x00f3> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->amount, network.amount); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00f4> *network, Packet_Fixed<0x00f4> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->soff1, native.soff1); + rv &= native_to_network(&network->amount, native.amount); + rv &= native_to_network(&network->name_id, native.name_id); + rv &= native_to_network(&network->identify, native.identify); + rv &= native_to_network(&network->broken_or_attribute, native.broken_or_attribute); + rv &= native_to_network(&network->refine, native.refine); + rv &= native_to_network(&network->card0, native.card0); + rv &= native_to_network(&network->card1, native.card1); + rv &= native_to_network(&network->card2, native.card2); + rv &= native_to_network(&network->card3, native.card3); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00f4> *native, NetPacket_Fixed<0x00f4> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->soff1, network.soff1); + rv &= network_to_native(&native->amount, network.amount); + rv &= network_to_native(&native->name_id, network.name_id); + rv &= network_to_native(&native->identify, network.identify); + rv &= network_to_native(&native->broken_or_attribute, network.broken_or_attribute); + rv &= network_to_native(&native->refine, network.refine); + rv &= network_to_native(&native->card0, network.card0); + rv &= network_to_native(&native->card1, network.card1); + rv &= network_to_native(&native->card2, network.card2); + rv &= network_to_native(&native->card3, network.card3); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00f5> *network, Packet_Fixed<0x00f5> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->soff1, native.soff1); + rv &= native_to_network(&network->amount, native.amount); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00f5> *native, NetPacket_Fixed<0x00f5> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->soff1, network.soff1); + rv &= network_to_native(&native->amount, network.amount); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00f6> *network, Packet_Fixed<0x00f6> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->soff1, native.soff1); + rv &= native_to_network(&network->amount, native.amount); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00f6> *native, NetPacket_Fixed<0x00f6> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->soff1, network.soff1); + rv &= network_to_native(&native->amount, network.amount); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00f7> *network, Packet_Fixed<0x00f7> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00f7> *native, NetPacket_Fixed<0x00f7> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00f8> *network, Packet_Fixed<0x00f8> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00f8> *native, NetPacket_Fixed<0x00f8> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00f9> *network, Packet_Fixed<0x00f9> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->party_name, native.party_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00f9> *native, NetPacket_Fixed<0x00f9> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->party_name, network.party_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00fa> *network, Packet_Fixed<0x00fa> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00fa> *native, NetPacket_Fixed<0x00fa> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x00fb> *network, Packet_Head<0x00fb> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->party_name, native.party_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x00fb> *native, NetPacket_Head<0x00fb> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->party_name, network.party_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x00fb> *network, Packet_Repeat<0x00fb> native) +{ + bool rv = true; + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->char_name, native.char_name); + rv &= native_to_network(&network->map_name, native.map_name); + rv &= native_to_network(&network->leader, native.leader); + rv &= native_to_network(&network->online, native.online); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x00fb> *native, NetPacket_Repeat<0x00fb> network) +{ + bool rv = true; + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->char_name, network.char_name); + rv &= network_to_native(&native->map_name, network.map_name); + rv &= network_to_native(&native->leader, network.leader); + rv &= network_to_native(&native->online, network.online); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00fc> *network, Packet_Fixed<0x00fc> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00fc> *native, NetPacket_Fixed<0x00fc> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00fd> *network, Packet_Fixed<0x00fd> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->char_name, native.char_name); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00fd> *native, NetPacket_Fixed<0x00fd> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->char_name, network.char_name); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00fe> *network, Packet_Fixed<0x00fe> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->party_name, native.party_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00fe> *native, NetPacket_Fixed<0x00fe> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->party_name, network.party_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x00ff> *network, Packet_Fixed<0x00ff> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x00ff> *native, NetPacket_Fixed<0x00ff> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0100> *network, Packet_Fixed<0x0100> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0100> *native, NetPacket_Fixed<0x0100> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0101> *network, Packet_Fixed<0x0101> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->exp, native.exp); + rv &= native_to_network(&network->item, native.item); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0101> *native, NetPacket_Fixed<0x0101> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->exp, network.exp); + rv &= network_to_native(&native->item, network.item); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0102> *network, Packet_Fixed<0x0102> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->exp, native.exp); + rv &= native_to_network(&network->item, native.item); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0102> *native, NetPacket_Fixed<0x0102> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->exp, network.exp); + rv &= network_to_native(&native->item, network.item); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0103> *network, Packet_Fixed<0x0103> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->unused_char_name, native.unused_char_name); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0103> *native, NetPacket_Fixed<0x0103> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->unused_char_name, network.unused_char_name); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0105> *network, Packet_Fixed<0x0105> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->char_name, native.char_name); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0105> *native, NetPacket_Fixed<0x0105> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->char_name, network.char_name); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0106> *network, Packet_Fixed<0x0106> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->hp, native.hp); + rv &= native_to_network(&network->max_hp, native.max_hp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0106> *native, NetPacket_Fixed<0x0106> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->hp, network.hp); + rv &= network_to_native(&native->max_hp, network.max_hp); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0107> *network, Packet_Fixed<0x0107> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->x, native.x); + rv &= native_to_network(&network->y, native.y); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0107> *native, NetPacket_Fixed<0x0107> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->x, network.x); + rv &= network_to_native(&native->y, network.y); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x0108> *network, Packet_Head<0x0108> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x0108> *native, NetPacket_Head<0x0108> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x0108> *network, Packet_Repeat<0x0108> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x0108> *native, NetPacket_Repeat<0x0108> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x0109> *network, Packet_Head<0x0109> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->account_id, native.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x0109> *native, NetPacket_Head<0x0109> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->account_id, network.account_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x0109> *network, Packet_Repeat<0x0109> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x0109> *native, NetPacket_Repeat<0x0109> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x010c> *network, Packet_Fixed<0x010c> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x010c> *native, NetPacket_Fixed<0x010c> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x010e> *network, Packet_Fixed<0x010e> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->skill_id, native.skill_id); + rv &= native_to_network(&network->level, native.level); + rv &= native_to_network(&network->sp, native.sp); + rv &= native_to_network(&network->range, native.range); + rv &= native_to_network(&network->can_raise, native.can_raise); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x010e> *native, NetPacket_Fixed<0x010e> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->skill_id, network.skill_id); + rv &= network_to_native(&native->level, network.level); + rv &= network_to_native(&native->sp, network.sp); + rv &= network_to_native(&native->range, network.range); + rv &= network_to_native(&native->can_raise, network.can_raise); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x010f> *network, Packet_Head<0x010f> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x010f> *native, NetPacket_Head<0x010f> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x010f> *network, Packet_Repeat<0x010f> native) +{ + bool rv = true; + rv &= native_to_network(&network->info, native.info); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x010f> *native, NetPacket_Repeat<0x010f> network) +{ + bool rv = true; + rv &= network_to_native(&native->info, network.info); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0110> *network, Packet_Fixed<0x0110> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->skill_id, native.skill_id); + rv &= native_to_network(&network->btype, native.btype); + rv &= native_to_network(&network->zero1, native.zero1); + rv &= native_to_network(&network->zero2, native.zero2); + rv &= native_to_network(&network->type, native.type); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0110> *native, NetPacket_Fixed<0x0110> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->skill_id, network.skill_id); + rv &= network_to_native(&native->btype, network.btype); + rv &= network_to_native(&native->zero1, network.zero1); + rv &= network_to_native(&native->zero2, network.zero2); + rv &= network_to_native(&native->type, network.type); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0112> *network, Packet_Fixed<0x0112> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->skill_id, native.skill_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0112> *native, NetPacket_Fixed<0x0112> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->skill_id, network.skill_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0118> *network, Packet_Fixed<0x0118> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0118> *native, NetPacket_Fixed<0x0118> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0119> *network, Packet_Fixed<0x0119> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->opt1, native.opt1); + rv &= native_to_network(&network->opt2, native.opt2); + rv &= native_to_network(&network->option, native.option); + rv &= native_to_network(&network->zero, native.zero); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0119> *native, NetPacket_Fixed<0x0119> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->opt1, network.opt1); + rv &= network_to_native(&native->opt2, network.opt2); + rv &= network_to_native(&native->option, network.option); + rv &= network_to_native(&native->zero, network.zero); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0139> *network, Packet_Fixed<0x0139> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->bl_x, native.bl_x); + rv &= native_to_network(&network->bl_y, native.bl_y); + rv &= native_to_network(&network->sd_x, native.sd_x); + rv &= native_to_network(&network->sd_y, native.sd_y); + rv &= native_to_network(&network->range, native.range); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0139> *native, NetPacket_Fixed<0x0139> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->bl_x, network.bl_x); + rv &= network_to_native(&native->bl_y, network.bl_y); + rv &= network_to_native(&native->sd_x, network.sd_x); + rv &= network_to_native(&native->sd_y, network.sd_y); + rv &= network_to_native(&native->range, network.range); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x013a> *network, Packet_Fixed<0x013a> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->attack_range, native.attack_range); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x013a> *native, NetPacket_Fixed<0x013a> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->attack_range, network.attack_range); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x013b> *network, Packet_Fixed<0x013b> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->type, native.type); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x013b> *native, NetPacket_Fixed<0x013b> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->type, network.type); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x013c> *network, Packet_Fixed<0x013c> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x013c> *native, NetPacket_Fixed<0x013c> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0141> *network, Packet_Fixed<0x0141> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->sp_type, native.sp_type); + rv &= native_to_network(&network->zero, native.zero); + rv &= native_to_network(&network->value_status, native.value_status); + rv &= native_to_network(&network->value_b_e, native.value_b_e); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0141> *native, NetPacket_Fixed<0x0141> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->sp_type, network.sp_type); + rv &= network_to_native(&native->zero, network.zero); + rv &= network_to_native(&native->value_status, network.value_status); + rv &= network_to_native(&native->value_b_e, network.value_b_e); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0142> *network, Packet_Fixed<0x0142> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0142> *native, NetPacket_Fixed<0x0142> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0143> *network, Packet_Fixed<0x0143> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->input_int_value, native.input_int_value); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0143> *native, NetPacket_Fixed<0x0143> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->input_int_value, network.input_int_value); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0146> *network, Packet_Fixed<0x0146> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0146> *native, NetPacket_Fixed<0x0146> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0147> *network, Packet_Fixed<0x0147> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->info, native.info); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0147> *native, NetPacket_Fixed<0x0147> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->info, network.info); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0148> *network, Packet_Fixed<0x0148> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->type, native.type); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0148> *native, NetPacket_Fixed<0x0148> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->type, network.type); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x014d> *network, Packet_Fixed<0x014d> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x014d> *native, NetPacket_Fixed<0x014d> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x018a> *network, Packet_Fixed<0x018a> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->unused, native.unused); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x018a> *native, NetPacket_Fixed<0x018a> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->unused, network.unused); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x018b> *network, Packet_Fixed<0x018b> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->okay, native.okay); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x018b> *native, NetPacket_Fixed<0x018b> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->okay, network.okay); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0195> *network, Packet_Fixed<0x0195> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->party_name, native.party_name); + rv &= native_to_network(&network->guild_name, native.guild_name); + rv &= native_to_network(&network->guild_pos, native.guild_pos); + rv &= native_to_network(&network->guild_pos_again, native.guild_pos_again); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0195> *native, NetPacket_Fixed<0x0195> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->party_name, network.party_name); + rv &= network_to_native(&native->guild_name, network.guild_name); + rv &= network_to_native(&native->guild_pos, network.guild_pos); + rv &= network_to_native(&native->guild_pos_again, network.guild_pos_again); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0196> *network, Packet_Fixed<0x0196> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->sc_type, native.sc_type); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->flag, native.flag); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0196> *native, NetPacket_Fixed<0x0196> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->sc_type, network.sc_type); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->flag, network.flag); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x019b> *network, Packet_Fixed<0x019b> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->type, native.type); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x019b> *native, NetPacket_Fixed<0x019b> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->type, network.type); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x01b1> *network, Packet_Fixed<0x01b1> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->amount, native.amount); + rv &= native_to_network(&network->fail, native.fail); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x01b1> *native, NetPacket_Fixed<0x01b1> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->amount, network.amount); + rv &= network_to_native(&native->fail, network.fail); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x01c8> *network, Packet_Fixed<0x01c8> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->name_id, native.name_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->amount, native.amount); + rv &= native_to_network(&network->ok, native.ok); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x01c8> *native, NetPacket_Fixed<0x01c8> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->name_id, network.name_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->amount, network.amount); + rv &= network_to_native(&native->ok, network.ok); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x01d4> *network, Packet_Fixed<0x01d4> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x01d4> *native, NetPacket_Fixed<0x01d4> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x01d5> *network, Packet_Head<0x01d5> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + rv &= native_to_network(&network->block_id, native.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x01d5> *native, NetPacket_Head<0x01d5> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + rv &= network_to_native(&native->block_id, network.block_id); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x01d5> *network, Packet_Repeat<0x01d5> native) +{ + bool rv = true; + rv &= native_to_network(&network->c, native.c); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x01d5> *native, NetPacket_Repeat<0x01d5> network) +{ + bool rv = true; + rv &= network_to_native(&native->c, network.c); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x01d7> *network, Packet_Fixed<0x01d7> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->look_type, native.look_type); + rv &= native_to_network(&network->weapon_or_name_id_or_value, native.weapon_or_name_id_or_value); + rv &= native_to_network(&network->shield, native.shield); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x01d7> *native, NetPacket_Fixed<0x01d7> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->look_type, network.look_type); + rv &= network_to_native(&native->weapon_or_name_id_or_value, network.weapon_or_name_id_or_value); + rv &= network_to_native(&native->shield, network.shield); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x01d8> *network, Packet_Fixed<0x01d8> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->speed, native.speed); + rv &= native_to_network(&network->opt1, native.opt1); + rv &= native_to_network(&network->opt2, native.opt2); + rv &= native_to_network(&network->option, native.option); + rv &= native_to_network(&network->species, native.species); + rv &= native_to_network(&network->hair_style, native.hair_style); + rv &= native_to_network(&network->weapon, native.weapon); + rv &= native_to_network(&network->shield, native.shield); + rv &= native_to_network(&network->head_bottom, native.head_bottom); + rv &= native_to_network(&network->head_top, native.head_top); + rv &= native_to_network(&network->head_mid, native.head_mid); + rv &= native_to_network(&network->hair_color, native.hair_color); + rv &= native_to_network(&network->clothes_color, native.clothes_color); + rv &= native_to_network(&network->head_dir, native.head_dir); + rv &= native_to_network(&network->unused2, native.unused2); + rv &= native_to_network(&network->guild_id, native.guild_id); + rv &= native_to_network(&network->guild_emblem_id, native.guild_emblem_id); + rv &= native_to_network(&network->manner, native.manner); + rv &= native_to_network(&network->opt3, native.opt3); + rv &= native_to_network(&network->karma, native.karma); + rv &= native_to_network(&network->sex, native.sex); + rv &= native_to_network(&network->pos, native.pos); + rv &= native_to_network(&network->gm_bits, native.gm_bits); + rv &= native_to_network(&network->dead_sit, native.dead_sit); + rv &= native_to_network(&network->unused, native.unused); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x01d8> *native, NetPacket_Fixed<0x01d8> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->speed, network.speed); + rv &= network_to_native(&native->opt1, network.opt1); + rv &= network_to_native(&native->opt2, network.opt2); + rv &= network_to_native(&native->option, network.option); + rv &= network_to_native(&native->species, network.species); + rv &= network_to_native(&native->hair_style, network.hair_style); + rv &= network_to_native(&native->weapon, network.weapon); + rv &= network_to_native(&native->shield, network.shield); + rv &= network_to_native(&native->head_bottom, network.head_bottom); + rv &= network_to_native(&native->head_top, network.head_top); + rv &= network_to_native(&native->head_mid, network.head_mid); + rv &= network_to_native(&native->hair_color, network.hair_color); + rv &= network_to_native(&native->clothes_color, network.clothes_color); + rv &= network_to_native(&native->head_dir, network.head_dir); + rv &= network_to_native(&native->unused2, network.unused2); + rv &= network_to_native(&native->guild_id, network.guild_id); + rv &= network_to_native(&native->guild_emblem_id, network.guild_emblem_id); + rv &= network_to_native(&native->manner, network.manner); + rv &= network_to_native(&native->opt3, network.opt3); + rv &= network_to_native(&native->karma, network.karma); + rv &= network_to_native(&native->sex, network.sex); + rv &= network_to_native(&native->pos, network.pos); + rv &= network_to_native(&native->gm_bits, network.gm_bits); + rv &= network_to_native(&native->dead_sit, network.dead_sit); + rv &= network_to_native(&native->unused, network.unused); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x01d9> *network, Packet_Fixed<0x01d9> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->speed, native.speed); + rv &= native_to_network(&network->opt1, native.opt1); + rv &= native_to_network(&network->opt2, native.opt2); + rv &= native_to_network(&network->option, native.option); + rv &= native_to_network(&network->species, native.species); + rv &= native_to_network(&network->hair_style, native.hair_style); + rv &= native_to_network(&network->weapon, native.weapon); + rv &= native_to_network(&network->shield, native.shield); + rv &= native_to_network(&network->head_bottom, native.head_bottom); + rv &= native_to_network(&network->head_top, native.head_top); + rv &= native_to_network(&network->head_mid, native.head_mid); + rv &= native_to_network(&network->hair_color, native.hair_color); + rv &= native_to_network(&network->clothes_color, native.clothes_color); + rv &= native_to_network(&network->head_dir, native.head_dir); + rv &= native_to_network(&network->unused2, native.unused2); + rv &= native_to_network(&network->guild_id, native.guild_id); + rv &= native_to_network(&network->guild_emblem_id, native.guild_emblem_id); + rv &= native_to_network(&network->manner, native.manner); + rv &= native_to_network(&network->opt3, native.opt3); + rv &= native_to_network(&network->karma, native.karma); + rv &= native_to_network(&network->sex, native.sex); + rv &= native_to_network(&network->pos, native.pos); + rv &= native_to_network(&network->gm_bits, native.gm_bits); + rv &= native_to_network(&network->unused, native.unused); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x01d9> *native, NetPacket_Fixed<0x01d9> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->speed, network.speed); + rv &= network_to_native(&native->opt1, network.opt1); + rv &= network_to_native(&native->opt2, network.opt2); + rv &= network_to_native(&native->option, network.option); + rv &= network_to_native(&native->species, network.species); + rv &= network_to_native(&native->hair_style, network.hair_style); + rv &= network_to_native(&native->weapon, network.weapon); + rv &= network_to_native(&native->shield, network.shield); + rv &= network_to_native(&native->head_bottom, network.head_bottom); + rv &= network_to_native(&native->head_top, network.head_top); + rv &= network_to_native(&native->head_mid, network.head_mid); + rv &= network_to_native(&native->hair_color, network.hair_color); + rv &= network_to_native(&native->clothes_color, network.clothes_color); + rv &= network_to_native(&native->head_dir, network.head_dir); + rv &= network_to_native(&native->unused2, network.unused2); + rv &= network_to_native(&native->guild_id, network.guild_id); + rv &= network_to_native(&native->guild_emblem_id, network.guild_emblem_id); + rv &= network_to_native(&native->manner, network.manner); + rv &= network_to_native(&native->opt3, network.opt3); + rv &= network_to_native(&native->karma, network.karma); + rv &= network_to_native(&native->sex, network.sex); + rv &= network_to_native(&native->pos, network.pos); + rv &= network_to_native(&native->gm_bits, network.gm_bits); + rv &= network_to_native(&native->unused, network.unused); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x01da> *network, Packet_Fixed<0x01da> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->speed, native.speed); + rv &= native_to_network(&network->opt1, native.opt1); + rv &= native_to_network(&network->opt2, native.opt2); + rv &= native_to_network(&network->option, native.option); + rv &= native_to_network(&network->species, native.species); + rv &= native_to_network(&network->hair_style, native.hair_style); + rv &= native_to_network(&network->weapon, native.weapon); + rv &= native_to_network(&network->shield, native.shield); + rv &= native_to_network(&network->head_bottom, native.head_bottom); + rv &= native_to_network(&network->tick, native.tick); + rv &= native_to_network(&network->head_top, native.head_top); + rv &= native_to_network(&network->head_mid, native.head_mid); + rv &= native_to_network(&network->hair_color, native.hair_color); + rv &= native_to_network(&network->clothes_color, native.clothes_color); + rv &= native_to_network(&network->head_dir, native.head_dir); + rv &= native_to_network(&network->unused2, native.unused2); + rv &= native_to_network(&network->guild_id, native.guild_id); + rv &= native_to_network(&network->guild_emblem_id, native.guild_emblem_id); + rv &= native_to_network(&network->manner, native.manner); + rv &= native_to_network(&network->opt3, native.opt3); + rv &= native_to_network(&network->karma, native.karma); + rv &= native_to_network(&network->sex, native.sex); + rv &= native_to_network(&network->pos2, native.pos2); + rv &= native_to_network(&network->gm_bits, native.gm_bits); + rv &= native_to_network(&network->five, native.five); + rv &= native_to_network(&network->unused, native.unused); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x01da> *native, NetPacket_Fixed<0x01da> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->speed, network.speed); + rv &= network_to_native(&native->opt1, network.opt1); + rv &= network_to_native(&native->opt2, network.opt2); + rv &= network_to_native(&native->option, network.option); + rv &= network_to_native(&native->species, network.species); + rv &= network_to_native(&native->hair_style, network.hair_style); + rv &= network_to_native(&native->weapon, network.weapon); + rv &= network_to_native(&native->shield, network.shield); + rv &= network_to_native(&native->head_bottom, network.head_bottom); + rv &= network_to_native(&native->tick, network.tick); + rv &= network_to_native(&native->head_top, network.head_top); + rv &= network_to_native(&native->head_mid, network.head_mid); + rv &= network_to_native(&native->hair_color, network.hair_color); + rv &= network_to_native(&native->clothes_color, network.clothes_color); + rv &= network_to_native(&native->head_dir, network.head_dir); + rv &= network_to_native(&native->unused2, network.unused2); + rv &= network_to_native(&native->guild_id, network.guild_id); + rv &= network_to_native(&native->guild_emblem_id, network.guild_emblem_id); + rv &= network_to_native(&native->manner, network.manner); + rv &= network_to_native(&native->opt3, network.opt3); + rv &= network_to_native(&native->karma, network.karma); + rv &= network_to_native(&native->sex, network.sex); + rv &= network_to_native(&native->pos2, network.pos2); + rv &= network_to_native(&native->gm_bits, network.gm_bits); + rv &= network_to_native(&native->five, network.five); + rv &= network_to_native(&native->unused, network.unused); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x01de> *network, Packet_Fixed<0x01de> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->skill_id, native.skill_id); + rv &= native_to_network(&network->src_id, native.src_id); + rv &= native_to_network(&network->dst_id, native.dst_id); + rv &= native_to_network(&network->tick, native.tick); + rv &= native_to_network(&network->sdelay, native.sdelay); + rv &= native_to_network(&network->ddelay, native.ddelay); + rv &= native_to_network(&network->damage, native.damage); + rv &= native_to_network(&network->skill_level, native.skill_level); + rv &= native_to_network(&network->div, native.div); + rv &= native_to_network(&network->type_or_hit, native.type_or_hit); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x01de> *native, NetPacket_Fixed<0x01de> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->skill_id, network.skill_id); + rv &= network_to_native(&native->src_id, network.src_id); + rv &= network_to_native(&native->dst_id, network.dst_id); + rv &= network_to_native(&native->tick, network.tick); + rv &= network_to_native(&native->sdelay, network.sdelay); + rv &= network_to_native(&native->ddelay, network.ddelay); + rv &= network_to_native(&native->damage, network.damage); + rv &= network_to_native(&native->skill_level, network.skill_level); + rv &= network_to_native(&native->div, network.div); + rv &= network_to_native(&native->type_or_hit, network.type_or_hit); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x01ee> *network, Packet_Head<0x01ee> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x01ee> *native, NetPacket_Head<0x01ee> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x01ee> *network, Packet_Repeat<0x01ee> native) +{ + bool rv = true; + rv &= native_to_network(&network->ioff2, native.ioff2); + rv &= native_to_network(&network->name_id, native.name_id); + rv &= native_to_network(&network->item_type, native.item_type); + rv &= native_to_network(&network->identify, native.identify); + rv &= native_to_network(&network->amount, native.amount); + rv &= native_to_network(&network->epos, native.epos); + rv &= native_to_network(&network->card0, native.card0); + rv &= native_to_network(&network->card1, native.card1); + rv &= native_to_network(&network->card2, native.card2); + rv &= native_to_network(&network->card3, native.card3); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x01ee> *native, NetPacket_Repeat<0x01ee> network) +{ + bool rv = true; + rv &= network_to_native(&native->ioff2, network.ioff2); + rv &= network_to_native(&native->name_id, network.name_id); + rv &= network_to_native(&native->item_type, network.item_type); + rv &= network_to_native(&native->identify, network.identify); + rv &= network_to_native(&native->amount, network.amount); + rv &= network_to_native(&native->epos, network.epos); + rv &= network_to_native(&native->card0, network.card0); + rv &= network_to_native(&native->card1, network.card1); + rv &= network_to_native(&native->card2, network.card2); + rv &= network_to_native(&native->card3, network.card3); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Head<0x01f0> *network, Packet_Head<0x01f0> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->magic_packet_length, native.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Head<0x01f0> *native, NetPacket_Head<0x01f0> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->magic_packet_length, network.magic_packet_length); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Repeat<0x01f0> *network, Packet_Repeat<0x01f0> native) +{ + bool rv = true; + rv &= native_to_network(&network->soff1, native.soff1); + rv &= native_to_network(&network->name_id, native.name_id); + rv &= native_to_network(&network->item_type, native.item_type); + rv &= native_to_network(&network->identify, native.identify); + rv &= native_to_network(&network->amount, native.amount); + rv &= native_to_network(&network->epos_zero, native.epos_zero); + rv &= native_to_network(&network->card0, native.card0); + rv &= native_to_network(&network->card1, native.card1); + rv &= native_to_network(&network->card2, native.card2); + rv &= native_to_network(&network->card3, native.card3); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Repeat<0x01f0> *native, NetPacket_Repeat<0x01f0> network) +{ + bool rv = true; + rv &= network_to_native(&native->soff1, network.soff1); + rv &= network_to_native(&native->name_id, network.name_id); + rv &= network_to_native(&native->item_type, network.item_type); + rv &= network_to_native(&native->identify, network.identify); + rv &= network_to_native(&native->amount, network.amount); + rv &= network_to_native(&native->epos_zero, network.epos_zero); + rv &= network_to_native(&native->card0, network.card0); + rv &= network_to_native(&native->card1, network.card1); + rv &= network_to_native(&native->card2, network.card2); + rv &= network_to_native(&native->card3, network.card3); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x020c> *network, Packet_Fixed<0x020c> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->block_id, native.block_id); + rv &= native_to_network(&network->ip, native.ip); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x020c> *native, NetPacket_Fixed<0x020c> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->block_id, network.block_id); + rv &= network_to_native(&native->ip, network.ip); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPacket_Fixed<0x0212> *network, Packet_Fixed<0x0212> native) +{ + bool rv = true; + rv &= native_to_network(&network->magic_packet_id, native.magic_packet_id); + rv &= native_to_network(&network->npc_id, native.npc_id); + rv &= native_to_network(&network->command, native.command); + rv &= native_to_network(&network->id, native.id); + rv &= native_to_network(&network->x, native.x); + rv &= native_to_network(&network->y, native.y); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Packet_Fixed<0x0212> *native, NetPacket_Fixed<0x0212> network) +{ + bool rv = true; + rv &= network_to_native(&native->magic_packet_id, network.magic_packet_id); + rv &= network_to_native(&native->npc_id, network.npc_id); + rv &= network_to_native(&native->command, network.command); + rv &= network_to_native(&native->id, network.id); + rv &= network_to_native(&native->x, network.x); + rv &= network_to_native(&native->y, network.y); + return rv; +} + +} // namespace tmwa diff --git a/src/proto2/map-user_test.cpp b/src/proto2/map-user_test.cpp new file mode 100644 index 0000000..75d39d5 --- /dev/null +++ b/src/proto2/map-user_test.cpp @@ -0,0 +1,27 @@ +#include "map-user.hpp" +// map-user_test.cpp - TMWA network protocol: map/user +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +// This is a generated file, edit tools/protocol.py instead + +#include "../poison.hpp" + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/proto2/types.hpp b/src/proto2/types.hpp new file mode 100644 index 0000000..516889a --- /dev/null +++ b/src/proto2/types.hpp @@ -0,0 +1,1421 @@ +#pragma once +// proto2/types.hpp - Forward declarations of packet component types +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include "../generic/array.hpp" +#include "../mmo/consts.hpp" + +//TODO split the includes +#include <cstdint> +#include "../ints/little.hpp" +#include "../strings/vstring.hpp" +#include "../net/ip.hpp" +#include "../net/timer.t.hpp" +#include "../mmo/consts.hpp" +#include "../mmo/enums.hpp" +#include "../mmo/human_time_diff.hpp" +#include "../mmo/ids.hpp" +#include "../mmo/strs.hpp" +#include "../mmo/utils.hpp" +#include "../mmo/version.hpp" +#include "../login/login.t.hpp" +#include "../map/clif.t.hpp" +#include "../map/skill.t.hpp" + +namespace tmwa +{ +template<class T> +bool native_to_network(T *network, T native) +{ + *network = native; + return true; +} +template<class T> +bool network_to_native(T *native, T network) +{ + *native = network; + return true; +} +template<class T, size_t N> +struct NetArray +{ + T data[N]; +}; +template<class T, class U, class I> +bool native_to_network(NetArray<T, I::alloc_size> *network, GenericArray<U, I> native) +{ + for (size_t i = 0; i < I::alloc_size; ++i) + { + if (!native_to_network(&(*network).data[i], native[I::offset_to_index(i)])) + return false; + } + return true; +} +template<class T, class U, class I> +bool network_to_native(GenericArray<U, I> *native, NetArray<T, I::alloc_size> network) +{ + for (size_t i = 0; i < I::alloc_size; ++i) + { + if (!network_to_native(&(*native)[I::offset_to_index(i)], network.data[i])) + return false; + } + return true; +} + +template<size_t N> +struct NetString +{ + char data[N]; +}; +template<size_t N> +bool native_to_network(NetString<N> *network, VString<N-1> native) +{ + // basically WBUF_STRING + char *const begin = network->data; + char *const end = begin + N; + char *const mid = std::copy(native.begin(), native.end(), begin); + std::fill(mid, end, '\0'); + return true; +} +template<size_t N> +bool network_to_native(VString<N-1> *native, NetString<N> network) +{ + // basically RBUF_STRING + const char *const begin = network.data; + const char *const end = begin + N; + const char *const mid = std::find(begin, end, '\0'); + *native = XString(begin, mid, nullptr); + return true; +} + +inline +bool native_to_network(NetString<24> *network, CharName native) +{ + VString<23> tmp = native.to__actual(); + bool rv = native_to_network(network, tmp); + return rv; +} +inline +bool network_to_native(CharName *native, NetString<24> network) +{ + VString<23> tmp; + bool rv = network_to_native(&tmp, network); + *native = stringish<CharName>(tmp); + return rv; +} + +inline +bool native_to_network(NetString<16> *network, MapName native) +{ + XString tmp = native; + bool rv = native_to_network(network, VString<15>(tmp)); + return rv; +} +inline +bool network_to_native(MapName *native, NetString<16> network) +{ + VString<15> tmp; + bool rv = network_to_native(&tmp, network); + *native = stringish<MapName>(tmp); + return rv; +} + +template<class T, size_t N> +struct SkewedLength +{ + T data; +}; +template<class T, size_t N, class U> +bool native_to_network(SkewedLength<T, N> *network, U native) +{ + native -= N; + return native_to_network(&network->data, native); +} +template<class T, size_t N, class U> +bool network_to_native(U *native, SkewedLength<T, N> network) +{ + bool rv = network_to_native(native, network.data); + *native += N; + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(Byte *network, DIR native) +{ + bool rv = true; + uint8_t tmp = static_cast<uint8_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(DIR *native, Byte network) +{ + bool rv = true; + uint8_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<DIR>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Byte *network, BeingRemoveWhy native) +{ + bool rv = true; + uint8_t tmp = static_cast<uint8_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(BeingRemoveWhy *native, Byte network) +{ + bool rv = true; + uint8_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<BeingRemoveWhy>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, Opt1 native) +{ + bool rv = true; + uint16_t tmp = static_cast<uint16_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Opt1 *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<Opt1>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, Opt2 native) +{ + bool rv = true; + uint16_t tmp = static_cast<uint16_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Opt2 *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<Opt2>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, Opt3 native) +{ + bool rv = true; + uint16_t tmp = static_cast<uint16_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Opt3 *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<Opt3>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Byte *network, ItemType native) +{ + bool rv = true; + uint8_t tmp = static_cast<uint8_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(ItemType *native, Byte network) +{ + bool rv = true; + uint8_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<ItemType>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Byte *network, PickupFail native) +{ + bool rv = true; + uint8_t tmp = static_cast<uint8_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(PickupFail *native, Byte network) +{ + bool rv = true; + uint8_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<PickupFail>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Byte *network, DamageType native) +{ + bool rv = true; + uint8_t tmp = static_cast<uint8_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(DamageType *native, Byte network) +{ + bool rv = true; + uint8_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<DamageType>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, SP native) +{ + bool rv = true; + uint16_t tmp = static_cast<uint16_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(SP *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<SP>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Byte *network, LOOK native) +{ + bool rv = true; + uint8_t tmp = static_cast<uint8_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(LOOK *native, Byte network) +{ + bool rv = true; + uint8_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<LOOK>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, SkillID native) +{ + bool rv = true; + uint16_t tmp = static_cast<uint16_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(SkillID *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<SkillID>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, StatusChange native) +{ + bool rv = true; + uint16_t tmp = static_cast<uint16_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(StatusChange *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<StatusChange>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, SkillFlags native) +{ + bool rv = true; + uint16_t tmp = static_cast<uint16_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(SkillFlags *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<SkillFlags>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Byte *network, SEX native) +{ + bool rv = true; + uint8_t tmp = static_cast<uint8_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(SEX *native, Byte network) +{ + bool rv = true; + uint8_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<SEX>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, Option native) +{ + bool rv = true; + uint16_t tmp = static_cast<uint16_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Option *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<Option>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, EPOS native) +{ + bool rv = true; + uint16_t tmp = static_cast<uint16_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(EPOS *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<EPOS>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, ItemLook native) +{ + bool rv = true; + uint16_t tmp = static_cast<uint16_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(ItemLook *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<ItemLook>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, Species native) +{ + bool rv = true; + uint16_t tmp = unwrap<Species>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Species *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = wrap<Species>(tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little32 *network, AccountId native) +{ + bool rv = true; + uint32_t tmp = unwrap<AccountId>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(AccountId *native, Little32 network) +{ + bool rv = true; + uint32_t tmp; + rv &= network_to_native(&tmp, network); + *native = wrap<AccountId>(tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little32 *network, CharId native) +{ + bool rv = true; + uint32_t tmp = unwrap<CharId>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(CharId *native, Little32 network) +{ + bool rv = true; + uint32_t tmp; + rv &= network_to_native(&tmp, network); + *native = wrap<CharId>(tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little32 *network, PartyId native) +{ + bool rv = true; + uint32_t tmp = unwrap<PartyId>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(PartyId *native, Little32 network) +{ + bool rv = true; + uint32_t tmp; + rv &= network_to_native(&tmp, network); + *native = wrap<PartyId>(tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *network, ItemNameId native) +{ + bool rv = true; + uint16_t tmp = unwrap<ItemNameId>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(ItemNameId *native, Little16 network) +{ + bool rv = true; + uint16_t tmp; + rv &= network_to_native(&tmp, network); + *native = wrap<ItemNameId>(tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little32 *network, ItemNameId native) +{ + bool rv = true; + uint32_t tmp = unwrap<ItemNameId>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(ItemNameId *native, Little32 network) +{ + bool rv = true; + uint32_t tmp; + rv &= network_to_native(&tmp, network); + *native = wrap<ItemNameId>(tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool native_to_network(Little32 *network, BlockId native) +{ + bool rv = true; + uint32_t tmp = unwrap<BlockId>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(BlockId *native, Little32 network) +{ + bool rv = true; + uint32_t tmp; + rv &= network_to_native(&tmp, network); + *native = wrap<BlockId>(tmp); + return rv; +} +struct NetHumanTimeDiff +{ + Little16 year; + Little16 month; + Little16 day; + Little16 hour; + Little16 minute; + Little16 second; +}; +inline __attribute__((warn_unused_result)) +bool native_to_network(NetHumanTimeDiff *network, HumanTimeDiff native) +{ + bool rv = true; + int16_t year = native.year; rv &= native_to_network(&network->year, year); + int16_t month = native.month; rv &= native_to_network(&network->month, month); + int16_t day = native.day; rv &= native_to_network(&network->day, day); + int16_t hour = native.hour; rv &= native_to_network(&network->hour, hour); + int16_t minute = native.minute; rv &= native_to_network(&network->minute, minute); + int16_t second = native.second; rv &= native_to_network(&network->second, second); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(HumanTimeDiff *native, NetHumanTimeDiff network) +{ + bool rv = true; + int16_t year; rv &= network_to_native(&year, network.year); native->year = year; + int16_t month; rv &= network_to_native(&month, network.month); native->month = month; + int16_t day; rv &= network_to_native(&day, network.day); native->day = day; + int16_t hour; rv &= network_to_native(&hour, network.hour); native->hour = hour; + int16_t minute; rv &= network_to_native(&minute, network.minute); native->minute = minute; + int16_t second; rv &= network_to_native(&second, network.second); native->second = second; + return rv; +} + +struct NetVersion +{ + Byte major; + Byte minor; + Byte patch; + Byte devel; + Byte flags; + Byte which; + Little16 vend; +}; +inline __attribute__((warn_unused_result)) +bool native_to_network(NetVersion *network, Version native) +{ + bool rv = true; + uint8_t major = native.major; rv &= native_to_network(&network->major, major); + uint8_t minor = native.minor; rv &= native_to_network(&network->minor, minor); + uint8_t patch = native.patch; rv &= native_to_network(&network->patch, patch); + uint8_t devel = native.devel; rv &= native_to_network(&network->devel, devel); + uint8_t flags = native.flags; rv &= native_to_network(&network->flags, flags); + uint8_t which = native.which; rv &= native_to_network(&network->which, which); + uint16_t vend = native.vend; rv &= native_to_network(&network->vend, vend); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Version *native, NetVersion network) +{ + bool rv = true; + uint8_t major; rv &= network_to_native(&major, network.major); native->major = major; + uint8_t minor; rv &= network_to_native(&minor, network.minor); native->minor = minor; + uint8_t patch; rv &= network_to_native(&patch, network.patch); native->patch = patch; + uint8_t devel; rv &= network_to_native(&devel, network.devel); native->devel = devel; + uint8_t flags; rv &= network_to_native(&flags, network.flags); native->flags = flags; + uint8_t which; rv &= network_to_native(&which, network.which); native->which = which; + uint16_t vend; rv &= network_to_native(&vend, network.vend); native->vend = vend; + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(Byte *network, VERSION_2 native) +{ + bool rv = true; + uint8_t tmp = static_cast<uint8_t>(native); + rv &= native_to_network(network, tmp); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(VERSION_2 *native, Byte network) +{ + bool rv = true; + uint8_t tmp; + rv &= network_to_native(&tmp, network); + *native = static_cast<VERSION_2>(tmp); + // TODO this is what really should be doing a checked cast + return rv; +} +struct Stats6 +{ + uint8_t str = {}; + uint8_t agi = {}; + uint8_t vit = {}; + uint8_t int_ = {}; + uint8_t dex = {}; + uint8_t luk = {}; +}; +struct NetStats6 +{ + Byte str; + Byte agi; + Byte vit; + Byte int_; + Byte dex; + Byte luk; +}; +static_assert(offsetof(NetStats6, str) == 0, "offsetof(NetStats6, str) == 0"); +static_assert(offsetof(NetStats6, agi) == 1, "offsetof(NetStats6, agi) == 1"); +static_assert(offsetof(NetStats6, vit) == 2, "offsetof(NetStats6, vit) == 2"); +static_assert(offsetof(NetStats6, int_) == 3, "offsetof(NetStats6, int_) == 3"); +static_assert(offsetof(NetStats6, dex) == 4, "offsetof(NetStats6, dex) == 4"); +static_assert(offsetof(NetStats6, luk) == 5, "offsetof(NetStats6, luk) == 5"); +static_assert(sizeof(NetStats6) == 6, "sizeof(NetStats6) == 6"); +static_assert(alignof(NetStats6) == 1, "alignof(NetStats6) == 1"); +inline __attribute__((warn_unused_result)) +bool native_to_network(NetStats6 *network, Stats6 native) +{ + bool rv = true; + rv &= native_to_network(&network->str, native.str); + rv &= native_to_network(&network->agi, native.agi); + rv &= native_to_network(&network->vit, native.vit); + rv &= native_to_network(&network->int_, native.int_); + rv &= native_to_network(&network->dex, native.dex); + rv &= native_to_network(&network->luk, native.luk); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Stats6 *native, NetStats6 network) +{ + bool rv = true; + rv &= network_to_native(&native->str, network.str); + rv &= network_to_native(&native->agi, network.agi); + rv &= network_to_native(&native->vit, network.vit); + rv &= network_to_native(&native->int_, network.int_); + rv &= network_to_native(&native->dex, network.dex); + rv &= network_to_native(&native->luk, network.luk); + return rv; +} + +struct CharSelect +{ + CharId char_id = {}; + uint32_t base_exp = {}; + uint32_t zeny = {}; + uint32_t job_exp = {}; + uint32_t job_level = {}; + ItemNameId shoes = {}; + ItemNameId gloves = {}; + ItemNameId cape = {}; + ItemNameId misc1 = {}; + Option option = {}; + uint16_t unused = {}; + uint32_t karma = {}; + uint32_t manner = {}; + uint16_t status_point = {}; + uint16_t hp = {}; + uint16_t max_hp = {}; + uint16_t sp = {}; + uint16_t max_sp = {}; + uint16_t speed = {}; + Species species = {}; + uint16_t hair_style = {}; + uint16_t weapon = {}; + uint16_t base_level = {}; + uint16_t skill_point = {}; + ItemNameId head_bottom = {}; + ItemNameId shield = {}; + ItemNameId head_top = {}; + ItemNameId head_mid = {}; + uint16_t hair_color = {}; + ItemNameId misc2 = {}; + CharName char_name = {}; + Stats6 stats = {}; + uint8_t char_num = {}; + uint8_t unused2 = {}; +}; +struct NetCharSelect +{ + Little32 char_id; + Little32 base_exp; + Little32 zeny; + Little32 job_exp; + Little32 job_level; + Little16 shoes; + Little16 gloves; + Little16 cape; + Little16 misc1; + Little16 option; + Little16 unused; + Little32 karma; + Little32 manner; + Little16 status_point; + Little16 hp; + Little16 max_hp; + Little16 sp; + Little16 max_sp; + Little16 speed; + Little16 species; + Little16 hair_style; + Little16 weapon; + Little16 base_level; + Little16 skill_point; + Little16 head_bottom; + Little16 shield; + Little16 head_top; + Little16 head_mid; + Little16 hair_color; + Little16 misc2; + NetString<sizeof(CharName)> char_name; + NetStats6 stats; + Byte char_num; + Byte unused2; +}; +static_assert(offsetof(NetCharSelect, char_id) == 0, "offsetof(NetCharSelect, char_id) == 0"); +static_assert(offsetof(NetCharSelect, base_exp) == 4, "offsetof(NetCharSelect, base_exp) == 4"); +static_assert(offsetof(NetCharSelect, zeny) == 8, "offsetof(NetCharSelect, zeny) == 8"); +static_assert(offsetof(NetCharSelect, job_exp) == 12, "offsetof(NetCharSelect, job_exp) == 12"); +static_assert(offsetof(NetCharSelect, job_level) == 16, "offsetof(NetCharSelect, job_level) == 16"); +static_assert(offsetof(NetCharSelect, shoes) == 20, "offsetof(NetCharSelect, shoes) == 20"); +static_assert(offsetof(NetCharSelect, gloves) == 22, "offsetof(NetCharSelect, gloves) == 22"); +static_assert(offsetof(NetCharSelect, cape) == 24, "offsetof(NetCharSelect, cape) == 24"); +static_assert(offsetof(NetCharSelect, misc1) == 26, "offsetof(NetCharSelect, misc1) == 26"); +static_assert(offsetof(NetCharSelect, option) == 28, "offsetof(NetCharSelect, option) == 28"); +static_assert(offsetof(NetCharSelect, unused) == 30, "offsetof(NetCharSelect, unused) == 30"); +static_assert(offsetof(NetCharSelect, karma) == 32, "offsetof(NetCharSelect, karma) == 32"); +static_assert(offsetof(NetCharSelect, manner) == 36, "offsetof(NetCharSelect, manner) == 36"); +static_assert(offsetof(NetCharSelect, status_point) == 40, "offsetof(NetCharSelect, status_point) == 40"); +static_assert(offsetof(NetCharSelect, hp) == 42, "offsetof(NetCharSelect, hp) == 42"); +static_assert(offsetof(NetCharSelect, max_hp) == 44, "offsetof(NetCharSelect, max_hp) == 44"); +static_assert(offsetof(NetCharSelect, sp) == 46, "offsetof(NetCharSelect, sp) == 46"); +static_assert(offsetof(NetCharSelect, max_sp) == 48, "offsetof(NetCharSelect, max_sp) == 48"); +static_assert(offsetof(NetCharSelect, speed) == 50, "offsetof(NetCharSelect, speed) == 50"); +static_assert(offsetof(NetCharSelect, species) == 52, "offsetof(NetCharSelect, species) == 52"); +static_assert(offsetof(NetCharSelect, hair_style) == 54, "offsetof(NetCharSelect, hair_style) == 54"); +static_assert(offsetof(NetCharSelect, weapon) == 56, "offsetof(NetCharSelect, weapon) == 56"); +static_assert(offsetof(NetCharSelect, base_level) == 58, "offsetof(NetCharSelect, base_level) == 58"); +static_assert(offsetof(NetCharSelect, skill_point) == 60, "offsetof(NetCharSelect, skill_point) == 60"); +static_assert(offsetof(NetCharSelect, head_bottom) == 62, "offsetof(NetCharSelect, head_bottom) == 62"); +static_assert(offsetof(NetCharSelect, shield) == 64, "offsetof(NetCharSelect, shield) == 64"); +static_assert(offsetof(NetCharSelect, head_top) == 66, "offsetof(NetCharSelect, head_top) == 66"); +static_assert(offsetof(NetCharSelect, head_mid) == 68, "offsetof(NetCharSelect, head_mid) == 68"); +static_assert(offsetof(NetCharSelect, hair_color) == 70, "offsetof(NetCharSelect, hair_color) == 70"); +static_assert(offsetof(NetCharSelect, misc2) == 72, "offsetof(NetCharSelect, misc2) == 72"); +static_assert(offsetof(NetCharSelect, char_name) == 74, "offsetof(NetCharSelect, char_name) == 74"); +static_assert(offsetof(NetCharSelect, stats) == 98, "offsetof(NetCharSelect, stats) == 98"); +static_assert(offsetof(NetCharSelect, char_num) == 104, "offsetof(NetCharSelect, char_num) == 104"); +static_assert(offsetof(NetCharSelect, unused2) == 105, "offsetof(NetCharSelect, unused2) == 105"); +static_assert(sizeof(NetCharSelect) == 106, "sizeof(NetCharSelect) == 106"); +static_assert(alignof(NetCharSelect) == 1, "alignof(NetCharSelect) == 1"); +inline __attribute__((warn_unused_result)) +bool native_to_network(NetCharSelect *network, CharSelect native) +{ + bool rv = true; + rv &= native_to_network(&network->char_id, native.char_id); + rv &= native_to_network(&network->base_exp, native.base_exp); + rv &= native_to_network(&network->zeny, native.zeny); + rv &= native_to_network(&network->job_exp, native.job_exp); + rv &= native_to_network(&network->job_level, native.job_level); + rv &= native_to_network(&network->shoes, native.shoes); + rv &= native_to_network(&network->gloves, native.gloves); + rv &= native_to_network(&network->cape, native.cape); + rv &= native_to_network(&network->misc1, native.misc1); + rv &= native_to_network(&network->option, native.option); + rv &= native_to_network(&network->unused, native.unused); + rv &= native_to_network(&network->karma, native.karma); + rv &= native_to_network(&network->manner, native.manner); + rv &= native_to_network(&network->status_point, native.status_point); + rv &= native_to_network(&network->hp, native.hp); + rv &= native_to_network(&network->max_hp, native.max_hp); + rv &= native_to_network(&network->sp, native.sp); + rv &= native_to_network(&network->max_sp, native.max_sp); + rv &= native_to_network(&network->speed, native.speed); + rv &= native_to_network(&network->species, native.species); + rv &= native_to_network(&network->hair_style, native.hair_style); + rv &= native_to_network(&network->weapon, native.weapon); + rv &= native_to_network(&network->base_level, native.base_level); + rv &= native_to_network(&network->skill_point, native.skill_point); + rv &= native_to_network(&network->head_bottom, native.head_bottom); + rv &= native_to_network(&network->shield, native.shield); + rv &= native_to_network(&network->head_top, native.head_top); + rv &= native_to_network(&network->head_mid, native.head_mid); + rv &= native_to_network(&network->hair_color, native.hair_color); + rv &= native_to_network(&network->misc2, native.misc2); + rv &= native_to_network(&network->char_name, native.char_name); + rv &= native_to_network(&network->stats, native.stats); + rv &= native_to_network(&network->char_num, native.char_num); + rv &= native_to_network(&network->unused2, native.unused2); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(CharSelect *native, NetCharSelect network) +{ + bool rv = true; + rv &= network_to_native(&native->char_id, network.char_id); + rv &= network_to_native(&native->base_exp, network.base_exp); + rv &= network_to_native(&native->zeny, network.zeny); + rv &= network_to_native(&native->job_exp, network.job_exp); + rv &= network_to_native(&native->job_level, network.job_level); + rv &= network_to_native(&native->shoes, network.shoes); + rv &= network_to_native(&native->gloves, network.gloves); + rv &= network_to_native(&native->cape, network.cape); + rv &= network_to_native(&native->misc1, network.misc1); + rv &= network_to_native(&native->option, network.option); + rv &= network_to_native(&native->unused, network.unused); + rv &= network_to_native(&native->karma, network.karma); + rv &= network_to_native(&native->manner, network.manner); + rv &= network_to_native(&native->status_point, network.status_point); + rv &= network_to_native(&native->hp, network.hp); + rv &= network_to_native(&native->max_hp, network.max_hp); + rv &= network_to_native(&native->sp, network.sp); + rv &= network_to_native(&native->max_sp, network.max_sp); + rv &= network_to_native(&native->speed, network.speed); + rv &= network_to_native(&native->species, network.species); + rv &= network_to_native(&native->hair_style, network.hair_style); + rv &= network_to_native(&native->weapon, network.weapon); + rv &= network_to_native(&native->base_level, network.base_level); + rv &= network_to_native(&native->skill_point, network.skill_point); + rv &= network_to_native(&native->head_bottom, network.head_bottom); + rv &= network_to_native(&native->shield, network.shield); + rv &= network_to_native(&native->head_top, network.head_top); + rv &= network_to_native(&native->head_mid, network.head_mid); + rv &= network_to_native(&native->hair_color, network.hair_color); + rv &= network_to_native(&native->misc2, network.misc2); + rv &= network_to_native(&native->char_name, network.char_name); + rv &= network_to_native(&native->stats, network.stats); + rv &= network_to_native(&native->char_num, network.char_num); + rv &= network_to_native(&native->unused2, network.unused2); + return rv; +} + +struct SkillInfo +{ + SkillID skill_id = {}; + uint16_t type_or_inf = {}; + SkillFlags flags = {}; + uint16_t level = {}; + uint16_t sp = {}; + uint16_t range = {}; + VString<23> unused = {}; + uint8_t can_raise = {}; +}; +struct NetSkillInfo +{ + Little16 skill_id; + Little16 type_or_inf; + Little16 flags; + Little16 level; + Little16 sp; + Little16 range; + NetString<sizeof(VString<23>)> unused; + Byte can_raise; +}; +static_assert(offsetof(NetSkillInfo, skill_id) == 0, "offsetof(NetSkillInfo, skill_id) == 0"); +static_assert(offsetof(NetSkillInfo, type_or_inf) == 2, "offsetof(NetSkillInfo, type_or_inf) == 2"); +static_assert(offsetof(NetSkillInfo, flags) == 4, "offsetof(NetSkillInfo, flags) == 4"); +static_assert(offsetof(NetSkillInfo, level) == 6, "offsetof(NetSkillInfo, level) == 6"); +static_assert(offsetof(NetSkillInfo, sp) == 8, "offsetof(NetSkillInfo, sp) == 8"); +static_assert(offsetof(NetSkillInfo, range) == 10, "offsetof(NetSkillInfo, range) == 10"); +static_assert(offsetof(NetSkillInfo, unused) == 12, "offsetof(NetSkillInfo, unused) == 12"); +static_assert(offsetof(NetSkillInfo, can_raise) == 36, "offsetof(NetSkillInfo, can_raise) == 36"); +static_assert(sizeof(NetSkillInfo) == 37, "sizeof(NetSkillInfo) == 37"); +static_assert(alignof(NetSkillInfo) == 1, "alignof(NetSkillInfo) == 1"); +inline __attribute__((warn_unused_result)) +bool native_to_network(NetSkillInfo *network, SkillInfo native) +{ + bool rv = true; + rv &= native_to_network(&network->skill_id, native.skill_id); + rv &= native_to_network(&network->type_or_inf, native.type_or_inf); + rv &= native_to_network(&network->flags, native.flags); + rv &= native_to_network(&network->level, native.level); + rv &= native_to_network(&network->sp, native.sp); + rv &= native_to_network(&network->range, native.range); + rv &= native_to_network(&network->unused, native.unused); + rv &= native_to_network(&network->can_raise, native.can_raise); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(SkillInfo *native, NetSkillInfo network) +{ + bool rv = true; + rv &= network_to_native(&native->skill_id, network.skill_id); + rv &= network_to_native(&native->type_or_inf, network.type_or_inf); + rv &= network_to_native(&native->flags, network.flags); + rv &= network_to_native(&native->level, network.level); + rv &= network_to_native(&native->sp, network.sp); + rv &= network_to_native(&native->range, network.range); + rv &= network_to_native(&native->unused, network.unused); + rv &= network_to_native(&native->can_raise, network.can_raise); + return rv; +} + +struct Item +{ + ItemNameId nameid = {}; + int16_t amount = {}; + EPOS equip = {}; +}; +struct NetItem +{ + Little16 nameid; + Little16 amount; + Little16 equip; +}; +static_assert(alignof(NetItem) == 1, "alignof(NetItem) == 1"); +inline __attribute__((warn_unused_result)) +bool native_to_network(NetItem *network, Item native) +{ + bool rv = true; + rv &= native_to_network(&network->nameid, native.nameid); + rv &= native_to_network(&network->amount, native.amount); + rv &= native_to_network(&network->equip, native.equip); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Item *native, NetItem network) +{ + bool rv = true; + rv &= network_to_native(&native->nameid, network.nameid); + rv &= network_to_native(&native->amount, network.amount); + rv &= network_to_native(&native->equip, network.equip); + return rv; +} + +struct Point +{ + MapName map_ = {}; + int16_t x = {}; + int16_t y = {}; + Point() = default; + Point(MapName _map_, int16_t _x, int16_t _y) : map_(_map_), x(_x), y(_y) {} +}; +struct NetPoint +{ + NetString<sizeof(MapName)> map_; + Little16 x; + Little16 y; +}; +static_assert(alignof(NetPoint) == 1, "alignof(NetPoint) == 1"); +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPoint *network, Point native) +{ + bool rv = true; + rv &= native_to_network(&network->map_, native.map_); + rv &= native_to_network(&network->x, native.x); + rv &= native_to_network(&network->y, native.y); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Point *native, NetPoint network) +{ + bool rv = true; + rv &= network_to_native(&native->map_, network.map_); + rv &= network_to_native(&native->x, network.x); + rv &= network_to_native(&native->y, network.y); + return rv; +} + +struct SkillValue +{ + uint16_t lv = {}; + SkillFlags flags = {}; +}; +struct NetSkillValue +{ + Little16 lv; + Little16 flags; +}; +static_assert(alignof(NetSkillValue) == 1, "alignof(NetSkillValue) == 1"); +inline __attribute__((warn_unused_result)) +bool native_to_network(NetSkillValue *network, SkillValue native) +{ + bool rv = true; + rv &= native_to_network(&network->lv, native.lv); + rv &= native_to_network(&network->flags, native.flags); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(SkillValue *native, NetSkillValue network) +{ + bool rv = true; + rv &= network_to_native(&native->lv, network.lv); + rv &= network_to_native(&native->flags, network.flags); + return rv; +} + +struct GlobalReg +{ + VarName str = {}; + int32_t value = {}; +}; +struct NetGlobalReg +{ + NetString<sizeof(VarName)> str; + Little32 value; +}; +static_assert(alignof(NetGlobalReg) == 1, "alignof(NetGlobalReg) == 1"); +inline __attribute__((warn_unused_result)) +bool native_to_network(NetGlobalReg *network, GlobalReg native) +{ + bool rv = true; + rv &= native_to_network(&network->str, native.str); + rv &= native_to_network(&network->value, native.value); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(GlobalReg *native, NetGlobalReg network) +{ + bool rv = true; + rv &= network_to_native(&native->str, network.str); + rv &= network_to_native(&native->value, network.value); + return rv; +} + +struct CharKey +{ + CharName name = {}; + AccountId account_id = {}; + CharId char_id = {}; + uint8_t char_num = {}; +}; +struct NetCharKey +{ + NetString<sizeof(CharName)> name; + Little32 account_id; + Little32 char_id; + Byte char_num; +}; +static_assert(alignof(NetCharKey) == 1, "alignof(NetCharKey) == 1"); +inline __attribute__((warn_unused_result)) +bool native_to_network(NetCharKey *network, CharKey native) +{ + bool rv = true; + rv &= native_to_network(&network->name, native.name); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->char_id, native.char_id); + rv &= native_to_network(&network->char_num, native.char_num); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(CharKey *native, NetCharKey network) +{ + bool rv = true; + rv &= network_to_native(&native->name, network.name); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->char_id, network.char_id); + rv &= network_to_native(&native->char_num, network.char_num); + return rv; +} + +struct CharData +{ + CharId partner_id = {}; + int32_t base_exp = {}; + int32_t job_exp = {}; + int32_t zeny = {}; + Species species = {}; + int16_t status_point = {}; + int16_t skill_point = {}; + int32_t hp = {}; + int32_t max_hp = {}; + int32_t sp = {}; + int32_t max_sp = {}; + Option option = {}; + int16_t karma = {}; + int16_t manner = {}; + int16_t hair = {}; + int16_t hair_color = {}; + int16_t clothes_color = {}; + PartyId party_id = {}; + ItemLook weapon = {}; + ItemNameId shield = {}; + ItemNameId head_top = {}; + ItemNameId head_mid = {}; + ItemNameId head_bottom = {}; + uint8_t base_level = {}; + uint8_t job_level = {}; + earray<int16_t, ATTR, ATTR::COUNT> attrs = {}; + SEX sex = {}; + IP4Address mapip = {}; + uint16_t mapport = {}; + Point last_point = {}; + Point save_point = {}; + GenericArray<Item, InventoryIndexing<IOff0, MAX_INVENTORY>> inventory = {}; + earray<SkillValue, SkillID, MAX_SKILL> skill = {}; + int32_t global_reg_num = {}; + Array<GlobalReg, GLOBAL_REG_NUM> global_reg = {}; + int32_t account_reg_num = {}; + Array<GlobalReg, ACCOUNT_REG_NUM> account_reg = {}; + int32_t account_reg2_num = {}; + Array<GlobalReg, ACCOUNT_REG2_NUM> account_reg2 = {}; +}; +struct NetCharData +{ + Little32 partner_id; + Little32 base_exp; + Little32 job_exp; + Little32 zeny; + Little16 species; + Little16 status_point; + Little16 skill_point; + Little32 hp; + Little32 max_hp; + Little32 sp; + Little32 max_sp; + Little16 option; + Little16 karma; + Little16 manner; + Little16 hair; + Little16 hair_color; + Little16 clothes_color; + Little32 party_id; + Little16 weapon; + Little16 shield; + Little16 head_top; + Little16 head_mid; + Little16 head_bottom; + Byte base_level; + Byte job_level; + NetArray<Little16, static_cast<size_t>(ATTR::COUNT)> attrs; + Byte sex; + IP4Address mapip; + Little16 mapport; + NetPoint last_point; + NetPoint save_point; + NetArray<NetItem, MAX_INVENTORY> inventory; + NetArray<NetSkillValue, static_cast<size_t>(MAX_SKILL)> skill; + Little32 global_reg_num; + NetArray<NetGlobalReg, GLOBAL_REG_NUM> global_reg; + Little32 account_reg_num; + NetArray<NetGlobalReg, ACCOUNT_REG_NUM> account_reg; + Little32 account_reg2_num; + NetArray<NetGlobalReg, ACCOUNT_REG2_NUM> account_reg2; +}; +static_assert(alignof(NetCharData) == 1, "alignof(NetCharData) == 1"); +inline __attribute__((warn_unused_result)) +bool native_to_network(NetCharData *network, CharData native) +{ + bool rv = true; + rv &= native_to_network(&network->partner_id, native.partner_id); + rv &= native_to_network(&network->base_exp, native.base_exp); + rv &= native_to_network(&network->job_exp, native.job_exp); + rv &= native_to_network(&network->zeny, native.zeny); + rv &= native_to_network(&network->species, native.species); + rv &= native_to_network(&network->status_point, native.status_point); + rv &= native_to_network(&network->skill_point, native.skill_point); + rv &= native_to_network(&network->hp, native.hp); + rv &= native_to_network(&network->max_hp, native.max_hp); + rv &= native_to_network(&network->sp, native.sp); + rv &= native_to_network(&network->max_sp, native.max_sp); + rv &= native_to_network(&network->option, native.option); + rv &= native_to_network(&network->karma, native.karma); + rv &= native_to_network(&network->manner, native.manner); + rv &= native_to_network(&network->hair, native.hair); + rv &= native_to_network(&network->hair_color, native.hair_color); + rv &= native_to_network(&network->clothes_color, native.clothes_color); + rv &= native_to_network(&network->party_id, native.party_id); + rv &= native_to_network(&network->weapon, native.weapon); + rv &= native_to_network(&network->shield, native.shield); + rv &= native_to_network(&network->head_top, native.head_top); + rv &= native_to_network(&network->head_mid, native.head_mid); + rv &= native_to_network(&network->head_bottom, native.head_bottom); + rv &= native_to_network(&network->base_level, native.base_level); + rv &= native_to_network(&network->job_level, native.job_level); + rv &= native_to_network(&network->attrs, native.attrs); + rv &= native_to_network(&network->sex, native.sex); + rv &= native_to_network(&network->mapip, native.mapip); + rv &= native_to_network(&network->mapport, native.mapport); + rv &= native_to_network(&network->last_point, native.last_point); + rv &= native_to_network(&network->save_point, native.save_point); + rv &= native_to_network(&network->inventory, native.inventory); + rv &= native_to_network(&network->skill, native.skill); + rv &= native_to_network(&network->global_reg_num, native.global_reg_num); + rv &= native_to_network(&network->global_reg, native.global_reg); + rv &= native_to_network(&network->account_reg_num, native.account_reg_num); + rv &= native_to_network(&network->account_reg, native.account_reg); + rv &= native_to_network(&network->account_reg2_num, native.account_reg2_num); + rv &= native_to_network(&network->account_reg2, native.account_reg2); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(CharData *native, NetCharData network) +{ + bool rv = true; + rv &= network_to_native(&native->partner_id, network.partner_id); + rv &= network_to_native(&native->base_exp, network.base_exp); + rv &= network_to_native(&native->job_exp, network.job_exp); + rv &= network_to_native(&native->zeny, network.zeny); + rv &= network_to_native(&native->species, network.species); + rv &= network_to_native(&native->status_point, network.status_point); + rv &= network_to_native(&native->skill_point, network.skill_point); + rv &= network_to_native(&native->hp, network.hp); + rv &= network_to_native(&native->max_hp, network.max_hp); + rv &= network_to_native(&native->sp, network.sp); + rv &= network_to_native(&native->max_sp, network.max_sp); + rv &= network_to_native(&native->option, network.option); + rv &= network_to_native(&native->karma, network.karma); + rv &= network_to_native(&native->manner, network.manner); + rv &= network_to_native(&native->hair, network.hair); + rv &= network_to_native(&native->hair_color, network.hair_color); + rv &= network_to_native(&native->clothes_color, network.clothes_color); + rv &= network_to_native(&native->party_id, network.party_id); + rv &= network_to_native(&native->weapon, network.weapon); + rv &= network_to_native(&native->shield, network.shield); + rv &= network_to_native(&native->head_top, network.head_top); + rv &= network_to_native(&native->head_mid, network.head_mid); + rv &= network_to_native(&native->head_bottom, network.head_bottom); + rv &= network_to_native(&native->base_level, network.base_level); + rv &= network_to_native(&native->job_level, network.job_level); + rv &= network_to_native(&native->attrs, network.attrs); + rv &= network_to_native(&native->sex, network.sex); + rv &= network_to_native(&native->mapip, network.mapip); + rv &= network_to_native(&native->mapport, network.mapport); + rv &= network_to_native(&native->last_point, network.last_point); + rv &= network_to_native(&native->save_point, network.save_point); + rv &= network_to_native(&native->inventory, network.inventory); + rv &= network_to_native(&native->skill, network.skill); + rv &= network_to_native(&native->global_reg_num, network.global_reg_num); + rv &= network_to_native(&native->global_reg, network.global_reg); + rv &= network_to_native(&native->account_reg_num, network.account_reg_num); + rv &= network_to_native(&native->account_reg, network.account_reg); + rv &= network_to_native(&native->account_reg2_num, network.account_reg2_num); + rv &= network_to_native(&native->account_reg2, network.account_reg2); + return rv; +} + +struct NetPartyMember +{ + Little32 account_id; + NetString<sizeof(CharName)> name; + NetString<sizeof(MapName)> map; + Little32 leader; + Little32 online; + Little32 lv; +}; +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPartyMember *network, PartyMember native) +{ + bool rv = true; + AccountId account_id = native.account_id; rv &= native_to_network(&network->account_id, account_id); + CharName name = native.name; rv &= native_to_network(&network->name, name); + MapName map = native.map; rv &= native_to_network(&network->map, map); + int32_t leader = native.leader; rv &= native_to_network(&network->leader, leader); + int32_t online = native.online; rv &= native_to_network(&network->online, online); + int32_t lv = native.lv; rv &= native_to_network(&network->lv, lv); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(PartyMember *native, NetPartyMember network) +{ + bool rv = true; + AccountId account_id; rv &= network_to_native(&account_id, network.account_id); native->account_id = account_id; + CharName name; rv &= network_to_native(&name, network.name); native->name = name; + MapName map; rv &= network_to_native(&map, network.map); native->map = map; + int32_t leader; rv &= network_to_native(&leader, network.leader); native->leader = leader; + int32_t online; rv &= network_to_native(&online, network.online); native->online = online; + int32_t lv; rv &= network_to_native(&lv, network.lv); native->lv = lv; + return rv; +} + +struct PartyMost +{ + PartyName name = {}; + int32_t exp = {}; + int32_t item = {}; + Array<PartyMember, MAX_PARTY> member = {}; +}; +struct NetPartyMost +{ + NetString<sizeof(PartyName)> name; + Little32 exp; + Little32 item; + NetArray<NetPartyMember, MAX_PARTY> member; +}; +static_assert(alignof(NetPartyMost) == 1, "alignof(NetPartyMost) == 1"); +inline __attribute__((warn_unused_result)) +bool native_to_network(NetPartyMost *network, PartyMost native) +{ + bool rv = true; + rv &= native_to_network(&network->name, native.name); + rv &= native_to_network(&network->exp, native.exp); + rv &= native_to_network(&network->item, native.item); + rv &= native_to_network(&network->member, native.member); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(PartyMost *native, NetPartyMost network) +{ + bool rv = true; + rv &= network_to_native(&native->name, network.name); + rv &= network_to_native(&native->exp, network.exp); + rv &= network_to_native(&native->item, network.item); + rv &= network_to_native(&native->member, network.member); + return rv; +} + +struct Storage +{ + bool dirty = {}; + AccountId account_id = {}; + int16_t storage_status = {}; + int16_t storage_amount = {}; + GenericArray<Item, InventoryIndexing<SOff0, MAX_STORAGE>> storage_ = {}; +}; +struct NetStorage +{ + bool dirty; + Little32 account_id; + Little16 storage_status; + Little16 storage_amount; + NetArray<NetItem, MAX_STORAGE> storage_; +}; +static_assert(alignof(NetStorage) == 1, "alignof(NetStorage) == 1"); +inline __attribute__((warn_unused_result)) +bool native_to_network(NetStorage *network, Storage native) +{ + bool rv = true; + rv &= native_to_network(&network->dirty, native.dirty); + rv &= native_to_network(&network->account_id, native.account_id); + rv &= native_to_network(&network->storage_status, native.storage_status); + rv &= native_to_network(&network->storage_amount, native.storage_amount); + rv &= native_to_network(&network->storage_, native.storage_); + return rv; +} +inline __attribute__((warn_unused_result)) +bool network_to_native(Storage *native, NetStorage network) +{ + bool rv = true; + rv &= network_to_native(&native->dirty, network.dirty); + rv &= network_to_native(&native->account_id, network.account_id); + rv &= network_to_native(&native->storage_status, network.storage_status); + rv &= network_to_native(&native->storage_amount, network.storage_amount); + rv &= network_to_native(&native->storage_, network.storage_); + return rv; +} + +} // namespace tmwa diff --git a/src/range/fwd.hpp b/src/range/fwd.hpp new file mode 100644 index 0000000..646eadb --- /dev/null +++ b/src/range/fwd.hpp @@ -0,0 +1,29 @@ +#pragma once +// range/fwd.hpp - list of type names for range lib +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +// meh, add more when I feel like it +template<class T> +class Slice; +} // namespace tmwa diff --git a/src/range/slice.cpp b/src/range/slice.cpp index 5e00233..f93c19f 100644 --- a/src/range/slice.cpp +++ b/src/range/slice.cpp @@ -19,3 +19,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/range/slice.hpp b/src/range/slice.hpp index f645595..da52e5f 100644 --- a/src/range/slice.hpp +++ b/src/range/slice.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_GENERIC_SLICE_HPP -#define TMWA_GENERIC_SLICE_HPP +#pragma once // slice.hpp - a borrowed array // // Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,14 +18,16 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstddef> +#include <cstddef> -# include <type_traits> +#include <type_traits> +#include <vector> -# include <vector> +namespace tmwa +{ template<class T> class Slice { @@ -68,7 +69,6 @@ public: Slice pslice(size_t b, size_t e) const; Slice islice(iterator b, iterator e) const; }; +} // namespace tmwa -# include "slice.tcc" - -#endif // TMWA_GENERIC_SLICE_HPP +#include "slice.tcc" diff --git a/src/range/slice.tcc b/src/range/slice.tcc index 3a1ceb5..a1c136f 100644 --- a/src/range/slice.tcc +++ b/src/range/slice.tcc @@ -1,4 +1,4 @@ -// strings/base.tcc - Inline functions for strings/base.hpp +// ranges/slice.tcc - Inline functions for strings/base.hpp // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> // @@ -19,8 +19,9 @@ #include <cassert> -#include <algorithm> +namespace tmwa +{ // simple pointer-wrapping iterator template<class T> class Slice<T>::iterator @@ -214,3 +215,4 @@ Slice<T> Slice<T>::islice(iterator b, iterator e) const { return Slice(&*b, &*e); } +} // namespace tmwa diff --git a/src/range/slice_test.cpp b/src/range/slice_test.cpp index f59bf84..d31d973 100644 --- a/src/range/slice_test.cpp +++ b/src/range/slice_test.cpp @@ -22,6 +22,9 @@ #include "../poison.hpp" + +namespace tmwa +{ TEST(slice, slice) { int init[] = {1, 2, 3, 4, 5}; @@ -107,3 +110,4 @@ TEST(slice, cast) EXPECT_EQ(foos.size(), slice.size()); EXPECT_EQ(&foos.end()[-1], &slice.end()[-1]); } +} // namespace tmwa diff --git a/src/sanity.hpp b/src/sanity.hpp index f29a7c3..c00d9b2 100644 --- a/src/sanity.hpp +++ b/src/sanity.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_SANITY_HPP -#define TMWA_SANITY_HPP +#pragma once // sanity.hpp - Keep spatulas out of the build environment. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,32 +18,33 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# if 0 -# include "../sanity.hpp" -# endif +// just mention "fwd.hpp" to make formatter happy -# ifndef __cplusplus -# error "Please compile in C++ mode" -# endif // __cplusplus -# if __GNUC__ < 4 -# error "Your compiler is absolutely ancient. You have no chance ..." -# endif // __GNUC__ < 4 +namespace tmwa +{ +#ifndef __cplusplus +# error "Please compile in C++ mode" +#endif // __cplusplus -# if __GNUC__ == 4 +#if __GNUC__ < 4 +# error "Your compiler is absolutely ancient. You have no chance ..." +#endif // __GNUC__ < 4 + +#if __GNUC__ == 4 // clang identifies as GCC 4.2, but is mostly okay. // Until a bug-free release of it happens, though, I won't recommend it. -// (patched) clang 3.1 would be the requirement -# if __GNUC_MINOR__ < 6 && !defined(__clang__) -# error "Please upgrade to at least GCC 4.6" -# endif // __GNUC_MINOR__ < 6 && !defined(__clang__) -# endif // __GNUC__ == 4 +// clang 3.2 is the minimum that the CI builds are using +# if __GNUC_MINOR__ < 7 && !defined(__clang__) +# error "Please upgrade to at least GCC 4.7" +# endif // __GNUC_MINOR__ < 7 && !defined(__clang__) +#endif // __GNUC__ == 4 -# if not defined(__i386__) and not defined(__x86_64__) +#if not defined(__i386__) and not defined(__x86_64__) // Known platform dependencies: // endianness for the [RW]FIFO.* macros // possibly, some signal-handling -# error "Unsupported platform, we use x86 / amd64 only" -# endif // not __i386__ - -#endif // TMWA_SANITY_HPP +// some integer sizes (partially fixed for the x32 ABI) +# error "Unsupported platform, we use x86 / amd64 only" +#endif // not __i386__ +} // namespace tmwa diff --git a/src/compat/alg.cpp b/src/sexpr/bind.cpp index 8cfd00a..d8d0caa 100644 --- a/src/compat/alg.cpp +++ b/src/sexpr/bind.cpp @@ -1,5 +1,5 @@ -#include "alg.hpp" -// alg.cpp - Silly math stuff. +#include "bind.hpp" +// bind.cpp - Just include the header file. // // Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> // @@ -19,3 +19,11 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../poison.hpp" + + +namespace tmwa +{ +namespace sexpr +{ +} // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/bind.hpp b/src/sexpr/bind.hpp new file mode 100644 index 0000000..79d7cae --- /dev/null +++ b/src/sexpr/bind.hpp @@ -0,0 +1,48 @@ +#pragma once +// bind.hpp - Like std::bind, but with arbitrary arguments. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <utility> + +#include "fwd.hpp" + + +namespace tmwa +{ +namespace sexpr +{ + template<class F, class T> + struct VariadicBind + { + // note: may be lvalue references + F&& f; + T&& t; + template<class... A> + auto operator()(A&&... a) -> decltype(std::forward<F>(f)(std::forward<T>(t), std::forward<A>(a)...)) + { + return std::forward<F>(f)(std::forward<T>(t), std::forward<A>(a)...); + } + }; + template<class F, class T> + VariadicBind<F, T> bind_variadic(F&& func, T&& arg1) + { + return VariadicBind<F, T>{std::forward<F>(func), std::forward<T>(arg1)}; + } +} // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/fwd.hpp b/src/sexpr/fwd.hpp new file mode 100644 index 0000000..580b322 --- /dev/null +++ b/src/sexpr/fwd.hpp @@ -0,0 +1,27 @@ +#pragma once +// sexpr/fwd.hpp - list of type names for sexpr lib +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +// meh, add more when I feel like it +} // namespace tmwa diff --git a/src/sexpr/lexer.cpp b/src/sexpr/lexer.cpp index 8c1c380..ea1890e 100644 --- a/src/sexpr/lexer.cpp +++ b/src/sexpr/lexer.cpp @@ -19,23 +19,28 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../strings/mstring.hpp" +#include "../strings/vstring.hpp" +#include "../strings/literal.hpp" #include "../io/cxxstdio.hpp" #include "../poison.hpp" + +namespace tmwa +{ namespace sexpr { Lexeme Lexer::_adv() { - XString whitespace = " \t\n\r\v\f"; + LString whitespace = " \t\n\r\v\f"_s; while (true) { if (!_in.get(_span.begin)) { if (!_depth.empty()) { - _depth.back().error("Unmatched '('"); + _depth.back().error("Unmatched '('"_s); return TOK_ERROR; } return TOK_EOF; @@ -52,14 +57,14 @@ namespace sexpr switch (co) { case '(': - _string = "("; + _string = "("_s; _depth.push_back(_span.end); return TOK_OPEN; case ')': - _string = ")"; + _string = ")"_s; if (_depth.empty()) { - _span.end.error("Unmatched ')'"); + _span.end.error("Unmatched ')'"_s); return TOK_ERROR; } _depth.pop_back(); @@ -73,7 +78,7 @@ namespace sexpr { if (!_in.get(_span.end)) { - _span.error("EOF in string literal"); + _span.error("EOF in string literal"_s); return TOK_ERROR; } char ch = _span.end.ch(); @@ -89,7 +94,7 @@ namespace sexpr if (!_in.get(_span.end)) { - _span.end.error("EOF at backslash in string"); + _span.end.error("EOF at backslash in string"_s); return TOK_ERROR; } ch = _span.end.ch(); @@ -97,7 +102,7 @@ namespace sexpr switch (ch) { default: - _span.end.error("Unknown backslash sequence"); + _span.end.error("Unknown backslash sequence"_s); return TOK_ERROR; case 'a': collect += '\a'; break; case 'b': collect += '\b'; break; @@ -117,7 +122,7 @@ namespace sexpr tmp *= 16; if (!_in.get(_span.end)) { - _span.end.error("EOF after \\x in string"); + _span.end.error("EOF after \\x in string"_s); return TOK_ERROR; } char cx = _span.end.ch(); @@ -130,7 +135,7 @@ namespace sexpr tmp += cx - 'a' + 10; else { - _span.end.error("Non-hex char after \\x"); + _span.end.error("Non-hex char after \\x"_s); return TOK_ERROR; } } @@ -143,7 +148,7 @@ namespace sexpr } case '\'': case '\\': - _span.end.error("forbidden character"); + _span.end.error("forbidden character"_s); return TOK_ERROR; default: // this includes integers - they are differentiated in parsing @@ -168,7 +173,7 @@ namespace sexpr } _string = AString(collect); if (!_string.is_print()) - _span.error("String is not entirely printable"); + _span.error("String is not entirely printable"_s); return TOK_TOKEN; } } @@ -178,23 +183,23 @@ namespace sexpr { switch (c) { - case '\a': return {"\\a"}; - case '\b': return {"\\b"}; - case '\e': return {"\\e"}; - case '\f': return {"\\f"}; - //case '\n': return {"\\n"}; - case '\r': return {"\\r"}; - case '\t': return {"\\t"}; - case '\v': return {"\\v"}; - case '\\': return {"\\\\"}; - case '\"': return {"\\\""}; + case '\a': return "\\a"_s; + case '\b': return "\\b"_s; + case '\e': return "\\e"_s; + case '\f': return "\\f"_s; + //case '\n': return "\\n"_s; + case '\r': return "\\r"_s; + case '\t': return "\\t"_s; + case '\v': return "\\v"_s; + case '\\': return "\\\\"_s; + case '\"': return "\\\""_s; default: if (c == '\n') return c; if (' ' <= c && c <= '~') return c; else - return STRNPRINTF(5, "\\x%02x", static_cast<uint8_t>(c)); + return STRNPRINTF(5, "\\x%02x"_fmt, static_cast<uint8_t>(c)); } } AString escape(XString s) @@ -207,22 +212,23 @@ namespace sexpr return AString(m); } - ZString token_name(Lexeme tok) + LString token_name(Lexeme tok) { switch (tok) { case TOK_EOF: - return ZString("EOF"); + return "EOF"_s; case TOK_OPEN: - return ZString("OPEN"); + return "OPEN"_s; case TOK_CLOSE: - return ZString("CLOSE"); + return "CLOSE"_s; case TOK_STRING: - return ZString("STRING"); + return "STRING"_s; case TOK_TOKEN: - return ZString("TOKEN"); + return "TOKEN"_s; default: - return ZString("ERROR"); + return "ERROR"_s; } } } // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/lexer.hpp b/src/sexpr/lexer.hpp index 7bce620..63be72d 100644 --- a/src/sexpr/lexer.hpp +++ b/src/sexpr/lexer.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_SEXPR_LEXER_HPP -#define TMWA_SEXPR_LEXER_HPP +#pragma once // lexer.hpp - tokenize a stream of S-expressions // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,15 +18,21 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/astring.hpp" -# include "../strings/vstring.hpp" -# include "../strings/xstring.hpp" -# include "../strings/zstring.hpp" +#include <vector> -# include "../io/line.hpp" +#include "../strings/fwd.hpp" +#include "../strings/astring.hpp" +#include "../strings/zstring.hpp" +#include "../io/line.hpp" + +#include "fwd.hpp" + + +namespace tmwa +{ namespace sexpr { enum Lexeme @@ -67,7 +72,6 @@ namespace sexpr VString<4> escape(char c); AString escape(XString s); - ZString token_name(Lexeme tok); + LString token_name(Lexeme tok); } // namespace sexpr - -#endif // TMWA_SEXPR_LEXER_HPP +} // namespace tmwa diff --git a/src/sexpr/lexer_test.cpp b/src/sexpr/lexer_test.cpp index ade79af..fdb47f2 100644 --- a/src/sexpr/lexer_test.cpp +++ b/src/sexpr/lexer_test.cpp @@ -20,8 +20,15 @@ #include <gtest/gtest.h> +#include "../strings/vstring.hpp" + +#include "../tests/fdhack.hpp" + #include "../poison.hpp" + +namespace tmwa +{ static io::FD string_pipe(ZString sz) { @@ -40,69 +47,69 @@ io::FD string_pipe(ZString sz) TEST(sexpr, escape) { - EXPECT_EQ(sexpr::escape('\0'), "\\x00"); - EXPECT_EQ(sexpr::escape('\x1f'), "\\x1f"); - EXPECT_EQ(sexpr::escape('\x20'), " "); - EXPECT_EQ(sexpr::escape('\x7e'), "~"); - EXPECT_EQ(sexpr::escape('\x7f'), "\\x7f"); - EXPECT_EQ(sexpr::escape('\x80'), "\\x80"); - EXPECT_EQ(sexpr::escape('\xff'), "\\xff"); - EXPECT_EQ(sexpr::escape('\a'), "\\a"); - EXPECT_EQ(sexpr::escape('\b'), "\\b"); - EXPECT_EQ(sexpr::escape('\e'), "\\e"); - EXPECT_EQ(sexpr::escape('\f'), "\\f"); - //EXPECT_EQ(sexpr::escape('\n'), "\\n"); - EXPECT_EQ(sexpr::escape('\n'), "\n"); - EXPECT_EQ(sexpr::escape('\r'), "\\r"); - EXPECT_EQ(sexpr::escape('\t'), "\\t"); - EXPECT_EQ(sexpr::escape('\v'), "\\v"); - EXPECT_EQ(sexpr::escape('\\'), "\\\\"); - EXPECT_EQ(sexpr::escape('\"'), "\\\""); + EXPECT_EQ(sexpr::escape('\0'), "\\x00"_s); + EXPECT_EQ(sexpr::escape('\x1f'), "\\x1f"_s); + EXPECT_EQ(sexpr::escape('\x20'), " "_s); + EXPECT_EQ(sexpr::escape('\x7e'), "~"_s); + EXPECT_EQ(sexpr::escape('\x7f'), "\\x7f"_s); + EXPECT_EQ(sexpr::escape('\x80'), "\\x80"_s); + EXPECT_EQ(sexpr::escape('\xff'), "\\xff"_s); + EXPECT_EQ(sexpr::escape('\a'), "\\a"_s); + EXPECT_EQ(sexpr::escape('\b'), "\\b"_s); + EXPECT_EQ(sexpr::escape('\e'), "\\e"_s); + EXPECT_EQ(sexpr::escape('\f'), "\\f"_s); + //EXPECT_EQ(sexpr::escape('\n'), "\\n"_s); + EXPECT_EQ(sexpr::escape('\n'), "\n"_s); + EXPECT_EQ(sexpr::escape('\r'), "\\r"_s); + EXPECT_EQ(sexpr::escape('\t'), "\\t"_s); + EXPECT_EQ(sexpr::escape('\v'), "\\v"_s); + EXPECT_EQ(sexpr::escape('\\'), "\\\\"_s); + EXPECT_EQ(sexpr::escape('\"'), "\\\""_s); - EXPECT_EQ(sexpr::escape("\x1f\x20\x7e\x7f\x80\xff\a\b\e\f\r\t\v\\\""), - "\"\\x1f ~\\x7f\\x80\\xff\\a\\b\\e\\f\\r\\t\\v\\\\\\\"\""); + EXPECT_EQ(sexpr::escape("\x1f\x20\x7e\x7f\x80\xff\a\b\e\f\r\t\v\\\""_s), + "\"\\x1f ~\\x7f\\x80\\xff\\a\\b\\e\\f\\r\\t\\v\\\\\\\"\""_s); } TEST(sexpr, lexer) { io::LineSpan span; - sexpr::Lexer lexer("<lexer-test1>", string_pipe(" foo( ) 123\"\" \n")); + sexpr::Lexer lexer("<lexer-test1>"_s, string_pipe(" foo( ) 123\"\" \n"_s)); EXPECT_EQ(lexer.peek(), sexpr::TOK_TOKEN); - EXPECT_EQ(lexer.val_string(), "foo"); - EXPECT_EQ(lexer.span().message_str("error", "test"), + EXPECT_EQ(lexer.val_string(), "foo"_s); + EXPECT_EQ(lexer.span().message_str("error"_s, "test"_s), "<lexer-test1>:1:2: error: test\n" " foo( ) 123\"\" \n" - " ^~~\n" + " ^~~\n"_s ); lexer.adv(); EXPECT_EQ(lexer.peek(), sexpr::TOK_OPEN); - EXPECT_EQ(lexer.span().message_str("error", "test"), + EXPECT_EQ(lexer.span().message_str("error"_s, "test"_s), "<lexer-test1>:1:5: error: test\n" " foo( ) 123\"\" \n" - " ^\n" + " ^\n"_s ); lexer.adv(); EXPECT_EQ(lexer.peek(), sexpr::TOK_CLOSE); - EXPECT_EQ(lexer.span().message_str("error", "test"), + EXPECT_EQ(lexer.span().message_str("error"_s, "test"_s), "<lexer-test1>:1:7: error: test\n" " foo( ) 123\"\" \n" - " ^\n" + " ^\n"_s ); lexer.adv(); EXPECT_EQ(lexer.peek(), sexpr::TOK_TOKEN); - EXPECT_EQ(lexer.val_string(), "123"); - EXPECT_EQ(lexer.span().message_str("error", "test"), + EXPECT_EQ(lexer.val_string(), "123"_s); + EXPECT_EQ(lexer.span().message_str("error"_s, "test"_s), "<lexer-test1>:1:9: error: test\n" " foo( ) 123\"\" \n" - " ^~~\n" + " ^~~\n"_s ); lexer.adv(); EXPECT_EQ(lexer.peek(), sexpr::TOK_STRING); - EXPECT_EQ(lexer.val_string(), ""); - EXPECT_EQ(lexer.span().message_str("error", "test"), + EXPECT_EQ(lexer.val_string(), ""_s); + EXPECT_EQ(lexer.span().message_str("error"_s, "test"_s), "<lexer-test1>:1:12: error: test\n" " foo( ) 123\"\" \n" - " ^~\n" + " ^~\n"_s ); lexer.adv(); EXPECT_EQ(lexer.peek(), sexpr::TOK_EOF); @@ -110,24 +117,26 @@ TEST(sexpr, lexer) TEST(sexpr, lexbad) { + QuietFd q; { io::LineSpan span; - sexpr::Lexer lexer("<lexer-bad>", string_pipe("(\n")); + sexpr::Lexer lexer("<lexer-bad>"_s, string_pipe("(\n"_s)); EXPECT_EQ(lexer.peek(), sexpr::TOK_OPEN); lexer.adv(); EXPECT_EQ(lexer.peek(), sexpr::TOK_ERROR); } for (ZString bad : { - ZString(")\n"), - ZString("\"\n"), - ZString("'\n"), - ZString("\\\n"), - ZString("\"\\"), - ZString("\"\\z\""), + ZString(")\n"_s), + ZString("\"\n"_s), + ZString("'\n"_s), + ZString("\\\n"_s), + ZString("\"\\"_s), + ZString("\"\\z\""_s), }) { io::LineSpan span; - sexpr::Lexer lexer("<lexer-bad>", string_pipe(bad)); + sexpr::Lexer lexer("<lexer-bad>"_s, string_pipe(bad)); EXPECT_EQ(lexer.peek(), sexpr::TOK_ERROR); } } +} // namespace tmwa diff --git a/src/sexpr/main.cpp b/src/sexpr/main.cpp deleted file mode 100644 index 18cb8c2..0000000 --- a/src/sexpr/main.cpp +++ /dev/null @@ -1,148 +0,0 @@ -// sexpr/main.cpp - Driver for new magic formatter. -// -// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> -// -// This file is part of The Mana World (Athena server) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <stack> -#include <map> - -#include "../io/cxxstdio.hpp" - -#include "lexer.hpp" -#include "parser.hpp" - -#include "../poison.hpp" - -enum Spacing -{ - LINES, - SIMPLE, - SPACES, - SPACES_1, - SPACES_2, - SPACES_3, - SPACES_4, -}; - -static -void do_spacing(bool& first, Spacing& sp, int depth) -{ - if (first) - { - first = false; - return; - } - switch (sp) - { - case LINES: - PRINTF("\n%*s", (depth - 1) * 4, ""); - return; - case SPACES: - case SIMPLE: - PRINTF(" "); - return; - case SPACES_1: - PRINTF(" "); - sp = LINES; - return; - case SPACES_2: - PRINTF(" "); - sp = SPACES_1; - return; - case SPACES_3: - PRINTF(" "); - sp = SPACES_2; - return; - case SPACES_4: - PRINTF(" "); - sp = SPACES_3; - return; - } -} - -static -void adjust_spacing(Spacing& sp, ZString val) -{ - std::map<ZString, Spacing> spaces = - { - {"BLOCK", LINES}, - {"GUARD", LINES}, - {"DISABLED", LINES}, - {"PROCEDURE", SPACES_2}, - {"SPELL", SPACES_4}, - {"IF", SPACES_1}, - {"set_script_variable", SPACES_2}, - }; - auto it = spaces.find(val); - if (it != spaces.end()) - sp = it->second; -} - -int main() -{ - if (1 == 1) - { - sexpr::Lexer lexer("/dev/stdin"); - sexpr::SExpr sexpr; - while (sexpr::parse(lexer, sexpr)) - { - PRINTF(""); - } - if (lexer.peek() != sexpr::TOK_EOF) - { - lexer.span().error(STRPRINTF("Incomplete: %s: %s\n", - sexpr::token_name(lexer.peek()), lexer.val_string())); - } - return 0; - } - - std::stack<Spacing> spacing; - spacing.push(LINES); - sexpr::Lexer lexer("/dev/stdin"); - bool first = true; - while (sexpr::Lexeme tok = lexer.peek()) - { - switch (tok) - { - case sexpr::TOK_OPEN: - if (spacing.top() == SIMPLE) - spacing.top() = LINES; - do_spacing(first, spacing.top(), spacing.size()); - PRINTF("("); - spacing.push(SIMPLE); - first = true; - break; - case sexpr::TOK_CLOSE: - PRINTF(")"); - spacing.pop(); - first = false; - break; - case sexpr::TOK_STRING: - do_spacing(first, spacing.top(), spacing.size()); - PRINTF("%s", sexpr::escape(lexer.val_string())); - break; - case sexpr::TOK_TOKEN: - do_spacing(first, spacing.top(), spacing.size()); - PRINTF("%s", lexer.val_string()); - adjust_spacing(spacing.top(), lexer.val_string()); - break; - default: - abort(); - } - lexer.adv(); - } - PRINTF("\n"); -} diff --git a/src/sexpr/parser.cpp b/src/sexpr/parser.cpp index 2068565..8768e14 100644 --- a/src/sexpr/parser.cpp +++ b/src/sexpr/parser.cpp @@ -18,8 +18,16 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include <cerrno> + +#include "../strings/zstring.hpp" +#include "../strings/xstring.hpp" + #include "../poison.hpp" + +namespace tmwa +{ namespace sexpr { bool token_is_int(ZString s, int64_t& out, bool& ok) @@ -77,3 +85,4 @@ namespace sexpr return rv; } } // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/parser.hpp b/src/sexpr/parser.hpp index 6097f78..feed636 100644 --- a/src/sexpr/parser.hpp +++ b/src/sexpr/parser.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_SEXPR_PARSER_HPP -#define TMWA_SEXPR_PARSER_HPP +#pragma once // parser.hpp - build a tree of S-expressions // // Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,14 +18,21 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "../strings/zstring.hpp" +#include <cstdlib> -# include "../io/line.hpp" +#include "../strings/fwd.hpp" -# include "lexer.hpp" +#include "../io/line.hpp" +#include "lexer.hpp" + +#include "fwd.hpp" + + +namespace tmwa +{ namespace sexpr { enum Type @@ -76,5 +82,4 @@ namespace sexpr /// return false on error or eof, check lex.peek() == TOK_EOF to see bool parse(Lexer& lex, SExpr& out); } // namespace sexpr - -#endif // TMWA_SEXPR_PARSER_HPP +} // namespace tmwa diff --git a/src/sexpr/parser.py b/src/sexpr/parser.py index d638259..201f457 100644 --- a/src/sexpr/parser.py +++ b/src/sexpr/parser.py @@ -2,7 +2,7 @@ class SExpr(object): ''' print a SExpr ''' __slots__ = ('_value') - name = 'sexpr::SExpr' + name = 'tmwa::sexpr::SExpr' enabled = True def __init__(self, value): diff --git a/src/sexpr/parser_test.cpp b/src/sexpr/parser_test.cpp index d67d041..846d425 100644 --- a/src/sexpr/parser_test.cpp +++ b/src/sexpr/parser_test.cpp @@ -22,6 +22,9 @@ #include "../poison.hpp" + +namespace tmwa +{ static io::FD string_pipe(ZString sz) { @@ -42,11 +45,11 @@ TEST(sexpr, parser) { sexpr::SExpr s; io::LineSpan span; - sexpr::Lexer lexer("<parser-test1>", string_pipe(" foo( ) 123\"\" \n")); + sexpr::Lexer lexer("<parser-test1>"_s, string_pipe(" foo( ) 123\"\" \n"_s)); EXPECT_TRUE(sexpr::parse(lexer, s)); EXPECT_EQ(s._type, sexpr::TOKEN); - EXPECT_EQ(s._str, "foo"); + EXPECT_EQ(s._str, "foo"_s); EXPECT_TRUE(sexpr::parse(lexer, s)); EXPECT_EQ(s._type, sexpr::LIST); @@ -58,7 +61,7 @@ TEST(sexpr, parser) EXPECT_TRUE(sexpr::parse(lexer, s)); EXPECT_EQ(s._type, sexpr::STRING); - EXPECT_EQ(s._str, ""); + EXPECT_EQ(s._str, ""_s); EXPECT_FALSE(sexpr::parse(lexer, s)); EXPECT_EQ(lexer.peek(), sexpr::TOK_EOF); @@ -67,19 +70,19 @@ TEST(sexpr, parser) TEST(sexpr, parselist) { sexpr::SExpr s; - sexpr::Lexer lexer("<parser-test1>", string_pipe("(foo)(bar)\n")); + sexpr::Lexer lexer("<parser-test1>"_s, string_pipe("(foo)(bar)\n"_s)); EXPECT_TRUE(sexpr::parse(lexer, s)); EXPECT_EQ(s._type, sexpr::LIST); EXPECT_EQ(s._list.size(), 1); EXPECT_EQ(s._list[0]._type, sexpr::TOKEN); - EXPECT_EQ(s._list[0]._str, "foo"); + EXPECT_EQ(s._list[0]._str, "foo"_s); EXPECT_TRUE(sexpr::parse(lexer, s)); EXPECT_EQ(s._type, sexpr::LIST); EXPECT_EQ(s._list.size(), 1); EXPECT_EQ(s._list[0]._type, sexpr::TOKEN); - EXPECT_EQ(s._list[0]._str, "bar"); + EXPECT_EQ(s._list[0]._str, "bar"_s); EXPECT_FALSE(sexpr::parse(lexer, s)); EXPECT_EQ(lexer.peek(), sexpr::TOK_EOF); @@ -87,23 +90,24 @@ TEST(sexpr, parselist) TEST(sexpr, parsebad) { - for (ZString bad : { - ZString("(\n"), - ZString(")\n"), - ZString("\"\n"), - ZString("'\n"), - ZString("\\\n"), - ZString("\"\\"), - ZString("\"\\z\""), - ZString("(()\n"), - ZString("((\n"), - ZString("((\"\n"), + for (LString bad : { + "(\n"_s, + ")\n"_s, + "\"_s\n"_s, + "'\n"_s, + "\\\n"_s, + "\"_s\\"_s, + "\"_s\\z\""_s, + "(()\n"_s, + "((\n"_s, + "((\"\n"_s, }) { sexpr::SExpr s; io::LineSpan span; - sexpr::Lexer lexer("<parse-bad>", string_pipe(bad)); + sexpr::Lexer lexer("<parse-bad>"_s, string_pipe(bad)); EXPECT_FALSE(sexpr::parse(lexer, s)); EXPECT_EQ(lexer.peek(), sexpr::TOK_ERROR); } } +} // namespace tmwa diff --git a/src/sexpr/union.cpp b/src/sexpr/union.cpp new file mode 100644 index 0000000..6f65012 --- /dev/null +++ b/src/sexpr/union.cpp @@ -0,0 +1,44 @@ +#include "union.hpp" +// union.cpp - Just include the header file and try to instantiate. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +namespace sexpr +{ +namespace +{ + struct Foo + { + Foo(); + Foo(const Foo&); + Foo& operator = (const Foo&); + ~Foo(); + }; +} // anonymous namespace +static Union<int, Foo> u; + +static_assert(u.index<int>() == 0, "int"); +static_assert(u.index<Foo>() == 1, "Foo"); +static_assert(u.index<char>() == size_t(-1), "char"); +} // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/union.hpp b/src/sexpr/union.hpp new file mode 100644 index 0000000..6a0b6b0 --- /dev/null +++ b/src/sexpr/union.hpp @@ -0,0 +1,105 @@ +#pragma once +// union.hpp - A (unsafe!) convenience wrapper for classes in unions. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <utility> +#include <type_traits> +#include <cstddef> +#include <new> + +#include "fwd.hpp" + + +namespace tmwa +{ +namespace sexpr +{ + template<class... T> + class Union; + + template<> + class Union<> + { + public: + template<class T> + constexpr static size_t index() + { + return -1; + } + Union() = default; + ~Union() = default; + Union(const Union&) = delete; + Union& operator = (const Union&) = delete; + }; + + template<class F, class... R> + class Union<F, R...> + { + static_assert(!std::is_const<F>::value, "union elements are not const"); + static_assert(!std::is_volatile<F>::value, "union elements are not volatile"); + static_assert(!std::is_reference<F>::value, "union elements are not references"); + static_assert(Union<R...>::template index<F>() == size_t(-1), "unions do not contain duplicates"); + union Impl + { + F first; + Union<R...> rest; + + Impl() {} + ~Impl() {} + } data; + public: + template<class T> + constexpr static size_t index() + { + return std::is_same<F, T>::value + ? 0 + : 1 + Union<R...>::template index<T>() + ?: -1; + } + template<class T> + void get(T*& p) { data.rest.get(p); } + void get(F*& p) { p = std::addressof(data.first); } + template<class T> + void get(const T*& p) const { data.rest.get(p); } + void get(const F*& p) const { p = std::addressof(data.first); } + + template<class T> + T *get() { T *out; get(out); return out; } + template<class T> + const T *get() const { const T *out; get(out); return out; } + + Union() = default; + ~Union() = default; + Union(const Union&) = delete; + Union& operator = (const Union&) = delete; + + template<class T, class... A> + void construct(A&&... a) + { + new (get<T>()) T(std::forward<A>(a)...); + } + + template<class T> + void destruct() + { + get<T>()->~T(); + } + }; +} // namespace sexpr +} // namespace tmwa diff --git a/src/compat/alg.hpp b/src/sexpr/variant.cpp index adf3f3f..b1f500a 100644 --- a/src/compat/alg.hpp +++ b/src/sexpr/variant.cpp @@ -1,6 +1,5 @@ -#ifndef TMWA_COMPAT_ALG_HPP -#define TMWA_COMPAT_ALG_HPP -// alg.hpp - Silly math stuff. +#include "variant.hpp" +// variant.cpp - Just include the header file. // // Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> // @@ -19,21 +18,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "../poison.hpp" -# include <type_traits> - -template<class A, class B> -typename std::common_type<A, B>::type min(A a, B b) +namespace tmwa { - return a < b ? a : b; -} - -template<class A, class B> -typename std::common_type<A, B>::type max(A a, B b) +namespace sexpr { - return b < a ? a : b; -} - -#endif // TMWA_COMPAT_ALG_HPP +namespace +{ + struct Foo + { + Foo() {} + ~Foo() {} + Foo(Foo&&) {} + Foo& operator = (Foo&&) { return *this; } + }; +} // anonymous namespace + static Variant<int, Foo> v; +} // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/variant.hpp b/src/sexpr/variant.hpp new file mode 100644 index 0000000..04f35dc --- /dev/null +++ b/src/sexpr/variant.hpp @@ -0,0 +1,116 @@ +#pragma once +// variant.hpp - A single value, multiple type container. Better than boost's. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <type_traits> +#include <cstdint> +#include <cstddef> +#include <utility> + +#include "union.hpp" +#include "void.hpp" + +#include "fwd.hpp" + + +namespace tmwa +{ +namespace sexpr +{ +#define JOIN(a, b) a##b + +#define WITH_VAR(ty, var, expr) \ + for (bool JOIN(var, _guard) = true; JOIN(var, _guard); ) \ + for (ty var = expr; JOIN(var, _guard); JOIN(var, _guard) = false) +#define MATCH(expr) \ + WITH_VAR(auto&&, _match_var, expr) \ + switch (tmwa::sexpr::VariantFriend::get_state(_match_var)) +#define CASE(ty, var) \ + break; \ + case tmwa::sexpr::VariantFriend::get_state_for<ty, decltype(_match_var)>(): \ + WITH_VAR(ty, var, tmwa::sexpr::VariantFriend::unchecked_get<ty>(_match_var)) + + template<class... T> + class Variant + { + static_assert(sizeof...(T), "A variant must not be empty"); + }; + template<class D, class... T> + class Variant<D, T...> + { + constexpr static size_t state_count = 1 + sizeof...(T); + + // simplify things immensely + friend class VariantFriend; + + typedef Union<D, T...> DataType; + DataType data; + size_t state; + + void do_destruct(); + template<class C, class... A> + void do_construct(A&&... a); + public: + Variant(); + ~Variant(); + + void reset(); + template<class C, class... A> + void emplace(A&&... a); + + Variant(const Variant& r); + Variant(Variant&& r); + Variant& operator = (const Variant& r); + Variant& operator = (Variant&& r); + + template<class E> + Variant(E e) + { + do_construct<E, E>(std::move(e)); + } + + template<class E> + Variant& operator = (E e) + { + emplace<E, E>(std::move(e)); + return *this; + } + + // use these ONLY if only one type makes sense + // otherwise use apply + template<class E> + bool is() const; + + template<class E> + E *get_if(); + + template<class E> + const E *get_if() const; + }; + + template<class R, class F> + void apply(R& r, F&& f); + template<class R, class F, class V1, class... V> + void apply(R& r, F&& f, V1&& v1, V&&... v); + template<class F, class... V> + void apply(Void&& r, F&& f, V&&... v); +} // namespace sexpr +} // namespace tmwa + +#include "variant.tcc" diff --git a/src/sexpr/variant.tcc b/src/sexpr/variant.tcc new file mode 100644 index 0000000..424a8f1 --- /dev/null +++ b/src/sexpr/variant.tcc @@ -0,0 +1,293 @@ +// variant.tcc - implementation of inlines and templates in variant.hpp +// +// Copyright © 2012-2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <cassert> +#include "bind.hpp" + +namespace tmwa +{ +namespace sexpr +{ + class VariantFriend + { + public: + template<class U, class... T, class... A> + static void unchecked_do_construct(Variant<T...> *var, A&&... a) + { + var->template do_construct<U, A...>(std::forward<A>(a)...); + } + template<class E, class... T> + static E& unchecked_get(Variant<T...>& var) + { + return *var.data.template get<E>(); + } + template<class E, class... T> + static const E& unchecked_get(const Variant<T...>& var) + { + return *var.data.template get<E>(); + } + template<class E, class... T> + static E&& unchecked_get(Variant<T...>&& var) + { + return std::move(*var.data.template get<E>()); + } + template<class E, class... T> + static const E&& unchecked_get(const Variant<T...>&& var) + { + return std::move(*var.data.template get<E>()); + } + + template<class E, class R, class F, class V1, class... V> + static void _apply_unchecked(R& r, F&& f, V1&& v1, V&&... v) + { + apply(r, bind_variadic(std::forward<F>(f), VariantFriend::unchecked_get<E>(std::forward<V1>(v1))), std::forward<V>(v)...); + } + + template<class... T, class R, class F, class V1, class... V> + static void _apply_dispatch(const Variant<T...> *, R& r, F&& f, V1&& v1, V&&... v) + { + typedef void (*Function)(R&, F&&, V1&&, V&&...); + constexpr static Function dispatch[sizeof...(T)] = { _apply_unchecked<T, R, F, V1, V...>... }; + assert(v1.state < sizeof...(T)); + dispatch[v1.state](r, std::forward<F>(f), std::forward<V1>(v1), std::forward<V>(v)...); + } + + template<class... T> + static size_t get_state(const Variant<T...>& variant) + { + return variant.state; + } + + template<class W, class V> + constexpr static size_t get_state_for() + { + return std::remove_reference<V>::type::DataType::template index<W>(); + } + }; + + + struct Destruct + { + template<class U> + void operator ()(U& v) + { + v.~U(); + } + }; + + template<class D, class... T> + void Variant<D, T...>::do_destruct() + { + apply(Void(), Destruct(), *this); + } + + template<class D, class... T> + template<class C, class... A> + void Variant<D, T...>::do_construct(A&&... a) + { + try + { + data.template construct<C, A...>(std::forward<A>(a)...); + state = Union<D, T...>::template index<C>(); + } + catch(...) + { + static_assert(std::is_nothrow_constructible<D>::value, "first element is nothrow constructible"); + data.template construct<D>(); + state = 0; + throw; + } + } + + template<class D, class... T> + Variant<D, T...>::Variant() + { + do_construct<D>(); + state = 0; + } + + template<class D, class... T> + Variant<D, T...>::~Variant() + { + do_destruct(); + } + + template<class D, class... T> + void Variant<D, T...>::reset() + { + do_destruct(); + do_construct<D>(); + } + + template<class D, class... T> + template<class C, class... A> + void Variant<D, T...>::emplace(A&&... a) + { + do_destruct(); + do_construct<C, A...>(std::forward<A>(a)...); + } + + template<class... T> + class CopyConstruct + { + Variant<T...> *target; + public: + CopyConstruct(Variant<T...> *v) : target(v) {} + template<class U> + void operator ()(const U& u) + { + VariantFriend::unchecked_do_construct<U>(target, u); + } + }; + template<class... T> + class MoveConstruct + { + Variant<T...> *target; + public: + MoveConstruct(Variant<T...> *v) : target(v) {} + template<class U> + void operator ()(U&& u) + { + VariantFriend::unchecked_do_construct<U>(target, std::move(u)); + } + }; + + // assignment requires unchecked access + template<class... T> + class CopyAssign + { + Union<T...> *data; + public: + CopyAssign(Union<T...> *d) : data(d) {} + template<class U> + void operator ()(const U& u) + { + *data->template get<U>() = u; + } + }; + + template<class... T> + class MoveAssign + { + Union<T...> *data; + public: + MoveAssign(Union<T...> *d) : data(d) {} + template<class U> + void operator () (U&& u) + { + *data->template get<U>() = std::move(u); + } + }; + + template<class D, class... T> + Variant<D, T...>::Variant(const Variant& r) + { + apply(Void(), CopyConstruct<D, T...>(this), r); + } + + template<class D, class... T> + Variant<D, T...>::Variant(Variant&& r) + { + apply(Void(), MoveConstruct<D, T...>(this), std::move(r)); + } + + template<class D, class... T> + Variant<D, T...>& Variant<D, T...>::operator = (const Variant& r) + { + if (state == r.state) + apply(Void(), CopyAssign<D, T...>(this), r); + else + { + do_destruct(); + apply(Void(), CopyConstruct<D, T...>(this), r); + } + return *this; + } + + template<class D, class... T> + Variant<D, T...>& Variant<D, T...>::operator = (Variant&& r) + { + if (state == r.state) + apply(Void(), MoveAssign<D, T...>(&data), std::move(r)); + else + { + do_destruct(); + apply(Void(), MoveConstruct<D, T...>(this), std::move(r)); + } + return *this; + } + + template<class D, class... T> + template<class E> + bool Variant<D, T...>::is() const + { + return get_if<E>(); + } + + template<class D, class... T> + template<class E> + E *Variant<D, T...>::get_if() + { + if (state == Union<D, T...>::template index<E>()) + return data.template get<E>(); + return nullptr; + } + + template<class D, class... T> + template<class E> + const E *Variant<D, T...>::get_if() const + { + if (state == Union<D, T...>::template index<E>()) + return data.template get<E>(); + return nullptr; + } + + template<class R, class F> + void _apply_assign(std::true_type, R& r, F&& f) + { + std::forward<F>(f)(); + r = Void(); + } + + template<class R, class F> + void _apply_assign(std::false_type, R& r, F&& f) + { + r = std::forward<F>(f)(); + } + + template<class R, class F> + void apply(R& r, F&& f) + { + _apply_assign(std::is_void<decltype(std::forward<F>(f)())>(), r, std::forward<F>(f)); + } + + template<class R, class F, class V1, class... V> + void apply(R& r, F&& f, V1&& v1, V&&... v) + { + VariantFriend::_apply_dispatch(&v1, r, std::forward<F>(f), std::forward<V1>(v1), std::forward<V>(v)...); + } + + template<class F, class... V> + void apply(Void&& r, F&& f, V&&... v) + { + apply(r, std::forward<F>(f), std::forward<V>(v)...); + } + +} // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/variant_test.cpp b/src/sexpr/variant_test.cpp new file mode 100644 index 0000000..5a75780 --- /dev/null +++ b/src/sexpr/variant_test.cpp @@ -0,0 +1,123 @@ +#include "variant.hpp" +// variant_test.cpp - Testsuite for multi-type container that's better than boost's. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <gtest/gtest.h> + +#include "../strings/vstring.hpp" + +//#include "../poison.hpp" + + +namespace tmwa +{ + struct Tracker + { + int id, moves, copies; + + explicit + Tracker(int i) + : id(i), moves(0), copies(0) + {} + Tracker(Tracker&& rhs) + : id(rhs.id), moves(rhs.moves + 1), copies(rhs.copies) + { rhs.id = 0; } + Tracker(const Tracker& rhs) + : id(rhs.id), moves(rhs.moves), copies(rhs.copies + 1) + {} + Tracker& operator = (Tracker&& rhs) + { id = rhs.id; moves = rhs.moves + 1; copies = rhs.copies; rhs.id = 0; return *this; } + Tracker& operator = (const Tracker& rhs) + { id = rhs.id; moves = rhs.moves; copies = rhs.copies + 1; return *this; } + }; + struct Foo : Tracker + { + // needed for first param of variant + Foo() noexcept : Tracker(0) { abort(); } + + Foo(int i) : Tracker(i) {} + }; + struct Bar : Tracker + { + Bar(int i) : Tracker(i) {} + }; + struct Qux : Tracker + { + // needed for first param of variant + Qux() noexcept : Tracker(0) { abort(); } + + Qux(int i) : Tracker(i) {} + Qux(Qux&&) = default; + Qux(const Qux&) = delete; + Qux& operator = (Qux&&) = default; + Qux& operator = (const Qux&) = default; + }; + +TEST(variant, match) +{ + struct Sub : sexpr::Variant<Foo, Bar> + { + Sub() + : sexpr::Variant<Foo, Bar>(Foo(1)) + {} + }; + Sub v1; + MATCH (v1) + { + // This is not a public API, it's just for testing. + default: + FAIL(); + + CASE(Foo, f) + { + (void)f; + SUCCEED(); + } + CASE(Bar, b) + { + (void)b; + FAIL(); + } + } + v1.emplace<Bar>(2); + MATCH (v1) + { + // This is not a public API, it's just for testing. + default: + FAIL(); + + CASE(Foo, f) + { + (void)f; + FAIL(); + } + CASE(Bar, b) + { + (void)b; + SUCCEED(); + } + } +} + +TEST(variant, copymove) +{ + sexpr::Variant<Qux> moveonly(Qux(3)); + (void)moveonly; +} +} // namespace tmwa diff --git a/src/sexpr/void.cpp b/src/sexpr/void.cpp new file mode 100644 index 0000000..9f0eeb5 --- /dev/null +++ b/src/sexpr/void.cpp @@ -0,0 +1,29 @@ +#include "void.hpp" +// void.cpp - Just include the header file. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +namespace sexpr +{ +} // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/void.hpp b/src/sexpr/void.hpp new file mode 100644 index 0000000..a17de9d --- /dev/null +++ b/src/sexpr/void.hpp @@ -0,0 +1,40 @@ +#pragma once +// void.hpp - A type that represents nothing and anything. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + + +namespace tmwa +{ +namespace sexpr +{ + struct Void + { + template<class T> + constexpr operator T() const noexcept { return T(); } + template<class T> + void operator = (T&&) noexcept {} + template<class T> + constexpr Void(T&&) noexcept {} + constexpr Void() noexcept; + }; + constexpr Void::Void() noexcept = default; +} // namespace sexpr +} // namespace tmwa diff --git a/src/shared/lib.cpp b/src/shared/lib.cpp new file mode 100644 index 0000000..a9dc9b1 --- /dev/null +++ b/src/shared/lib.cpp @@ -0,0 +1,80 @@ +#include <tmwa/shared.hpp> +// shared/lib.cpp - Public library to ensure install is working. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../conf/install.hpp" + +#include "../strings/literal.hpp" +#include "../strings/astring.hpp" +#include "../strings/zstring.hpp" + +#include "../io/cxxstdio.hpp" +#include "../io/dir.hpp" +#include "../io/read.hpp" +#include "../io/write.hpp" + +#include "../poison.hpp" + + +namespace tmwa +{ +#define PRINT_VAR(var) PRINTF("%s = %s\n"_fmt, #var##_s, var) + + static + void try_read(const io::DirFd& dirfd, ZString filename) + { + io::ReadFile rf(dirfd, filename); + if (!rf.is_open()) + abort(); + AString line; + if (!rf.getline(line)) + abort(); + } + + static + void try_write(const io::DirFd& dirfd, ZString filename) + { + io::WriteFile wf(dirfd, filename); + if (!wf.is_open()) + abort(); + wf.put_line("Hello, World!"_s); + if (!wf.close()) + abort(); + } + + void check_paths() + { + ZString portable_root(strings::really_construct_from_a_pointer, getenv("TMWA_PORTABLE") ?: "", nullptr); + bool portable = bool(portable_root); + if (!portable) + portable_root = "."_s; + + io::DirFd root(portable_root); + + io::DirFd etc(root, PACKAGESYSCONFDIR.xslice_t(portable)); + io::DirFd var(root, PACKAGELOCALSTATEDIR.xslice_t(portable)); + io::DirFd share(root, PACKAGEDATADIR.xslice_t(portable)); + + try_read(etc, "shared.conf"_s); + try_read(share, "shared.data"_s); + try_write(var, "shared.test"_s); + + // io::FD::open(); + } +} // namespace tmwa diff --git a/src/spell-convert/ast.cpp b/src/spell-convert/ast.cpp deleted file mode 100644 index e9ec19c..0000000 --- a/src/spell-convert/ast.cpp +++ /dev/null @@ -1,280 +0,0 @@ -#include "ast.hpp" -// ast.cpp - Hacky converter between magic formats. -// -// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> -// -// This file is part of The Mana World (Athena server) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. - -#include "../io/cxxstdio.hpp" - -#include "../poison.hpp" - -void Constant::dump() -{ - PRINTF("(CONST %s\n", name); - body->show(); - PRINTF(")\n"); -} -void Teleport::dump() -{ - PRINTF("(TELEPORT-ANCHOR %s\n", name); - ident->show(); - body->show(); - PRINTF(")\n"); -} -void Procedure::dump() -{ - PRINTF("(PROCEDURE %s\n", name); - PRINTF("("); - for (RString& a : *args) - PRINTF(" %s ", a); - PRINTF(")\n"); - for (Effect *f : *body) - { - f->print(); - } - PRINTF(")\n"); -} -void Spell::dump() -{ - PRINTF("(SPELL \n"); - PRINTF("("); - for (RString fl : *flags) - PRINTF(" %s ", fl); - PRINTF(")"); - PRINTF("%s", name); - ident->show(); - PRINTF("( %s %s )", arg->vartype, arg->varname); - for (Assignment *a : *body->lets) - { - PRINTF("(LET %s ", a->name); - a->body->show(); - PRINTF(")\n"); - } - for (SpellBod *b : *body->body) - { - b->say(); - } - PRINTF(")\n"); -} -void Assignment::dump() -{ - PRINTF("(SET %s\n", name); - body->show(); - PRINTF(")\n"); -} - -void EffectList::print() -{ - PRINTF("(BLOCK\n"); - for (Effect *ef : *body) - ef->print(); - PRINTF(")\n"); -} -void SimpleEffect::print() -{ - PRINTF("( %s )", text); -} -void ScriptEffect::print() -{ - PRINTF("(SCRIPT %s )", text); -} -void Assignment::print() -{ - PRINTF("(SET %s\n", name); - body->show(); - PRINTF(")\n"); -} -void ForeachEffect::print() -{ - PRINTF("(FOREACH %s %s ", selection, var); - expr->show(); - PRINTF("\n"); - effect->print(); - PRINTF(")"); -} -void ForEffect::print() -{ - PRINTF("(FOR %s", var); - low->show(); - high->show(); - effect->print(); - PRINTF(")"); -} -void IfEffect::print() -{ - PRINTF("(IF "); - cond->show(); - if_true->print(); - if (if_false_maybe) - if_false_maybe->print(); - PRINTF(")"); -} -void ExplicitCallEffect::print() -{ - PRINTF("(CALL %s ", userfunc); - for (Expression *x : *args) - x->show(); - PRINTF(")"); -} -void SleepEffect::print() -{ - PRINTF("(WAIT "); - time_->show(); - PRINTF(")"); -} -void CallExpr::print() -{ - PRINTF("(%s ", func); - for (Expression *x : *args) - x->show(); - PRINTF(")"); -} - -void SimpleExpr::show() -{ - PRINTF(" %s ", content); -} -void BinExpr::show() -{ - PRINTF("(%s ", op); - left->show(); - right->show(); - PRINTF(")"); -} -void CallExpr::show() -{ - PRINTF("(%s ", func); - for (Expression *x : *args) - x->show(); - PRINTF(")"); -} -void AreaLoc::show() -{ - PRINTF("(@ "); - loc->map->show(); - loc->x->show(); - loc->y->show(); - PRINTF(")"); -} -void AreaRect::show() -{ - PRINTF("(@+ "); - AreaLoc{loc}.show(); - width->show(); - height->show(); - PRINTF(")"); -} -void AreaBar::show() -{ - PRINTF("(TOWARD "); - AreaLoc{loc}.show(); - dir->show(); - width->show(); - depth->show(); - PRINTF(")"); -} - -void SpellBodGuarded::say() -{ - PRINTF("(=> "); - guard->declare(); - body->say(); - PRINTF(")"); -} -void SpellBodList::say() -{ - PRINTF("(|\n"); - for (SpellBod *b : *body) - b->say(); - PRINTF(")"); -} -void SpellBodEffect::say() -{ - PRINTF("(EFFECT\n"); - for (Effect *f : *body) - f->print(); - if (maybe_trigger) - { - PRINTF("(ATTRIGGER\n"); - for (Effect *f : *maybe_trigger) - f->print(); - PRINTF(")"); - } - if (maybe_end) - { - PRINTF("(ATEND\n"); - for (Effect *f : *maybe_end) - f->print(); - PRINTF(")"); - } - PRINTF(")"); -} - -void SpellGuardOr::declare() -{ - PRINTF("(OR\n"); - for (SpellGuard *sg : *any) - sg->declare(); - PRINTF(")"); -} -void SpellGuardList::declare() -{ - PRINTF("(GUARD\n"); - for (SpellGuard *sg : *all) - sg->declare(); - PRINTF(")"); -} -void SpellGuardRequire::declare() -{ - PRINTF("(REQUIRE "); - expr->show(); - PRINTF(")"); -} -static -void do_item(Item *itm) -{ - if (itm->count) - PRINTF("( %s %s )", itm->count, itm->item); - else - PRINTF(" %s ", itm->item); -} -void SpellGuardCatalysts::declare() -{ - PRINTF("(CATALYSTS "); - for (Item *itm : *items) - do_item(itm); - PRINTF(")"); -} -void SpellGuardComponents::declare() -{ - PRINTF("(COMPONENTS "); - for (Item *itm : *items) - do_item(itm); - PRINTF(")"); -} -void SpellGuardMana::declare() -{ - PRINTF("(MANA "); - sp->show(); - PRINTF(")"); -} -void SpellGuardCasttime::declare() -{ - PRINTF("(CASTTIME "); - time_->show(); - PRINTF(")"); -} diff --git a/src/spell-convert/ast.hpp b/src/spell-convert/ast.hpp deleted file mode 100644 index 3d2f282..0000000 --- a/src/spell-convert/ast.hpp +++ /dev/null @@ -1,465 +0,0 @@ -#ifndef TMWA_SPELL_CONVERT_AST_HPP -#define TMWA_SPELL_CONVERT_AST_HPP -// ast.hpp - Hacky converter between magic formats. -// -// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> -// -// This file is part of The Mana World (Athena server) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. - -# include "../sanity.hpp" - -# include <deque> -# include <vector> - -# include "../strings/rstring.hpp" - -# if __GNUC__ == 4 && __GNUC_MINOR__ == 6 -# define override -# endif - -// We just leak -# pragma GCC diagnostic ignored "-Wnon-virtual-dtor" - -struct TopLevel; -struct Constant; -struct Teleport; -struct Procedure; -struct Spell; -struct SpellArg; -struct Effect; -struct EffectList; -struct SimpleEffect; -struct ScriptEffect; -struct Assignment; -struct ForeachEffect; -struct ForEffect; -struct IfEffect; -struct ExplicitCallEffect; -struct SleepEffect; -struct SpellDef; -struct SpellBod; -struct SpellBodGuarded; -struct SpellBodList; -struct SpellBodEffect; -struct SpellGuard; -struct SpellGuardOr; -struct SpellGuardList; -struct SpellGuardRequire; -struct SpellGuardCatalysts; -struct SpellGuardComponents; -struct SpellGuardMana; -struct SpellGuardCasttime; -struct Item; -struct Expression; -struct SimpleExpr; -struct BinExpr; -struct CallExpr; -struct Location; -struct AreaLoc; -struct AreaRect; -struct AreaBar; - - -struct TopLevel -{ - virtual void dump() = 0; -}; - -struct Constant : TopLevel -{ - RString name; - Expression *body; - - Constant(RString n, Expression *b) - : name(n), body(b) - {} - - virtual void dump() override; -}; - -struct Teleport : TopLevel -{ - RString name; - Expression *ident; - Expression *body; - - Teleport(RString n, Expression *i, Expression *b) - : name(n), ident(i), body(b) - {} - - virtual void dump() override; -}; - -struct Procedure : TopLevel -{ - RString name; - std::vector<RString> *args; - std::deque<Effect *> *body; - - Procedure(RString n, std::vector<RString> *a, std::deque<Effect *> *b) - : name(n), args(a), body(b) - {} - - virtual void dump() override; -}; - -struct Spell : TopLevel -{ - std::vector<RString> *flags; - RString name; - SpellArg *arg; - Expression *ident; - SpellDef *body; - - Spell(std::vector<RString> *f, RString n, SpellArg *a, Expression *i, SpellDef *b) - : flags(f), name(n), arg(a), ident(i), body(b) - {} - - virtual void dump() override; -}; - -struct SpellArg -{ - RString varname; - RString vartype; - - SpellArg() : varname(), vartype() {} - SpellArg(RString n, RString t) : varname(n), vartype(t) {} -}; - -struct Effect -{ - virtual void print() = 0; -}; - -struct EffectList : Effect -{ - std::deque<Effect *> *body; - - EffectList(std::deque<Effect *> *b) - : body(b) - {} - - virtual void print() override; -}; -struct SimpleEffect : Effect -{ - RString text; - - SimpleEffect(RString t) : text(t) {} - - virtual void print() override; -}; -struct ScriptEffect : Effect -{ - RString text; - - ScriptEffect(RString t) : text(t) {} - - virtual void print() override; -}; - -struct Assignment : TopLevel, Effect -{ - RString name; - Expression *body; - - Assignment(RString n, Expression *b) - : name(n), body(b) - {} - - // toplevel - virtual void dump() override; - // effect - virtual void print() override; -}; - -struct ForeachEffect : Effect -{ - RString selection; - RString var; - Expression *expr; - Effect *effect; - - ForeachEffect(RString s, RString v, Expression *x, Effect *f) - : selection(s), var(v), expr(x), effect(f) - {} - - virtual void print() override; -}; - -struct ForEffect : Effect -{ - RString var; - Expression *low; - Expression *high; - Effect *effect; - - ForEffect(RString v, Expression *l, Expression *h, Effect *f) - : var(v), low(l), high(h), effect(f) - {} - - virtual void print() override; -}; - -struct IfEffect : Effect -{ - Expression *cond; - Effect *if_true; - Effect *if_false_maybe; - - IfEffect(Expression *c, Effect *t, Effect *f=nullptr) - : cond(c), if_true(t), if_false_maybe(f) - {} - - virtual void print() override; -}; - -struct ExplicitCallEffect : Effect -{ - RString userfunc; - std::vector<Expression *> *args; - - ExplicitCallEffect(RString f, std::vector<Expression *> *a) - : userfunc(f), args(a) - {} - - virtual void print() override; -}; - -struct SleepEffect : Effect -{ - Expression *time_; - - SleepEffect(Expression *t) - : time_(t) - {} - - virtual void print() override; -}; - -struct SpellDef -{ - std::vector<Assignment *> *lets; - std::vector<SpellBod *> *body; -}; - -struct SpellBod -{ - virtual void say() = 0; -}; - -struct SpellBodGuarded : SpellBod -{ - SpellGuard *guard; - SpellBod *body; - - SpellBodGuarded(SpellGuard *g, SpellBod *b) - : guard(g), body(b) - {} - - virtual void say() override; -}; - -struct SpellBodList : SpellBod -{ - std::vector<SpellBod *> *body; - - SpellBodList(std::vector<SpellBod *> *b) - : body(b) - {} - - virtual void say() override; -}; - -struct SpellBodEffect : SpellBod -{ - std::deque<Effect *> *body; - std::deque<Effect *> *maybe_trigger; - std::deque<Effect *> *maybe_end; - - SpellBodEffect(std::deque<Effect *> *b, std::deque<Effect *> *t, std::deque<Effect *> *e) - : body(b), maybe_trigger(t), maybe_end(e) - {} - - virtual void say() override; -}; - -struct SpellGuard -{ - virtual void declare() = 0; -}; - -struct SpellGuardOr : SpellGuard -{ - std::vector<SpellGuard *> *any; - - SpellGuardOr(std::vector<SpellGuard *> *a) : any(a) {} - SpellGuardOr(SpellGuard *left, SpellGuard *right) - : any(new std::vector<SpellGuard *>({left, right})) - {} - - virtual void declare() override; -}; -struct SpellGuardList : SpellGuard -{ - std::vector<SpellGuard *> *all; - - SpellGuardList(std::vector<SpellGuard *> *a) : all(a) {} - - virtual void declare() override; -}; -struct SpellGuardRequire : SpellGuard -{ - Expression *expr; - - SpellGuardRequire(Expression *x) : expr(x) {} - - virtual void declare() override; -}; -struct SpellGuardCatalysts : SpellGuard -{ - std::vector<Item *> *items; - - SpellGuardCatalysts(std::vector<Item *> *i) : items(i) {} - - virtual void declare() override; -}; -struct SpellGuardComponents : SpellGuard -{ - std::vector<Item *> *items; - - SpellGuardComponents(std::vector<Item *> *i) : items(i) {} - - virtual void declare() override; -}; -struct SpellGuardMana : SpellGuard -{ - Expression *sp; - - SpellGuardMana(Expression *x) : sp(x) {} - - virtual void declare() override; -}; -struct SpellGuardCasttime : SpellGuard -{ - Expression *time_; - - SpellGuardCasttime(Expression *x) : time_(x) {} - - virtual void declare() override; -}; - -struct Item -{ - RString count; - RString item; - - Item(RString c, RString i) : count(c), item(i) {} -}; - -struct Expression -{ - virtual void show() = 0; -}; - -struct SimpleExpr : Expression -{ - RString content; - - SimpleExpr(RString c) : content(c) {} - - virtual void show() override; -}; - -struct BinExpr : Expression -{ - Expression *left; - RString op; - Expression *right; - - BinExpr(Expression *l, RString o, Expression *r) - : left(l), op(o), right(r) - {} - - virtual void show() override; -}; - -struct CallExpr : Expression, Effect -{ - RString func; - std::vector<Expression *> *args; - - CallExpr(RString f, std::vector<Expression *> *a) - : func(f), args(a) - {} - - // expression - virtual void show() override; - // effect - virtual void print() override; -}; - -struct Location -{ - Expression *map; - Expression *x; - Expression *y; -}; - -struct AreaLoc : Expression -{ - Location *loc; - - AreaLoc(Location *l) - : loc(l) - {} - - virtual void show() override; -}; - -struct AreaRect : Expression -{ - Location *loc; - Expression *width; - Expression *height; - - AreaRect(Location *l, Expression *w, Expression *h) - : loc(l), width(w), height(h) - {} - - virtual void show() override; -}; - -struct AreaBar : Expression -{ - Location *loc; - Expression *dir; - Expression *width; - Expression *depth; - - AreaBar(Location *l, Expression *a, Expression *w, Expression *d) - : loc(l), dir(a), width(w), depth(d) - {} - - virtual void show() override; -}; - -# ifdef override -# undef override -# endif - -#endif // TMWA_SPELL_CONVERT_AST_HPP diff --git a/src/spell-convert/lexer.cpp b/src/spell-convert/lexer.cpp deleted file mode 100644 index e06817f..0000000 --- a/src/spell-convert/lexer.cpp +++ /dev/null @@ -1,2331 +0,0 @@ -#line 2 "src/spell-convert/lexer.cpp" - -#line 4 "src/spell-convert/lexer.cpp" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define yy_create_buffer spell_converter_create_buffer -#define yy_delete_buffer spell_converter_delete_buffer -#define yy_flex_debug spell_converter_flex_debug -#define yy_init_buffer spell_converter_init_buffer -#define yy_flush_buffer spell_converter_flush_buffer -#define yy_load_buffer_state spell_converter_load_buffer_state -#define yy_switch_to_buffer spell_converter_switch_to_buffer -#define yyin spell_converterin -#define yyleng spell_converterleng -#define yylex spell_converterlex -#define yylineno spell_converterlineno -#define yyout spell_converterout -#define yyrestart spell_converterrestart -#define yytext spell_convertertext -#define yywrap spell_converterwrap -#define yyalloc spell_converteralloc -#define yyrealloc spell_converterrealloc -#define yyfree spell_converterfree - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include <inttypes.h> -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#endif /* ! C99 */ - -#endif /* ! FLEXINT_H */ - -#ifdef __cplusplus - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -/* C99 requires __STDC__ to be defined as 1. */ -#if defined (__STDC__) - -#define YY_USE_CONST - -#endif /* defined (__STDC__) */ -#endif /* ! __cplusplus */ - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN (yy_start) = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START (((yy_start) - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE spell_converterrestart(spell_converterin ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -extern int spell_converterleng; - -extern FILE *spell_converterin, *spell_converterout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - #define YY_LESS_LINENO(n) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up spell_convertertext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = (yy_hold_char); \ - YY_RESTORE_YY_MORE_OFFSET \ - (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up spell_convertertext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, (yytext_ptr) ) - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via spell_converterrestart()), so that the user can continue scanning by - * just pointing spell_converterin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* Stack of input buffers. */ -static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ -static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ -static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ - ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ - : NULL) - -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] - -/* yy_hold_char holds the character lost when spell_convertertext is formed. */ -static char yy_hold_char; -static int yy_n_chars; /* number of characters read into yy_ch_buf */ -int spell_converterleng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = (char *) 0; -static int yy_init = 0; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow spell_converterwrap()'s to do buffer switches - * instead of setting up a fresh spell_converterin. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void spell_converterrestart (FILE *input_file ); -void spell_converter_switch_to_buffer (YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE spell_converter_create_buffer (FILE *file,int size ); -void spell_converter_delete_buffer (YY_BUFFER_STATE b ); -void spell_converter_flush_buffer (YY_BUFFER_STATE b ); -void spell_converterpush_buffer_state (YY_BUFFER_STATE new_buffer ); -void spell_converterpop_buffer_state (void ); - -static void spell_converterensure_buffer_stack (void ); -static void spell_converter_load_buffer_state (void ); -static void spell_converter_init_buffer (YY_BUFFER_STATE b,FILE *file ); - -#define YY_FLUSH_BUFFER spell_converter_flush_buffer(YY_CURRENT_BUFFER ) - -YY_BUFFER_STATE spell_converter_scan_buffer (char *base,yy_size_t size ); -YY_BUFFER_STATE spell_converter_scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE spell_converter_scan_bytes (yyconst char *bytes,int len ); - -void *spell_converteralloc (yy_size_t ); -void *spell_converterrealloc (void *,yy_size_t ); -void spell_converterfree (void * ); - -#define yy_new_buffer spell_converter_create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - spell_converterensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - spell_converter_create_buffer(spell_converterin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - spell_converterensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - spell_converter_create_buffer(spell_converterin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ - -#define spell_converterwrap(n) 1 -#define YY_SKIP_YYWRAP - -typedef unsigned char YY_CHAR; - -FILE *spell_converterin = (FILE *) 0, *spell_converterout = (FILE *) 0; - -typedef int yy_state_type; - -extern int spell_converterlineno; - -int spell_converterlineno = 1; - -extern char *spell_convertertext; -#define yytext_ptr spell_convertertext - -static yy_state_type yy_get_previous_state (void ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); -static int yy_get_next_buffer (void ); -static void yy_fatal_error (yyconst char msg[] ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up spell_convertertext. - */ -#define YY_DO_BEFORE_ACTION \ - (yytext_ptr) = yy_bp; \ - spell_converterleng = (size_t) (yy_cp - yy_bp); \ - (yy_hold_char) = *yy_cp; \ - *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; - -#define YY_NUM_RULES 86 -#define YY_END_OF_BUFFER 87 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static yyconst flex_int16_t yy_accept[240] = - { 0, - 0, 0, 87, 85, 84, 84, 85, 85, 85, 23, - 33, 17, 18, 21, 19, 28, 20, 35, 22, 79, - 79, 27, 26, 14, 9, 13, 29, 81, 81, 81, - 81, 7, 81, 81, 81, 81, 81, 5, 81, 81, - 81, 1, 81, 3, 31, 32, 34, 85, 30, 12, - 0, 78, 0, 0, 82, 24, 79, 0, 0, 36, - 16, 11, 10, 51, 15, 37, 81, 81, 81, 81, - 81, 81, 75, 81, 81, 81, 81, 70, 49, 81, - 81, 81, 81, 6, 81, 81, 4, 40, 65, 81, - 81, 8, 81, 81, 81, 81, 2, 81, 81, 81, - - 41, 81, 0, 0, 77, 25, 0, 78, 0, 0, - 83, 80, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 50, 81, 74, 48, 81, 81, 67, - 81, 66, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 0, 0, 77, 81, 81, 81, 81, - 39, 81, 81, 81, 81, 81, 72, 81, 81, 81, - 56, 81, 81, 81, 81, 58, 81, 81, 81, 81, - 71, 81, 76, 59, 62, 81, 60, 81, 81, 81, - 64, 81, 81, 81, 45, 81, 81, 81, 81, 47, - 81, 81, 81, 81, 81, 81, 81, 81, 61, 68, - - 81, 81, 81, 81, 44, 52, 69, 81, 81, 81, - 81, 81, 81, 73, 81, 81, 53, 81, 42, 81, - 57, 81, 81, 46, 81, 81, 63, 54, 81, 38, - 81, 55, 81, 81, 81, 81, 81, 43, 0 - } ; - -static yyconst flex_int32_t yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 4, 5, 6, 1, 7, 8, 1, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 19, 20, 21, - 22, 23, 1, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 34, 46, 34, 47, 34, - 48, 49, 50, 51, 52, 1, 53, 53, 53, 53, - - 53, 53, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 54, - 34, 34, 55, 56, 57, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static yyconst flex_int32_t yy_meta[58] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 1, 1, 3, 3, 1, 1, - 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, - 1, 2, 3, 2, 1, 1, 1 - } ; - -static yyconst flex_int16_t yy_base[248] = - { 0, - 0, 0, 289, 290, 290, 290, 266, 53, 284, 290, - 278, 290, 290, 290, 290, 290, 42, 290, 269, 44, - 46, 290, 290, 44, 46, 48, 290, 46, 242, 48, - 244, 44, 243, 0, 45, 47, 52, 49, 239, 52, - 251, 64, 80, 254, 290, 290, 290, 35, 222, 290, - 76, 290, 98, 274, 290, 290, 89, 273, 0, 290, - 290, 290, 290, 290, 290, 290, 0, 236, 56, 245, - 77, 77, 0, 243, 229, 83, 229, 0, 0, 226, - 242, 230, 241, 0, 228, 238, 0, 0, 0, 225, - 222, 0, 226, 228, 231, 217, 0, 216, 221, 227, - - 209, 221, 67, 93, 290, 290, 112, 113, 123, 250, - 290, 0, 210, 213, 208, 224, 212, 203, 221, 205, - 201, 214, 213, 0, 208, 211, 0, 214, 213, 0, - 200, 0, 209, 190, 205, 193, 196, 198, 199, 200, - 190, 202, 182, 73, 120, 80, 181, 196, 190, 187, - 0, 177, 184, 180, 174, 190, 0, 172, 190, 178, - 0, 188, 183, 178, 172, 0, 173, 170, 178, 166, - 0, 163, 0, 0, 0, 173, 0, 170, 155, 163, - 0, 156, 152, 171, 0, 145, 147, 132, 129, 0, - 140, 126, 129, 139, 135, 128, 121, 134, 0, 0, - - 128, 126, 113, 128, 0, 0, 0, 114, 112, 125, - 124, 108, 113, 0, 122, 106, 0, 102, 0, 103, - 0, 101, 99, 0, 112, 126, 0, 0, 96, 0, - 113, 0, 98, 108, 102, 94, 90, 0, 290, 177, - 180, 182, 185, 188, 191, 128, 194 - } ; - -static yyconst flex_int16_t yy_def[248] = - { 0, - 239, 1, 239, 239, 239, 239, 239, 240, 241, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 239, 239, 239, 243, 239, 239, - 240, 239, 244, 241, 239, 239, 239, 245, 246, 239, - 239, 239, 239, 239, 239, 239, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - - 242, 242, 243, 247, 239, 239, 240, 240, 244, 245, - 239, 246, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 243, 247, 243, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 0, 239, - 239, 239, 239, 239, 239, 239, 239 - } ; - -static yyconst flex_int16_t yy_nxt[348] = - { 0, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 34, 35, 34, 34, 36, 37, 38, 39, 40, - 34, 41, 42, 43, 34, 44, 34, 45, 4, 46, - 47, 4, 34, 34, 48, 49, 4, 52, 57, 57, - 57, 57, 57, 57, 60, 61, 62, 63, 64, 65, - 66, 68, 71, 74, 78, 80, 82, 84, 89, 75, - 52, 76, 79, 104, 114, 81, 72, 85, 86, 69, - 83, 105, 92, 90, 87, 103, 93, 59, 94, 115, - - 51, 53, 108, 95, 98, 57, 57, 96, 99, 97, - 124, 100, 117, 120, 121, 104, 52, 52, 101, 118, - 119, 104, 103, 105, 53, 51, 125, 108, 104, 105, - 112, 238, 237, 236, 235, 234, 105, 233, 232, 231, - 230, 145, 229, 228, 227, 226, 109, 225, 224, 146, - 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, - 53, 53, 213, 212, 211, 210, 209, 208, 145, 207, - 206, 109, 205, 204, 203, 202, 146, 51, 51, 51, - 54, 54, 54, 67, 67, 103, 103, 103, 107, 107, - 107, 110, 110, 110, 144, 144, 144, 201, 200, 199, - - 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, - 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, - 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, - 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, - 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, - 148, 147, 111, 143, 142, 141, 140, 139, 138, 137, - 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, - 126, 123, 122, 116, 113, 111, 55, 106, 102, 91, - 88, 77, 73, 70, 58, 56, 55, 50, 239, 3, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239 - } ; - -static yyconst flex_int16_t yy_chk[348] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 8, 17, 17, - 20, 20, 21, 21, 24, 24, 24, 25, 25, 26, - 26, 28, 30, 32, 35, 36, 37, 38, 40, 32, - 51, 32, 35, 48, 69, 36, 30, 38, 38, 28, - 37, 48, 42, 40, 38, 104, 42, 20, 42, 69, - - 53, 8, 53, 42, 43, 57, 57, 42, 43, 42, - 76, 43, 71, 72, 72, 103, 107, 108, 43, 71, - 71, 144, 145, 103, 51, 109, 76, 109, 146, 144, - 246, 237, 236, 235, 234, 233, 146, 231, 229, 226, - 225, 104, 223, 222, 220, 218, 53, 216, 215, 104, - 213, 212, 211, 210, 209, 208, 204, 203, 202, 201, - 107, 108, 198, 197, 196, 195, 194, 193, 145, 192, - 191, 109, 189, 188, 187, 186, 145, 240, 240, 240, - 241, 241, 241, 242, 242, 243, 243, 243, 244, 244, - 244, 245, 245, 245, 247, 247, 247, 184, 183, 182, - - 180, 179, 178, 176, 172, 170, 169, 168, 167, 165, - 164, 163, 162, 160, 159, 158, 156, 155, 154, 153, - 152, 150, 149, 148, 147, 143, 142, 141, 140, 139, - 138, 137, 136, 135, 134, 133, 131, 129, 128, 126, - 125, 123, 122, 121, 120, 119, 118, 117, 116, 115, - 114, 113, 110, 102, 101, 100, 99, 98, 96, 95, - 94, 93, 91, 90, 86, 85, 83, 82, 81, 80, - 77, 75, 74, 70, 68, 58, 54, 49, 44, 41, - 39, 33, 31, 29, 19, 11, 9, 7, 3, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239 - } ; - -static yy_state_type yy_last_accepting_state; -static char *yy_last_accepting_cpos; - -extern int spell_converter_flex_debug; -int spell_converter_flex_debug = 0; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -char *spell_convertertext; -#line 1 "../src/spell-convert/lexer.lpp" -#line 2 "../src/spell-convert/lexer.lpp" -/* vim: set ft=lex: */ -//#include "lexer.hpp" - -#include "../strings/rstring.hpp" -#include "../strings/zstring.hpp" - -#include "../io/cxxstdio.hpp" - -#include "../sexpr/lexer.hpp" - -#include "parser.hpp" - -#define yylval spell_converterlval - -RString *str(const char *s) -{ - return new RString(ZString(strings::really_construct_from_a_pointer, s, nullptr)); -} -#define YY_NO_INPUT 1 -#line 657 "src/spell-convert/lexer.cpp" - -#define INITIAL 0 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include <unistd.h> -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -static int yy_init_globals (void ); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int spell_converterlex_destroy (void ); - -int spell_converterget_debug (void ); - -void spell_converterset_debug (int debug_flag ); - -YY_EXTRA_TYPE spell_converterget_extra (void ); - -void spell_converterset_extra (YY_EXTRA_TYPE user_defined ); - -FILE *spell_converterget_in (void ); - -void spell_converterset_in (FILE * in_str ); - -FILE *spell_converterget_out (void ); - -void spell_converterset_out (FILE * out_str ); - -int spell_converterget_leng (void ); - -char *spell_converterget_text (void ); - -int spell_converterget_lineno (void ); - -void spell_converterset_lineno (int line_number ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int spell_converterwrap (void ); -#else -extern int spell_converterwrap (void ); -#endif -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ); -#endif - -#ifndef YY_NO_INPUT - -#ifdef __cplusplus -static int yyinput (void ); -#else -static int input (void ); -#endif - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO do { if (fwrite( spell_convertertext, spell_converterleng, 1, spell_converterout )) {} } while (0) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ - { \ - int c = '*'; \ - size_t n; \ - for ( n = 0; n < max_size && \ - (c = getc( spell_converterin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( spell_converterin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = fread(buf, 1, max_size, spell_converterin))==0 && ferror(spell_converterin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(spell_converterin); \ - } \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int spell_converterlex (void); - -#define YY_DECL int spell_converterlex (void) -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after spell_convertertext and spell_converterleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; - -#line 27 "../src/spell-convert/lexer.lpp" - - -#line 845 "src/spell-convert/lexer.cpp" - - if ( !(yy_init) ) - { - (yy_init) = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ - - if ( ! spell_converterin ) - spell_converterin = stdin; - - if ( ! spell_converterout ) - spell_converterout = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - spell_converterensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - spell_converter_create_buffer(spell_converterin,YY_BUF_SIZE ); - } - - spell_converter_load_buffer_state( ); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = (yy_c_buf_p); - - /* Support of spell_convertertext. */ - *yy_cp = (yy_hold_char); - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = (yy_start); -yy_match: - do - { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 240 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - ++yy_cp; - } - while ( yy_base[yy_current_state] != 290 ); - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - yy_act = yy_accept[yy_current_state]; - } - - YY_DO_BEFORE_ACTION; - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = (yy_hold_char); - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 29 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return DIR; } - YY_BREAK -case 2: -YY_RULE_SETUP -#line 30 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return DIR; } - YY_BREAK -case 3: -YY_RULE_SETUP -#line 31 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return DIR; } - YY_BREAK -case 4: -YY_RULE_SETUP -#line 32 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return DIR; } - YY_BREAK -case 5: -YY_RULE_SETUP -#line 33 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return DIR; } - YY_BREAK -case 6: -YY_RULE_SETUP -#line 34 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return DIR; } - YY_BREAK -case 7: -YY_RULE_SETUP -#line 35 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return DIR; } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 36 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return DIR; } - YY_BREAK -case 9: -YY_RULE_SETUP -#line 37 "../src/spell-convert/lexer.lpp" -{ return '='; } - YY_BREAK -case 10: -YY_RULE_SETUP -#line 38 "../src/spell-convert/lexer.lpp" -{ return EQ; } - YY_BREAK -case 11: -YY_RULE_SETUP -#line 39 "../src/spell-convert/lexer.lpp" -{ return NEQ; } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 40 "../src/spell-convert/lexer.lpp" -{ return NEQ; } - YY_BREAK -case 13: -YY_RULE_SETUP -#line 41 "../src/spell-convert/lexer.lpp" -{ return '>'; } - YY_BREAK -case 14: -YY_RULE_SETUP -#line 42 "../src/spell-convert/lexer.lpp" -{ return '<'; } - YY_BREAK -case 15: -YY_RULE_SETUP -#line 43 "../src/spell-convert/lexer.lpp" -{ return GTE; } - YY_BREAK -case 16: -YY_RULE_SETUP -#line 44 "../src/spell-convert/lexer.lpp" -{ return LTE; } - YY_BREAK -case 17: -YY_RULE_SETUP -#line 45 "../src/spell-convert/lexer.lpp" -{ return '('; } - YY_BREAK -case 18: -YY_RULE_SETUP -#line 46 "../src/spell-convert/lexer.lpp" -{ return ')'; } - YY_BREAK -case 19: -YY_RULE_SETUP -#line 47 "../src/spell-convert/lexer.lpp" -{ return '+'; } - YY_BREAK -case 20: -YY_RULE_SETUP -#line 48 "../src/spell-convert/lexer.lpp" -{ return '-'; } - YY_BREAK -case 21: -YY_RULE_SETUP -#line 49 "../src/spell-convert/lexer.lpp" -{ return '*'; } - YY_BREAK -case 22: -YY_RULE_SETUP -#line 50 "../src/spell-convert/lexer.lpp" -{ return '/'; } - YY_BREAK -case 23: -YY_RULE_SETUP -#line 51 "../src/spell-convert/lexer.lpp" -{ return '%'; } - YY_BREAK -case 24: -YY_RULE_SETUP -#line 52 "../src/spell-convert/lexer.lpp" -{ return ANDAND; } - YY_BREAK -case 25: -YY_RULE_SETUP -#line 53 "../src/spell-convert/lexer.lpp" -{ return OROR; } - YY_BREAK -case 26: -YY_RULE_SETUP -#line 54 "../src/spell-convert/lexer.lpp" -{ return ';'; } - YY_BREAK -case 27: -YY_RULE_SETUP -#line 55 "../src/spell-convert/lexer.lpp" -{ return ':'; } - YY_BREAK -case 28: -YY_RULE_SETUP -#line 56 "../src/spell-convert/lexer.lpp" -{ return ','; } - YY_BREAK -case 29: -YY_RULE_SETUP -#line 57 "../src/spell-convert/lexer.lpp" -{ return '@'; } - YY_BREAK -case 30: -YY_RULE_SETUP -#line 58 "../src/spell-convert/lexer.lpp" -{ return '|'; } - YY_BREAK -case 31: -YY_RULE_SETUP -#line 59 "../src/spell-convert/lexer.lpp" -{ return '['; } - YY_BREAK -case 32: -YY_RULE_SETUP -#line 60 "../src/spell-convert/lexer.lpp" -{ return ']'; } - YY_BREAK -case 33: -YY_RULE_SETUP -#line 61 "../src/spell-convert/lexer.lpp" -{ return '&'; } - YY_BREAK -case 34: -YY_RULE_SETUP -#line 62 "../src/spell-convert/lexer.lpp" -{ return '^'; } - YY_BREAK -case 35: -YY_RULE_SETUP -#line 63 "../src/spell-convert/lexer.lpp" -{ return '.'; } - YY_BREAK -case 36: -YY_RULE_SETUP -#line 64 "../src/spell-convert/lexer.lpp" -{ return SHL; } - YY_BREAK -case 37: -YY_RULE_SETUP -#line 65 "../src/spell-convert/lexer.lpp" -{ return SHR; } - YY_BREAK -case 38: -YY_RULE_SETUP -#line 66 "../src/spell-convert/lexer.lpp" -{ return PROCEDURE; } - YY_BREAK -case 39: -YY_RULE_SETUP -#line 67 "../src/spell-convert/lexer.lpp" -{ return CALL; } - YY_BREAK -case 40: -YY_RULE_SETUP -#line 68 "../src/spell-convert/lexer.lpp" -{ return OR; } - YY_BREAK -case 41: -YY_RULE_SETUP -#line 69 "../src/spell-convert/lexer.lpp" -{ return TO; } - YY_BREAK -case 42: -YY_RULE_SETUP -#line 70 "../src/spell-convert/lexer.lpp" -{ return TOWARDS; } - YY_BREAK -case 43: -YY_RULE_SETUP -#line 71 "../src/spell-convert/lexer.lpp" -{ return TELEPORT_ANCHOR; } - YY_BREAK -case 44: -YY_RULE_SETUP -#line 72 "../src/spell-convert/lexer.lpp" -{ return SILENT; } - YY_BREAK -case 45: -YY_RULE_SETUP -#line 73 "../src/spell-convert/lexer.lpp" -{ return LOCAL; } - YY_BREAK -case 46: -YY_RULE_SETUP -#line 74 "../src/spell-convert/lexer.lpp" -{ return NONMAGIC; } - YY_BREAK -case 47: -YY_RULE_SETUP -#line 75 "../src/spell-convert/lexer.lpp" -{ return SPELL; } - YY_BREAK -case 48: -YY_RULE_SETUP -#line 76 "../src/spell-convert/lexer.lpp" -{ return LET; } - YY_BREAK -case 49: -YY_RULE_SETUP -#line 77 "../src/spell-convert/lexer.lpp" -{ return IN; } - YY_BREAK -case 50: -YY_RULE_SETUP -#line 78 "../src/spell-convert/lexer.lpp" -{ return END; } - YY_BREAK -case 51: -YY_RULE_SETUP -#line 79 "../src/spell-convert/lexer.lpp" -{ return DARROW; } - YY_BREAK -case 52: -YY_RULE_SETUP -#line 80 "../src/spell-convert/lexer.lpp" -{ return STRING_TY; } - YY_BREAK -case 53: -YY_RULE_SETUP -#line 81 "../src/spell-convert/lexer.lpp" -{ return REQUIRE; } - YY_BREAK -case 54: -YY_RULE_SETUP -#line 82 "../src/spell-convert/lexer.lpp" -{ return CATALYSTS; } - YY_BREAK -case 55: -YY_RULE_SETUP -#line 83 "../src/spell-convert/lexer.lpp" -{ return COMPONENTS; } - YY_BREAK -case 56: -YY_RULE_SETUP -#line 84 "../src/spell-convert/lexer.lpp" -{ return MANA; } - YY_BREAK -case 57: -YY_RULE_SETUP -#line 85 "../src/spell-convert/lexer.lpp" -{ return CASTTIME; } - YY_BREAK -case 58: -YY_RULE_SETUP -#line 86 "../src/spell-convert/lexer.lpp" -{ return SKIP; } - YY_BREAK -case 59: -YY_RULE_SETUP -#line 87 "../src/spell-convert/lexer.lpp" -{ return ABORT; } - YY_BREAK -case 60: -YY_RULE_SETUP -#line 88 "../src/spell-convert/lexer.lpp" -{ return BREAK; } - YY_BREAK -case 61: -YY_RULE_SETUP -#line 89 "../src/spell-convert/lexer.lpp" -{ return EFFECT_; } - YY_BREAK -case 62: -YY_RULE_SETUP -#line 90 "../src/spell-convert/lexer.lpp" -{ return ATEND; } - YY_BREAK -case 63: -YY_RULE_SETUP -#line 91 "../src/spell-convert/lexer.lpp" -{ return ATTRIGGER; } - YY_BREAK -case 64: -YY_RULE_SETUP -#line 92 "../src/spell-convert/lexer.lpp" -{ return CONST; } - YY_BREAK -case 65: -YY_RULE_SETUP -#line 93 "../src/spell-convert/lexer.lpp" -{ return PC_F; } - YY_BREAK -case 66: -YY_RULE_SETUP -#line 94 "../src/spell-convert/lexer.lpp" -{ return NPC_F; } - YY_BREAK -case 67: -YY_RULE_SETUP -#line 95 "../src/spell-convert/lexer.lpp" -{ return MOB_F; } - YY_BREAK -case 68: -YY_RULE_SETUP -#line 96 "../src/spell-convert/lexer.lpp" -{ return ENTITY_F; } - YY_BREAK -case 69: -YY_RULE_SETUP -#line 97 "../src/spell-convert/lexer.lpp" -{ return TARGET_F; } - YY_BREAK -case 70: -YY_RULE_SETUP -#line 98 "../src/spell-convert/lexer.lpp" -{ return IF; } - YY_BREAK -case 71: -YY_RULE_SETUP -#line 99 "../src/spell-convert/lexer.lpp" -{ return THEN; } - YY_BREAK -case 72: -YY_RULE_SETUP -#line 100 "../src/spell-convert/lexer.lpp" -{ return ELSE; } - YY_BREAK -case 73: -YY_RULE_SETUP -#line 101 "../src/spell-convert/lexer.lpp" -{ return FOREACH; } - YY_BREAK -case 74: -YY_RULE_SETUP -#line 102 "../src/spell-convert/lexer.lpp" -{ return FOR; } - YY_BREAK -case 75: -YY_RULE_SETUP -#line 103 "../src/spell-convert/lexer.lpp" -{ return DO; } - YY_BREAK -case 76: -YY_RULE_SETUP -#line 104 "../src/spell-convert/lexer.lpp" -{ return SLEEP; } - YY_BREAK -case 77: -/* rule 77 can match eol */ -YY_RULE_SETUP -#line 106 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return SCRIPT_DATA; } - YY_BREAK -case 78: -/* rule 78 can match eol */ -YY_RULE_SETUP -#line 107 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return STRING; } - YY_BREAK -case 79: -YY_RULE_SETUP -#line 108 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return INT; } - YY_BREAK -case 80: -YY_RULE_SETUP -#line 109 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return INT; } - YY_BREAK -case 81: -YY_RULE_SETUP -#line 110 "../src/spell-convert/lexer.lpp" -{ yylval.s = str(spell_convertertext); return ID; } - YY_BREAK -case 82: -*yy_cp = (yy_hold_char); /* undo effects of setting up spell_convertertext */ -(yy_c_buf_p) = yy_cp -= 1; -YY_DO_BEFORE_ACTION; /* set up spell_convertertext again */ -YY_RULE_SETUP -#line 111 "../src/spell-convert/lexer.lpp" -{ PRINTF("%s\n", sexpr::escape(*str(spell_convertertext + 1))); } - YY_BREAK -case 83: -*yy_cp = (yy_hold_char); /* undo effects of setting up spell_convertertext */ -(yy_c_buf_p) = yy_cp -= 1; -YY_DO_BEFORE_ACTION; /* set up spell_convertertext again */ -YY_RULE_SETUP -#line 112 "../src/spell-convert/lexer.lpp" -{ PRINTF("%s\n", sexpr::escape(*str(spell_convertertext + 2))); } - YY_BREAK -case 84: -/* rule 84 can match eol */ -YY_RULE_SETUP -#line 113 "../src/spell-convert/lexer.lpp" -/* ignore whitespace */ - YY_BREAK -case 85: -YY_RULE_SETUP -#line 114 "../src/spell-convert/lexer.lpp" -{ abort(); } - YY_BREAK -case 86: -YY_RULE_SETUP -#line 116 "../src/spell-convert/lexer.lpp" -ECHO; - YY_BREAK -#line 1367 "src/spell-convert/lexer.cpp" -case YY_STATE_EOF(INITIAL): - yyterminate(); - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = (yy_hold_char); - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed spell_converterin at a new source and called - * spell_converterlex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = spell_converterin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++(yy_c_buf_p); - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = (yy_c_buf_p); - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_END_OF_FILE: - { - (yy_did_buffer_switch_on_eof) = 0; - - if ( spell_converterwrap( ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * spell_convertertext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = - (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - (yy_c_buf_p) = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ -} /* end of spell_converterlex */ - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int yy_get_next_buffer (void) -{ - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = (yytext_ptr); - register int number_to_move, i; - int ret_val; - - if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; - - int yy_c_buf_p_offset = - (int) ((yy_c_buf_p) - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - spell_converterrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - if ( (yy_n_chars) == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - spell_converterrestart(spell_converterin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) spell_converterrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - } - - (yy_n_chars) += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; - - (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - static yy_state_type yy_get_previous_state (void) -{ - register yy_state_type yy_current_state; - register char *yy_cp; - - yy_current_state = (yy_start); - - for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) - { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 240 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) -{ - register int yy_is_jam; - register char *yy_cp = (yy_c_buf_p); - - register YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 240 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 239); - - return yy_is_jam ? 0 : yy_current_state; -} - -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (void) -#else - static int input (void) -#endif - -{ - int c; - - *(yy_c_buf_p) = (yy_hold_char); - - if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - /* This was really a NUL. */ - *(yy_c_buf_p) = '\0'; - - else - { /* need more input */ - int offset = (yy_c_buf_p) - (yytext_ptr); - ++(yy_c_buf_p); - - switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - spell_converterrestart(spell_converterin ); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( spell_converterwrap( ) ) - return EOF; - - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = (yytext_ptr) + offset; - break; - } - } - } - - c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve spell_convertertext */ - (yy_hold_char) = *++(yy_c_buf_p); - - return c; -} -#endif /* ifndef YY_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void spell_converterrestart (FILE * input_file ) -{ - - if ( ! YY_CURRENT_BUFFER ){ - spell_converterensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - spell_converter_create_buffer(spell_converterin,YY_BUF_SIZE ); - } - - spell_converter_init_buffer(YY_CURRENT_BUFFER,input_file ); - spell_converter_load_buffer_state( ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void spell_converter_switch_to_buffer (YY_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * spell_converterpop_buffer_state(); - * spell_converterpush_buffer_state(new_buffer); - */ - spell_converterensure_buffer_stack (); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - spell_converter_load_buffer_state( ); - - /* We don't actually know whether we did this switch during - * EOF (spell_converterwrap()) processing, but the only time this flag - * is looked at is after spell_converterwrap() is called, so it's safe - * to go ahead and always set it. - */ - (yy_did_buffer_switch_on_eof) = 1; -} - -static void spell_converter_load_buffer_state (void) -{ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - spell_converterin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - (yy_hold_char) = *(yy_c_buf_p); -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE spell_converter_create_buffer (FILE * file, int size ) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) spell_converteralloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in spell_converter_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) spell_converteralloc(b->yy_buf_size + 2 ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in spell_converter_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - spell_converter_init_buffer(b,file ); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with spell_converter_create_buffer() - * - */ - void spell_converter_delete_buffer (YY_BUFFER_STATE b ) -{ - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - spell_converterfree((void *) b->yy_ch_buf ); - - spell_converterfree((void *) b ); -} - -#ifndef __cplusplus -extern int isatty (int ); -#endif /* __cplusplus */ - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a spell_converterrestart() or at EOF. - */ - static void spell_converter_init_buffer (YY_BUFFER_STATE b, FILE * file ) - -{ - int oerrno = errno; - - spell_converter_flush_buffer(b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then spell_converter_init_buffer was _probably_ - * called from spell_converterrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * - */ - void spell_converter_flush_buffer (YY_BUFFER_STATE b ) -{ - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - spell_converter_load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void spell_converterpush_buffer_state (YY_BUFFER_STATE new_buffer ) -{ - if (new_buffer == NULL) - return; - - spell_converterensure_buffer_stack(); - - /* This block is copied from spell_converter_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - (yy_buffer_stack_top)++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from spell_converter_switch_to_buffer. */ - spell_converter_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void spell_converterpop_buffer_state (void) -{ - if (!YY_CURRENT_BUFFER) - return; - - spell_converter_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - if ((yy_buffer_stack_top) > 0) - --(yy_buffer_stack_top); - - if (YY_CURRENT_BUFFER) { - spell_converter_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void spell_converterensure_buffer_stack (void) -{ - int num_to_alloc; - - if (!(yy_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; - (yy_buffer_stack) = (struct yy_buffer_state**)spell_converteralloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in spell_converterensure_buffer_stack()" ); - - memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - (yy_buffer_stack_max) = num_to_alloc; - (yy_buffer_stack_top) = 0; - return; - } - - if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)spell_converterrealloc - ((yy_buffer_stack), - num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in spell_converterensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); - (yy_buffer_stack_max) = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE spell_converter_scan_buffer (char * base, yy_size_t size ) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (YY_BUFFER_STATE) spell_converteralloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in spell_converter_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - spell_converter_switch_to_buffer(b ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to spell_converterlex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * spell_converter_scan_bytes() instead. - */ -YY_BUFFER_STATE spell_converter_scan_string (yyconst char * yystr ) -{ - - return spell_converter_scan_bytes(yystr,strlen(yystr) ); -} - -/** Setup the input buffer state to scan the given bytes. The next call to spell_converterlex() will - * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE spell_converter_scan_bytes (yyconst char * yybytes, int _yybytes_len ) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; - buf = (char *) spell_converteralloc(n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in spell_converter_scan_bytes()" ); - - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - - b = spell_converter_scan_buffer(buf,n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in spell_converter_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -static void yy_fatal_error (yyconst char* msg ) -{ - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up spell_convertertext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - spell_convertertext[spell_converterleng] = (yy_hold_char); \ - (yy_c_buf_p) = spell_convertertext + yyless_macro_arg; \ - (yy_hold_char) = *(yy_c_buf_p); \ - *(yy_c_buf_p) = '\0'; \ - spell_converterleng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the current line number. - * - */ -int spell_converterget_lineno (void) -{ - - return spell_converterlineno; -} - -/** Get the input stream. - * - */ -FILE *spell_converterget_in (void) -{ - return spell_converterin; -} - -/** Get the output stream. - * - */ -FILE *spell_converterget_out (void) -{ - return spell_converterout; -} - -/** Get the length of the current token. - * - */ -int spell_converterget_leng (void) -{ - return spell_converterleng; -} - -/** Get the current token. - * - */ - -char *spell_converterget_text (void) -{ - return spell_convertertext; -} - -/** Set the current line number. - * @param line_number - * - */ -void spell_converterset_lineno (int line_number ) -{ - - spell_converterlineno = line_number; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param in_str A readable stream. - * - * @see spell_converter_switch_to_buffer - */ -void spell_converterset_in (FILE * in_str ) -{ - spell_converterin = in_str ; -} - -void spell_converterset_out (FILE * out_str ) -{ - spell_converterout = out_str ; -} - -int spell_converterget_debug (void) -{ - return spell_converter_flex_debug; -} - -void spell_converterset_debug (int bdebug ) -{ - spell_converter_flex_debug = bdebug ; -} - -static int yy_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from spell_converterlex_destroy(), so don't allocate here. - */ - - (yy_buffer_stack) = 0; - (yy_buffer_stack_top) = 0; - (yy_buffer_stack_max) = 0; - (yy_c_buf_p) = (char *) 0; - (yy_init) = 0; - (yy_start) = 0; - -/* Defined in main.c */ -#ifdef YY_STDINIT - spell_converterin = stdin; - spell_converterout = stdout; -#else - spell_converterin = (FILE *) 0; - spell_converterout = (FILE *) 0; -#endif - - /* For future reference: Set errno on error, since we are called by - * spell_converterlex_init() - */ - return 0; -} - -/* spell_converterlex_destroy is for both reentrant and non-reentrant scanners. */ -int spell_converterlex_destroy (void) -{ - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - spell_converter_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - spell_converterpop_buffer_state(); - } - - /* Destroy the stack itself. */ - spell_converterfree((yy_buffer_stack) ); - (yy_buffer_stack) = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * spell_converterlex() is called, initialization will occur. */ - yy_init_globals( ); - - return 0; -} - -/* - * Internal utility routines. - */ - -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) -{ - register int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s ) -{ - register int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *spell_converteralloc (yy_size_t size ) -{ - return (void *) malloc( size ); -} - -void *spell_converterrealloc (void * ptr, yy_size_t size ) -{ - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); -} - -void spell_converterfree (void * ptr ) -{ - free( (char *) ptr ); /* see spell_converterrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" - -#line 116 "../src/spell-convert/lexer.lpp" - - -// nothing to see here, move along - diff --git a/src/spell-convert/lexer.hpp b/src/spell-convert/lexer.hpp deleted file mode 100644 index 82c6ba2..0000000 --- a/src/spell-convert/lexer.hpp +++ /dev/null @@ -1,335 +0,0 @@ -#ifndef spell_converterHEADER_H -#define spell_converterHEADER_H 1 -#define spell_converterIN_HEADER 1 - -#line 6 "src/spell-convert/lexer.hpp" - -#line 8 "src/spell-convert/lexer.hpp" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include <inttypes.h> -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#endif /* ! C99 */ - -#endif /* ! FLEXINT_H */ - -#ifdef __cplusplus - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -/* C99 requires __STDC__ to be defined as 1. */ -#if defined (__STDC__) - -#define YY_USE_CONST - -#endif /* defined (__STDC__) */ -#endif /* ! __cplusplus */ - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -extern int spell_converterleng; - -extern FILE *spell_converterin, *spell_converterout; - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -void spell_converterrestart (FILE *input_file ); -void spell_converter_switch_to_buffer (YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE spell_converter_create_buffer (FILE *file,int size ); -void spell_converter_delete_buffer (YY_BUFFER_STATE b ); -void spell_converter_flush_buffer (YY_BUFFER_STATE b ); -void spell_converterpush_buffer_state (YY_BUFFER_STATE new_buffer ); -void spell_converterpop_buffer_state (void ); - -YY_BUFFER_STATE spell_converter_scan_buffer (char *base,yy_size_t size ); -YY_BUFFER_STATE spell_converter_scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE spell_converter_scan_bytes (yyconst char *bytes,int len ); - -void *spell_converteralloc (yy_size_t ); -void *spell_converterrealloc (void *,yy_size_t ); -void spell_converterfree (void * ); - -/* Begin user sect3 */ - -#define spell_converterwrap(n) 1 -#define YY_SKIP_YYWRAP - -extern int spell_converterlineno; - -extern char *spell_convertertext; -#define yytext_ptr spell_convertertext - -#ifdef YY_HEADER_EXPORT_START_CONDITIONS -#define INITIAL 0 - -#endif - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include <unistd.h> -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int spell_converterlex_destroy (void ); - -int spell_converterget_debug (void ); - -void spell_converterset_debug (int debug_flag ); - -YY_EXTRA_TYPE spell_converterget_extra (void ); - -void spell_converterset_extra (YY_EXTRA_TYPE user_defined ); - -FILE *spell_converterget_in (void ); - -void spell_converterset_in (FILE * in_str ); - -FILE *spell_converterget_out (void ); - -void spell_converterset_out (FILE * out_str ); - -int spell_converterget_leng (void ); - -char *spell_converterget_text (void ); - -int spell_converterget_lineno (void ); - -void spell_converterset_lineno (int line_number ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int spell_converterwrap (void ); -#else -extern int spell_converterwrap (void ); -#endif -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ); -#endif - -#ifndef YY_NO_INPUT - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int spell_converterlex (void); - -#define YY_DECL int spell_converterlex (void) -#endif /* !YY_DECL */ - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - -#undef YY_NEW_FILE -#undef YY_FLUSH_BUFFER -#undef yy_set_bol -#undef yy_new_buffer -#undef yy_set_interactive -#undef YY_DO_BEFORE_ACTION - -#ifdef YY_DECL_IS_OURS -#undef YY_DECL_IS_OURS -#undef YY_DECL -#endif - -#line 116 "../src/spell-convert/lexer.lpp" - - -#line 334 "src/spell-convert/lexer.hpp" -#undef spell_converterIN_HEADER -#endif /* spell_converterHEADER_H */ diff --git a/src/spell-convert/lexer.lpp b/src/spell-convert/lexer.lpp deleted file mode 100644 index b6c6d76..0000000 --- a/src/spell-convert/lexer.lpp +++ /dev/null @@ -1,136 +0,0 @@ -%{ -/* vim: set ft=lex: */ -//#include "lexer.hpp" -// magic-interpreter-lexer.lpp - Old magic tokenizer -// -// Copyright © 2004-2011 The Mana World Development Team -// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> -// -// This file is part of The Mana World (Athena server) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. - -#include "../strings/rstring.hpp" -#include "../strings/zstring.hpp" - -#include "../io/cxxstdio.hpp" - -#include "../sexpr/lexer.hpp" - -#include "parser.hpp" - -#define yylval spell_converterlval - -RString *str(const char *s) -{ - return new RString(ZString(strings::really_construct_from_a_pointer, s, nullptr)); -} -%} - -%option noyywrap -%option prefix="spell_converter" -%option nounput -%option noinput - -%% - -"S" { yylval.s = str(yytext); return DIR; } -"SW" { yylval.s = str(yytext); return DIR; } -"W" { yylval.s = str(yytext); return DIR; } -"NW" { yylval.s = str(yytext); return DIR; } -"N" { yylval.s = str(yytext); return DIR; } -"NE" { yylval.s = str(yytext); return DIR; } -"E" { yylval.s = str(yytext); return DIR; } -"SE" { yylval.s = str(yytext); return DIR; } -"=" { return '='; } -"==" { return EQ; } -"<>" { return NEQ; } -"!=" { return NEQ; } -">" { return '>'; } -"<" { return '<'; } -">=" { return GTE; } -"<=" { return LTE; } -"(" { return '('; } -")" { return ')'; } -"+" { return '+'; } -"-" { return '-'; } -"*" { return '*'; } -"/" { return '/'; } -"%" { return '%'; } -"&&" { return ANDAND; } -"||" { return OROR; } -";" { return ';'; } -":" { return ':'; } -"," { return ','; } -"@" { return '@'; } -"|" { return '|'; } -"[" { return '['; } -"]" { return ']'; } -"&" { return '&'; } -"^" { return '^'; } -"." { return '.'; } -"<<" { return SHL; } -">>" { return SHR; } -"PROCEDURE" { return PROCEDURE; } -"CALL" { return CALL; } -"OR" { return OR; } -"TO" { return TO; } -"TOWARDS" { return TOWARDS; } -"TELEPORT-ANCHOR" { return TELEPORT_ANCHOR; } -"SILENT" { return SILENT; } -"LOCAL" { return LOCAL; } -"NONMAGIC" { return NONMAGIC; } -"SPELL" { return SPELL; } -"LET" { return LET; } -"IN" { return IN; } -"END" { return END; } -"=>" { return DARROW; } -"STRING" { return STRING_TY; } -"REQUIRE" { return REQUIRE; } -"CATALYSTS" { return CATALYSTS; } -"COMPONENTS" { return COMPONENTS; } -"MANA" { return MANA; } -"CASTTIME" { return CASTTIME; } -"SKIP" { return SKIP; } -"ABORT" { return ABORT; } -"BREAK" { return BREAK; } -"EFFECT" { return EFFECT_; } -"ATEND" { return ATEND; } -"ATTRIGGER" { return ATTRIGGER; } -"CONST" { return CONST; } -"PC" { return PC_F; } -"NPC" { return NPC_F; } -"MOB" { return MOB_F; } -"ENTITY" { return ENTITY_F; } -"TARGET" { return TARGET_F; } -"IF" { return IF; } -"THEN" { return THEN; } -"ELSE" { return ELSE; } -"FOREACH" { return FOREACH; } -"FOR" { return FOR; } -"DO" { return DO; } -"WAIT" { return SLEEP; } - -\{([^\}]|\\.)*\} { yylval.s = str(yytext); return SCRIPT_DATA; } -\"([^\"]|\\.)*\" { yylval.s = str(yytext); return STRING; } -"-"?[0-9]+ { yylval.s = str(yytext); return INT; } -"0x"[0-9a-fA-F]+ { yylval.s = str(yytext); return INT; } -[a-zA-Z][-_a-zA-Z0-9]* { yylval.s = str(yytext); return ID; } -"#".*$ { PRINTF("%s\n", sexpr::escape(*str(yytext + 1))); } -"//".*$ { PRINTF("%s\n", sexpr::escape(*str(yytext + 2))); } -[ \n\t\r] /* ignore whitespace */ -. { abort(); } - -%% -// nothing to see here, move along diff --git a/src/spell-convert/parser.cpp b/src/spell-convert/parser.cpp deleted file mode 100644 index 0744630..0000000 --- a/src/spell-convert/parser.cpp +++ /dev/null @@ -1,2732 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.0.2. */ - -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "3.0.2" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - - -/* Substitute the variable and function names. */ -#define yyparse spell_converterparse -#define yylex spell_converterlex -#define yyerror spell_convertererror -#define yydebug spell_converterdebug -#define yynerrs spell_converternerrs - -#define yylval spell_converterlval -#define yychar spell_converterchar - -/* Copy the first part of user declarations. */ - -#line 75 "src/spell-convert/parser.cpp" /* yacc.c:339 */ - -# ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr -# else -# define YY_NULLPTR 0 -# endif -# endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* In a future release of Bison, this section will be replaced - by #include "parser.hpp". */ -#ifndef YY_SPELL_CONVERTER_SRC_SPELL_CONVERT_PARSER_HPP_INCLUDED -# define YY_SPELL_CONVERTER_SRC_SPELL_CONVERT_PARSER_HPP_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int spell_converterdebug; -#endif -/* "%code requires" blocks. */ -#line 2 "../src/spell-convert/parser.ypp" /* yacc.c:355 */ - -/* vim: set ft=yacc: */ -#include "../strings/rstring.hpp" - -#include "ast.hpp" - -#undef YYERROR_VERBOSE -#define YYERROR_VERBOSE 1 - -#line 115 "src/spell-convert/parser.cpp" /* yacc.c:355 */ - -/* Token type. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - INT = 258, - STRING = 259, - ID = 260, - DIR = 261, - CONST = 262, - PROCEDURE = 263, - CALL = 264, - SILENT = 265, - LOCAL = 266, - NONMAGIC = 267, - SHL = 268, - SHR = 269, - EQ = 270, - NEQ = 271, - GTE = 272, - LTE = 273, - ANDAND = 274, - OROR = 275, - SCRIPT_DATA = 276, - TO = 277, - TOWARDS = 278, - TELEPORT_ANCHOR = 279, - SPELL = 280, - LET = 281, - IN = 282, - END = 283, - DARROW = 284, - STRING_TY = 285, - REQUIRE = 286, - CATALYSTS = 287, - COMPONENTS = 288, - MANA = 289, - CASTTIME = 290, - SKIP = 291, - ABORT = 292, - BREAK = 293, - EFFECT_ = 294, - ATEND = 295, - ATTRIGGER = 296, - PC_F = 297, - NPC_F = 298, - MOB_F = 299, - ENTITY_F = 300, - TARGET_F = 301, - IF = 302, - THEN = 303, - ELSE = 304, - FOREACH = 305, - FOR = 306, - DO = 307, - SLEEP = 308, - OR = 309 - }; -#endif - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE YYSTYPE; -union YYSTYPE -{ -#line 27 "../src/spell-convert/parser.ypp" /* yacc.c:355 */ - - RString *s; - std::vector<RString> *vs; - Effect *e; - std::deque<Effect *> *ve; - SpellDef *spelldef; - SpellArg *spellarg; - TopLevel *top; - Expression *expr; - std::vector<Expression *> *vx; - Location *loc; - Item *it; - std::vector<Item *> *vit; - Assignment *a; - std::vector<Assignment *> *va; - SpellBod *b; - std::vector<SpellBod *> *vb; - SpellGuard *g; - std::vector<SpellGuard *> *vg; - -#line 203 "src/spell-convert/parser.cpp" /* yacc.c:355 */ -}; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - -extern YYSTYPE spell_converterlval; - -int spell_converterparse (void); - -#endif /* !YY_SPELL_CONVERTER_SRC_SPELL_CONVERT_PARSER_HPP_INCLUDED */ - -/* Copy the second part of user declarations. */ - -#line 218 "src/spell-convert/parser.cpp" /* yacc.c:358 */ -/* Unqualified %code blocks. */ -#line 13 "../src/spell-convert/parser.ypp" /* yacc.c:359 */ - -//#include "parser.hpp" -#include "lexer.hpp" - -#include "../io/cxxstdio.hpp" - -#include "../sexpr/lexer.hpp" - -void yyerror(const char *msg) { FPRINTF(stderr, "Fatal: %s\n", msg); abort(); } - -#line 231 "src/spell-convert/parser.cpp" /* yacc.c:359 */ - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#else -typedef signed char yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short int yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short int yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T -# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned int -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) -# endif -# endif -# ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - -#ifndef YY_ATTRIBUTE -# if (defined __GNUC__ \ - && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ - || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C -# define YY_ATTRIBUTE(Spec) __attribute__(Spec) -# else -# define YY_ATTRIBUTE(Spec) /* empty */ -# endif -#endif - -#ifndef YY_ATTRIBUTE_PURE -# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) -#endif - -#ifndef YY_ATTRIBUTE_UNUSED -# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) -#endif - -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) -# else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) -#else -# define YYUSE(E) /* empty */ -#endif - -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") -#else -# define YY_INITIAL_VALUE(Value) Value -#endif -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS -# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's 'empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (0) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (0) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 2 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 990 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 75 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 32 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 111 -/* YYNSTATES -- Number of states. */ -#define YYNSTATES 248 - -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 309 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 14, 23, 2, - 73, 74, 12, 10, 16, 11, 17, 13, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 18, 19, - 8, 7, 9, 2, 15, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 21, 2, 22, 24, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 20, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72 -}; - -#if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 167, 167, 171, 179, 183, 191, 195, 205, 211, - 222, 227, 232, 237, 242, 253, 257, 263, 269, 281, - 285, 295, 300, 310, 315, 320, 330, 335, 340, 345, - 350, 355, 360, 365, 370, 375, 380, 385, 390, 395, - 400, 405, 410, 415, 420, 425, 430, 436, 441, 446, - 451, 462, 466, 476, 482, 493, 503, 508, 513, 523, - 528, 538, 543, 554, 564, 570, 581, 586, 591, 602, - 606, 617, 621, 631, 636, 641, 651, 657, 668, 673, - 678, 683, 688, 698, 708, 714, 725, 730, 740, 745, - 755, 760, 765, 770, 775, 780, 790, 795, 800, 805, - 810, 815, 820, 825, 830, 835, 840, 845, 850, 856, - 867, 871 -}; -#endif - -#if YYDEBUG || YYERROR_VERBOSE || 0 -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "INT", "STRING", "ID", "DIR", "'='", - "'<'", "'>'", "'+'", "'-'", "'*'", "'/'", "'%'", "'@'", "','", "'.'", - "':'", "';'", "'|'", "'['", "']'", "'&'", "'^'", "CONST", "PROCEDURE", - "CALL", "SILENT", "LOCAL", "NONMAGIC", "SHL", "SHR", "EQ", "NEQ", "GTE", - "LTE", "ANDAND", "OROR", "SCRIPT_DATA", "TO", "TOWARDS", - "TELEPORT_ANCHOR", "SPELL", "LET", "IN", "END", "DARROW", "STRING_TY", - "REQUIRE", "CATALYSTS", "COMPONENTS", "MANA", "CASTTIME", "SKIP", - "ABORT", "BREAK", "EFFECT_", "ATEND", "ATTRIGGER", "PC_F", "NPC_F", - "MOB_F", "ENTITY_F", "TARGET_F", "IF", "THEN", "ELSE", "FOREACH", "FOR", - "DO", "SLEEP", "OR", "'('", "')'", "$accept", "spellconf", "semicolons", - "proc_formals_list", "proc_formals_list_ne", "spellconf_option", - "spell_flags", "argopt", "arg_ty", "value", "expr", "arg_list", - "arg_list_ne", "location", "area", "spelldef", "defs", "def", - "spellbody_list", "spellbody", "maybe_trigger", "maybe_end", - "spellguard", "spellguard_list", "prereq", "items", "item_list", "item", - "item_name", "selection", "effect", "effect_list", YY_NULLPTR -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 61, 60, 62, - 43, 45, 42, 47, 37, 64, 44, 46, 58, 59, - 124, 91, 93, 38, 94, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 40, 41 -}; -# endif - -#define YYPACT_NINF -171 - -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-171))) - -#define YYTABLE_NINF -13 - -#define yytable_value_is_error(Yytable_value) \ - 0 - - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -static const yytype_int16 yypact[] = -{ - -171, 19, -171, 156, 17, -171, 46, 60, 64, -171, - 104, 91, 65, 2, 80, -171, -171, -171, 73, -171, - -171, 27, -171, 28, 91, -171, 780, 39, -171, 91, - 98, 91, 35, 91, 91, 230, 91, 91, 91, 91, - 91, 91, 91, 91, 111, 91, 91, 91, 91, 91, - 91, 91, 91, 91, 91, 91, 99, 91, 780, -171, - 49, 106, 812, 115, 107, 780, 50, 114, 556, -171, - -1, 937, 937, 958, 958, 184, 184, 184, -171, -1, - -1, -1, -1, -1, 937, 937, 937, 937, 907, 876, - 68, 588, 142, 145, 91, 134, 91, -171, 91, 91, - 91, 81, 163, -171, 484, 14, 844, 780, 620, 652, - 91, -2, 148, -171, 136, 138, 139, 140, 91, 123, - 160, 91, 163, -171, -171, -171, -171, 93, 6, 91, - 91, 684, 91, 91, 96, -171, -171, -171, -171, 462, - -171, -171, -171, -171, -171, -171, 166, 165, 716, 100, - 124, -171, -171, 91, 152, 152, 91, 91, 163, 87, - -171, 157, -171, -25, -171, 262, 306, 91, 748, 102, - 91, 163, 149, 91, -171, -171, -171, 177, 3, 780, - 11, -171, -171, 780, 780, 141, -13, -25, -14, 172, - 172, 62, -171, -171, 338, -171, 180, 129, 143, 91, - 522, 198, 172, -171, 194, -171, 48, -171, -171, 163, - 153, -171, 62, -171, 172, -171, -171, 62, -171, -171, - -171, 193, 163, 382, 91, 91, 157, 177, 63, 11, - -171, -171, 163, -171, 154, 154, -171, -171, 163, 422, - 780, -171, -171, -171, -171, -171, 163, -171 -}; - - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ -static const yytype_uint8 yydefact[] = -{ - 2, 4, 1, 15, 0, 5, 0, 0, 0, 3, - 0, 0, 0, 0, 0, 18, 16, 17, 0, 24, - 25, 27, 23, 0, 0, 26, 10, 56, 28, 0, - 6, 0, 19, 51, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 11, 8, - 0, 7, 0, 0, 0, 53, 0, 52, 0, 49, - 46, 34, 35, 29, 30, 31, 33, 32, 50, 38, - 36, 37, 39, 40, 45, 47, 42, 41, 43, 44, - 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, - 0, 0, 110, 9, 46, 0, 0, 54, 0, 0, - 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, - 0, 0, 110, 4, 13, 22, 21, 0, 0, 0, - 0, 0, 0, 51, 0, 99, 97, 98, 100, 0, - 93, 90, 95, 91, 92, 94, 0, 0, 0, 0, - 110, 20, 4, 0, 0, 0, 0, 0, 110, 0, - 14, 59, 64, 0, 73, 0, 0, 0, 0, 0, - 51, 0, 0, 0, 106, 96, 111, 61, 0, 78, - 0, 79, 80, 81, 82, 69, 0, 76, 0, 0, - 0, 0, 55, 57, 0, 101, 0, 0, 105, 0, - 0, 0, 0, 4, 89, 88, 0, 84, 87, 110, - 71, 67, 0, 75, 0, 65, 66, 0, 74, 58, - 107, 0, 0, 0, 0, 0, 60, 62, 0, 0, - 83, 70, 110, 68, 77, 76, 109, 104, 0, 0, - 63, 89, 86, 85, 72, 102, 0, 103 -}; - - /* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -171, -171, -119, -171, -171, -171, -171, -171, -171, -171, - -11, -84, -171, -171, -171, -171, -171, -171, -125, -108, - -171, -171, -86, -171, -171, 72, -171, -9, 5, -171, - -170, -105 -}; - - /* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 1, 3, 60, 61, 9, 10, 64, 127, 25, - 65, 66, 67, 27, 28, 160, 178, 203, 186, 162, - 210, 233, 163, 188, 164, 181, 206, 207, 208, 146, - 123, 124 -}; - - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_int16 yytable[] = -{ - 26, 198, 212, 161, 150, 132, 36, 189, 201, 19, - 20, 21, 22, 35, 204, 205, 44, 149, 58, 2, - 62, 23, 190, 68, 11, 70, 71, 72, 73, 74, - 75, 76, 77, 177, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 176, 91, 191, 202, 169, - 152, 12, 237, 185, 56, 153, 154, 155, 156, 157, - 213, 211, 125, 158, 229, 13, 241, 205, 245, 14, - 230, 133, 29, 187, 126, 30, 247, 226, 32, 159, - 57, 215, 216, 104, 227, 106, 197, 107, 108, 109, - 19, 20, 21, 22, 19, 20, 21, 22, 31, 131, - 33, 34, 23, 59, 231, 218, 23, 139, 63, 90, - 148, 153, 154, 155, 156, 157, 78, 70, 165, 166, - 95, 168, 93, 92, 97, 96, 234, 244, 187, 111, - 98, 235, 15, 16, 17, 217, 153, 154, 155, 156, - 157, 100, 179, 5, 158, 183, 184, 18, 35, 102, - 103, 112, 105, 134, 110, 135, 194, 136, 137, 138, - 159, 4, 200, 113, 24, 147, 140, 151, 111, 170, - 114, 172, 173, 180, 175, 5, 196, 189, 115, 116, - 117, 6, 7, 141, 142, 143, 144, 145, 223, 118, - 112, 36, 119, 120, 199, 121, 5, 122, 8, 220, - 209, 44, 113, 221, 45, 225, 228, 46, 47, 114, - 222, 232, 236, 239, 240, 48, 49, 115, 116, 117, - 243, 153, 154, 155, 156, 157, 191, 182, 118, 158, - 0, 119, 120, 242, 121, 0, 122, 36, 37, 38, - 39, 40, 41, 42, 43, 214, 0, 44, 0, 0, - 45, 0, 0, 46, 47, 0, 0, 0, 0, 0, - 0, 48, 49, 50, 51, 52, 53, 54, 55, 36, - 37, 38, 39, 40, 41, 42, 43, 0, 0, 44, - 0, 0, 45, 0, 0, 46, 47, 0, 0, 0, - 0, 0, 0, 48, 49, 50, 51, 52, 53, 54, - 55, 0, 0, 0, 69, 0, 0, 0, 0, 0, - 0, 0, 0, 36, 37, 38, 39, 40, 41, 42, - 43, 0, 0, 44, 0, 0, 45, 0, 0, 46, - 47, 0, 0, 0, 0, 0, 192, 48, 49, 50, - 51, 52, 53, 54, 55, 36, 37, 38, 39, 40, - 41, 42, 43, 0, 0, 44, 0, 0, 45, 0, - 0, 46, 47, 0, 0, 0, 0, 0, 0, 48, - 49, 50, 51, 52, 53, 54, 55, 0, 0, 0, - 193, 0, 0, 0, 0, 0, 0, 0, 0, 36, - 37, 38, 39, 40, 41, 42, 43, 0, 0, 44, - 0, 0, 45, 0, 0, 46, 47, 0, 0, 0, - 0, 0, 219, 48, 49, 50, 51, 52, 53, 54, - 55, 0, 0, 0, 0, 0, 0, 0, 0, 36, - 37, 38, 39, 40, 41, 42, 43, 0, 0, 44, - 0, 0, 45, 0, 0, 46, 47, 0, 0, 0, - 0, 0, 238, 48, 49, 50, 51, 52, 53, 54, - 55, 0, 0, 0, 0, 0, 0, 0, 0, 36, - 37, 38, 39, 40, 41, 42, 43, 0, 0, 44, - 0, 0, 45, 0, -12, 46, 47, 0, 0, -12, - 0, 36, 246, 48, 49, 50, 51, 52, 53, 54, - 55, 44, 0, -12, 0, 0, 0, 0, 0, -12, - -12, 0, -12, -12, -12, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -12, -12, 171, 36, - 37, 38, 39, 40, 41, 42, 43, 0, 0, 44, - 0, 0, 45, 0, 0, 46, 47, 0, 0, 0, - 0, 0, 0, 48, 49, 50, 51, 52, 53, 54, - 55, 0, 224, 36, 37, 38, 39, 40, 41, 42, - 43, 0, 99, 44, 0, 0, 45, 0, 0, 46, - 47, 0, 0, 0, 0, 0, 0, 48, 49, 50, - 51, 52, 53, 54, 55, 36, 37, 38, 39, 40, - 41, 42, 43, 0, 0, 44, 101, 0, 45, 0, - 0, 46, 47, 0, 0, 0, 0, 0, 0, 48, - 49, 50, 51, 52, 53, 54, 55, 36, 37, 38, - 39, 40, 41, 42, 43, 0, 129, 44, 0, 0, - 45, 0, 0, 46, 47, 0, 0, 0, 0, 0, - 0, 48, 49, 50, 51, 52, 53, 54, 55, 36, - 37, 38, 39, 40, 41, 42, 43, 0, 130, 44, - 0, 0, 45, 0, 0, 46, 47, 0, 0, 0, - 0, 0, 0, 48, 49, 50, 51, 52, 53, 54, - 55, 36, 37, 38, 39, 40, 41, 42, 43, 0, - 167, 44, 0, 0, 45, 0, 0, 46, 47, 0, - 0, 0, 0, 0, 0, 48, 49, 50, 51, 52, - 53, 54, 55, 36, 37, 38, 39, 40, 41, 42, - 43, 0, 0, 44, 0, 174, 45, 0, 0, 46, - 47, 0, 0, 0, 0, 0, 0, 48, 49, 50, - 51, 52, 53, 54, 55, 36, 37, 38, 39, 40, - 41, 42, 43, 0, 0, 44, 0, 195, 45, 0, - 0, 46, 47, 0, 0, 0, 0, 0, 0, 48, - 49, 50, 51, 52, 53, 54, 55, 36, 37, 38, - 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, - 45, 0, 0, 46, 47, 0, 0, 0, 0, 0, - 0, 48, 49, 50, 51, 52, 53, 54, 55, 94, - 37, 38, 39, 40, 41, 42, 43, 0, 0, 44, - 0, 0, 45, 0, 0, 46, 47, 0, 0, 0, - 0, 0, 0, 48, 49, 50, 51, 52, 53, 54, - 55, 128, 37, 38, 39, 40, 41, 42, 43, 0, - 0, 44, 0, 0, 45, 0, 0, 46, 47, 0, - 0, 0, 0, 0, 0, 48, 49, 50, 51, 52, - 53, 54, 55, 36, 37, 38, 39, 40, 41, 42, - 43, 0, 0, 44, 0, 0, 45, 0, 0, 46, - 47, 0, 0, 0, 0, 0, 0, 48, 49, 50, - 51, 52, 53, 54, 36, 37, 38, 39, 40, 41, - 42, 43, 0, 0, 44, 0, 0, 45, 0, 0, - 46, 47, 0, 0, 0, 0, 0, 0, 48, 49, - 50, 51, 52, 53, 36, 0, 0, 39, 40, 41, - 42, 43, 0, 0, 44, 0, 0, 45, 0, 0, - 46, 47, 0, 0, 0, 36, 0, 0, 48, 49, - 41, 42, 43, 0, 0, 44, 0, 0, 45, 0, - 0, 46, 47, 0, 0, 0, 0, 0, 0, 48, - 49 -}; - -static const yytype_int16 yycheck[] = -{ - 11, 171, 16, 128, 123, 7, 7, 20, 5, 3, - 4, 5, 6, 24, 3, 4, 17, 122, 29, 0, - 31, 15, 47, 34, 7, 36, 37, 38, 39, 40, - 41, 42, 43, 152, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 150, 57, 72, 45, 133, - 44, 5, 222, 158, 15, 49, 50, 51, 52, 53, - 74, 74, 48, 57, 16, 5, 3, 4, 238, 5, - 22, 73, 7, 159, 60, 73, 246, 202, 5, 73, - 41, 189, 190, 94, 203, 96, 170, 98, 99, 100, - 3, 4, 5, 6, 3, 4, 5, 6, 18, 110, - 73, 73, 15, 5, 209, 191, 15, 118, 73, 10, - 121, 49, 50, 51, 52, 53, 5, 128, 129, 130, - 5, 132, 16, 74, 74, 18, 212, 232, 214, 5, - 16, 217, 28, 29, 30, 73, 49, 50, 51, 52, - 53, 73, 153, 19, 57, 156, 157, 43, 159, 7, - 5, 27, 18, 5, 73, 19, 167, 19, 19, 19, - 73, 5, 173, 39, 73, 5, 43, 74, 5, 73, - 46, 5, 7, 21, 74, 19, 74, 20, 54, 55, - 56, 25, 26, 60, 61, 62, 63, 64, 199, 65, - 27, 7, 68, 69, 45, 71, 19, 73, 42, 19, - 59, 17, 39, 74, 20, 7, 12, 23, 24, 46, - 67, 58, 19, 224, 225, 31, 32, 54, 55, 56, - 229, 49, 50, 51, 52, 53, 72, 155, 65, 57, - -1, 68, 69, 228, 71, -1, 73, 7, 8, 9, - 10, 11, 12, 13, 14, 73, -1, 17, -1, -1, - 20, -1, -1, 23, 24, -1, -1, -1, -1, -1, - -1, 31, 32, 33, 34, 35, 36, 37, 38, 7, - 8, 9, 10, 11, 12, 13, 14, -1, -1, 17, - -1, -1, 20, -1, -1, 23, 24, -1, -1, -1, - -1, -1, -1, 31, 32, 33, 34, 35, 36, 37, - 38, -1, -1, -1, 74, -1, -1, -1, -1, -1, - -1, -1, -1, 7, 8, 9, 10, 11, 12, 13, - 14, -1, -1, 17, -1, -1, 20, -1, -1, 23, - 24, -1, -1, -1, -1, -1, 74, 31, 32, 33, - 34, 35, 36, 37, 38, 7, 8, 9, 10, 11, - 12, 13, 14, -1, -1, 17, -1, -1, 20, -1, - -1, 23, 24, -1, -1, -1, -1, -1, -1, 31, - 32, 33, 34, 35, 36, 37, 38, -1, -1, -1, - 74, -1, -1, -1, -1, -1, -1, -1, -1, 7, - 8, 9, 10, 11, 12, 13, 14, -1, -1, 17, - -1, -1, 20, -1, -1, 23, 24, -1, -1, -1, - -1, -1, 74, 31, 32, 33, 34, 35, 36, 37, - 38, -1, -1, -1, -1, -1, -1, -1, -1, 7, - 8, 9, 10, 11, 12, 13, 14, -1, -1, 17, - -1, -1, 20, -1, -1, 23, 24, -1, -1, -1, - -1, -1, 70, 31, 32, 33, 34, 35, 36, 37, - 38, -1, -1, -1, -1, -1, -1, -1, -1, 7, - 8, 9, 10, 11, 12, 13, 14, -1, -1, 17, - -1, -1, 20, -1, 0, 23, 24, -1, -1, 5, - -1, 7, 70, 31, 32, 33, 34, 35, 36, 37, - 38, 17, -1, 19, -1, -1, -1, -1, -1, 25, - 26, -1, 28, 29, 30, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 42, 43, 66, 7, - 8, 9, 10, 11, 12, 13, 14, -1, -1, 17, - -1, -1, 20, -1, -1, 23, 24, -1, -1, -1, - -1, -1, -1, 31, 32, 33, 34, 35, 36, 37, - 38, -1, 40, 7, 8, 9, 10, 11, 12, 13, - 14, -1, 16, 17, -1, -1, 20, -1, -1, 23, - 24, -1, -1, -1, -1, -1, -1, 31, 32, 33, - 34, 35, 36, 37, 38, 7, 8, 9, 10, 11, - 12, 13, 14, -1, -1, 17, 18, -1, 20, -1, - -1, 23, 24, -1, -1, -1, -1, -1, -1, 31, - 32, 33, 34, 35, 36, 37, 38, 7, 8, 9, - 10, 11, 12, 13, 14, -1, 16, 17, -1, -1, - 20, -1, -1, 23, 24, -1, -1, -1, -1, -1, - -1, 31, 32, 33, 34, 35, 36, 37, 38, 7, - 8, 9, 10, 11, 12, 13, 14, -1, 16, 17, - -1, -1, 20, -1, -1, 23, 24, -1, -1, -1, - -1, -1, -1, 31, 32, 33, 34, 35, 36, 37, - 38, 7, 8, 9, 10, 11, 12, 13, 14, -1, - 16, 17, -1, -1, 20, -1, -1, 23, 24, -1, - -1, -1, -1, -1, -1, 31, 32, 33, 34, 35, - 36, 37, 38, 7, 8, 9, 10, 11, 12, 13, - 14, -1, -1, 17, -1, 19, 20, -1, -1, 23, - 24, -1, -1, -1, -1, -1, -1, 31, 32, 33, - 34, 35, 36, 37, 38, 7, 8, 9, 10, 11, - 12, 13, 14, -1, -1, 17, -1, 19, 20, -1, - -1, 23, 24, -1, -1, -1, -1, -1, -1, 31, - 32, 33, 34, 35, 36, 37, 38, 7, 8, 9, - 10, 11, 12, 13, 14, -1, -1, 17, -1, -1, - 20, -1, -1, 23, 24, -1, -1, -1, -1, -1, - -1, 31, 32, 33, 34, 35, 36, 37, 38, 7, - 8, 9, 10, 11, 12, 13, 14, -1, -1, 17, - -1, -1, 20, -1, -1, 23, 24, -1, -1, -1, - -1, -1, -1, 31, 32, 33, 34, 35, 36, 37, - 38, 7, 8, 9, 10, 11, 12, 13, 14, -1, - -1, 17, -1, -1, 20, -1, -1, 23, 24, -1, - -1, -1, -1, -1, -1, 31, 32, 33, 34, 35, - 36, 37, 38, 7, 8, 9, 10, 11, 12, 13, - 14, -1, -1, 17, -1, -1, 20, -1, -1, 23, - 24, -1, -1, -1, -1, -1, -1, 31, 32, 33, - 34, 35, 36, 37, 7, 8, 9, 10, 11, 12, - 13, 14, -1, -1, 17, -1, -1, 20, -1, -1, - 23, 24, -1, -1, -1, -1, -1, -1, 31, 32, - 33, 34, 35, 36, 7, -1, -1, 10, 11, 12, - 13, 14, -1, -1, 17, -1, -1, 20, -1, -1, - 23, 24, -1, -1, -1, 7, -1, -1, 31, 32, - 12, 13, 14, -1, -1, 17, -1, -1, 20, -1, - -1, 23, 24, -1, -1, -1, -1, -1, -1, 31, - 32 -}; - - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint8 yystos[] = -{ - 0, 76, 0, 77, 5, 19, 25, 26, 42, 80, - 81, 7, 5, 5, 5, 28, 29, 30, 43, 3, - 4, 5, 6, 15, 73, 84, 85, 88, 89, 7, - 73, 18, 5, 73, 73, 85, 7, 8, 9, 10, - 11, 12, 13, 14, 17, 20, 23, 24, 31, 32, - 33, 34, 35, 36, 37, 38, 15, 41, 85, 5, - 78, 79, 85, 73, 82, 85, 86, 87, 85, 74, - 85, 85, 85, 85, 85, 85, 85, 85, 5, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 10, 85, 74, 16, 7, 5, 18, 74, 16, 16, - 73, 18, 7, 5, 85, 18, 85, 85, 85, 85, - 73, 5, 27, 39, 46, 54, 55, 56, 65, 68, - 69, 71, 73, 105, 106, 48, 60, 83, 7, 16, - 16, 85, 7, 73, 5, 19, 19, 19, 19, 85, - 43, 60, 61, 62, 63, 64, 104, 5, 85, 106, - 77, 74, 44, 49, 50, 51, 52, 53, 57, 73, - 90, 93, 94, 97, 99, 85, 85, 16, 85, 86, - 73, 66, 5, 7, 19, 74, 106, 77, 91, 85, - 21, 100, 100, 85, 85, 106, 93, 97, 98, 20, - 47, 72, 74, 74, 85, 19, 74, 86, 105, 45, - 85, 5, 45, 92, 3, 4, 101, 102, 103, 59, - 95, 74, 16, 74, 73, 94, 94, 73, 97, 74, - 19, 74, 67, 85, 40, 7, 93, 77, 12, 16, - 22, 106, 58, 96, 97, 97, 19, 105, 70, 85, - 85, 3, 103, 102, 106, 105, 70, 105 -}; - - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 75, 76, 76, 77, 77, 78, 78, 79, 79, - 80, 80, 80, 80, 80, 81, 81, 81, 81, 82, - 82, 83, 83, 84, 84, 84, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 86, 86, 87, 87, 88, 89, 89, 89, 90, - 90, 91, 91, 92, 93, 93, 94, 94, 94, 95, - 95, 96, 96, 97, 97, 97, 98, 98, 99, 99, - 99, 99, 99, 100, 101, 101, 102, 102, 103, 103, - 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, - 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, - 106, 106 -}; - - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 0, 3, 0, 2, 0, 1, 1, 3, - 3, 4, 6, 7, 8, 0, 2, 2, 2, 0, - 5, 1, 1, 1, 1, 1, 1, 1, 1, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, - 3, 0, 1, 1, 3, 8, 1, 8, 9, 1, - 4, 1, 3, 3, 1, 3, 3, 3, 4, 0, - 2, 0, 2, 1, 3, 3, 1, 3, 2, 2, - 2, 2, 2, 3, 1, 3, 3, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 2, 2, 2, - 2, 4, 7, 8, 6, 4, 3, 5, 1, 6, - 0, 3 -}; - - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) - -/* Error token number */ -#define YYTERROR 1 -#define YYERRCODE 256 - - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - -/* This macro is provided for backward compatibility. */ -#ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -#endif - - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) - - -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ - -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -{ - FILE *yyo = yyoutput; - YYUSE (yyo); - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif - YYUSE (yytype); -} - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -{ - YYFPRINTF (yyoutput, "%s %s (", - yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - - yy_symbol_value_print (yyoutput, yytype, yyvaluep); - YYFPRINTF (yyoutput, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -static void -yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) -{ - unsigned long int yylno = yyrline[yyrule]; - int yynrhs = yyr2[yyrule]; - int yyi; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, - yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) - ); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, Rule); \ -} while (0) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -static YYSIZE_T -yystrlen (const char *yystr) -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -yystpcpy (char *yydest, const char *yysrc) -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) -{ - YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); - YYSIZE_T yysize = yysize0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULLPTR; - /* Arguments of yyformat. */ - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ - int yycount = 0; - - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yytoken != YYEMPTY) - { - int yyn = yypact[*yyssp]; - yyarg[yycount++] = yytname[yytoken]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - } - } - } - - switch (yycount) - { -# define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } - - { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; - } - - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - yyp++; - yyformat++; - } - } - return 0; -} -#endif /* YYERROR_VERBOSE */ - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -{ - YYUSE (yyvaluep); - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yytype); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - - - -/* The lookahead symbol. */ -int yychar; - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; -/* Number of syntax errors so far. */ -int yynerrs; - - -/*----------. -| yyparse. | -`----------*/ - -int -yyparse (void) -{ - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values. - - Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; - - int yyn; - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken = 0; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yystacksize = YYINITDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyss + yystacksize - 1 <= yyssp) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = yylex (); - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yytable_value_is_error (yyn)) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - - yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - '$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 3: -#line 172 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyvsp[0].top)->dump(); -} -#line 1633 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 6: -#line 191 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vs) = new std::vector<RString>(); -} -#line 1641 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 7: -#line 196 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vs) = (yyvsp[0].vs); -} -#line 1649 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 8: -#line 206 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vs) = new std::vector<RString>(); - (yyval.vs)->push_back(*(yyvsp[0].s)); -} -#line 1658 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 9: -#line 212 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vs) = (yyvsp[-2].vs); - (yyval.vs)->push_back(*(yyvsp[0].s)); -} -#line 1667 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 10: -#line 223 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.top) = new Assignment{*(yyvsp[-2].s), (yyvsp[0].expr)}; -} -#line 1675 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 11: -#line 228 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.top) = new Constant{*(yyvsp[-2].s), (yyvsp[0].expr)}; -} -#line 1683 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 12: -#line 233 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.top) = new Teleport{*(yyvsp[-4].s), (yyvsp[-2].expr), (yyvsp[0].expr)}; -} -#line 1691 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 13: -#line 238 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.top) = new Procedure{*(yyvsp[-5].s), (yyvsp[-3].vs), (yyvsp[0].ve)}; -} -#line 1699 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 14: -#line 243 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.top) = new Spell{(yyvsp[-7].vs), *(yyvsp[-5].s), (yyvsp[-4].spellarg), (yyvsp[-2].expr), (yyvsp[0].spelldef)}; -} -#line 1707 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 15: -#line 253 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vs) = new std::vector<RString>(); -} -#line 1715 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 16: -#line 258 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vs) = (yyvsp[-1].vs); - (yyval.vs)->push_back("LOCAL"); -} -#line 1724 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 17: -#line 264 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vs) = (yyvsp[-1].vs); - (yyval.vs)->push_back("NONMAGIC"); -} -#line 1733 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 18: -#line 270 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vs) = (yyvsp[-1].vs); - (yyval.vs)->push_back("SILENT"); -} -#line 1742 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 19: -#line 281 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.spellarg) = new SpellArg{}; -} -#line 1750 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 20: -#line 286 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.spellarg) = new SpellArg{*(yyvsp[-3].s), *(yyvsp[-1].s)}; -} -#line 1758 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 21: -#line 296 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = new RString("PC"); -} -#line 1766 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 22: -#line 301 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = new RString("STRING"); -} -#line 1774 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 23: -#line 311 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = (yyvsp[0].s); -} -#line 1782 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 24: -#line 316 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = (yyvsp[0].s); -} -#line 1790 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 25: -#line 321 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = (yyvsp[0].s); -} -#line 1798 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 26: -#line 331 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new SimpleExpr{*(yyvsp[0].s)}; -} -#line 1806 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 27: -#line 336 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new SimpleExpr{*(yyvsp[0].s)}; -} -#line 1814 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 28: -#line 341 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = (yyvsp[0].expr); -} -#line 1822 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 29: -#line 346 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "+", (yyvsp[0].expr)}; -} -#line 1830 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 30: -#line 351 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "-", (yyvsp[0].expr)}; -} -#line 1838 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 31: -#line 356 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "*", (yyvsp[0].expr)}; -} -#line 1846 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 32: -#line 361 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "%", (yyvsp[0].expr)}; -} -#line 1854 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 33: -#line 366 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "/", (yyvsp[0].expr)}; -} -#line 1862 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 34: -#line 371 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "<", (yyvsp[0].expr)}; -} -#line 1870 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 35: -#line 376 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), ">", (yyvsp[0].expr)}; -} -#line 1878 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 36: -#line 381 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "&", (yyvsp[0].expr)}; -} -#line 1886 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 37: -#line 386 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "^", (yyvsp[0].expr)}; -} -#line 1894 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 38: -#line 391 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "|", (yyvsp[0].expr)}; -} -#line 1902 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 39: -#line 396 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "<<", (yyvsp[0].expr)}; -} -#line 1910 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 40: -#line 401 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), ">>", (yyvsp[0].expr)}; -} -#line 1918 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 41: -#line 406 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "<=", (yyvsp[0].expr)}; -} -#line 1926 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 42: -#line 411 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), ">=", (yyvsp[0].expr)}; -} -#line 1934 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 43: -#line 416 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "&&", (yyvsp[0].expr)}; -} -#line 1942 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 44: -#line 421 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "||", (yyvsp[0].expr)}; -} -#line 1950 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 45: -#line 426 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "==", (yyvsp[0].expr)}; -} -#line 1958 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 46: -#line 431 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - // convert to == - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "==", (yyvsp[0].expr)}; -} -#line 1967 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 47: -#line 437 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), "!=", (yyvsp[0].expr)}; -} -#line 1975 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 48: -#line 442 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new CallExpr{*(yyvsp[-3].s), (yyvsp[-1].vx)}; -} -#line 1983 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 49: -#line 447 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = (yyvsp[-1].expr); -} -#line 1991 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 50: -#line 452 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new BinExpr{(yyvsp[-2].expr), ".", new SimpleExpr(*(yyvsp[0].s))}; -} -#line 1999 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 51: -#line 462 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vx) = new std::vector<Expression *>(); -} -#line 2007 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 52: -#line 467 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vx) = (yyvsp[0].vx); -} -#line 2015 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 53: -#line 477 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vx) = new std::vector<Expression *>(); - (yyval.vx)->push_back((yyvsp[0].expr)); -} -#line 2024 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 54: -#line 483 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vx) = (yyvsp[-2].vx); - (yyval.vx)->push_back((yyvsp[0].expr)); -} -#line 2033 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 55: -#line 494 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.loc) = new Location{(yyvsp[-5].expr), (yyvsp[-3].expr), (yyvsp[-1].expr)}; -} -#line 2041 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 56: -#line 504 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new AreaLoc{(yyvsp[0].loc)}; -} -#line 2049 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 57: -#line 509 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new AreaRect{(yyvsp[-7].loc), (yyvsp[-3].expr), (yyvsp[-1].expr)}; -} -#line 2057 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 58: -#line 514 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.expr) = new AreaBar{(yyvsp[-8].loc), (yyvsp[-6].expr), (yyvsp[-3].expr), (yyvsp[-1].expr)}; -} -#line 2065 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 59: -#line 524 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.spelldef) = new SpellDef{new std::vector<Assignment *>{}, (yyvsp[0].vb)}; -} -#line 2073 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 60: -#line 529 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.spelldef) = new SpellDef{(yyvsp[-2].va), (yyvsp[0].vb)}; -} -#line 2081 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 61: -#line 539 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.va) = new std::vector<Assignment *>(); -} -#line 2089 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 62: -#line 544 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.va) = (yyvsp[-2].va); - (yyval.va)->push_back((yyvsp[-1].a)); -} -#line 2098 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 63: -#line 555 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.a) = new Assignment{*(yyvsp[-2].s), (yyvsp[0].expr)}; -} -#line 2106 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 64: -#line 565 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vb) = new std::vector<SpellBod *>(); - (yyval.vb)->push_back((yyvsp[0].b)); -} -#line 2115 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 65: -#line 571 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vb) = (yyvsp[-2].vb); - (yyval.vb)->push_back((yyvsp[0].b)); -} -#line 2124 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 66: -#line 582 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.b) = new SpellBodGuarded{(yyvsp[-2].g), (yyvsp[0].b)}; -} -#line 2132 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 67: -#line 587 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.b) = new SpellBodList{(yyvsp[-1].vb)}; -} -#line 2140 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 68: -#line 592 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.b) = new SpellBodEffect{(yyvsp[-2].ve), (yyvsp[-1].ve), (yyvsp[0].ve)}; -} -#line 2148 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 69: -#line 602 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.ve) = nullptr; -} -#line 2156 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 70: -#line 607 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.ve) = (yyvsp[0].ve); -} -#line 2164 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 71: -#line 617 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.ve) = nullptr; -} -#line 2172 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 72: -#line 622 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.ve) = (yyvsp[0].ve); -} -#line 2180 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 73: -#line 632 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.g) = (yyvsp[0].g); -} -#line 2188 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 74: -#line 637 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.g) = new SpellGuardOr((yyvsp[-2].g), (yyvsp[0].g)); -} -#line 2196 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 75: -#line 642 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.g) = new SpellGuardList{(yyvsp[-1].vg)}; -} -#line 2204 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 76: -#line 652 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vg) = new std::vector<SpellGuard *>(); - (yyval.vg)->push_back((yyvsp[0].g)); -} -#line 2213 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 77: -#line 658 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vg) = (yyvsp[-2].vg); - (yyval.vg)->push_back((yyvsp[0].g)); -} -#line 2222 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 78: -#line 669 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.g) = new SpellGuardRequire{(yyvsp[0].expr)}; -} -#line 2230 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 79: -#line 674 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.g) = new SpellGuardCatalysts{(yyvsp[0].vit)}; -} -#line 2238 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 80: -#line 679 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.g) = new SpellGuardComponents{(yyvsp[0].vit)}; -} -#line 2246 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 81: -#line 684 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.g) = new SpellGuardMana{(yyvsp[0].expr)}; -} -#line 2254 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 82: -#line 689 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.g) = new SpellGuardCasttime{(yyvsp[0].expr)}; -} -#line 2262 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 83: -#line 699 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vit) = (yyvsp[-1].vit); -} -#line 2270 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 84: -#line 709 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vit) = new std::vector<Item *>(); - (yyval.vit)->push_back((yyvsp[0].it)); -} -#line 2279 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 85: -#line 715 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.vit) = (yyvsp[-2].vit); - (yyval.vit)->push_back((yyvsp[0].it)); -} -#line 2288 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 86: -#line 726 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.it) = new Item{*(yyvsp[-2].s), *(yyvsp[0].s)}; -} -#line 2296 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 87: -#line 731 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.it) = new Item{RString(), *(yyvsp[0].s)}; -} -#line 2304 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 88: -#line 741 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = (yyvsp[0].s); -} -#line 2312 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 89: -#line 746 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = (yyvsp[0].s); -} -#line 2320 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 90: -#line 756 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = new RString{"PC"}; -} -#line 2328 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 91: -#line 761 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = new RString{"MOB"}; -} -#line 2336 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 92: -#line 766 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = new RString{"ENTITY"}; -} -#line 2344 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 93: -#line 771 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = new RString{"SPELL"}; -} -#line 2352 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 94: -#line 776 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = new RString{"TARGET"}; -} -#line 2360 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 95: -#line 781 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.s) = new RString{"NPC"}; -} -#line 2368 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 96: -#line 791 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new EffectList{(yyvsp[-1].ve)}; -} -#line 2376 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 97: -#line 796 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new SimpleEffect{"SKIP"}; -} -#line 2384 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 98: -#line 801 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new SimpleEffect{"ABORT"}; -} -#line 2392 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 99: -#line 806 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new SimpleEffect{"END"}; -} -#line 2400 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 100: -#line 811 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new SimpleEffect{"BREAK"}; -} -#line 2408 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 101: -#line 816 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new Assignment(*(yyvsp[-3].s), (yyvsp[-1].expr)); -} -#line 2416 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 102: -#line 821 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new ForeachEffect{*(yyvsp[-5].s), *(yyvsp[-4].s), (yyvsp[-2].expr), (yyvsp[0].e)}; -} -#line 2424 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 103: -#line 826 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new ForEffect{*(yyvsp[-6].s), (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].e)}; -} -#line 2432 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 104: -#line 831 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new IfEffect{(yyvsp[-4].expr), (yyvsp[-2].e), (yyvsp[0].e)}; -} -#line 2440 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 105: -#line 836 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new IfEffect{(yyvsp[-2].expr), (yyvsp[0].e)}; -} -#line 2448 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 106: -#line 841 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new SleepEffect{(yyvsp[-1].expr)}; -} -#line 2456 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 107: -#line 846 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new CallExpr{*(yyvsp[-4].s), (yyvsp[-2].vx)}; -} -#line 2464 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 108: -#line 851 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - AString tmp = sexpr::escape(*(yyvsp[0].s)); - (yyval.e) = new ScriptEffect{RString(tmp)}; -} -#line 2473 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 109: -#line 857 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.e) = new ExplicitCallEffect{*(yyvsp[-4].s), (yyvsp[-2].vx)}; -} -#line 2481 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 110: -#line 867 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - (yyval.ve) = new std::deque<Effect *>(); -} -#line 2489 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - case 111: -#line 872 "../src/spell-convert/parser.ypp" /* yacc.c:1646 */ - { - // because of grammar problems, doing this right generates reduce/reduce conflicts - (yyval.ve) = (yyvsp[0].ve); - (yyval.ve)->push_front((yyvsp[-2].e)); -} -#line 2499 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - break; - - -#line 2503 "src/spell-convert/parser.cpp" /* yacc.c:1646 */ - default: break; - } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - - /* Now 'shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; - - goto yynewstate; - - -/*--------------------------------------. -| yyerrlab -- here on detecting error. | -`--------------------------------------*/ -yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); - - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); -#else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ - yyssp, yytoken) - { - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == 1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); - if (!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror (yymsgp); - if (yysyntax_error_status == 2) - goto yyexhaustedlab; - } -# undef YYSYNTAX_ERROR -#endif - } - - - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - /* Do not reclaim the symbols of the rule whose action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - yystos[yystate], yyvsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -#if !defined yyoverflow || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - -yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - } - /* Do not reclaim the symbols of the rule whose action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - return yyresult; -} -#line 881 "../src/spell-convert/parser.ypp" /* yacc.c:1906 */ - -// Nothing to see here, move along diff --git a/src/spell-convert/parser.hpp b/src/spell-convert/parser.hpp deleted file mode 100644 index 889f2bb..0000000 --- a/src/spell-convert/parser.hpp +++ /dev/null @@ -1,152 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.0.2. */ - -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -#ifndef YY_SPELL_CONVERTER_SRC_SPELL_CONVERT_PARSER_HPP_INCLUDED -# define YY_SPELL_CONVERTER_SRC_SPELL_CONVERT_PARSER_HPP_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int spell_converterdebug; -#endif -/* "%code requires" blocks. */ -#line 2 "../src/spell-convert/parser.ypp" /* yacc.c:1909 */ - -/* vim: set ft=yacc: */ -#include "../strings/rstring.hpp" - -#include "ast.hpp" - -#undef YYERROR_VERBOSE -#define YYERROR_VERBOSE 1 - -#line 54 "src/spell-convert/parser.hpp" /* yacc.c:1909 */ - -/* Token type. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - INT = 258, - STRING = 259, - ID = 260, - DIR = 261, - CONST = 262, - PROCEDURE = 263, - CALL = 264, - SILENT = 265, - LOCAL = 266, - NONMAGIC = 267, - SHL = 268, - SHR = 269, - EQ = 270, - NEQ = 271, - GTE = 272, - LTE = 273, - ANDAND = 274, - OROR = 275, - SCRIPT_DATA = 276, - TO = 277, - TOWARDS = 278, - TELEPORT_ANCHOR = 279, - SPELL = 280, - LET = 281, - IN = 282, - END = 283, - DARROW = 284, - STRING_TY = 285, - REQUIRE = 286, - CATALYSTS = 287, - COMPONENTS = 288, - MANA = 289, - CASTTIME = 290, - SKIP = 291, - ABORT = 292, - BREAK = 293, - EFFECT_ = 294, - ATEND = 295, - ATTRIGGER = 296, - PC_F = 297, - NPC_F = 298, - MOB_F = 299, - ENTITY_F = 300, - TARGET_F = 301, - IF = 302, - THEN = 303, - ELSE = 304, - FOREACH = 305, - FOR = 306, - DO = 307, - SLEEP = 308, - OR = 309 - }; -#endif - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE YYSTYPE; -union YYSTYPE -{ -#line 27 "../src/spell-convert/parser.ypp" /* yacc.c:1909 */ - - RString *s; - std::vector<RString> *vs; - Effect *e; - std::deque<Effect *> *ve; - SpellDef *spelldef; - SpellArg *spellarg; - TopLevel *top; - Expression *expr; - std::vector<Expression *> *vx; - Location *loc; - Item *it; - std::vector<Item *> *vit; - Assignment *a; - std::vector<Assignment *> *va; - SpellBod *b; - std::vector<SpellBod *> *vb; - SpellGuard *g; - std::vector<SpellGuard *> *vg; - -#line 142 "src/spell-convert/parser.hpp" /* yacc.c:1909 */ -}; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - -extern YYSTYPE spell_converterlval; - -int spell_converterparse (void); - -#endif /* !YY_SPELL_CONVERTER_SRC_SPELL_CONVERT_PARSER_HPP_INCLUDED */ diff --git a/src/spell-convert/parser.ypp b/src/spell-convert/parser.ypp deleted file mode 100644 index 8a40543..0000000 --- a/src/spell-convert/parser.ypp +++ /dev/null @@ -1,902 +0,0 @@ -%code requires -{ -/* vim: set ft=yacc: */ -// magic-interpreter-parser.ypp - Old magic tokenizer -// -// Copyright © 2004-2011 The Mana World Development Team -// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> -// -// This file is part of The Mana World (Athena server) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. - -#include "../strings/rstring.hpp" - -#include "ast.hpp" - -#undef YYERROR_VERBOSE -#define YYERROR_VERBOSE 1 -} // %code requires - -%code -{ -//#include "parser.hpp" -#include "lexer.hpp" - -#include "../io/cxxstdio.hpp" - -#include "../sexpr/lexer.hpp" - -void yyerror(const char *msg) { FPRINTF(stderr, "Fatal: %s\n", msg); abort(); } -} // %code - -%name-prefix "spell_converter" - -%union -{ - RString *s; - std::vector<RString> *vs; - Effect *e; - std::deque<Effect *> *ve; - SpellDef *spelldef; - SpellArg *spellarg; - TopLevel *top; - Expression *expr; - std::vector<Expression *> *vx; - Location *loc; - Item *it; - std::vector<Item *> *vit; - Assignment *a; - std::vector<Assignment *> *va; - SpellBod *b; - std::vector<SpellBod *> *vb; - SpellGuard *g; - std::vector<SpellGuard *> *vg; -} // %union - -%expect 7 - -%token <s> INT -%token <s> STRING -%token <s> ID -%token <s> DIR - -%token '=' -%token '<' -%token '>' -%token '+' -%token '-' -%token '*' -%token '/' -%token '%' -%token '@' -%token ',' -%token '.' -%token ':' -%token ';' -%token '|' -%token '[' -%token ']' -%token '&' -%token '^' - -%token CONST -%token PROCEDURE -%token CALL -%token SILENT -%token LOCAL -%token NONMAGIC -%token SHL -%token SHR -%token EQ -%token NEQ -%token GTE -%token LTE -%token ANDAND -%token OROR -%token <s> SCRIPT_DATA -%token TO -%token TOWARDS -%token TELEPORT_ANCHOR -%token SPELL -%token LET -%token IN -%token END -%token DARROW -%token STRING_TY -%token REQUIRE -%token CATALYSTS -%token COMPONENTS -%token MANA -%token CASTTIME -%token SKIP -%token ABORT -%token BREAK -%token EFFECT_ -%token ATEND -%token ATTRIGGER -%token PC_F -%token NPC_F -%token MOB_F -%token ENTITY_F -%token TARGET_F -%token IF -%token THEN -%token ELSE -%token FOREACH -%token FOR -%token DO -%token SLEEP - -%type <s> value -%type <loc> location -%type <expr> area -%type <vx> arg_list -%type <vx> arg_list_ne -%type <va> defs -%type <spelldef> spelldef -%type <spellarg> argopt -%type <a> def -%type <vb> spellbody_list -%type <b> spellbody -%type <g> spellguard -%type <vg> spellguard_list -%type <g> prereq -%type <it> item -%type <vit> items -%type <vit> item_list -%type <s> item_name -%type <s> selection; -%type <e> effect -%type <ve> effect_list -%type <ve> maybe_trigger -%type <ve> maybe_end -%type <vs> spell_flags; - -%type <expr> expr -%type <s> arg_ty -%type <vs> proc_formals_list -%type <vs> proc_formals_list_ne - -%type <top> spellconf_option - -%left OROR -%left ANDAND -%left '<' '>' GTE LTE NEQ EQ -%left '+' '-' -%left '*' '/' '%' -%left SHL SHR '&' '^' '|' -%right '=' -%left OR -%left DARROW -%left '.' - -%% - -spellconf - -: /* empty */ - -| spellconf semicolons spellconf_option -{ - $3->dump(); -} - -; - - -semicolons - -: /* empty */ - -| semicolons ';' - -; - - -proc_formals_list - -: /* empty */ -{ - $$ = new std::vector<RString>(); -} - -| proc_formals_list_ne -{ - $$ = $1; -} - -; - - -proc_formals_list_ne - -: ID -{ - $$ = new std::vector<RString>(); - $$->push_back(*$1); -} - -| proc_formals_list_ne ',' ID -{ - $$ = $1; - $$->push_back(*$3); -} - -; - - -spellconf_option - -: ID '=' expr -{ - $$ = new Assignment{*$1, $3}; -} - -| CONST ID '=' expr -{ - $$ = new Constant{*$2, $4}; -} - -| TELEPORT_ANCHOR ID ':' expr '=' expr -{ - $$ = new Teleport{*$2, $4, $6}; -} - -| PROCEDURE ID '(' proc_formals_list ')' '=' effect_list -{ - $$ = new Procedure{*$2, $4, $7}; -} - -| spell_flags SPELL ID argopt ':' expr '=' spelldef -{ - $$ = new Spell{$1, *$3, $4, $6, $8}; -} - -; - - -spell_flags - -: /* empty */ -{ - $$ = new std::vector<RString>(); -} - -| spell_flags LOCAL -{ - $$ = $1; - $$->push_back("LOCAL"); -} - -| spell_flags NONMAGIC -{ - $$ = $1; - $$->push_back("NONMAGIC"); -} - -| spell_flags SILENT -{ - $$ = $1; - $$->push_back("SILENT"); -} - -; - - -argopt - -: /* empty */ -{ - $$ = new SpellArg{}; -} - -| '(' ID ':' arg_ty ')' -{ - $$ = new SpellArg{*$2, *$4}; -} - -; - - -arg_ty - -: PC_F -{ - $$ = new RString("PC"); -} - -| STRING_TY -{ - $$ = new RString("STRING"); -} - -; - - -value - -: DIR -{ - $$ = $1; -} - -| INT -{ - $$ = $1; -} - -| STRING -{ - $$ = $1; -} - -; - - -expr - -: value -{ - $$ = new SimpleExpr{*$1}; -} - -| ID -{ - $$ = new SimpleExpr{*$1}; -} - -| area -{ - $$ = $1; -} - -| expr '+' expr -{ - $$ = new BinExpr{$1, "+", $3}; -} - -| expr '-' expr -{ - $$ = new BinExpr{$1, "-", $3}; -} - -| expr '*' expr -{ - $$ = new BinExpr{$1, "*", $3}; -} - -| expr '%' expr -{ - $$ = new BinExpr{$1, "%", $3}; -} - -| expr '/' expr -{ - $$ = new BinExpr{$1, "/", $3}; -} - -| expr '<' expr -{ - $$ = new BinExpr{$1, "<", $3}; -} - -| expr '>' expr -{ - $$ = new BinExpr{$1, ">", $3}; -} - -| expr '&' expr -{ - $$ = new BinExpr{$1, "&", $3}; -} - -| expr '^' expr -{ - $$ = new BinExpr{$1, "^", $3}; -} - -| expr '|' expr -{ - $$ = new BinExpr{$1, "|", $3}; -} - -| expr SHL expr -{ - $$ = new BinExpr{$1, "<<", $3}; -} - -| expr SHR expr -{ - $$ = new BinExpr{$1, ">>", $3}; -} - -| expr LTE expr -{ - $$ = new BinExpr{$1, "<=", $3}; -} - -| expr GTE expr -{ - $$ = new BinExpr{$1, ">=", $3}; -} - -| expr ANDAND expr -{ - $$ = new BinExpr{$1, "&&", $3}; -} - -| expr OROR expr -{ - $$ = new BinExpr{$1, "||", $3}; -} - -| expr EQ expr -{ - $$ = new BinExpr{$1, "==", $3}; -} - -| expr '=' expr -{ - // convert to == - $$ = new BinExpr{$1, "==", $3}; -} - -| expr NEQ expr -{ - $$ = new BinExpr{$1, "!=", $3}; -} - -| ID '(' arg_list ')' -{ - $$ = new CallExpr{*$1, $3}; -} - -| '(' expr ')' -{ - $$ = $2; -} - -| expr '.' ID -{ - $$ = new BinExpr{$1, ".", new SimpleExpr(*$3)}; -} - -; - - -arg_list - -: /* empty */ -{ - $$ = new std::vector<Expression *>(); -} - -| arg_list_ne -{ - $$ = $1; -} - -; - - -arg_list_ne - -: expr -{ - $$ = new std::vector<Expression *>(); - $$->push_back($1); -} - -| arg_list_ne ',' expr -{ - $$ = $1; - $$->push_back($3); -} - -; - - -location - -: '@' '(' expr ',' expr ',' expr ')' -{ - $$ = new Location{$3, $5, $7}; -} - -; - - -area - -: location -{ - $$ = new AreaLoc{$1}; -} - -| location '@' '+' '(' expr ',' expr ')' -{ - $$ = new AreaRect{$1, $5, $7}; -} - -| location TOWARDS expr ':' '(' expr ',' expr ')' -{ - $$ = new AreaBar{$1, $3, $6, $8}; -} - -; - - -spelldef - -: spellbody_list -{ - $$ = new SpellDef{new std::vector<Assignment *>{}, $1}; -} - -| LET defs IN spellbody_list -{ - $$ = new SpellDef{$2, $4}; -} - -; - - -defs - -: semicolons -{ - $$ = new std::vector<Assignment *>(); -} - -| defs def semicolons -{ - $$ = $1; - $$->push_back($2); -} - -; - - -def - -: ID '=' expr -{ - $$ = new Assignment{*$1, $3}; -} - -; - - -spellbody_list - -: spellbody -{ - $$ = new std::vector<SpellBod *>(); - $$->push_back($1); -} - -| spellbody_list '|' spellbody -{ - $$ = $1; - $$->push_back($3); -} - -; - - -spellbody - -: spellguard DARROW spellbody -{ - $$ = new SpellBodGuarded{$1, $3}; -} - -| '(' spellbody_list ')' -{ - $$ = new SpellBodList{$2}; -} - -| EFFECT_ effect_list maybe_trigger maybe_end -{ - $$ = new SpellBodEffect{$2, $3, $4}; -} - -; - - -maybe_trigger - -: /* empty */ -{ - $$ = nullptr; -} - -| ATTRIGGER effect_list -{ - $$ = $2; -} - -; - - -maybe_end - -: /* empty */ -{ - $$ = nullptr; -} - -| ATEND effect_list -{ - $$ = $2; -} - -; - - -spellguard - -: prereq -{ - $$ = $1; -} - -| spellguard OR spellguard -{ - $$ = new SpellGuardOr($1, $3); -} - -| '(' spellguard_list ')' -{ - $$ = new SpellGuardList{$2}; -} - -; - - -spellguard_list - -: spellguard -{ - $$ = new std::vector<SpellGuard *>(); - $$->push_back($1); -} - -| spellguard_list ',' spellguard -{ - $$ = $1; - $$->push_back($3); -} - -; - - -prereq - -: REQUIRE expr -{ - $$ = new SpellGuardRequire{$2}; -} - -| CATALYSTS items -{ - $$ = new SpellGuardCatalysts{$2}; -} - -| COMPONENTS items -{ - $$ = new SpellGuardComponents{$2}; -} - -| MANA expr -{ - $$ = new SpellGuardMana{$2}; -} - -| CASTTIME expr -{ - $$ = new SpellGuardCasttime{$2}; -} - -; - - -items - -: '[' item_list ']' -{ - $$ = $2; -} - -; - - -item_list - -: item -{ - $$ = new std::vector<Item *>(); - $$->push_back($1); -} - -| item_list ',' item -{ - $$ = $1; - $$->push_back($3); -} - -; - - -item - -: INT '*' item_name -{ - $$ = new Item{*$1, *$3}; -} - -| item_name -{ - $$ = new Item{RString(), *$1}; -} - -; - - -item_name - -: STRING -{ - $$ = $1; -} - -| INT -{ - $$ = $1; -} - -; - - -selection - -: PC_F -{ - $$ = new RString{"PC"}; -} - -| MOB_F -{ - $$ = new RString{"MOB"}; -} - -| ENTITY_F -{ - $$ = new RString{"ENTITY"}; -} - -| SPELL -{ - $$ = new RString{"SPELL"}; -} - -| TARGET_F -{ - $$ = new RString{"TARGET"}; -} - -| NPC_F -{ - $$ = new RString{"NPC"}; -} - -; - - -effect - -: '(' effect_list ')' -{ - $$ = new EffectList{$2}; -} - -| SKIP ';' -{ - $$ = new SimpleEffect{"SKIP"}; -} - -| ABORT ';' -{ - $$ = new SimpleEffect{"ABORT"}; -} - -| END ';' -{ - $$ = new SimpleEffect{"END"}; -} - -| BREAK ';' -{ - $$ = new SimpleEffect{"BREAK"}; -} - -| ID '=' expr ';' -{ - $$ = new Assignment(*$1, $3); -} - -| FOREACH selection ID IN expr DO effect -{ - $$ = new ForeachEffect{*$2, *$3, $5, $7}; -} - -| FOR ID '=' expr TO expr DO effect -{ - $$ = new ForEffect{*$2, $4, $6, $8}; -} - -| IF expr THEN effect ELSE effect -{ - $$ = new IfEffect{$2, $4, $6}; -} - -| IF expr THEN effect -{ - $$ = new IfEffect{$2, $4}; -} - -| SLEEP expr ';' -{ - $$ = new SleepEffect{$2}; -} - -| ID '(' arg_list ')' ';' -{ - $$ = new CallExpr{*$1, $3}; -} - -| SCRIPT_DATA -{ - AString tmp = sexpr::escape(*$1); - $$ = new ScriptEffect{RString(tmp)}; -} - -| CALL ID '(' arg_list ')' ';' -{ - $$ = new ExplicitCallEffect{*$2, $4}; -} - -; - - -effect_list - -: /* empty */ -{ - $$ = new std::deque<Effect *>(); -} - -| effect semicolons effect_list -{ - // because of grammar problems, doing this right generates reduce/reduce conflicts - $$ = $3; - $$->push_front($1); -} - -; - - -%% -// Nothing to see here, move along diff --git a/src/strings/all.hpp b/src/strings/all.hpp index 26079ed..8e13b92 100644 --- a/src/strings/all.hpp +++ b/src/strings/all.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_STRINGS_ALL_HPP -#define TMWA_STRINGS_ALL_HPP +#pragma once // strings/all.hpp - All the string classes you'll ever need. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,16 +18,20 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "base.hpp" -# include "mstring.hpp" -# include "rstring.hpp" -# include "astring.hpp" -# include "tstring.hpp" -# include "sstring.hpp" -# include "zstring.hpp" -# include "xstring.hpp" -# include "vstring.hpp" +#include "base.hpp" +#include "mstring.hpp" +#include "rstring.hpp" +#include "astring.hpp" +#include "tstring.hpp" +#include "sstring.hpp" +#include "zstring.hpp" +#include "xstring.hpp" +#include "literal.hpp" +#include "vstring.hpp" -#endif // TMWA_STRINGS_ALL_HPP + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/strings/astring.cpp b/src/strings/astring.cpp index f1e9030..f1f12c3 100644 --- a/src/strings/astring.cpp +++ b/src/strings/astring.cpp @@ -18,15 +18,25 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include <cstdarg> +#include <cstdio> +#include <cstdlib> + +#include <algorithm> + #include "mstring.hpp" #include "tstring.hpp" #include "sstring.hpp" #include "zstring.hpp" #include "xstring.hpp" -#include "vstring.hpp" +#include "literal.hpp" +// doing sneaky tricks here //#include "../poison.hpp" + +namespace tmwa +{ namespace strings { static_assert(sizeof(AString) == 256, "AString"); @@ -156,6 +166,13 @@ namespace strings special = 255 - x.size(); } } + AString::AString(LString l) + : data{}, special() + { + new(r_ptr()) RString(); + special = 255; + *this = XString(l); + } AString::iterator AString::begin() const { @@ -205,27 +222,5 @@ namespace strings out = AString(buffer, buffer + len); return len; } - - AStringConverter::AStringConverter(AString& s) - : out(s), mid(nullptr) - {} - - AStringConverter::~AStringConverter() - { - if (mid) - { - out = ZString(really_construct_from_a_pointer, mid, nullptr); - free(mid); - } - } - - char **AStringConverter::operator &() - { - return ∣ - } - - AStringConverter convert_for_scanf(AString& s) - { - return AStringConverter(s); - } } // namespace strings +} // namespace tmwa diff --git a/src/strings/astring.hpp b/src/strings/astring.hpp index aab14cf..83399f0 100644 --- a/src/strings/astring.hpp +++ b/src/strings/astring.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_STRINGS_ASTRING_HPP -#define TMWA_STRINGS_ASTRING_HPP +#pragma once // strings/astring.hpp - An owned, reference-counted immutable string. // // Copyright © 2013-2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,20 +18,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdarg> -# include <cstring> +#include "base.hpp" +#include "rstring.hpp" -# include "base.hpp" -# include "rstring.hpp" +namespace tmwa +{ namespace strings { /// An owning string that has reached its final contents. /// The storage is NUL-terminated class AString : public _crtp_string<AString, AString, ZPair> { +#ifdef __clang__ + __attribute__((unused)) +#endif RString *align[0]; char data[255]; unsigned char special; @@ -49,12 +51,6 @@ namespace strings explicit AString(const MString& s); - template<size_t n> - AString(char (&s)[n]) = delete; - - template<size_t n> - AString(const char (&s)[n]); - template<class It> AString(It b, It e); @@ -66,6 +62,7 @@ namespace strings AString(XString); template<uint8_t n> AString(const VString<n>& v); + AString(LString s); iterator begin() const; iterator end() const; @@ -81,20 +78,7 @@ namespace strings __attribute__((format(printf, 2, 0))) int do_vprint(AString& out, const char *fmt, va_list ap); - - class AStringConverter - { - AString& out; - char *mid; - public: - AStringConverter(AString& s); - ~AStringConverter(); - char **operator &(); - }; - - AStringConverter convert_for_scanf(AString& s); } // namespace strings +} // namespace tmwa -# include "astring.tcc" - -#endif // TMWA_STRINGS_ASTRING_HPP +#include "astring.tcc" diff --git a/src/strings/astring.py b/src/strings/astring.py index ec1dafe..063e721 100644 --- a/src/strings/astring.py +++ b/src/strings/astring.py @@ -2,7 +2,7 @@ class AString(object): ''' print an AString ''' __slots__ = ('_value') - name = 'strings::AString' + name = 'tmwa::strings::AString' enabled = True def __init__(self, value): diff --git a/src/strings/astring.tcc b/src/strings/astring.tcc index ed07bd9..f2d0dc9 100644 --- a/src/strings/astring.tcc +++ b/src/strings/astring.tcc @@ -19,25 +19,11 @@ #include "mstring.hpp" + +namespace tmwa +{ namespace strings { - template<size_t n> - AString::AString(const char (&s)[n]) - : data{}, special() - { - XPair x = s; - if (x.size() > 255 || x.size() == 0) - { - new(r_ptr()) RString(x); - special = 255; - } - else - { - *std::copy(x.begin(), x.end(), data) = '\0'; - special = 255 - x.size(); - } - } - template<class It> AString::AString(It b, It e) : data{}, special() @@ -74,3 +60,4 @@ namespace strings new(r_ptr()) RString(); } } // namespace strings +} // namespace tmwa diff --git a/src/strings/base.hpp b/src/strings/base.hpp index ee7480b..b6b3df0 100644 --- a/src/strings/base.hpp +++ b/src/strings/base.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_STRINGS_BASE_HPP -#define TMWA_STRINGS_BASE_HPP +#pragma once // strings/base.hpp - CRTP base for string implementations. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,15 +18,16 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" +#include "pair.hpp" -# include "fwd.hpp" -# include "pair.hpp" +#include <cstddef> -# include <cstddef> +#include <iterator> -# include <iterator> +namespace tmwa +{ // It is a common mistake to assume that one string class for everything. // Because C++ and TMWA have a C legacy, there are a few more here // than would probably be necessary in an ideal language. @@ -197,7 +197,6 @@ namespace strings template<class L, class R, typename=typename std::enable_if<string_comparison_allowed<L, R>::value>::type> auto operator >= (const L& l, const R& r) -> decltype((pair_compare(l, r), true)); } // namespace strings +} // namespace tmwa -# include "base.tcc" - -#endif // TMWA_STRINGS_BASE_HPP +#include "base.tcc" diff --git a/src/strings/base.tcc b/src/strings/base.tcc index a5a57d0..83dff70 100644 --- a/src/strings/base.tcc +++ b/src/strings/base.tcc @@ -17,10 +17,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include <cstddef> + #include <algorithm> #include "pair.hpp" + +namespace tmwa +{ namespace strings { namespace detail @@ -440,3 +445,4 @@ namespace strings return pair_compare(l, r) >= 0; } } // namespace strings +} // namespace tmwa diff --git a/src/strings/base_test.cpp b/src/strings/base_test.cpp index 52c44dc..f9b9ca6 100644 --- a/src/strings/base_test.cpp +++ b/src/strings/base_test.cpp @@ -23,9 +23,13 @@ #include "vstring.hpp" #include "xstring.hpp" #include "rstring.hpp" +#include "literal.hpp" #include "../poison.hpp" + +namespace tmwa +{ using namespace strings; struct _test : VString<1> {}; @@ -42,7 +46,8 @@ static_assert(string_comparison_allowed<XString, RString>::value, "xf"); TEST(strings, contains) { - XString hi = "Hello"; - EXPECT_TRUE(hi.contains_any("Hi")); - EXPECT_FALSE(hi.contains_any("hi")); + XString hi = "Hello"_s; + EXPECT_TRUE(hi.contains_any("Hi"_s)); + EXPECT_FALSE(hi.contains_any("hi"_s)); } +} // namespace tmwa diff --git a/src/strings/fwd.hpp b/src/strings/fwd.hpp index 4c58e03..b1b8266 100644 --- a/src/strings/fwd.hpp +++ b/src/strings/fwd.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_STRINGS_FWD_HPP -#define TMWA_STRINGS_FWD_HPP +#pragma once // strings/fwd.hpp - Forward declarations for all the string classes. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,10 +18,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "../sanity.hpp" -# include <cstdint> +#include <cstddef> +#include <cstdint> + +namespace tmwa +{ // It is a common mistake to assume that one string class for everything. // Because C++ and TMWA have a C legacy, there are a few more here // than would probably be necessary in an ideal language. @@ -40,12 +43,18 @@ namespace strings class XString; // semi-owning + class LString; + class FormatString; template<uint8_t len> class VString; - // refactor this into a function? + // TODO refactor this into a function? enum _type_that_just_has_a_name_to_fix_linkage { really_construct_from_a_pointer }; + + LString operator "" _s(const char *, size_t); + constexpr + FormatString operator "" _fmt(const char *, size_t); } // namespace strings using strings::MString; @@ -57,6 +66,10 @@ using strings::SString; using strings::ZString; using strings::XString; +using strings::LString; +using strings::FormatString; using strings::VString; -#endif // TMWA_STRINGS_FWD_HPP +using strings::operator "" _s; +using strings::operator "" _fmt; +} // namespace tmwa diff --git a/src/strings/literal.cpp b/src/strings/literal.cpp new file mode 100644 index 0000000..252bfcb --- /dev/null +++ b/src/strings/literal.cpp @@ -0,0 +1,56 @@ +#include "literal.hpp" +// strings/literal.cpp - A string stored in the readonly data segment. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <cstdio> + +#include "../poison.hpp" + + +namespace tmwa +{ +namespace strings +{ + LString::LString(const char *b, const char *e) + : _b(b), _e(e) + {} + + LString::iterator LString::begin() const + { + return _b; + } + LString::iterator LString::end() const + { + return _e; + } + const RString *LString::base() const + { + return nullptr; + } + const char *LString::c_str() const + { + return &*begin(); + } + + const char *decay_for_printf(const LString& zs) + { + return zs.c_str(); + } +} // namespace strings +} // namespace tmwa diff --git a/src/strings/literal.hpp b/src/strings/literal.hpp new file mode 100644 index 0000000..67bd317 --- /dev/null +++ b/src/strings/literal.hpp @@ -0,0 +1,79 @@ +#pragma once +// strings/literal.hpp - A string stored in the readonly data segment. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include "base.hpp" + + +namespace tmwa +{ +namespace strings +{ + /// A statically owned string that is guaranteed to be NUL-terminated. + /// This is a more permissive lifetime than anybody else has. + class LString : public _crtp_string<LString, AString, LPair> + { + iterator _b, _e; + private: + LString(const char *b, const char *e); + friend LString operator "" _s(const char *, size_t); + // for tail slicing + LString(const char *b, const char *e, const RString *) : LString(b, e) {} + friend class _crtp_string<LString, AString, LPair>; + public: + + iterator begin() const; + iterator end() const; + const RString *base() const; + const char *c_str() const; + }; + + class FormatString + { + const char *_format; + + friend constexpr FormatString operator "" _fmt(const char *, size_t); + constexpr explicit + FormatString(const char *f) : _format(f) {} + public: + constexpr + const char *format_string() const { return _format; } + }; + + + // cxxstdio helpers + // I think the conversion will happen automatically. TODO test this. + // Nope, it doesn't, since there's a template + // Actually, it might now. + const char *decay_for_printf(const LString& zs); + + inline + LString operator "" _s(const char *s, size_t) + { + return LString(s, s + __builtin_strlen(s)); + } + constexpr + FormatString operator "" _fmt(const char *s, size_t) + { + return FormatString(s); + } +} // namespace strings +} // namespace tmwa diff --git a/src/strings/mstring.cpp b/src/strings/mstring.cpp index 2a1ca62..d48bff2 100644 --- a/src/strings/mstring.cpp +++ b/src/strings/mstring.cpp @@ -22,6 +22,9 @@ #include "../poison.hpp" + +namespace tmwa +{ namespace strings { MString::iterator MString::begin() @@ -100,3 +103,4 @@ namespace strings return _hack.back(); } } // namespace strings +} // namespace tmwa diff --git a/src/strings/mstring.hpp b/src/strings/mstring.hpp index 8225d9e..4f40919 100644 --- a/src/strings/mstring.hpp +++ b/src/strings/mstring.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_STRINGS_MSTRING_HPP -#define TMWA_STRINGS_MSTRING_HPP +#pragma once // strings/mstring.hpp - A mutable string. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,12 +18,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <deque> +#include <deque> -# include "base.hpp" +namespace tmwa +{ namespace strings { /// An owning string that is still expected to change. @@ -64,5 +64,4 @@ namespace strings char& back(); }; } // namespace strings - -#endif // TMWA_STRINGS_MSTRING_HPP +} // namespace tmwa diff --git a/src/strings/pair.hpp b/src/strings/pair.hpp index a592a91..9c1cd9f 100644 --- a/src/strings/pair.hpp +++ b/src/strings/pair.hpp @@ -1,8 +1,7 @@ -#ifndef TMWA_STRINGS_PAIR_HPP -#define TMWA_STRINGS_PAIR_HPP +#pragma once // strings/pair.hpp - Internal contiguous range. // -// Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> +// Copyright © 2013-2014 Ben Longbons <b.r.longbons@gmail.com> // // This file is part of The Mana World (Athena server) // @@ -19,12 +18,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstring> - -# include "fwd.hpp" +namespace tmwa +{ namespace strings { // TODO instead typedef ranges::Contiguous<const char> @@ -40,12 +38,6 @@ namespace strings XPair(const char *b, const char *e) : _begin(b), _end(e) {} - template<size_t n> - XPair(char (&arr)[n]) = delete; - template<size_t n> - XPair(const char (&arr)[n]) - : _begin(arr), _end(arr + strlen(arr)) - {} const char *begin() const { return _begin; } const char *end() const { return _end; } @@ -59,13 +51,15 @@ namespace strings ZPair(const char *b, const char *e) : XPair(b, e) {} - template<size_t n> - ZPair(char (&arr)[n]) = delete; - template<size_t n> - ZPair(const char (&arr)[n]) - : XPair(arr) + }; + struct LPair : ZPair + { + typedef LString TailSlice; + typedef XString FullSlice; + + LPair(const char *b, const char *e) + : ZPair(b, e) {} }; } // namespace strings - -#endif // TMWA_STRINGS_PAIR_HPP +} // namespace tmwa diff --git a/src/strings/rstring.cpp b/src/strings/rstring.cpp index c0e231e..3e5a46d 100644 --- a/src/strings/rstring.cpp +++ b/src/strings/rstring.cpp @@ -18,15 +18,22 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include <cstdio> + #include "mstring.hpp" +#include "astring.hpp" #include "tstring.hpp" #include "sstring.hpp" #include "zstring.hpp" #include "xstring.hpp" -#include "vstring.hpp" +#include "literal.hpp" +// doing sneaky tricks here //#include "../poison.hpp" + +namespace tmwa +{ namespace strings { static_assert(sizeof(RString) == sizeof(const char *), "RString"); @@ -54,7 +61,7 @@ namespace strings { // order important for self-assign r.owned->count++; - // owned can be NULL from ctors + // owned can be nullptr from ctors // TODO do ctors *properly* (requires gcc 4.7 to stay sane) if (owned && !owned->count--) ::operator delete(owned); @@ -125,6 +132,11 @@ namespace strings else _assign(x.begin(), x.end()); } + RString::RString(LString l) + : owned(nullptr) + { + *this = XString(l); + } RString::iterator RString::begin() const { @@ -164,3 +176,4 @@ namespace strings return len; } } // namespace strings +} // namespace tmwa diff --git a/src/strings/rstring.hpp b/src/strings/rstring.hpp index 7cb19d6..fd3ee65 100644 --- a/src/strings/rstring.hpp +++ b/src/strings/rstring.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_STRINGS_RSTRING_HPP -#define TMWA_STRINGS_RSTRING_HPP +#pragma once // strings/rstring.hpp - An owned, reference-counted immutable string. // // Copyright © 2013-2014 Ben Longbons <b.r.longbons@gmail.com> @@ -19,13 +18,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstdarg> -# include <cstring> +#include <cstdarg> -# include "base.hpp" +#include "base.hpp" + +namespace tmwa +{ namespace strings { /// An owning string that has reached its final contents. @@ -56,12 +57,6 @@ namespace strings explicit RString(const MString& s); - template<size_t n> - RString(char (&s)[n]) = delete; - - template<size_t n> - RString(const char (&s)[n]); - template<class It> RString(It b, It e); @@ -73,6 +68,7 @@ namespace strings RString(XString); template<uint8_t n> RString(const VString<n>& v); + RString(LString s); iterator begin() const; iterator end() const; @@ -89,7 +85,6 @@ namespace strings __attribute__((format(printf, 2, 0))) int do_vprint(RString& out, const char *fmt, va_list ap); } // namespace strings +} // namespace tmwa -# include "rstring.tcc" - -#endif // TMWA_STRINGS_RSTRING_HPP +#include "rstring.tcc" diff --git a/src/strings/rstring.py b/src/strings/rstring.py index f0618d6..8021ec2 100644 --- a/src/strings/rstring.py +++ b/src/strings/rstring.py @@ -2,7 +2,7 @@ class RString(object): ''' print a RString ''' __slots__ = ('_value') - name = 'strings::RString' + name = 'tmwa::strings::RString' enabled = True def __init__(self, value): diff --git a/src/strings/rstring.tcc b/src/strings/rstring.tcc index 8b4c0c0..c247b8f 100644 --- a/src/strings/rstring.tcc +++ b/src/strings/rstring.tcc @@ -19,6 +19,9 @@ #include "mstring.hpp" + +namespace tmwa +{ namespace strings { template<class It> @@ -47,12 +50,6 @@ namespace strings owned->body[diff] = '\0'; } - template<size_t n> - RString::RString(const char (&s)[n]) - { - _assign(s, s + strlen(s)); - } - template<class It> RString::RString(It b, It e) { @@ -65,3 +62,4 @@ namespace strings _assign(v.begin(), v.end()); } } // namespace strings +} // namespace tmwa diff --git a/src/strings/sstring.cpp b/src/strings/sstring.cpp index 76f0994..0500129 100644 --- a/src/strings/sstring.cpp +++ b/src/strings/sstring.cpp @@ -18,12 +18,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include "rstring.hpp" +#include "astring.hpp" #include "tstring.hpp" #include "zstring.hpp" #include "xstring.hpp" +#include "literal.hpp" #include "../poison.hpp" + +namespace tmwa +{ namespace strings { SString::SString() @@ -54,6 +60,10 @@ namespace strings else *this = RString(x); } + SString::SString(const LString& l) + { + *this = XString(l); + } SString::SString(RString r, size_t b, size_t e) : _s(std::move(r)), _b(b), _e(e) @@ -95,3 +105,4 @@ namespace strings return &_s; } } // namespace strings +} // namespace tmwa diff --git a/src/strings/sstring.hpp b/src/strings/sstring.hpp index 7166e94..a65616d 100644 --- a/src/strings/sstring.hpp +++ b/src/strings/sstring.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_STRINGS_SSTRING_HPP -#define TMWA_STRINGS_SSTRING_HPP +#pragma once // strings/sstring.hpp - A full slice of an RString. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,11 +18,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "base.hpp" -# include "rstring.hpp" +#include "base.hpp" +#include "rstring.hpp" + +namespace tmwa +{ namespace strings { /// An owning string that represents a arbitrary slice of an RString. @@ -42,10 +44,7 @@ namespace strings SString(const XString&); template<uint8_t n> SString(const VString<n>& v); - template<size_t n> - SString(char (&s)[n]) = delete; - template<size_t n> - SString(const char (&s)[n]); + SString(const LString&); //template<class It> //SString(It b, It e) : _s(b, e), _b(0), _e(_s.size()) {} SString(RString f, size_t b, size_t e); @@ -57,7 +56,6 @@ namespace strings const RString *base() const; }; } // namespace strings +} // namespace tmwa -# include "sstring.tcc" - -#endif // TMWA_STRINGS_SSTRING_HPP +#include "sstring.tcc" diff --git a/src/strings/sstring.tcc b/src/strings/sstring.tcc index 4be33dd..315e19a 100644 --- a/src/strings/sstring.tcc +++ b/src/strings/sstring.tcc @@ -19,15 +19,14 @@ #include "vstring.hpp" + +namespace tmwa +{ namespace strings { template<uint8_t n> SString::SString(const VString<n>& v) : _s(v), _b(0), _e(_s.size()) {} - - template<size_t n> - SString::SString(const char (&s)[n]) - : _s(s), _b(0), _e(_s.size()) - {} } // namespace strings +} // namespace tmwa diff --git a/src/strings/strings2_test.cpp b/src/strings/strings2_test.cpp index e5d5281..18c7db4 100644 --- a/src/strings/strings2_test.cpp +++ b/src/strings/strings2_test.cpp @@ -1,4 +1,3 @@ -#include "all.hpp" // strings2_test.cpp - Testsuite part 2 for strings. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -18,30 +17,34 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. - #include <gtest/gtest.h> +#include "all.hpp" + #include "../poison.hpp" + +namespace tmwa +{ TEST(StringTests, traits2) { - ZString print_non = "\t\e"; - ZString print_mix = "n\t"; - RString print_all = "n "; + ZString print_non = "\t\e"_s; + ZString print_mix = "n\t"_s; + RString print_all = "n "_s; EXPECT_FALSE(print_non.has_print()); EXPECT_TRUE(print_mix.has_print()); EXPECT_TRUE(print_all.has_print()); EXPECT_FALSE(print_non.is_print()); EXPECT_FALSE(print_mix.is_print()); EXPECT_TRUE(print_all.is_print()); - EXPECT_EQ("__", print_non.to_print()); - EXPECT_EQ("n_", print_mix.to_print()); - EXPECT_EQ("n ", print_all.to_print()); + EXPECT_EQ("__"_s, print_non.to_print()); + EXPECT_EQ("n_"_s, print_mix.to_print()); + EXPECT_EQ("n "_s, print_all.to_print()); EXPECT_EQ(print_all.begin(), print_all.to_print().begin()); - ZString graph_non = " \e"; - ZString graph_mix = "n "; - RString graph_all = "n."; + ZString graph_non = " \e"_s; + ZString graph_mix = "n "_s; + RString graph_all = "n."_s; EXPECT_FALSE(graph_non.has_graph()); EXPECT_TRUE(graph_mix.has_graph()); EXPECT_TRUE(graph_all.has_graph()); @@ -49,37 +52,37 @@ TEST(StringTests, traits2) EXPECT_FALSE(graph_mix.is_graph()); EXPECT_TRUE(graph_all.is_graph()); - ZString lower_non = "0A"; - ZString lower_mix = "Oa"; - RString lower_all = "oa"; + ZString lower_non = "0A"_s; + ZString lower_mix = "Oa"_s; + RString lower_all = "oa"_s; EXPECT_FALSE(lower_non.has_lower()); EXPECT_TRUE(lower_mix.has_lower()); EXPECT_TRUE(lower_all.has_lower()); EXPECT_FALSE(lower_non.is_lower()); EXPECT_FALSE(lower_mix.is_lower()); EXPECT_TRUE(lower_all.is_lower()); - EXPECT_EQ("0a", lower_non.to_lower()); - EXPECT_EQ("oa", lower_mix.to_lower()); - EXPECT_EQ("oa", lower_all.to_lower()); + EXPECT_EQ("0a"_s, lower_non.to_lower()); + EXPECT_EQ("oa"_s, lower_mix.to_lower()); + EXPECT_EQ("oa"_s, lower_all.to_lower()); EXPECT_EQ(lower_all.begin(), lower_all.to_lower().begin()); - ZString upper_non = "0a"; - ZString upper_mix = "oA"; - RString upper_all = "OA"; + ZString upper_non = "0a"_s; + ZString upper_mix = "oA"_s; + RString upper_all = "OA"_s; EXPECT_FALSE(upper_non.has_upper()); EXPECT_TRUE(upper_mix.has_upper()); EXPECT_TRUE(upper_all.has_upper()); EXPECT_FALSE(upper_non.is_upper()); EXPECT_FALSE(upper_mix.is_upper()); EXPECT_TRUE(upper_all.is_upper()); - EXPECT_EQ("0A", upper_non.to_upper()); - EXPECT_EQ("OA", upper_mix.to_upper()); - EXPECT_EQ("OA", upper_all.to_upper()); + EXPECT_EQ("0A"_s, upper_non.to_upper()); + EXPECT_EQ("OA"_s, upper_mix.to_upper()); + EXPECT_EQ("OA"_s, upper_all.to_upper()); EXPECT_EQ(upper_all.begin(), upper_all.to_upper().begin()); - ZString alpha_non = " 0"; - ZString alpha_mix = "n "; - RString alpha_all = "nA"; + ZString alpha_non = " 0"_s; + ZString alpha_mix = "n "_s; + RString alpha_all = "nA"_s; EXPECT_FALSE(alpha_non.has_alpha()); EXPECT_TRUE(alpha_mix.has_alpha()); EXPECT_TRUE(alpha_all.has_alpha()); @@ -87,9 +90,9 @@ TEST(StringTests, traits2) EXPECT_FALSE(alpha_mix.is_alpha()); EXPECT_TRUE(alpha_all.is_alpha()); - ZString digit2_non = "a9"; - ZString digit2_mix = "20"; - RString digit2_all = "01"; + ZString digit2_non = "a9"_s; + ZString digit2_mix = "20"_s; + RString digit2_all = "01"_s; EXPECT_FALSE(digit2_non.has_digit2()); EXPECT_TRUE(digit2_mix.has_digit2()); EXPECT_TRUE(digit2_all.has_digit2()); @@ -97,9 +100,9 @@ TEST(StringTests, traits2) EXPECT_FALSE(digit2_mix.is_digit2()); EXPECT_TRUE(digit2_all.is_digit2()); - ZString digit8_non = "a9"; - ZString digit8_mix = "80"; - RString digit8_all = "37"; + ZString digit8_non = "a9"_s; + ZString digit8_mix = "80"_s; + RString digit8_all = "37"_s; EXPECT_FALSE(digit8_non.has_digit8()); EXPECT_TRUE(digit8_mix.has_digit8()); EXPECT_TRUE(digit8_all.has_digit8()); @@ -107,9 +110,9 @@ TEST(StringTests, traits2) EXPECT_FALSE(digit8_mix.is_digit8()); EXPECT_TRUE(digit8_all.is_digit8()); - ZString digit10_non = "az"; - ZString digit10_mix = "a9"; - RString digit10_all = "42"; + ZString digit10_non = "az"_s; + ZString digit10_mix = "a9"_s; + RString digit10_all = "42"_s; EXPECT_FALSE(digit10_non.has_digit10()); EXPECT_TRUE(digit10_mix.has_digit10()); EXPECT_TRUE(digit10_all.has_digit10()); @@ -117,9 +120,9 @@ TEST(StringTests, traits2) EXPECT_FALSE(digit10_mix.is_digit10()); EXPECT_TRUE(digit10_all.is_digit10()); - ZString digit16_non = "gz"; - ZString digit16_mix = "ao"; - RString digit16_all = "be"; + ZString digit16_non = "gz"_s; + ZString digit16_mix = "ao"_s; + RString digit16_all = "be"_s; EXPECT_FALSE(digit16_non.has_digit16()); EXPECT_TRUE(digit16_mix.has_digit16()); EXPECT_TRUE(digit16_all.has_digit16()); @@ -127,9 +130,9 @@ TEST(StringTests, traits2) EXPECT_FALSE(digit16_mix.is_digit16()); EXPECT_TRUE(digit16_all.is_digit16()); - ZString alnum_non = " ."; - ZString alnum_mix = "n "; - RString alnum_all = "n0"; + ZString alnum_non = " ."_s; + ZString alnum_mix = "n "_s; + RString alnum_all = "n0"_s; EXPECT_FALSE(alnum_non.has_alnum()); EXPECT_TRUE(alnum_mix.has_alnum()); EXPECT_TRUE(alnum_all.has_alnum()); @@ -140,7 +143,7 @@ TEST(StringTests, traits2) TEST(StringTests, rempty) { - const char empty_text[] = ""; + LString empty_text = ""_s; RString r = empty_text; EXPECT_EQ(r.size(), 0); AString a = empty_text; @@ -166,7 +169,7 @@ TEST(StringTests, rempty) } TEST(StringTests, rshort) { - const char short_text[] = "0123456789"; + LString short_text = "0123456789"_s; RString r = short_text; EXPECT_EQ(r.size(), 10); AString a = short_text; @@ -193,13 +196,13 @@ TEST(StringTests, rshort) TEST(StringTests, rlong) { - const char long_text[] = + LString long_text = "01234567890123456789012345678901234567890123456789" "0123456789012345678901234567890123456789012345 100" "01234567890123456789012345678901234567890123456789" "0123456789012345678901234567890123456789012345 200" "01234567890123456789012345678901234567890123456789" - "0123456789012345678901234567890123456789012345 300"; + "0123456789012345678901234567890123456789012345 300"_s; RString r = long_text; EXPECT_EQ(r.size(), 300); AString a = long_text; @@ -223,3 +226,4 @@ TEST(StringTests, rlong) EXPECT_EQ(&*r.begin(), &*r3.begin()); EXPECT_EQ(&*a.begin(), &*a3.begin()); } +} // namespace tmwa diff --git a/src/strings/strings_test.cpp b/src/strings/strings_test.cpp index dca463d..a95499d 100644 --- a/src/strings/strings_test.cpp +++ b/src/strings/strings_test.cpp @@ -1,4 +1,3 @@ -#include "all.hpp" // strings_test.cpp - Testsuite part 1 for strings. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -22,8 +21,13 @@ #include <gtest/gtest.h> +#include "all.hpp" + #include "../poison.hpp" + +namespace tmwa +{ template<typename T> class StringTest : public ::testing::Test { @@ -32,10 +36,10 @@ TYPED_TEST_CASE_P(StringTest); TYPED_TEST_P(StringTest, basic) { - TypeParam hi("Hello"); + TypeParam hi("Hello"_s); EXPECT_EQ(5, hi.size()); EXPECT_EQ(hi, hi); - const char hi2[] = "Hello\0random garbage"; + LString hi2 = "Hello\0random garbage"_s; EXPECT_EQ(hi, hi2); TypeParam hi0; EXPECT_EQ(0, hi0.size()); @@ -47,9 +51,9 @@ TYPED_TEST_P(StringTest, basic) TYPED_TEST_P(StringTest, order) { TypeParam a; - TypeParam b("Hello"); - TypeParam c("Hello,"); - TypeParam d("World!"); + TypeParam b("Hello"_s); + TypeParam c("Hello,"_s); + TypeParam d("World!"_s); // not using EXPECT_LT, etc. for better visibility @@ -158,7 +162,7 @@ TYPED_TEST_P(StringTest, order) TYPED_TEST_P(StringTest, iterators) { - TypeParam hi("Hello"); + TypeParam hi("Hello"_s); EXPECT_EQ(hi.begin(), hi.begin()); EXPECT_NE(hi.begin(), hi.end()); EXPECT_EQ(5, std::distance(hi.begin(), hi.end())); @@ -168,19 +172,19 @@ TYPED_TEST_P(StringTest, iterators) TYPED_TEST_P(StringTest, xslice) { - TypeParam hi("Hello, World!"); - EXPECT_EQ(" World!", hi.xslice_t(6)); - EXPECT_EQ("Hello,", hi.xslice_h(6)); - EXPECT_EQ("World!", hi.xrslice_t(6)); - EXPECT_EQ("Hello, ", hi.xrslice_h(6)); + TypeParam hi("Hello, World!"_s); + EXPECT_EQ(" World!"_s, hi.xslice_t(6)); + EXPECT_EQ("Hello,"_s, hi.xslice_h(6)); + EXPECT_EQ("World!"_s, hi.xrslice_t(6)); + EXPECT_EQ("Hello, "_s, hi.xrslice_h(6)); typename TypeParam::iterator it = std::find(hi.begin(), hi.end(), ' '); - EXPECT_EQ(" World!", hi.xislice_t(it)); - EXPECT_EQ("Hello,", hi.xislice_h(it)); - EXPECT_EQ("World", hi.xlslice(7, 5)); - EXPECT_EQ("World", hi.xpslice(7, 12)); - EXPECT_EQ("World", hi.xislice(hi.begin() + 7, hi.begin() + 12)); - EXPECT_TRUE(hi.startswith("Hello")); - EXPECT_TRUE(hi.endswith("World!")); + EXPECT_EQ(" World!"_s, hi.xislice_t(it)); + EXPECT_EQ("Hello,"_s, hi.xislice_h(it)); + EXPECT_EQ("World"_s, hi.xlslice(7, 5)); + EXPECT_EQ("World"_s, hi.xpslice(7, 12)); + EXPECT_EQ("World"_s, hi.xislice(hi.begin() + 7, hi.begin() + 12)); + EXPECT_TRUE(hi.startswith("Hello"_s)); + EXPECT_TRUE(hi.endswith("World!"_s)); } TYPED_TEST_P(StringTest, convert) @@ -188,15 +192,15 @@ TYPED_TEST_P(StringTest, convert) constexpr bool is_zstring = std::is_same<TypeParam, ZString>::value; typedef typename std::conditional<is_zstring, TString, SString>::type Sstring; typedef typename std::conditional<is_zstring, ZString, XString>::type Xstring; - RString r = "r"; - AString a = "a"; - TString t = "t"; - Sstring s = "s"; - ZString z = "z"; - Xstring x = "x"; - VString<255> v = "v"; - const char l[] = "l"; - VString<5> hi = "hello"; + RString r = "r"_s; + AString a = "a"_s; + TString t = "t"_s; + Sstring s = "s"_s; + ZString z = "z"_s; + Xstring x = "x"_s; + VString<255> v = "v"_s; + LString l = "l"_s; + VString<5> hi = "hello"_s; TypeParam r2 = r; TypeParam a2 = a; @@ -270,7 +274,7 @@ INSTANTIATE_TYPED_TEST_CASE_P(StringStuff, StringTest, MostStringTypes); TEST(VStringTest, basic) { - VString<5> hi = "Hello"; + VString<5> hi = "Hello"_s; EXPECT_EQ(5, hi.size()); EXPECT_EQ(hi, hi); // truncation @@ -278,7 +282,7 @@ TEST(VStringTest, basic) EXPECT_EQ(5, hi2.size()); EXPECT_EQ(hi, hi2); // short - hi = "hi"; + hi = "hi"_s; EXPECT_EQ(2, hi.size()); VString<5> hi0; EXPECT_EQ(0, hi0.size()); @@ -292,7 +296,7 @@ TYPED_TEST_CASE_P(NulStringTest); TYPED_TEST_P(NulStringTest, basic) { - TypeParam hi("hello"); + TypeParam hi("hello"_s); EXPECT_EQ(hi.size(), strlen(hi.c_str())); EXPECT_STREQ("hello", hi.c_str()); } @@ -304,3 +308,4 @@ typedef ::testing::Types< RString, AString, TString, ZString, VString<255> > NulStringTypes; INSTANTIATE_TYPED_TEST_CASE_P(NulStringStuff, NulStringTest, NulStringTypes); +} // namespace tmwa diff --git a/src/strings/tstring.cpp b/src/strings/tstring.cpp index 5f463ca..b0bd74a 100644 --- a/src/strings/tstring.cpp +++ b/src/strings/tstring.cpp @@ -18,12 +18,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include "rstring.hpp" +#include "astring.hpp" #include "sstring.hpp" #include "zstring.hpp" #include "xstring.hpp" +#include "literal.hpp" #include "../poison.hpp" + +namespace tmwa +{ namespace strings { TString::TString() @@ -67,6 +73,10 @@ namespace strings else *this = RString(x); } + TString::TString(const LString& l) + { + *this = XString(l); + } TString::TString(XPair p) : _s(p), _o(0) @@ -94,3 +104,4 @@ namespace strings return ts.c_str(); } } // namespace strings +} // namespace tmwa diff --git a/src/strings/tstring.hpp b/src/strings/tstring.hpp index 7003d37..b0da566 100644 --- a/src/strings/tstring.hpp +++ b/src/strings/tstring.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_STRINGS_TSTRING_HPP -#define TMWA_STRINGS_TSTRING_HPP +#pragma once // strings/tstring.hpp - A tail slice of a string. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,11 +18,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "base.hpp" -# include "rstring.hpp" +#include "base.hpp" +#include "rstring.hpp" + +namespace tmwa +{ namespace strings { /// An owning string that represents a tail slice of an RString. @@ -43,10 +45,7 @@ namespace strings TString(const XString&); template<uint8_t n> TString(const VString<n>& v); - template<size_t n> - TString(char (&s)[n]) = delete; - template<size_t n> - TString(const char (&s)[n]); + TString(const LString&); //template<class It> //TString(It b, It e) : _s(b, e), _o(0) {} TString(XPair p); @@ -63,7 +62,6 @@ namespace strings // Actually, it might now. const char *decay_for_printf(const TString& ts); } // namespace strings +} // namespace tmwa -# include "tstring.tcc" - -#endif // TMWA_STRINGS_TSTRING_HPP +#include "tstring.tcc" diff --git a/src/strings/tstring.tcc b/src/strings/tstring.tcc index 4eba13f..2641fb7 100644 --- a/src/strings/tstring.tcc +++ b/src/strings/tstring.tcc @@ -19,14 +19,14 @@ #include "vstring.hpp" + +namespace tmwa +{ namespace strings { template<uint8_t n> TString::TString(const VString<n>& v) : _s(v), _o(0) {} - template<size_t n> - TString::TString(const char (&s)[n]) - : _s(s), _o(0) - {} } // namespace strings +} // namespace tmwa diff --git a/src/strings/vstring.cpp b/src/strings/vstring.cpp index 0ef8f3d..1cb313a 100644 --- a/src/strings/vstring.cpp +++ b/src/strings/vstring.cpp @@ -20,6 +20,10 @@ #include "../poison.hpp" + +namespace tmwa +{ namespace strings { } // namespace strings +} // namespace tmwa diff --git a/src/strings/vstring.hpp b/src/strings/vstring.hpp index 9952ff9..f3437a5 100644 --- a/src/strings/vstring.hpp +++ b/src/strings/vstring.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_STRINGS_VSTRING_HPP -#define TMWA_STRINGS_VSTRING_HPP +#pragma once // strings/vstring.hpp - A small string that stores its own value. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,10 +18,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "base.hpp" +#include <cstdio> +#include "base.hpp" + + +namespace tmwa +{ namespace strings { template<uint8_t n> @@ -40,10 +44,7 @@ namespace strings VString(ZString z); template<uint8_t m> VString(VString<m> v); - template<size_t m> - VString(char (&s)[m]) = delete; - template<size_t m> - VString(const char (&s)[m]); + VString(LString l); VString(decltype(really_construct_from_a_pointer) e, const char *s); VString(char c); VString(); @@ -74,7 +75,6 @@ T stringish(VString<sizeof(T) - 1> iv) static_cast<VString<sizeof(T) - 1>&>(rv) = iv; return rv; } +} // namespace tmwa -# include "vstring.tcc" - -#endif // TMWA_STRINGS_VSTRING_HPP +#include "vstring.tcc" diff --git a/src/strings/vstring.py b/src/strings/vstring.py index 39e657b..fa975b2 100644 --- a/src/strings/vstring.py +++ b/src/strings/vstring.py @@ -2,7 +2,7 @@ class VString(object): ''' print a VString ''' __slots__ = ('_value') - name = 'strings::VString' + name = 'tmwa::strings::VString' enabled = True def __init__(self, value): diff --git a/src/strings/vstring.tcc b/src/strings/vstring.tcc index 1aa163d..4f24a20 100644 --- a/src/strings/vstring.tcc +++ b/src/strings/vstring.tcc @@ -18,8 +18,8 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include <cassert> - -#include "../compat/cast.hpp" +#include <cstdarg> +#include <cstdio> #include "rstring.hpp" #include "astring.hpp" @@ -27,7 +27,11 @@ #include "sstring.hpp" #include "zstring.hpp" #include "xstring.hpp" +#include "literal.hpp" + +namespace tmwa +{ namespace strings { template<uint8_t n> @@ -76,11 +80,9 @@ namespace strings *this = XString(v); } template<uint8_t n> - template<size_t m> - VString<n>::VString(const char (&s)[m]) + VString<n>::VString(LString l) { - static_assert(m <= n + 1, "string would truncate"); - *this = XString(s); + *this = XString(l); } template<uint8_t n> VString<n>::VString(decltype(really_construct_from_a_pointer) e, const char *s) @@ -143,7 +145,8 @@ namespace strings char buffer[len + 1]; vsnprintf(buffer, len + 1, fmt, ap); - out = const_(buffer); + out = VString<len>(strings::really_construct_from_a_pointer, buffer); return len; } } // namespace strings +} // namespace tmwa diff --git a/src/strings/xstring.cpp b/src/strings/xstring.cpp index 0808104..4635a90 100644 --- a/src/strings/xstring.cpp +++ b/src/strings/xstring.cpp @@ -18,8 +18,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include "rstring.hpp" +#include "astring.hpp" +#include "tstring.hpp" +#include "sstring.hpp" +#include "zstring.hpp" +#include "literal.hpp" + #include "../poison.hpp" + +namespace tmwa +{ namespace strings { XString::XString() @@ -40,6 +50,9 @@ namespace strings XString::XString(const ZString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} + XString::XString(const LString& s) + : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) + {} XString::XString(const char *b, const char *e, const RString *base_) : _b(b), _e(e), _base(base_) @@ -65,3 +78,4 @@ namespace strings return _base; } } // namespace strings +} // namespace tmwa diff --git a/src/strings/xstring.hpp b/src/strings/xstring.hpp index 8f6eac5..2b000c4 100644 --- a/src/strings/xstring.hpp +++ b/src/strings/xstring.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_STRINGS_XSTRING_HPP -#define TMWA_STRINGS_XSTRING_HPP +#pragma once // strings/xstring.hpp - A full borrowed slice. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,10 +18,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "base.hpp" +#include "base.hpp" + +namespace tmwa +{ namespace strings { /// A non-owning string that is not guaranteed to be NUL-terminated. @@ -44,10 +46,7 @@ namespace strings XString(const ZString& s); template<uint8_t n> XString(const VString<n>& s); - template<size_t n> - XString(char (&s)[n]) = delete; - template<size_t n> - XString(const char (&s)[n]); + XString(const LString& s); // mostly internal XString(const char *b, const char *e, const RString *base_); XString(decltype(really_construct_from_a_pointer) e, const char *s, const RString *base_); @@ -58,7 +57,6 @@ namespace strings const RString *base() const; }; } // namespace strings +} // namespace tmwa -# include "xstring.tcc" - -#endif // TMWA_STRINGS_XSTRING_HPP +#include "xstring.tcc" diff --git a/src/strings/xstring.py b/src/strings/xstring.py index 92cb78b..fa0abcb 100644 --- a/src/strings/xstring.py +++ b/src/strings/xstring.py @@ -2,7 +2,7 @@ class XString(object): ''' print a XString ''' __slots__ = ('_value') - name = 'strings::XString' + name = 'tmwa::strings::XString' enabled = True def __init__(self, value): diff --git a/src/strings/xstring.tcc b/src/strings/xstring.tcc index aee87f8..e9f0f1e 100644 --- a/src/strings/xstring.tcc +++ b/src/strings/xstring.tcc @@ -19,14 +19,14 @@ #include "vstring.hpp" + +namespace tmwa +{ namespace strings { template<uint8_t n> XString::XString(const VString<n>& s) : _b(&*s.begin()), _e(&*s.end()), _base(nullptr) {} - template<size_t n> - XString::XString(const char (&s)[n]) - : _b(s), _e(s + strlen(s)), _base(nullptr) - {} } // namespace strings +} // namespace tmwa diff --git a/src/strings/zstring.cpp b/src/strings/zstring.cpp index e2a763f..01e9c2b 100644 --- a/src/strings/zstring.cpp +++ b/src/strings/zstring.cpp @@ -18,15 +18,24 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include "xstring.hpp" +#include <cstdio> +#include <cstring> + +#include "rstring.hpp" +#include "astring.hpp" +#include "tstring.hpp" +#include "literal.hpp" #include "../poison.hpp" + +namespace tmwa +{ namespace strings { ZString::ZString() { - *this = ZString(""); + *this = ZString(""_s); } ZString::ZString(const RString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) @@ -37,6 +46,9 @@ namespace strings ZString::ZString(const TString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} + ZString::ZString(const LString& s) + : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) + {} ZString::ZString(const char *b, const char *e, const RString *base_) : _b(b), _e(e), _base(base_) {} @@ -65,10 +77,5 @@ namespace strings { return zs.c_str(); } - - __attribute__((format(scanf, 2, 0))) - int do_vscan(ZString in, const char *fmt, va_list ap) - { - return vsscanf(in.c_str(), fmt, ap); - } } // namespace strings +} // namespace tmwa diff --git a/src/strings/zstring.hpp b/src/strings/zstring.hpp index 717da88..1e38662 100644 --- a/src/strings/zstring.hpp +++ b/src/strings/zstring.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_STRINGS_ZSTRING_HPP -#define TMWA_STRINGS_ZSTRING_HPP +#pragma once // strings/zstring.hpp - A borrowed tail slice of a string. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -19,12 +18,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include <cstring> +#include "base.hpp" -# include "base.hpp" +namespace tmwa +{ namespace strings { /// A non-owning string that is guaranteed to be NUL-terminated. @@ -45,13 +45,10 @@ namespace strings ZString(const XString&) = delete; template<uint8_t n> ZString(const VString<n>& s); + ZString(const LString& s); // dangerous ZString(const char *b, const char *e, const RString *base_); ZString(decltype(really_construct_from_a_pointer), const char *s, const RString *base_); - template<size_t n> - ZString(char (&s)[n]) = delete; - template<size_t n> - ZString(const char (&s)[n], const RString *base_=nullptr); iterator begin() const; iterator end() const; @@ -64,11 +61,7 @@ namespace strings // Nope, it doesn't, since there's a template // Actually, it might now. const char *decay_for_printf(const ZString& zs); - - __attribute__((format(scanf, 2, 0))) - int do_vscan(ZString in, const char *fmt, va_list ap); } // namespace strings +} // namespace tmwa -# include "zstring.tcc" - -#endif // TMWA_STRINGS_ZSTRING_HPP +#include "zstring.tcc" diff --git a/src/strings/zstring.py b/src/strings/zstring.py index 5021e1c..dca5f4e 100644 --- a/src/strings/zstring.py +++ b/src/strings/zstring.py @@ -2,7 +2,7 @@ class ZString(object): ''' print a ZString ''' __slots__ = ('_value') - name = 'strings::ZString' + name = 'tmwa::strings::ZString' enabled = True def __init__(self, value): diff --git a/src/strings/zstring.tcc b/src/strings/zstring.tcc index fe0e9f3..2eaa8c0 100644 --- a/src/strings/zstring.tcc +++ b/src/strings/zstring.tcc @@ -17,19 +17,16 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#include <cstring> - #include "vstring.hpp" + +namespace tmwa +{ namespace strings { template<uint8_t n> ZString::ZString(const VString<n>& s) : _b(&*s.begin()), _e(&*s.end()), _base(nullptr) {} - - template<size_t n> - ZString::ZString(const char (&s)[n], const RString *base_) - : _b(s), _e(s + strlen(s)), _base(base_) - {} } // namespace strings +} // namespace tmwa diff --git a/src/tests/fdhack.cpp b/src/tests/fdhack.cpp new file mode 100644 index 0000000..7a95431 --- /dev/null +++ b/src/tests/fdhack.cpp @@ -0,0 +1,26 @@ +#include "fdhack.hpp" +// fdhack.cpp - Move file descriptors around. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +} // namespace tmwa diff --git a/src/tests/fdhack.hpp b/src/tests/fdhack.hpp new file mode 100644 index 0000000..c75bfea --- /dev/null +++ b/src/tests/fdhack.hpp @@ -0,0 +1,58 @@ +#pragma once +// fdhack.hpp - Move file descriptors around. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "fwd.hpp" + +#include <cstddef> +#include <fcntl.h> + +#include <stdexcept> + +#include "../strings/literal.hpp" +#include "../strings/zstring.hpp" + +#include "../io/fd.hpp" + +namespace tmwa +{ +class ReplaceFd +{ + io::FD number, backup; +public: + ReplaceFd(io::FD num, io::FD handle, bool owned) + : number(handle.dup2(num)), backup(num.dup()) + { + if (owned) + handle.close(); + } + ~ReplaceFd() + { + backup.dup2(number); + backup.close(); + } +}; +class QuietFd : ReplaceFd +{ +public: + QuietFd(io::FD num=io::FD::stderr()) + : ReplaceFd(num, io::FD::open("/dev/null"_s, O_RDONLY), true) + {} +}; +} // namespace tmwa diff --git a/src/tests/fwd.hpp b/src/tests/fwd.hpp new file mode 100644 index 0000000..48627da --- /dev/null +++ b/src/tests/fwd.hpp @@ -0,0 +1,27 @@ +#pragma once +// tests/fwd.hpp - list of type names for test libs +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../sanity.hpp" + + +namespace tmwa +{ +// meh, add more when I feel like it +} // namespace tmwa diff --git a/src/tests/test.cpp b/src/tests/test.cpp index d9cba5e..d731d7c 100644 --- a/src/tests/test.cpp +++ b/src/tests/test.cpp @@ -1,4 +1,3 @@ -#include <gtest/gtest.h> // test.cpp - Driver for testwuite // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -18,8 +17,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +#include <gtest/gtest.h> + #include "../poison.hpp" + +namespace tmwa +{ +} // namespace tmwa + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/src/warnings.hpp b/src/warnings.hpp index 1ea0074..9389766 100644 --- a/src/warnings.hpp +++ b/src/warnings.hpp @@ -1,7 +1,7 @@ -// no include guards +#pragma once // This is the first file in every compilation, passed by the makefile. // This file contains only preprocessor directions. - +// The preceding sentence is a lie. // warnings.hpp - Make the compiler do the hard work. // // Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> @@ -21,700 +21,170 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -#if 0 -# include "../sanity.hpp" +// just mention "fwd.hpp" to make formatter happy + +#include "diagnostics.hpp" + + +namespace tmwa +{ +PRAGMA(GCC diagnostic warning "-Wall"); +PRAGMA(GCC diagnostic warning "-Wextra"); +PRAGMA(GCC diagnostic warning "-Wunused"); +PRAGMA(GCC diagnostic warning "-Wformat"); + +DIAG_E(abi); +DIAG_W(abi_tag); +DIAG_E(address); +DIAG_I(aggregate_return); +DIAG_E(array_bounds); +DIAG_E(attributes); +DIAG_E(builtin_macro_redefined); +DIAG_I(cxx0x_compat); +DIAG_I(cxx1y_extensions); +DIAG_E(cast_align); +DIAG_E(cast_qual); +DIAG_E(char_subscripts); +DIAG_E(clobbered); +DIAG_E(comment); +DIAG_E(conditionally_supported); +DIAG_E(constexpr_not_const); +DIAG_X(conversion); +DIAG_E(conversion_null); +DIAG_W(coverage_mismatch); +DIAG_X(covered_switch_default); +DIAG_W(cpp); +DIAG_E(ctor_dtor_privacy); +DIAG_E(date_time); +DIAG_E(delete_incomplete); +DIAG_E(delete_non_virtual_dtor); +DIAG_W(deprecated); +#ifdef QUIET +DIAG_I(deprecated_declarations); +#else +DIAG_W(deprecated_declarations); #endif - -// This file is currently targeted at: -// GCC 4.6 (incomplete due to bugs) -// GCC 4.7 (for few minor workarounds) -// GCC 4.8 (zarro boogs found) -// clang 3.1 (may ICE later) -// clang 3.2 (with a few major workarounds) - -// List of warnings that require arguments, -// and thus cannot reliably be activated: -// gcc 4.6: -// -Wlarger-than=<1024> -// -Wnormalized=<id|nfc|nfd> -// -Wsuggest-attribute=<noreturn,const,pure,format> -// gcc 4.7: -// -Wstack-usage=<8192> -// ??? -// -Wstrict-aliasing=<1> -// -Wstrict-overflow=<1> - -// options that enable other options -// only warnings so I can catch the errors -#pragma GCC diagnostic warning "-Wall" -#pragma GCC diagnostic warning "-Wextra" -#pragma GCC diagnostic warning "-Wunused" -#pragma GCC diagnostic warning "-Wformat" - -#ifdef __clang__ -# if __clang_major__ < 3 -# error "your clang is way too old" -# elif __clang_major__ == 3 -# if __clang_minor__ < 1 -# error "your clang is too old" -# endif // __clang_minor__ -# endif // __clang_major__ -#else // __clang__ -# if __GNUC__ < 4 -# error "your gcc is way too old" -# if __GNUC_MINOR__ < 6 -# error "your gcc is too old" -# elif __GNUC_MINOR__ == 6 -# if __GNUC_PATCHLEVEL__ < 3 -# error "TODO: test this patchlevel" -# endif // __GNUC_PATCHLEVEL__ -# elif __GNUC_MINOR__ == 7 -# if __GNUC_PATCHLEVEL__ < 2 -# error "your gcc has a known bad patchlevel" -# endif // __GNUC_PATCHLEVEL__ -# endif // __GNUC_MINOR__ -# endif // __GNUC__ -#endif // __clang__ - -// BEGIN Macros to make my life easier - -// stringification requirement - #sw within #ar -// this is a lie ^ -#define P(ar) _Pragma(#ar) - -// Use "GCC diagnostic" for warnings applicable to all versions. -#define I(sw) P(GCC diagnostic ignored sw) -#define W(sw) P(GCC diagnostic warning sw) -#define E(sw) P(GCC diagnostic error sw) -// configurable thing (also change in clang below!) -#define X(sw) I(sw) - - -#ifdef __clang__ - -// Use "clang diagnostic" for warnings specific to clang -# define IC(sw) P(clang diagnostic ignored sw) -# define WC(sw) P(clang diagnostic warning sw) -# define EC(sw) P(clang diagnostic error sw) -# define XC(sw) IC(sw) // this is below - -// warning specific to gcc -# define IG(sw) static_assert('I', sw "skipped for clang"); -# define WG(sw) static_assert('W', sw "skipped for clang"); -# define EG(sw) static_assert('E', sw "skipped for clang"); -# define XG(sw) static_assert('X', sw "skipped for clang"); - -# define IG47(sw) static_assert('I', sw "only for gcc 4.7+"); -# define WG47(sw) static_assert('W', sw "only for gcc 4.7+"); -# define EG47(sw) static_assert('E', sw "only for gcc 4.7+"); -# define XG47(sw) static_assert('X', sw "only for gcc 4.7+"); - -# define IG48(sw) static_assert('I', sw "only for gcc 4.8+"); -# define WG48(sw) static_assert('W', sw "only for gcc 4.8+"); -# define EG48(sw) static_assert('E', sw "only for gcc 4.8+"); -# define XG48(sw) static_assert('X', sw "only for gcc 4.8+"); - -# define I47(sw) I(sw) -# define W47(sw) W(sw) -# define E47(sw) E(sw) -# define X47(sw) X(sw) - -# define I48(sw) I(sw) -# define W48(sw) W(sw) -# define E48(sw) E(sw) -# define X48(sw) X(sw) - +DIAG_W(disabled_optimization); +DIAG_E(div_by_zero); +DIAG_W(documentation); +DIAG_I(double_promotion); +DIAG_I(effcxx); +DIAG_E(empty_body); +DIAG_E(endif_labels); +DIAG_E(enum_compare); +DIAG_E(extra_semi); +DIAG_E(float_equal); +DIAG_E(format); +DIAG_E(format_contains_nul); +DIAG_E(format_extra_args); +#if CLANG +DIAG_I(format_nonliteral); +DIAG_I(format_security); #else - -// warnings specific to clang -# define IC(sw) static_assert('I', sw "skipped for gcc"); -# define WC(sw) static_assert('W', sw "skipped for gcc"); -# define EC(sw) static_assert('E', sw "skipped for gcc"); -# define XC(sw) static_assert('X', sw "skipped for gcc"); - -// warnings specific to gcc -# define IG(sw) I(sw) -# define WG(sw) W(sw) -# define EG(sw) E(sw) -# define XG(sw) X(sw) - -// used both for warnings not implemented in a version -// and for warnings that falsely trigger -# if __GNUC__ == 4 -# if __GNUC_MINOR__ >= 7 -# define IG47(sw) IG(sw) -# define WG47(sw) WG(sw) -# define EG47(sw) EG(sw) -# define XG47(sw) XG(sw) - -# define I47(sw) I(sw) -# define W47(sw) W(sw) -# define E47(sw) E(sw) -# define X47(sw) X(sw) -# else -# define IG47(sw) static_assert('I', sw "only for gcc 4.7+"); -# define WG47(sw) static_assert('W', sw "only for gcc 4.7+"); -# define EG47(sw) static_assert('E', sw "only for gcc 4.7+"); -# define XG47(sw) static_assert('X', sw "only for gcc 4.7+"); - -# define I47(sw) static_assert('I', sw "only for gcc 4.7+ or clang"); -# define W47(sw) static_assert('W', sw "only for gcc 4.7+ or clang"); -# define E47(sw) static_assert('E', sw "only for gcc 4.7+ or clang"); -# define X47(sw) static_assert('X', sw "only for gcc 4.7+ or clang"); -# endif // __GNUC_MINOR__ -# if __GNUC_MINOR__ >= 8 -# define IG48(sw) IG(sw) -# define WG48(sw) WG(sw) -# define EG48(sw) EG(sw) -# define XG48(sw) XG(sw) - -# define I48(sw) IG(sw) -# define W48(sw) WG(sw) -# define E48(sw) EG(sw) -# define X48(sw) XG(sw) -# else -# define IG48(sw) static_assert('I', sw "only for gcc 4.8+"); -# define WG48(sw) static_assert('W', sw "only for gcc 4.8+"); -# define EG48(sw) static_assert('E', sw "only for gcc 4.8+"); -# define XG48(sw) static_assert('X', sw "only for gcc 4.8+"); - -# define I48(sw) static_assert('I', sw "only for gcc 4.8+ or clang"); -# define W48(sw) static_assert('W', sw "only for gcc 4.8+ or clang"); -# define E48(sw) static_assert('E', sw "only for gcc 4.8+ or clang"); -# define X48(sw) static_assert('X', sw "only for gcc 4.8+ or clang"); -# endif // __GNUC_MINOR__ -# endif // __GNUC__ -#endif // __clang__ - -// END macros to make my life easier - - -/// Warn about things that will change when compiling -/// with an ABI-compliant compiler -// see note about -fabi-version=6 in the makefile -E("-Wabi") - -/// Warn if a subobject has an abi_tag attribute that -/// the complete object type does not have -WG48("-Wabi-tag") - -/// Warn about suspicious uses of memory addresses -E("-Waddress") - -/// Warn about returning structures, unions or arrays -I("-Waggregate-return") - -/// Warn if an array is accessed out of bounds -E("-Warray-bounds") - -/// Warn about inappropriate attribute usage -E("-Wattributes") - -/// Warn when a built-in preprocessor macro is -// undefined or redefined -E("-Wbuiltin-macro-redefined") - -/// Warn about C++ constructs whose meaning differs -/// between ISO C++ 1998 and ISO C++ 2011 -// This has gone funky lately. It probably doesn't do anything useful anyway. -//E("-Wc++0x-compat") -//W("-Wc++11-compat") -I("-Wc++0x-compat") - -/// Warn about pointer casts which increase alignment -X("-Wcast-align") - -/// Warn about casts which discard qualifiers -E("-Wcast-qual") - -/// Warn about subscripts whose type is "char" -E("-Wchar-subscripts") - -/// Warn about variables that might be changed by -/// "longjmp" or "vfork" -EG("-Wclobbered") - -/// Warn about possibly nested block comments, and -/// C++ comments spanning more than one physical line -E("-Wcomment") - -// A fixable difference between c++11 and c++14 -#ifdef __clang__ -# if __has_warning("-Wconstexpr-not-const") -EC("-Wconstexpr-not-const") -# else -static_assert('E', "-Wconstexpr-not-const not in this clang version"); -# endif +DIAG_E(format_nonliteral); +DIAG_E(format_security); +#endif +DIAG_E(format_y2k); +DIAG_I(format_zero_length); +DIAG_E(free_nonheap_object); +DIAG_E(gnu_designator); +DIAG_E(ignored_qualifiers); +DIAG_E(implicit_fallthrough); +DIAG_W(inherited_variadic_ctor); +DIAG_E(init_self); +DIAG_X(inline); +DIAG_E(int_to_pointer_cast); +DIAG_W(invalid_memory_model); +DIAG_E(invalid_offsetof); +DIAG_E(invalid_pch); +DIAG_W(literal_suffix); +DIAG_W(logical_op); +DIAG_I(long_long); +DIAG_E(main); +DIAG_E(maybe_uninitialized); +DIAG_I(mismatched_tags); +DIAG_E(missing_braces); +DIAG_E(missing_declarations); +#if GCC +DIAG_I(missing_field_initializers); #else -static_assert('E', "-Wconstexpr-not-const not in GCC"); +DIAG_E(missing_field_initializers); #endif - -/// Warn for implicit type conversions that may -/// change a value -X("-Wconversion") - -/// Warn for converting NULL from/to a non-pointer -/// type -E("-Wconversion-null") - -/// Warn in case profiles in -fprofile-use do not -/// match -WG("-Wcoverage-mismatch") - -/// -XC("-Wcovered-switch-default") - -/// Warn when a #warning directive is encountered -WG("-Wcpp") - -/// Warn when all constructors and destructors are -/// private -E("-Wctor-dtor-privacy") - -/// Warn about deleting polymorphic objects with non- -/// virtual destructors -E47("-Wdelete-non-virtual-dtor") - -/// Warn if a deprecated compiler feature, class, -/// method, or field is used -W("-Wdeprecated") - -/// Warn about uses of __attribute__((deprecated)") -/// declarations -W("-Wdeprecated-declarations") -#ifdef QUIET -I("-Wdeprecated-declarations") +DIAG_E(missing_format_attribute); +DIAG_E(missing_include_dirs); +DIAG_W(missing_noreturn); +DIAG_E(missing_prototypes); +#ifndef GTEST_HAS_PTHREAD // this is a hack +DIAG_E(missing_variable_declarations); +#else +DIAG_I(missing_variable_declarations); #endif - -/// Warn when an optimization pass is disabled -W("-Wdisabled-optimization") - -/// Warn about compile-time integer division by zero -E("-Wdiv-by-zero") - -/// -WC("-Wdocumentation") - -/// Warn about implicit conversions from "float" to -/// "double" -IG("-Wdouble-promotion") - -/// Warn about violations of Effective C++ style rules -I("-Weffc++") - -/// Warn about an empty body in an if or else -/// statement -E("-Wempty-body") - -/// Warn about stray tokens after #elif and #endif -E("-Wendif-labels") - -/// Warn about comparison of different enum types -E("-Wenum-compare") - -/// -EC("-Wextra-semi") - -/// Warn if testing floating point numbers for -/// equality -E("-Wfloat-equal") - -/// Warn about printf/scanf/strftime/strfmon format -/// string anomalies -// see below -EG("-Wformat") -// but gcc 4.8 warns on %ms, since we enabled -Wpedantic. -//WG48("-Wformat") - -/// Warn about format strings that contain NUL bytes -EG("-Wformat-contains-nul") - -/// Warn if passing too many arguments to a function -/// for its format string -E("-Wformat-extra-args") - -/// Warn about format strings that are not literals -EG("-Wformat-nonliteral") -// Available in clang, but not smart enough to handle constexpr. -IC("-Wformat-nonliteral") - -/// Warn about possible security problems with format -/// functions -EG("-Wformat-security") -// Same. -IC("-Wformat-security") - -/// Warn about strftime formats yielding 2-digit years -E("-Wformat-y2k") - -/// Warn about zero-length formats -I("-Wformat-zero-length") - -/// Warn when attempting to free a non-heap object -EG47("-Wfree-nonheap-object") - -// -Wgnu is a clang alias for -Wpedantic - -/// Warn whenever type qualifiers are ignored. -E("-Wignored-qualifiers") - -/// -EC("-Wimplicit-fallthrough") - -/// Warn about C++11 inheriting constructors when the -/// base has a variadic constructor -WG48("-Winherited-variadic-ctor") - -/// Warn about variables which are initialized to -/// themselves -E("-Winit-self") - -/// Warn when an inlined function cannot be inlined -X("-Winline") - -/// Warn when there is a cast to a pointer from an -/// integer of a different size -E("-Wint-to-pointer-cast") - -/// Warn when an atomic memory model parameter is -/// known to be outside the valid range. -WG47("-Winvalid-memory-model") - -/// Warn about invalid uses of the "offsetof" macro -E("-Winvalid-offsetof") - -/// Warn about PCH files that are found but not used -E("-Winvalid-pch") - -/// Warn when a string or character literal is -/// followed by a ud-suffix which does not begin with -/// an underscore. -WG48("-Wliteral-suffix") - -/// Warn when a logical operator is suspiciously -/// always evaluating to true or false -WG("-Wlogical-op") - -/// Do not warn about using "long long" when -pedantic -I("-Wlong-long") - -/// Warn about suspicious declarations of "main" -E("-Wmain") - -/// Warn about maybe uninitialized automatic variables -EG47("-Wmaybe-uninitialized") - -/// Warn about possibly missing braces around -/// initializers -// beware of things like std::array! -E("-Wmissing-braces") - -/// Warn about global functions without previous -/// declarations -// This doesn't work for clang, it wants -Wmissing-prototypes instead. -E("-Wmissing-declarations") - -/// Warn about missing fields in struct initializers -// Actually supported by GCC, but gives warnings when I don't want, e.g.: -// Foo foo = {}; -EC("-Wmissing-field-initializers") -IG("-Wmissing-field-initializers") - -/// Warn about functions which might be candidates -/// for format attributes -E("-Wmissing-format-attribute") - -/// Warn about user-specified include directories -/// that do not exist -E("-Wmissing-include-dirs") - -/// Warn about functions which might be candidates -/// for __attribute__((noreturn)") -W("-Wmissing-noreturn") - -// clang uses this instead of -Wmissing-declarations -EC("-Wmissing-prototypes") - -/// -// like -Wmissing-declarations but for variables instead of functions +DIAG_E(mudflap); +DIAG_E(multichar); +DIAG_E(narrowing); +DIAG_W(noexcept); +DIAG_E(non_template_friend); +DIAG_E(non_virtual_dtor); +DIAG_E(nonnull); +DIAG_E(null_conversion); +DIAG_E(old_style_cast); +DIAG_W(overflow); +DIAG_E(openmp_simd); +DIAG_E(overloaded_virtual); +DIAG_E(packed); +DIAG_W(packed_bitfield_compat); +DIAG_I(padded); +DIAG_E(parentheses); +DIAG_I(pedantic); +DIAG_E(pmf_conversions); +DIAG_E(pointer_arith); +DIAG_E(pragmas); +DIAG_W(redundant_decls); +DIAG_E(reorder); +DIAG_W(return_local_addr); +DIAG_E(return_type); +DIAG_E(sequence_point); +DIAG_E(shadow); +DIAG_X(sign_compare); +DIAG_E(sign_promo); +DIAG_W(sizeof_pointer_memaccess); +DIAG_X(stack_protector); +DIAG_E(strict_aliasing); +DIAG_W(strict_null_sentinel); +DIAG_X(strict_overflow); +DIAG_I(switch); +DIAG_I(switch_default); +DIAG_I(switch_enum); +DIAG_W(sync_nand); +DIAG_E(trampolines); +DIAG_E(trigraphs); +DIAG_E(type_limits); +DIAG_E(undef); +DIAG_E(uninitialized); +DIAG_E(unknown_pragmas); +DIAG_W(unreachable_code); +DIAG_X(unsafe_loop_optimizations); +DIAG_E(unused_but_set_parameter); +DIAG_E(unused_but_set_variable); +DIAG_E(unused_function); +DIAG_E(unused_label); +DIAG_E(unused_local_typedefs); +DIAG_W(unused_macros); +DIAG_E(unused_parameter); +DIAG_E(unused_result); +DIAG_E(unused_value); +DIAG_E(unused_variable); +DIAG_E(useless_cast); +DIAG_E(varargs); +DIAG_W(variadic_macros); +DIAG_W(vector_operation_performance); +DIAG_E(virtual_move_assign); +DIAG_I(vla); +DIAG_E(volatile_register_var); +DIAG_E(write_strings); #ifndef GTEST_HAS_PTHREAD // this is a hack -EC("-Wmissing-variable-declarations") +DIAG_E(zero_as_null_pointer_constant); +#else +DIAG_I(zero_as_null_pointer_constant); #endif - -/// Warn about constructs not instrumented by -/// -fmudflap -EG("-Wmudflap") - -/// Warn about use of multi-character character -/// constants -E("-Wmultichar") - -/// Warn about narrowing conversions within { } that -/// are ill-formed in C++11 -EG47("-Wnarrowing") - -/// Warn when a noexcept expression evaluates to -/// false even though the expression can't actually -/// throw -WG("-Wnoexcept") - -/// Warn when non-templatized friend functions are -/// declared within a template -EG("-Wnon-template-friend") - -/// Warn about non-virtual destructors -E("-Wnon-virtual-dtor") - -/// Warn about NULL being passed to argument slots -/// marked as requiring non-NULL -E("-Wnonnull") - -/// -XC("-Wnull-conversion") - -/// Warn if a C-style cast is used in a program -E("-Wold-style-cast") - -/// Warn about overflow in arithmetic expressions -W("-Woverflow") - -/// Warn if a string is longer than the maximum -/// portable length specified by the standard -//X("-Woverlength-strings") - -/// Warn about overloaded virtual function names -E("-Woverloaded-virtual") - -/// Warn when the packed attribute has no effect on -/// struct layout -E("-Wpacked") - -/// Warn about packed bit-fields whose offset changed -/// in GCC 4.4 -WG("-Wpacked-bitfield-compat") - -/// Warn when padding is required to align structure -/// members -I("-Wpadded") - -/// Warn about possibly missing parentheses -E("-Wparentheses") - -/// Issue warnings needed for strict compliance to -/// the standard -//EG48("-Wpedantic") -// lots of minor extensions are used -IG48("-Wpedantic") -// a bit too noisy -XC("-Wpedantic") - -/// Warn when converting the type of pointers to -/// member functions -EG("-Wpmf-conversions") - -/// Warn about function pointer arithmetic -E("-Wpointer-arith") - -/// Warn about misuses of pragmas -EG("-Wpragmas") - -/// Warn about multiple declarations of the same -/// object -W("-Wredundant-decls") - -/// Warn when the compiler reorders code -E("-Wreorder") - -/// Warn about returning a pointer/reference to a -/// local or temporary variable. -WG48("-Wreturn-local-addr") - -/// Warn whenever a function's return type defaults -/// to "int" (C), or about inconsistent return types -/// (C++") -E("-Wreturn-type") - -/// Warn about possible violations of sequence point -/// rules -E("-Wsequence-point") - -/// Warn when one local variable shadows another -E("-Wshadow") - -/// Warn about signed-unsigned comparisons -X("-Wsign-compare") - -/// Warn when overload promotes from unsigned to -/// signed -X("-Wsign-promo") - -/// This switch lacks documentation -WG48("-Wsizeof-pointer-memaccess") - -/// Warn when not issuing stack smashing protection -/// for some reason -X("-Wstack-protector") - -/// Warn about code which might break strict aliasing -/// rules -E("-Wstrict-aliasing") - -/// Warn about uncasted NULL used as sentinel -WG("-Wstrict-null-sentinel") - -/// Warn about optimizations that assume that signed -/// overflow is undefined -X("-Wstrict-overflow") - -/// Warn about enumerated switches, with no default, -/// missing a case -X("-Wswitch") - -/// Warn about enumerated switches missing a -/// "default:" statement -X("-Wswitch-default") - -/// Warn about all enumerated switches missing a -/// specific case -X("-Wswitch-enum") - -/// Warn when __sync_fetch_and_nand and -/// __sync_nand_and_fetch built-in functions are used -WG("-Wsync-nand") - -/// Warn whenever a trampoline is generated -EG("-Wtrampolines") - -/// Warn if trigraphs are encountered that might -/// affect the meaning of the program -E("-Wtrigraphs") - -/// Warn if a comparison is always true or always -/// false due to the limited range of the data type -E("-Wtype-limits") - -/// Warn if an undefined macro is used in an #if -/// directive -E("-Wundef") - -/// Warn about uninitialized automatic variables -E("-Wuninitialized") - -/// Warn about unrecognized pragmas -E("-Wunknown-pragmas") - -/// -// Not an error because of some remaining enum+default -WC("-Wunreachable-code") - -/// Warn if the loop cannot be optimized due to -/// nontrivial assumptions. -XG("-Wunsafe-loop-optimizations") - -/// Warn when a function parameter is only set, -/// otherwise unused -EG("-Wunused-but-set-parameter") - -/// Warn when a variable is only set, otherwise unused -EG("-Wunused-but-set-variable") - -/// Warn when a function is unused -E("-Wunused-function") - -/// Warn when a label is unused -E("-Wunused-label") - -/// Warn when typedefs locally defined in a function -/// are not used -EG47("-Wunused-local-typedefs") - -/// Warn about macros defined in the main file that -/// are not used -W("-Wunused-macros") - -/// Warn when a function parameter is unused -E("-Wunused-parameter") - -/// Warn if a caller of a function, marked with -/// attribute warn_unused_result, does not use its -/// return value -E("-Wunused-result") - -/// Warn when an expression value is unused -E("-Wunused-value") - -/// Warn when a variable is unused -E("-Wunused-variable") - -/// Warn about useless casts -EG48("-Wuseless-cast") - -/// Warn about questionable usage of the macros used -/// to retrieve variable arguments -EG48("-Wvarargs") - -/// Warn about using variadic macros -W("-Wvariadic-macros") - -/// Warn when a vector operation is compiled -/// outside the SIMD -WG47("-Wvector-operation-performance") - -/// Warn if a virtual base has a non-trivial move -/// assignment operator -EG48("-Wvirtual-move-assign") - -/// Warn if a variable length array is used -I("-Wvla") - -/// Warn when a register variable is declared volatile -E("-Wvolatile-register-var") - -/// In C++, nonzero means warn about deprecated -/// conversion from string literals to 'char *'. In -/// C, similar warning, except that the conversion is -/// of course not deprecated by the ISO C standard. -E("-Wwrite-strings") - -/// Warn when a literal '0' is used as null -/// pointer -XG47("-Wzero-as-null-pointer-constant") - - -// clean up after myself -#undef P - -#undef I -#undef W -#undef E -#undef X - -#undef IC -#undef WC -#undef EC -#undef XC - -#undef IG -#undef WG -#undef EG -#undef XG - -#undef IG47 -#undef WG47 -#undef EG47 -#undef XG47 - -#undef IG48 -#undef WG48 -#undef EG48 -#undef XG48 - -#undef I47 -#undef W47 -#undef E47 -#undef X47 - -#undef I48 -#undef W48 -#undef E48 -#undef X48 +} // namespace tmwa diff --git a/tools/maybe-mv b/tools/maybe-mv index 996052f..56d8e9e 100755 --- a/tools/maybe-mv +++ b/tools/maybe-mv @@ -2,9 +2,7 @@ # Replace one file with another, but maybe don't update the timestamp if cmp "$1" "$2" then - echo rm "$1" rm "$1" else - echo mv "$1" "$2" mv "$1" "$2" fi diff --git a/tools/nightly b/tools/nightly new file mode 100755 index 0000000..7e72605 --- /dev/null +++ b/tools/nightly @@ -0,0 +1,68 @@ +#!/bin/bash -e + +WWW=${HOME}/www/ + +ALL_CONFIGS=( + config64 + config32 +) +# need a special kernel for configx32 + + +config32() { + # No one knows what number this is supposed to be: + # - the lib directory is called i386-linux-gnu + # - the 32-bit files are called i486-linux-gnu + # - the cross-32 configury says i586 + HOST=i586-linux-gnu + CXX='g++ -m32' + EXTRA_LIBS=( + /lib32/libc.so.6 + /lib32/libm.so.6 + /usr/lib32/libgcc_s.so.1 + /usr/lib32/libstdc++.so.6 + ) +} + +configx32() { + HOST=x86_64-linux-gnux32 + CXX='g++ -mx32' + EXTRA_LIBS=( + /libx32/libc.so.6 + /libx32/libm.so.6 + /usr/libx32/libgcc_s.so.1 + /usr/libx32/libstdc++.so.6 + ) +} + +config64() { + HOST=x86_64-linux-gnu + CXX='g++ -m64' + EXTRA_LIBS=( + /lib/x86_64-linux-gnu/libc.so.6 + /lib/x86_64-linux-gnu/libm.so.6 + /lib/x86_64-linux-gnu/libgcc_s.so.1 + /usr/lib/x86_64-linux-gnu/libstdc++.so.6 + ) +} + +first=true + +for config in ${ALL_CONFIGS[@]} +do + $config + mkdir -p build-$HOST + cd build-$HOST + ../configure --host=$HOST CXX="$CXX -Wno-deprecated-declarations" --prefix=/. --enable-rpath=relative + make -j3 all + make -j3 test + if $first + then + make -j3 dist + first=false + fi + make -j3 bindist BUNDLED_LIBS="${EXTRA_LIBS[*]}" + gzip -n -9 dist/*.tar + mv dist/*.tar.gz $WWW + cd .. +done diff --git a/tools/protocol.py b/tools/protocol.py new file mode 100755 index 0000000..91dbc81 --- /dev/null +++ b/tools/protocol.py @@ -0,0 +1,4226 @@ +#!/usr/bin/env python +# coding: utf-8 + +# protocol.py - generator for entire TMWA network protocol +# +# Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +# +# This file is part of The Mana World (Athena server) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import glob +import itertools +import os +from pipes import quote +from posixpath import relpath + +# The following code should be relatively easy to understand, but please +# keep your sanity fastened and your arms and legs inside at all times. + +# important note: all numbers in this file will make a lot more sense in +# decimal, but they're written in hex. + +generated = '// This is a generated file, edit %s instead\n' % __file__ + +copyright = '''// {filename} - {description} +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +''' + +class OpenWrite(object): + def __init__(self, filename): + self.filename = filename + + def __enter__(self): + self.handle = open(self.filename + '.tmp', 'w') + return self.handle + + def __exit__(self, ty, v, tb): + self.handle.close() + if ty is not None: + return + frag = ''' + if cmp {0}.tmp {0}.old + then + echo Unchanged: {0} + rm {0}.tmp + mv {0}.old {0} + else + echo Changed: {0} + rm {0}.old + mv {0}.tmp {0} + fi + '''.format(quote(self.filename)) + os.system(frag) + +class LowType(object): + __slots__ = () + +class NativeType(LowType): + __slots__ = ('name') + + def __init__(self, name): + self.name = name + + def a_tag(self): + return self.name + +class NetworkType(LowType): + __slots__ = ('name') + + def __init__(self, name): + self.name = name + + def e_tag(self): + return self.name + + +class Type(object): + __slots__ = () + +class NeutralType(Type): + __slots__ = ('name') + + def __init__(self, name): + self.name = name + + def native_tag(self): + return self.name + + def network_tag(self): + return self.name + + e_tag = network_tag + +class StringType(Type): + __slots__ = ('native') + + def __init__(self, native): + self.native = native + + def native_tag(self): + return self.native.a_tag() + + def network_tag(self): + return 'NetString<sizeof(%s)>' % self.native.a_tag() + + def dump(self, f): + # not implemented properly, uses a template in the meta instead + pass + +class ProvidedType(Type): + __slots__ = ('native', 'network') + + def __init__(self, native, network): + self.native = native + self.network = network + + def native_tag(self): + return self.native.a_tag() + + def network_tag(self): + return self.network.e_tag() + +class EnumType(Type): + __slots__ = ('native', 'under') + + def __init__(self, native, under): + self.native = native + self.under = under + + def native_tag(self): + return self.native.a_tag() + + def network_tag(self): + return self.under.network_tag() + + def dump(self, f): + native = self.native_tag() + under = self.under.native_tag() + network = self.network_tag() + + f.write('inline __attribute__((warn_unused_result))\n') + f.write('bool native_to_network({0} *network, {1} native)\n{{\n'.format(network, native)) + f.write(' bool rv = true;\n') + f.write(' {0} tmp = static_cast<{0}>(native);\n'.format(under)) + f.write(' rv &= native_to_network(network, tmp);\n') + f.write(' return rv;\n') + f.write('}\n') + f.write('inline __attribute__((warn_unused_result))\n') + f.write('bool network_to_native({0} *native, {1} network)\n{{\n'.format(native, network)) + f.write(' bool rv = true;\n') + f.write(' {0} tmp;\n'.format(under)) + f.write(' rv &= network_to_native(&tmp, network);\n') + f.write(' *native = static_cast<{0}>(tmp);\n'.format(native)) + f.write(' // TODO this is what really should be doing a checked cast\n') + f.write(' return rv;\n') + f.write('}\n') + +class WrappedType(Type): + __slots__ = ('native', 'under') + + def __init__(self, native, under): + self.native = native + self.under = under + + def native_tag(self): + return self.native.a_tag() + + def network_tag(self): + return self.under.network_tag() + + def dump(self, f): + native = self.native_tag() + under = self.under.native_tag() + network = self.network_tag() + + f.write('inline __attribute__((warn_unused_result))\n') + f.write('bool native_to_network({0} *network, {1} native)\n{{\n'.format(network, native)) + f.write(' bool rv = true;\n') + f.write(' {0} tmp = unwrap<{1}>(native);\n'.format(under, native)) + f.write(' rv &= native_to_network(network, tmp);\n') + f.write(' return rv;\n') + f.write('}\n') + f.write('inline __attribute__((warn_unused_result))\n') + f.write('bool network_to_native({0} *native, {1} network)\n{{\n'.format(native, network)) + f.write(' bool rv = true;\n') + f.write(' {0} tmp;\n'.format(under)) + f.write(' rv &= network_to_native(&tmp, network);\n') + f.write(' *native = wrap<{0}>(tmp);\n'.format(native)) + f.write(' return rv;\n') + f.write('}\n') + +class SkewLengthType(Type): + __slots__ = ('type', 'skew') + + def __init__(self, ty, skew): + self.type = ty + self.skew = skew + + def native_tag(self): + return self.type.native_tag() + + def network_tag(self): + return 'SkewedLength<%s, %d>' % (self.type.network_tag(), self.skew) + + def dumpx(self): + # not registered properly, so the method name is wrong + # TODO remind myself to kill this code with fire before release + # not implemented properly, uses a template in the meta instead + # insert another comment here so that it lines up properly + pass + +class StructType(Type): + __slots__ = ('id', 'name', 'fields', 'size', 'ctor') + + def __init__(self, id, name, fields, size, ctor=False): + self.id = id + self.name = name + self.fields = fields + self.size = size + self.ctor = ctor + + def native_tag(self): + return self.name + + def network_tag(self): + return 'Net' + self.name + + def dump(self, f): + self.dump_native(f) + self.dump_network(f) + self.dump_convert(f) + f.write('\n') + + def dump_fwd(self, fwd): + if self.id is not None: + fwd.write('template<>\n') + fwd.write('struct %s;\n' % self.name) + if self.id is not None: + fwd.write('template<>\n') + fwd.write('struct Net%s;\n' % self.name) + + def dump_native(self, f): + name = self.name + if self.id is not None: + f.write('template<>\n') + f.write('struct %s\n{\n' % name) + if self.id is not None: + f.write(' static const uint16_t PACKET_ID = 0x%04x;\n\n' % self.id) + for (o, l, n) in self.fields: + if n in ('magic_packet_id', 'magic_packet_length'): + f.write(' // TODO remove this\n') + if n == 'magic_packet_id': + f.write(' %s %s = PACKET_ID;\n' % (l.native_tag(), n)) + else: + f.write(' %s %s = {};\n' % (l.native_tag(), n)) + if self.ctor: + f.write(' %s() = default;\n' % name) + f.write(' %s(' % name) + f.write(', '.join('%s _%s' % (l.native_tag(), n) for (_, l, n) in self.fields)) + f.write(') : ') + f.write(', '.join('%s(_%s)' % (n, n) for (_, _, n) in self.fields)) + f.write(' {}\n') + f.write('};\n') + + def dump_network(self, f): + name = 'Net%s' % self.name + if self.id is not None: + f.write('template<>\n') + f.write('struct %s\n{\n' % name) + for (o, l, n) in self.fields: + f.write(' %s %s;\n' % (l.network_tag(), n)) + f.write('};\n') + for (o, l, n) in self.fields: + if o is not None: + s = 'offsetof(%s, %s) == %d' % (name, n, o) + f.write('static_assert({0}, "{0}");\n'.format(s)) + if self.size is not None: + s = 'sizeof(%s) == %d' % (name, self.size) + f.write('static_assert({0}, "{0}");\n'.format(s)) + s = 'alignof(%s) == 1' % (name) + f.write('static_assert({0}, "{0}");\n'.format(s)) + + def dump_convert(self, f): + f.write('inline __attribute__((warn_unused_result))\n') + f.write('bool native_to_network(Net{0} *network, {0} native)\n{{\n'.format(self.name)) + f.write(' bool rv = true;\n') + for (o, l, n) in self.fields: + f.write(' rv &= native_to_network(&network->{0}, native.{0});\n'.format(n)) + f.write(' return rv;\n') + f.write('}\n') + + f.write('inline __attribute__((warn_unused_result))\n') + f.write('bool network_to_native({0} *native, Net{0} network)\n{{\n'.format(self.name)) + f.write(' bool rv = true;\n') + for (o, l, n) in self.fields: + f.write(' rv &= network_to_native(&native->{0}, network.{0});\n'.format(n)) + f.write(' return rv;\n') + f.write('}\n') + +class PartialStructType(Type): + __slots__ = ('native', 'body') + + def __init__(self, native, body): + self.native = native + self.body = body + + def native_tag(self): + return self.native.a_tag() + + def network_tag(self): + return 'Net%s' % self.native_tag() + + def dump(self, f): + f.write('struct %s\n{\n' % self.network_tag()) + for n, t in self.body: + f.write(' %s %s;\n' % (t.network_tag(), n)) + f.write('};\n') + f.write('inline __attribute__((warn_unused_result))\n') + f.write('bool native_to_network(Net{0} *network, {0} native)\n{{\n'.format(self.native_tag())) + f.write(' bool rv = true;\n') + for n, t in self.body: + u = t.native_tag() + # probably not necessary + f.write(' {1} {0} = native.{0}; rv &= native_to_network(&network->{0}, {0});\n'.format(n, u)) + f.write(' return rv;\n') + f.write('}\n') + f.write('inline __attribute__((warn_unused_result))\n') + f.write('bool network_to_native({0} *native, Net{0} network)\n{{\n'.format(self.native_tag())) + f.write(' bool rv = true;\n') + for n, t in self.body: + # the temporary is ABSOLUTELY NECESSARY here + # the native type is permitted to differ from the declared type + # e.g. HumanTimeDiff uses int16_t instead of uint16_t + u = t.native_tag() + f.write(' {1} {0}; rv &= network_to_native(&{0}, network.{0}); native->{0} = {0};\n'.format(n, u)) + f.write(' return rv;\n') + f.write('}\n') + f.write('\n') + +class ArrayType(Type): + __slots__ = ('element', 'count') + + def __init__(self, element, count): + self.element = element + self.count = count + + def native_tag(self): + return 'Array<%s, %s>' % (self.element.native_tag(), self.count) + + def network_tag(self): + return 'NetArray<%s, %s>' % (self.element.network_tag(), self.count) + +class EArrayType(Type): + __slots__ = ('element', 'index', 'count') + + def __init__(self, element, index, count): + self.element = element + self.index = index + self.count = count + + def native_tag(self): + return 'earray<%s, %s, %s>' % (self.element.native_tag(), self.index, self.count) + + def network_tag(self): + return 'NetArray<%s, static_cast<size_t>(%s)>' % (self.element.network_tag(), self.count) + +class InvArrayType(Type): + __slots__ = ('element', 'index', 'count') + + def __init__(self, element, index, count): + self.element = element + self.index = index + self.count = count + + def native_tag(self): + return 'GenericArray<%s, InventoryIndexing<%s, %s>>' % (self.element.native_tag(), self.index, self.count) + + def network_tag(self): + return 'NetArray<%s, %s>' % (self.element.network_tag(), self.count) + + +class Include(object): + __slots__ = ('path', '_types') + + def __init__(self, path): + self.path = path + self._types = [] + + def testcase(self, outdir): + basename = os.path.basename(self.path.strip('<">')) + root = os.path.splitext(basename)[0] + filename = 'include_%s_test.cpp' % root.replace('.', '_') + desc = 'testsuite for protocol includes' + poison = relpath('src/poison.hpp', outdir) + with OpenWrite(os.path.join(outdir, filename)) as f: + f.write(self.pp(0)) + f.write(copyright.format(filename=filename, description=desc)) + f.write('\n') + f.write('#include "%s"\n\nnamespace tmwa\n{\n' % poison) + + for t in self._types: + f.write('using %s = %s;\n' % ('Test_' + ident(t.name), t.name)) + f.write('} // namespace tmwa\n') + + def pp(self, n): + return '#%*sinclude %s\n' % (n, '', self.path) + + + def native(self, name): + ty = NativeType(name) + self._types.append(ty) + return ty + + def network(self, name): + ty = NetworkType(name) + self._types.append(ty) + return ty + + def neutral(self, name): + ty = NeutralType(name) + self._types.append(ty) + return ty + + +class FixedPacket(object): + __slots__ = ('fixed_struct') + + def __init__(self, fixed_struct): + self.fixed_struct = fixed_struct + + def dump_fwd(self, fwd): + self.fixed_struct.dump_fwd(fwd) + fwd.write('\n') + + def dump_native(self, f): + self.fixed_struct.dump_native(f) + f.write('\n') + + def dump_network(self, f): + self.fixed_struct.dump_network(f) + f.write('\n') + + def dump_convert(self, f): + self.fixed_struct.dump_convert(f) + f.write('\n') + +class VarPacket(object): + __slots__ = ('head_struct', 'repeat_struct') + + def __init__(self, head_struct, repeat_struct): + self.head_struct = head_struct + self.repeat_struct = repeat_struct + + def dump_fwd(self, fwd): + self.head_struct.dump_fwd(fwd) + self.repeat_struct.dump_fwd(fwd) + fwd.write('\n') + + def dump_native(self, f): + self.head_struct.dump_native(f) + self.repeat_struct.dump_native(f) + f.write('\n') + + def dump_network(self, f): + self.head_struct.dump_network(f) + self.repeat_struct.dump_network(f) + f.write('\n') + + def dump_convert(self, f): + self.head_struct.dump_convert(f) + self.repeat_struct.dump_convert(f) + f.write('\n') + +def packet(id, name, + fixed=None, fixed_size=None, + payload=None, payload_size=None, + head=None, head_size=None, + repeat=None, repeat_size=None, + option=None, option_size=None, +): + assert (fixed is None) <= (fixed_size is None) + assert (payload is None) <= (payload_size is None) + assert (head is None) <= (head_size is None) + assert (repeat is None) <= (repeat_size is None) + assert (option is None) <= (option_size is None) + + if fixed is not None: + assert not head and not repeat and not option and not payload + return FixedPacket( + StructType(id, 'Packet_Fixed<0x%04x>' % id, fixed, fixed_size)) + elif payload is not None: + assert not head and not repeat and not option + return FixedPacket( + StructType(id, 'Packet_Payload<0x%04x>' % id, payload, payload_size)) + else: + assert head + if option: + return VarPacket( + StructType(id, 'Packet_Head<0x%04x>' % id, head, head_size), + StructType(id, 'Packet_Option<0x%04x>' % id, option, option_size)) + else: + assert repeat + return VarPacket( + StructType(id, 'Packet_Head<0x%04x>' % id, head, head_size), + StructType(id, 'Packet_Repeat<0x%04x>' % id, repeat, repeat_size)) + + +class Channel(object): + __slots__ = ('server', 'client', 'packets') + + def __init__(self, server, client): + self.server = server + self.client = client + self.packets = [] + + def x(self, id, name, **kwargs): + self.packets.append(packet(id, name, **kwargs)) + r = x + s = x + + def dump(self, outdir, fwd): + server = self.server + client = self.client + header = '%s-%s.hpp' % (server, client) + test = '%s-%s_test.cpp' % (server, client) + desc = 'TMWA network protocol: %s/%s' % (server, client) + with OpenWrite(os.path.join(outdir, header)) as f: + proto2 = relpath(outdir, 'src') + f.write('#pragma once\n') + f.write(copyright.format(filename=header, description=desc)) + f.write('\n') + f.write(generated) + f.write('\n') + f.write('#include "fwd.hpp"\n\n') + f.write('#include "types.hpp"\n') + f.write('\n') + f.write('namespace tmwa\n{\n') + if client == 'user': + f.write('// This is a public protocol, and changes require client cooperation\n') + else: + f.write('// This is an internal protocol, and can be changed without notice\n') + f.write('\n') + for p in self.packets: + p.dump_fwd(fwd) + fwd.write('\n') + for p in self.packets: + p.dump_native(f) + f.write('\n') + for p in self.packets: + p.dump_network(f) + f.write('\n') + for p in self.packets: + p.dump_convert(f) + f.write('} // namespace tmwa\n') + + with OpenWrite(os.path.join(outdir, test)) as f: + poison = relpath('src/poison.hpp', outdir) + f.write('#include "%s"\n' % header) + f.write(copyright.format(filename=test, description=desc)) + f.write('\n') + f.write(generated) + f.write('\n') + f.write('#include "%s"\n\nnamespace tmwa\n{\n' % poison) + f.write('} // namespace tmwa\n') + + +ident_translation = ''.join(chr(c) if chr(c).isalnum() else '_' for c in range(256)) + +def ident(s): + if s == 'packet id': + return 'magic_packet_id' + if s == 'packet length': + return 'magic_packet_length' + return s.translate(ident_translation) + + +def at(o, l, n): + return (o, l, ident(n)) + + +class Context(object): + __slots__ = ('outdir', '_includes', '_channels', '_types') + + def __init__(self, outdir): + self.outdir = outdir + self._includes = [] + self._channels = [] + self._types = [] + + + def sysinclude(self, name): + rv = Include('<%s>' % name) + self._includes.append(rv) + return rv + + def include(self, name): + rv = Include('"%s"' % relpath(name, self.outdir)) + self._includes.append(rv) + return rv + + def chan(self, server, client): + ch = Channel(server, client) + self._channels.append(ch) + return ch + + def dump(self): + outdir = self.outdir + for g in glob.glob(os.path.join(outdir, '*.[ch]pp')): + os.rename(g, g + '.old') + proto2 = relpath(outdir, 'src') + with OpenWrite(os.path.join(outdir, 'fwd.hpp')) as f: + header = '%s/fwd.hpp' % proto2 + desc = 'Forward declarations of network packets' + sanity = relpath('src/sanity.hpp', outdir) + f.write('#pragma once\n') + f.write(copyright.format(filename=header, description=desc)) + f.write('\n') + f.write('#include "%s"\n\n' % sanity) + f.write('#include <cstdint>\n\n') + f.write('namespace tmwa\n{\n') + for b in ['Fixed', 'Payload', 'Head', 'Repeat', 'Option']: + c = 'Packet_' + b + f.write('template<uint16_t PACKET_ID> class %s;\n' % c) + f.write('template<uint16_t PACKET_ID> class Net%s;\n' % c) + f.write('\n') + + for ch in self._channels: + ch.dump(outdir, f) + + f.write('} // namespace tmwa\n') + + with OpenWrite(os.path.join(outdir, 'types.hpp')) as f: + header = '%s/types.hpp' % proto2 + desc = 'Forward declarations of packet component types' + f.write('#pragma once\n') + f.write(copyright.format(filename=header, description=desc)) + f.write('\n') + f.write('#include "fwd.hpp"\n\n') + f.write('#include "../generic/array.hpp"\n') + f.write('#include "../mmo/consts.hpp"\n') + + f.write('\n//TODO split the includes\n') + for inc in self._includes: + f.write(inc.pp(0)) + # this is writing another file + inc.testcase(outdir) + f.write('\n') + f.write('namespace tmwa\n{\n') + + f.write('template<class T>\n') + f.write('bool native_to_network(T *network, T native)\n{\n') + f.write(' *network = native;\n') + f.write(' return true;\n') + f.write('}\n') + f.write('template<class T>\n') + f.write('bool network_to_native(T *native, T network)\n{\n') + f.write(' *native = network;\n') + f.write(' return true;\n') + f.write('}\n') + + f.write('template<class T, size_t N>\n') + f.write('struct NetArray\n{\n') + f.write(' T data[N];\n') + f.write('};\n') + f.write('template<class T, class U, class I>\n') + f.write('bool native_to_network(NetArray<T, I::alloc_size> *network, GenericArray<U, I> native)\n{\n') + f.write(' for (size_t i = 0; i < I::alloc_size; ++i)\n') + f.write(' {\n') + f.write(' if (!native_to_network(&(*network).data[i], native[I::offset_to_index(i)]))\n') + f.write(' return false;\n') + f.write(' }\n') + f.write(' return true;\n') + f.write('}\n') + f.write('template<class T, class U, class I>\n') + f.write('bool network_to_native(GenericArray<U, I> *native, NetArray<T, I::alloc_size> network)\n{\n') + f.write(' for (size_t i = 0; i < I::alloc_size; ++i)\n') + f.write(' {\n') + f.write(' if (!network_to_native(&(*native)[I::offset_to_index(i)], network.data[i]))\n') + f.write(' return false;\n') + f.write(' }\n') + f.write(' return true;\n') + f.write('}\n') + f.write('\n') + + f.write('template<size_t N>\n') + f.write('struct NetString\n{\n') + f.write(' char data[N];\n') + f.write('};\n') + f.write('template<size_t N>\n') + f.write('bool native_to_network(NetString<N> *network, VString<N-1> native)\n{\n') + f.write(' // basically WBUF_STRING\n') + f.write(' char *const begin = network->data;\n') + f.write(' char *const end = begin + N;\n') + f.write(' char *const mid = std::copy(native.begin(), native.end(), begin);\n') + f.write(' std::fill(mid, end, \'\\0\');\n') + f.write(' return true;\n') + f.write('}\n') + f.write('template<size_t N>\n') + f.write('bool network_to_native(VString<N-1> *native, NetString<N> network)\n{\n') + f.write(' // basically RBUF_STRING\n') + f.write(' const char *const begin = network.data;\n') + f.write(' const char *const end = begin + N;\n') + f.write(' const char *const mid = std::find(begin, end, \'\\0\');\n') + f.write(' *native = XString(begin, mid, nullptr);\n') + f.write(' return true;\n') + f.write('}\n') + f.write('\n') + f.write('inline\n') + f.write('bool native_to_network(NetString<24> *network, CharName native)\n{\n') + f.write(' VString<23> tmp = native.to__actual();\n') + f.write(' bool rv = native_to_network(network, tmp);\n') + f.write(' return rv;\n') + f.write('}\n') + f.write('inline\n') + f.write('bool network_to_native(CharName *native, NetString<24> network)\n{\n') + f.write(' VString<23> tmp;\n') + f.write(' bool rv = network_to_native(&tmp, network);\n') + f.write(' *native = stringish<CharName>(tmp);\n') + f.write(' return rv;\n') + f.write('}\n') + f.write('\n') + f.write('inline\n') + f.write('bool native_to_network(NetString<16> *network, MapName native)\n{\n') + f.write(' XString tmp = native;\n') + f.write(' bool rv = native_to_network(network, VString<15>(tmp));\n') + f.write(' return rv;\n') + f.write('}\n') + f.write('inline\n') + f.write('bool network_to_native(MapName *native, NetString<16> network)\n{\n') + f.write(' VString<15> tmp;\n') + f.write(' bool rv = network_to_native(&tmp, network);\n') + f.write(' *native = stringish<MapName>(tmp);\n') + f.write(' return rv;\n') + f.write('}\n') + f.write('\n') + + f.write('template<class T, size_t N>\n') + f.write('struct SkewedLength\n{\n') + f.write(' T data;\n') + f.write('};\n') + f.write('template<class T, size_t N, class U>\n') + f.write('bool native_to_network(SkewedLength<T, N> *network, U native)\n{\n') + f.write(' native -= N;\n') + f.write(' return native_to_network(&network->data, native);\n') + f.write('}\n') + f.write('template<class T, size_t N, class U>\n') + f.write('bool network_to_native(U *native, SkewedLength<T, N> network)\n{\n') + f.write(' bool rv = network_to_native(native, network.data);\n') + f.write(' *native += N;\n') + f.write(' return rv;\n') + f.write('}\n') + f.write('\n') + + for ty in self._types: + ty.dump(f) + f.write('} // namespace tmwa\n') + + for g in glob.glob(os.path.join(outdir, '*.old')): + print('Obsolete: %s' % g) + os.remove(g) + + # types + + def provided(self, native, network): + # the whole point of 'provided' is to not be implemented + return ProvidedType(native, network) + + def enum(self, native, under): + rv = EnumType(native, under) + self._types.append(rv) + return rv + + def wrap(self, native, under): + rv = WrappedType(native, under) + self._types.append(rv) + return rv + + def string(self, native): + rv = StringType(native) + self._types.append(rv) + return rv + + def struct(self, name, body, size, ctor=False): + rv = StructType(None, name, body, size, ctor) + self._types.append(rv) + return rv + + def partial_struct(self, native, body): + rv = PartialStructType(native, body) + self._types.append(rv) + return rv + + def array(self, element, count): + rv = ArrayType(element, count) + return rv + + def earray(self, element, index, count=None): + if count is None: + count = index + '::COUNT' + rv = EArrayType(element, index, count) + return rv + + def invarray(self, element, index, count): + rv = InvArrayType(element, index, count) + return rv + + +def main(): + + ## setup + + ctx = Context(outdir='src/proto2/') + + + ## headers + + cstdint = ctx.sysinclude('cstdint') + + endians_h = ctx.include('src/ints/little.hpp') + + vstring_h = ctx.include('src/strings/vstring.hpp') + + ip_h = ctx.include('src/net/ip.hpp') + timer_th = ctx.include('src/net/timer.t.hpp') + + consts_h = ctx.include('src/mmo/consts.hpp') + enums_h = ctx.include('src/mmo/enums.hpp') + human_time_diff_h = ctx.include('src/mmo/human_time_diff.hpp') + ids_h = ctx.include('src/mmo/ids.hpp') + strs_h = ctx.include('src/mmo/strs.hpp') + utils_h = ctx.include('src/mmo/utils.hpp') + version_h = ctx.include('src/mmo/version.hpp') + + login_th = ctx.include('src/login/login.t.hpp') + + clif_th = ctx.include('src/map/clif.t.hpp') + skill_th = ctx.include('src/map/skill.t.hpp') + + ## primitive types + char = NeutralType('char') + bit = NeutralType('bool') + + ## included types + + uint8_t = cstdint.native('uint8_t') + uint16_t = cstdint.native('uint16_t') + uint32_t = cstdint.native('uint32_t') + uint64_t = cstdint.native('uint64_t') + int8_t = cstdint.native('int8_t') + int16_t = cstdint.native('int16_t') + int32_t = cstdint.native('int32_t') + int64_t = cstdint.native('int64_t') + + Byte = endians_h.neutral('Byte') + Little16 = endians_h.network('Little16') + Little32 = endians_h.network('Little32') + Little64 = endians_h.network('Little64') + + SEX = enums_h.native('SEX') + Option = enums_h.native('Option') + EPOS = enums_h.native('EPOS') + ItemLook = enums_h.native('ItemLook') + + Species = ids_h.native('Species') + AccountId = ids_h.native('AccountId') + CharId = ids_h.native('CharId') + PartyId = ids_h.native('PartyId') + ItemNameId = ids_h.native('ItemNameId') + BlockId = ids_h.native('BlockId') + GmLevel = ids_h.native('GmLevel') + + party_member = consts_h.native('PartyMember') + + HumanTimeDiff = human_time_diff_h.native('HumanTimeDiff') + + Version = version_h.native('Version') + + ip4 = ip_h.neutral('IP4Address') + + TimeT = utils_h.native('TimeT') + + VString16 = vstring_h.native('VString<15>') + VString20 = vstring_h.native('VString<19>') + VString24 = vstring_h.native('VString<23>') + VString32 = vstring_h.native('VString<31>') + VString40 = vstring_h.native('VString<39>') + + # not all of these are used on the network side of things + # should this set of numbers be +1'ed ? + timestamp_seconds_buffer = utils_h.native('timestamp_seconds_buffer') + timestamp_milliseconds_buffer = utils_h.native('timestamp_milliseconds_buffer') + AccountName = strs_h.native('AccountName') + AccountPass = strs_h.native('AccountPass') + #AccountCrypt = strs_h.native('AccountCrypt') + AccountEmail = strs_h.native('AccountEmail') + ServerName = strs_h.native('ServerName') + PartyName = strs_h.native('PartyName') + VarName = strs_h.native('VarName') + CharName = strs_h.native('CharName') + MapName = strs_h.native('MapName') + #MobName = map_t_h.native('MobName') + #NpcName = map_t_h.native('NpcName') + #ScriptLabel = map_t_h.native('ScriptLabel') + #ItemName = map_t_h.native('ItemName') + #md5_native = md5_h.native('md5_native') + #SaltString = md5_h.native('SaltString') + + VERSION_2 = login_th.native('VERSION_2') + + + Position1 = clif_th.native('Position1') + NetPosition1 = clif_th.network('NetPosition1') + Position2 = clif_th.native('Position2') + NetPosition2 = clif_th.network('NetPosition2') + BeingRemoveWhy = clif_th.native('BeingRemoveWhy') + DIR = clif_th.native('DIR') + Opt1 = clif_th.native('Opt1') + Opt2 = clif_th.native('Opt2') + Opt3 = clif_th.native('Opt3') + ItemType = clif_th.native('ItemType') + PickupFail = clif_th.native('PickupFail') + DamageType = clif_th.native('DamageType') + SP = clif_th.native('SP') + LOOK = clif_th.native('LOOK') + IOff2 = clif_th.native('IOff2') + SOff1 = clif_th.native('SOff1') + + SkillID = skill_th.native('SkillID') + StatusChange = skill_th.native('StatusChange') + SkillFlags = skill_th.native('SkillFlags') + + tick_t = timer_th.native('tick_t') + interval_t = timer_th.native('interval_t') + + ## generated types + + u8 = ctx.provided(uint8_t, Byte) + u16 = ctx.provided(uint16_t, Little16) + u32 = ctx.provided(uint32_t, Little32) + u64 = ctx.provided(uint64_t, Little64) + i8 = ctx.provided(int8_t, Byte) + i16 = ctx.provided(int16_t, Little16) + i32 = ctx.provided(int32_t, Little32) + i64 = ctx.provided(int64_t, Little64) + + sex_char = ctx.provided(SEX, char) + + dir = ctx.enum(DIR, u8) + pos1 = ctx.provided(Position1, NetPosition1) + pos2 = ctx.provided(Position2, NetPosition2) + being_remove_why = ctx.enum(BeingRemoveWhy, u8) + opt1 = ctx.enum(Opt1, u16) + opt2 = ctx.enum(Opt2, u16) + opt3 = ctx.enum(Opt3, u16) + item_type = ctx.enum(ItemType, u8) + pickup_fail = ctx.enum(PickupFail, u8) + damage_type = ctx.enum(DamageType, u8) + sp = ctx.enum(SP, u16) + look = ctx.enum(LOOK, u8) + ioff2 = ctx.provided(IOff2, Little16) + soff1 = ctx.provided(SOff1, Little16) + + skill_id = ctx.enum(SkillID, u16) + status_change = ctx.enum(StatusChange, u16) + skill_flags = ctx.enum(SkillFlags, u16) + + tick32 = ctx.provided(tick_t, Little32) + interval32 = ctx.provided(interval_t, Little32) + interval16 = ctx.provided(interval_t, Little16) + + sex = ctx.enum(SEX, u8) + option = ctx.enum(Option, u16) + epos = ctx.enum(EPOS, u16) + item_look = ctx.enum(ItemLook, u16) + + species = ctx.wrap(Species, u16) + account_id = ctx.wrap(AccountId, u32) + char_id = ctx.wrap(CharId, u32) + party_id = ctx.wrap(PartyId, u32) + item_name_id = ctx.wrap(ItemNameId, u16) + item_name_id4 = ctx.wrap(ItemNameId, u32) + block_id = ctx.wrap(BlockId, u32) + + time32 = ctx.provided(TimeT, Little32) + time64 = ctx.provided(TimeT, Little64) + + gm1 = ctx.provided(GmLevel, Byte) + gm2 = ctx.provided(GmLevel, Little16) + gm = ctx.provided(GmLevel, Little32) + + str16 = ctx.string(VString16) + str20 = ctx.string(VString20) + str24 = ctx.string(VString24) + str32 = ctx.string(VString32) + str40 = ctx.string(VString40) + + seconds = ctx.string(timestamp_seconds_buffer) + millis = ctx.string(timestamp_milliseconds_buffer) + account_name = ctx.string(AccountName) + account_pass = ctx.string(AccountPass) + account_email = ctx.string(AccountEmail) + server_name = ctx.string(ServerName) + party_name = ctx.string(PartyName) + var_name = ctx.string(VarName) + char_name = ctx.string(CharName) + map_name = ctx.string(MapName) + + # this will be *so* useful when I do the party copy! + human_time_diff = ctx.partial_struct( + HumanTimeDiff, + [ + ('year', i16), + ('month', i16), + ('day', i16), + ('hour', i16), + ('minute', i16), + ('second', i16), + ] + ) + + version = ctx.partial_struct( + Version, + [ + ('major', u8), + ('minor', u8), + ('patch', u8), + ('devel', u8), + ('flags', u8), + ('which', u8), + ('vend', u16), + ] + ) + + version_2 = ctx.enum(VERSION_2, u8) + + stats6 = ctx.struct( + 'Stats6', + [ + at(0, u8, 'str'), + at(1, u8, 'agi'), + at(2, u8, 'vit'), + at(3, u8, 'int_'), + at(4, u8, 'dex'), + at(5, u8, 'luk'), + ], + size=6, + ) + char_select = ctx.struct( + 'CharSelect', + [ + at(0, char_id, 'char id'), + at(4, u32, 'base exp'), + at(8, u32, 'zeny'), + at(12, u32, 'job exp'), + at(16, u32, 'job level'), + + at(20, item_name_id, 'shoes'), + at(22, item_name_id, 'gloves'), + at(24, item_name_id, 'cape'), + at(26, item_name_id, 'misc1'), + at(28, option, 'option'), + at(30, u16, 'unused'), + + at(32, u32, 'karma'), + at(36, u32, 'manner'), + + at(40, u16, 'status point'), + at(42, u16, 'hp'), + at(44, u16, 'max hp'), + at(46, u16, 'sp'), + at(48, u16, 'max sp'), + at(50, u16, 'speed'), + at(52, species, 'species'), + at(54, u16, 'hair style'), + at(56, u16, 'weapon'), + at(58, u16, 'base level'), + at(60, u16, 'skill point'), + at(62, item_name_id, 'head bottom'), + at(64, item_name_id, 'shield'), + at(66, item_name_id, 'head top'), + at(68, item_name_id, 'head mid'), + at(70, u16, 'hair color'), + at(72, item_name_id, 'misc2'), + + at(74, char_name, 'char name'), + + at(98, stats6, 'stats'), + at(104, u8, 'char num'), + at(105, u8, 'unused2'), + ], + size=106, + ) + skill_info = ctx.struct( + 'SkillInfo', + [ + at(0, skill_id, 'skill id'), + at(2, u16, 'type or inf'), + at(4, skill_flags, 'flags'), + at(6, u16, 'level'), + at(8, u16, 'sp'), + at(10, u16, 'range'), + at(12, str24, 'unused'), + at(36, u8, 'can raise'), + ], + size=37, + ) + + item = ctx.struct( + 'Item', + [ + at(None, item_name_id, 'nameid'), + at(None, i16, 'amount'), + at(None, epos, 'equip'), + ], + size=None, + ) + + point = ctx.struct( + 'Point', + [ + at(None, map_name, 'map_'), + at(None, i16, 'x'), + at(None, i16, 'y'), + ], + size=None, + ctor=True, + ) + + skill_value = ctx.struct( + 'SkillValue', + [ + at(None, u16, 'lv'), + at(None, skill_flags, 'flags'), + ], + size=None, + ) + + global_reg = ctx.struct( + 'GlobalReg', + [ + at(None, var_name, 'str'), + at(None, i32, 'value'), + ], + size=None, + ) + + char_key = ctx.struct( + 'CharKey', + [ + at(None, char_name, 'name'), + at(None, account_id, 'account id'), + at(None, char_id, 'char id'), + at(None, u8, 'char num'), + ], + size=None, + ) + char_data = ctx.struct( + 'CharData', + [ + at(None, char_id, 'partner id'), + at(None, i32, 'base exp'), + at(None, i32, 'job exp'), + at(None, i32, 'zeny'), + at(None, species, 'species'), + at(None, i16, 'status point'), + at(None, i16, 'skill point'), + at(None, i32, 'hp'), + at(None, i32, 'max hp'), + at(None, i32, 'sp'), + at(None, i32, 'max sp'), + at(None, option, 'option'), + at(None, i16, 'karma'), + at(None, i16, 'manner'), + at(None, i16, 'hair'), + at(None, i16, 'hair color'), + at(None, i16, 'clothes color'), + at(None, party_id, 'party id'), + at(None, item_look, 'weapon'), + at(None, item_name_id, 'shield'), + at(None, item_name_id, 'head top'), + at(None, item_name_id, 'head mid'), + at(None, item_name_id, 'head bottom'), + at(None, u8, 'base level'), + at(None, u8, 'job level'), + at(None, ctx.earray(i16, 'ATTR'), 'attrs'), + at(None, sex, 'sex'), + at(None, ip4, 'mapip'), + at(None, u16, 'mapport'), + at(None, point, 'last point'), + at(None, point, 'save point'), + at(None, ctx.invarray(item, 'IOff0', 'MAX_INVENTORY'), 'inventory'), + at(None, ctx.earray(skill_value, 'SkillID', 'MAX_SKILL'), 'skill'), + at(None, i32, 'global reg num'), + at(None, ctx.array(global_reg, 'GLOBAL_REG_NUM'), 'global reg'), + at(None, i32, 'account reg num'), + at(None, ctx.array(global_reg, 'ACCOUNT_REG_NUM'), 'account reg'), + at(None, i32, 'account reg2 num'), + at(None, ctx.array(global_reg, 'ACCOUNT_REG2_NUM'), 'account reg2'), + ], + size=None, + ) + + party_member = ctx.partial_struct( + party_member, + [ + ('account_id', account_id), + ('name', char_name), + ('map', map_name), + ('leader', i32), + ('online', i32), + ('lv', i32), + ] + ) + + party_most = ctx.struct( + 'PartyMost', + [ + at(None, party_name, 'name'), + at(None, i32, 'exp'), + at(None, i32, 'item'), + at(None, ctx.array(party_member, 'MAX_PARTY'), 'member'), + ], + size=None, + ) + + storage = ctx.struct( + 'Storage', + [ + at(None, bit, 'dirty'), + at(None, account_id, 'account id'), + at(None, i16, 'storage status'), + at(None, i16, 'storage amount'), + at(None, ctx.invarray(item, 'SOff0', 'MAX_STORAGE'), 'storage_'), + ], + size=None, + ) + + + ## packet channels + + # this is a somewhat simplistic view. For packets that get forwarded, + # it may be worth pretending something like admin->char, map->login ... + # that does break the tree format though + + # (long term) TODO reimagine this with dbus terminology: + # every request generates exactly one reply or error, *even* if the + # other end dies halfway through. There are also signals, which are + # broadcast and have no reply and no error, even if no one is listening + + # (short term) + # Having 'repeat' as a separate struct is a wart. Ideally it would be + # a std::vector or AString member of the packet itself. Also, it should + # be Slice or XString for input - so we need 3 types. Except, net type + # is turning out to be not as meaningful as we thought it would be. + # + # A native type is either a builtin type or a type from a header. + # A type is one of: + # - a native type + # - a structure + # - a string of fixed size + # - a string of implicit size (deprecated) + # - a string of explicit size + # - an array of fixed size + # - an array of implicit size (deprecated) + # - an array of explicit size + # - a map of fixed size + # - a map of implicit size (deprecated) + # - a map of explicit size + # - a custom-translated type + # The last field of a struct may be of implicit size, in which case + # the struct itself is also of implicit size. Otherwise, the struct is + # explicitly sized if any of its members is explicitly sized, and fixed + # sized if all of its members are fixed sized. + # + # The element type of an array shall not be of implicit size. + # The element type of an array *may* be of explicit size, in which + # + # A string is just an array of characters, except that it may be padded + # with '\0' bytes even when it is sized. + # A map is just an array of two-element structs (key, value) + # However, strings and maps have custom classes used to represent them + # on the sender and receiver (earray also has this). + # + # It would probably be a good idea if everybody parsed network input as + # padded with '\0's if it is too short, and ignored the extra if it is + # too long. However, there are efficiency concerns with this, since we + # don't want to branch everywhere. + + login_char = ctx.chan('login', 'char') + login_admin = ctx.chan('login', 'admin') + login_bot = NotImplemented + login_user = ctx.chan('login', 'user') + + char_map = ctx.chan('char', 'map') + char_admin = NotImplemented + char_bot = NotImplemented + char_user = ctx.chan('char', 'user') + + map_admin = NotImplemented + map_bot = NotImplemented + map_user = ctx.chan('map', 'user') + + any_user = ctx.chan('any', 'user') + + + ## legacy packets + + # * user + char_user.r(0x0061, 'change password request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_pass, 'old pass'), + at(26, account_pass, 'new pass'), + ], + fixed_size=50, + ) + char_user.s(0x0062, 'change password response', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'status'), + ], + fixed_size=3, + ) + login_user.r(0x0063, 'update host', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[at(0, u8, 'c')], + repeat_size=1, + ) + login_user.r(0x0064, 'login request', + fixed=[ + at(0, u16, 'packet id'), + at(2, u32, 'unknown'), + at(6, account_name, 'account name'), + at(30, account_pass, 'account pass'), + at(54, version_2, 'version 2 flags'), + ], + fixed_size=55, + ) + char_user.r(0x0065, 'char-server connection request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u32, 'login id1'), + at(10, u32, 'login id2'), + at(14, u16, 'packet tmw version'), + at(16, sex, 'sex'), + ], + fixed_size=17, + ) + char_user.r(0x0066, 'select character request', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'code'), + ], + fixed_size=3, + ) + char_user.r(0x0067, 'create character request', + fixed=[ + at(0, u16, 'packet id'), + at(2, char_name, 'char name'), + at(26, stats6, 'stats'), + at(32, u8, 'slot'), + at(33, u16, 'hair color'), + at(35, u16, 'hair style'), + ], + fixed_size=37, + ) + char_user.r(0x0068, 'delete character request', + fixed=[ + at(0, u16, 'packet id'), + at(2, char_id, 'char id'), + at(6, account_email, 'email'), + ], + fixed_size=46, + ) + login_user.r(0x0069, 'login data', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, u32, 'login id1'), + at(8, account_id, 'account id'), + at(12, u32, 'login id2'), + at(16, u32, 'unused'), + at(20, millis, 'last login string'), + at(44, u16, 'unused2'), + at(46, sex, 'sex'), + ], + head_size=47, + repeat=[ + at(0, ip4, 'ip'), + at(4, u16, 'port'), + at(6, server_name, 'server name'), + at(26, u16, 'users'), + at(28, u16, 'maintenance'), + at(30, u16, 'is new'), + ], + repeat_size=32, + ) + login_user.s(0x006a, 'login error', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'error code'), + at(3, seconds, 'error message'), + ], + fixed_size=23, + ) + char_user.s(0x006b, 'update character list', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, str20, 'unused'), + ], + head_size=24, + repeat=[ + at(0, char_select, 'char select'), + ], + repeat_size=106, + ) + char_user.s(0x006c, 'login error', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'code'), + ], + fixed_size=3, + ) + char_user.s(0x006d, 'create character succeeded', + fixed=[ + at(0, u16, 'packet id'), + at(2, char_select, 'char select'), + ], + fixed_size=108, + ) + char_user.s(0x006e, 'create character failed', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'code'), + ], + fixed_size=3, + ) + char_user.s(0x006f, 'delete character succeeded', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + char_user.s(0x0070, 'delete character failed', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'code'), + ], + fixed_size=3, + ) + char_user.s(0x0071, 'char-map info', + fixed=[ + at(0, u16, 'packet id'), + at(2, char_id, 'char id'), + at(6, map_name, 'map name'), + at(22, ip4, 'ip'), + at(26, u16, 'port'), + ], + fixed_size=28, + ) + map_user.r(0x0072, 'map server connect', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, char_id, 'char id'), + at(10, u32, 'login id1'), + at(14, u32, 'client tick'), + at(18, sex, 'sex'), + ], + fixed_size=19, + ) + map_user.s(0x0073, 'map login succeeded', + fixed=[ + at(0, u16, 'packet id'), + at(2, tick32, 'tick'), + at(6, pos1, 'pos'), + at(9, u8, 'five1'), + at(10, u8, 'five2'), + ], + fixed_size=11, + ) + map_user.s(0x0078, 'being visibility', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, interval16, 'speed'), + at(8, opt1, 'opt1'), + at(10, opt2, 'opt2'), + at(12, option, 'option'), + at(14, species, 'species'), + at(16, u16, 'unused hair style'), + at(18, u16, 'unused weapon'), + at(20, u16, 'unused head bottom or species again'), + at(22, u16, 'unused shield or part of guild emblem'), + at(24, u16, 'unused head top or unused part of guild emblem'), + at(26, u16, 'unused head mid or part of guild id'), + at(28, u16, 'unused hair color or part of guild id'), + at(30, u16, 'unused clothes color'), + at(32, u16, 'unused 1'), + at(34, u16, 'unused 2'), + at(36, pos1, 'unused pos again'), + at(39, u8, 'unused 4b'), + at(40, u16, 'unused 5'), + at(42, u16, 'unused zero 1'), + at(44, u8, 'unused zero 2'), + at(45, u8, 'unused sex'), + at(46, pos1, 'pos'), + at(49, u8, 'five1'), + at(50, u8, 'five2'), + at(51, u8, 'zero'), + at(52, u16, 'level'), + ], + fixed_size=54, + ) + map_user.s(0x007b, 'being move', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, interval16, 'speed'), + at(8, opt1, 'opt1'), + at(10, opt2, 'opt2'), + at(12, option, 'option'), + at(14, species, 'mob class'), + at(16, u16, 'unused hair style'), + at(18, u16, 'unused weapon'), + at(20, u16, 'unused head bottom'), + at(22, tick32, 'tick and maybe part of guild emblem'), + at(26, u16, 'unused shield or maybe part of guild emblem'), + at(28, u16, 'unused head top or maybe part of guild id'), + at(30, u16, 'unused head mid or maybe part of guild id'), + at(32, u16, 'unused hair color'), + at(34, u16, 'unused clothes color'), + at(36, u16, 'unused 1'), + at(38, u16, 'unused 2'), + at(40, u16, 'unused 3'), + at(42, u16, 'unused 4'), + at(44, u16, 'unused 5'), + at(46, u16, 'unused zero 1'), + at(48, u8, 'unused zero 2'), + at(49, u8, 'unused sex'), + at(50, pos2, 'pos2'), + at(55, u8, 'zero'), + at(56, u8, 'five1'), + at(57, u8, 'five2'), + at(58, u16, 'level'), + ], + fixed_size=60, + ) + map_user.s(0x007c, 'being spawn', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, interval16, 'speed'), + at(8, opt1, 'opt1'), + at(10, opt2, 'opt2'), + at(12, option, 'option'), + at(14, u16, 'unknown 1'), + at(16, u16, 'unknown 2'), + at(18, u16, 'unknown 3'), + at(20, species, 'species'), + at(22, u16, 'unknown 4'), + at(24, u16, 'unknown 5'), + at(26, u16, 'unknown 6'), + at(28, u16, 'unknown 7'), + at(30, u16, 'unknown 8'), + at(32, u16, 'unknown 9'), + at(34, u16, 'unknown 10'), + at(36, pos1, 'pos'), + at(39, u16, 'unknown 11'), + ], + fixed_size=41, + ) + map_user.r(0x007d, 'map loaded', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + map_user.r(0x007e, 'client ping', + fixed=[ + at(0, u16, 'packet id'), + at(2, u32, 'client tick'), + ], + fixed_size=6, + ) + map_user.s(0x007f, 'server ping', + fixed=[ + at(0, u16, 'packet id'), + at(2, tick32, 'tick'), + ], + fixed_size=6, + ) + map_user.s(0x0080, 'remove being', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, being_remove_why, 'type'), + ], + fixed_size=7, + ) + any_user.s(0x0081, 'connection problem', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'error code'), + ], + fixed_size=3, + ) + map_user.r(0x0085, 'change player destination', + fixed=[ + at(0, u16, 'packet id'), + at(2, pos1, 'pos'), + ], + fixed_size=5, + ) + map_user.s(0x0087, 'walk response', + fixed=[ + at(0, u16, 'packet id'), + at(2, tick32, 'tick'), + at(6, pos2, 'pos2'), + at(11, u8, 'zero'), + ], + fixed_size=12, + ) + map_user.s(0x0088, 'player stop', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, u16, 'x'), + at(8, u16, 'y'), + ], + fixed_size=10, + ) + map_user.r(0x0089, 'player action', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'target id'), + at(6, damage_type, 'action'), + ], + fixed_size=7, + ) + map_user.s(0x008a, 'being action', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'src id'), + at(6, block_id, 'dst id'), + at(10, tick32, 'tick'), + at(14, interval32, 'sdelay'), + at(18, interval32, 'ddelay'), + at(22, u16, 'damage'), + at(24, u16, 'div'), + at(26, damage_type, 'damage type'), + at(27, u16, 'damage2'), + ], + fixed_size=29, + ) + map_user.r(0x008c, 'character chat', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + map_user.s(0x008d, 'being chat', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, block_id, 'block id'), + ], + head_size=8, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + map_user.s(0x008e, 'player chat', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + map_user.r(0x0090, 'chat to npc', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, u8, 'unused'), + ], + fixed_size=7, + ) + map_user.s(0x0091, 'warp player', + fixed=[ + at(0, u16, 'packet id'), + at(2, map_name, 'map name'), + at(18, u16, 'x'), + at(20, u16, 'y'), + ], + fixed_size=22, + ) + map_user.s(0x0092, 'change map server', + fixed=[ + at(0, u16, 'packet id'), + at(2, map_name, 'map name'), + at(18, u16, 'x'), + at(20, u16, 'y'), + at(22, ip4, 'ip'), + at(26, u16, 'port'), + ], + fixed_size=28, + ) + map_user.r(0x0094, 'request being name', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + ], + fixed_size=6, + ) + map_user.s(0x0095, 'being name response', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, char_name, 'char name'), + ], + fixed_size=30, + ) + map_user.r(0x0096, 'send whisper', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, char_name, 'target name'), + ], + head_size=28, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + map_user.s(0x0097, 'receive whisper', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, char_name, 'char name'), + ], + head_size=28, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + map_user.s(0x0098, 'whisper status', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'flag'), + ], + fixed_size=3, + ) + map_user.s(0x009a, 'gm announcement', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + map_user.r(0x009b, 'change player direction', + fixed=[ + at(0, u16, 'packet id'), + at(2, u16, 'unused'), + at(4, u8, 'client dir'), + ], + fixed_size=5, + ) + map_user.s(0x009c, 'being changed direction', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, u16, 'zero'), + at(8, u8, 'client dir'), + ], + fixed_size=9, + ) + map_user.s(0x009d, 'visible item', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, item_name_id, 'name id'), + at(8, u8, 'identify'), + at(9, u16, 'x'), + at(11, u16, 'y'), + at(13, u16, 'amount'), + at(15, u8, 'subx'), + at(16, u8, 'suby'), + ], + fixed_size=17, + ) + map_user.s(0x009e, 'dropped item', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, item_name_id, 'name id'), + at(8, u8, 'identify'), + at(9, u16, 'x'), + at(11, u16, 'y'), + at(13, u8, 'subx'), + at(14, u8, 'suby'), + at(15, u16, 'amount'), + ], + fixed_size=17, + ) + map_user.r(0x009f, 'pickup item', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'object id'), + ], + fixed_size=6, + ) + map_user.s(0x00a0, 'add item to inventory', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + at(4, u16, 'amount'), + at(6, item_name_id, 'name id'), + at(8, u8, 'identify'), + at(9, u8, 'broken or attribute'), + at(10, u8, 'refine'), + at(11, u16, 'card0'), + at(13, u16, 'card1'), + at(15, u16, 'card2'), + at(17, u16, 'card3'), + at(19, epos, 'epos'), + at(21, item_type, 'item type'), + at(22, pickup_fail, 'pickup fail'), + ], + fixed_size=23, + ) + map_user.s(0x00a1, 'item removed', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + ], + fixed_size=6, + ) + map_user.r(0x00a2, 'drop an item', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + at(4, u16, 'amount'), + ], + fixed_size=6, + ) + map_user.s(0x00a4, 'player equipment', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, ioff2, 'ioff2'), + at(2, item_name_id, 'name id'), + at(4, item_type, 'item type'), + at(5, u8, 'identify'), + at(6, epos, 'epos pc'), + at(8, epos, 'epos inv'), + at(10, u8, 'broken or attribute'), + at(11, u8, 'refine'), + at(12, u16, 'card0'), + at(14, u16, 'card1'), + at(16, u16, 'card2'), + at(18, u16, 'card3'), + ], + repeat_size=20, + ) + map_user.s(0x00a6, 'storage equipment', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, soff1, 'soff1'), + at(2, item_name_id, 'name id'), + at(4, item_type, 'item type'), + at(5, u8, 'identify'), + at(6, epos, 'epos id'), + at(8, epos, 'epos stor'), + at(10, u8, 'broken or attribute'), + at(11, u8, 'refine'), + at(12, u16, 'card0'), + at(14, u16, 'card1'), + at(16, u16, 'card2'), + at(18, u16, 'card3'), + ], + repeat_size=20, + ) + map_user.r(0x00a7, 'use inventory item', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + at(4, u32, 'unused id'), + ], + fixed_size=8, + ) + map_user.s(0x00a8, 'item usage response', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + at(4, u16, 'amount'), + at(6, u8, 'ok'), + ], + fixed_size=7, + ) + map_user.r(0x00a9, 'equip an item request', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + at(4, epos, 'epos ignored'), + ], + fixed_size=6, + ) + map_user.s(0x00aa, 'item equip ack', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + at(4, epos, 'epos'), + at(6, u8, 'ok'), + ], + fixed_size=7, + ) + map_user.r(0x00ab, 'unequip an item', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + ], + fixed_size=4, + ) + map_user.s(0x00ac, 'unequip item ack', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + at(4, epos, 'epos'), + at(6, u8, 'ok'), + ], + fixed_size=7, + ) + map_user.s(0x00af, 'remove item from inventory', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + at(4, u16, 'amount'), + ], + fixed_size=6, + ) + map_user.s(0x00b0, 'player stat update 1', + fixed=[ + at(0, u16, 'packet id'), + at(2, sp, 'sp type'), + at(4, u32, 'value'), + ], + fixed_size=8, + ) + map_user.s(0x00b1, 'player stat update 2', + fixed=[ + at(0, u16, 'packet id'), + at(2, sp, 'sp type'), + at(4, u32, 'value'), + ], + fixed_size=8, + ) + map_user.r(0x00b2, 'switch or respawn the character', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'flag'), + ], + fixed_size=3, + ) + map_user.s(0x00b3, 'character switch response', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'one'), + ], + fixed_size=3, + ) + map_user.s(0x00b4, 'npc message', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, block_id, 'block id'), + ], + head_size=8, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + map_user.s(0x00b5, 'npc message continues', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + ], + fixed_size=6, + ) + map_user.s(0x00b6, 'npc message ends', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + ], + fixed_size=6, + ) + map_user.s(0x00b7, 'npc prompts a choice', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, block_id, 'block id'), + ], + head_size=8, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + map_user.r(0x00b8, 'send npc response', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'npc id'), + at(6, u8, 'menu entry'), + ], + fixed_size=7, + ) + map_user.r(0x00b9, 'request next npc message', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'npc id'), + ], + fixed_size=6, + ) + map_user.r(0x00bb, 'request a stat update', + fixed=[ + at(0, u16, 'packet id'), + at(2, sp, 'asp'), + at(4, u8, 'unused'), + ], + fixed_size=5, + ) + map_user.s(0x00bc, 'player stat update 4', + fixed=[ + at(0, u16, 'packet id'), + at(2, sp, 'sp type'), + at(4, u8, 'ok'), + at(5, u8, 'val'), + ], + fixed_size=6, + ) + map_user.s(0x00bd, 'player stat update 5', + fixed=[ + at(0, u16, 'packet id'), + at(2, u16, 'status point'), + at(4, u8, 'str attr'), + at(5, u8, 'str upd'), + at(6, u8, 'agi attr'), + at(7, u8, 'agi upd'), + at(8, u8, 'vit attr'), + at(9, u8, 'vit upd'), + at(10, u8, 'int attr'), + at(11, u8, 'int upd'), + at(12, u8, 'dex attr'), + at(13, u8, 'dex upd'), + at(14, u8, 'luk attr'), + at(15, u8, 'luk upd'), + at(16, u16, 'atk sum'), + at(18, u16, 'watk2'), + at(20, u16, 'matk1'), + at(22, u16, 'matk2'), + at(24, u16, 'def'), + at(26, u16, 'def2'), + at(28, u16, 'mdef'), + at(30, u16, 'mdef2'), + at(32, u16, 'hit'), + at(34, u16, 'flee'), + at(36, u16, 'flee2'), + at(38, u16, 'critical'), + at(40, u16, 'karma'), + at(42, u16, 'manner'), + ], + fixed_size=44, + ) + map_user.s(0x00be, 'player stat update 6', + fixed=[ + at(0, u16, 'packet id'), + at(2, sp, 'sp type'), + at(4, u8, 'value'), + ], + fixed_size=5, + ) + map_user.r(0x00bf, 'show an emote', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'emote'), + ], + fixed_size=3, + ) + map_user.s(0x00c0, 'show the emote of a being', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, u8, 'type'), + ], + fixed_size=7, + ) + map_user.r(0x00c1, 'request online users (unused)', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + map_user.s(0x00c2, 'online users response (unused)', + fixed=[ + at(0, u16, 'packet id'), + at(2, u32, 'users'), + ], + fixed_size=6, + ) + map_user.s(0x00c4, 'npc shop choice', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + ], + fixed_size=6, + ) + map_user.r(0x00c5, 'npc shop request', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, u8, 'type'), + ], + fixed_size=7, + ) + map_user.s(0x00c6, 'npc buy prompt', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, u32, 'base price'), + at(4, u32, 'actual price'), + at(8, item_type, 'type'), + at(9, item_name_id, 'name id'), + ], + repeat_size=11, + ) + map_user.s(0x00c7, 'npc sell prompt', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, ioff2, 'ioff2'), + at(2, u32, 'base price'), + at(6, u32, 'actual price'), + ], + repeat_size=10, + ) + map_user.r(0x00c8, 'npc buy request', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, u16, 'count'), + at(2, item_name_id, 'name id'), + ], + repeat_size=4, + ) + map_user.r(0x00c9, 'npc sell request', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, ioff2, 'ioff2'), + at(2, u16, 'count'), + ], + repeat_size=4, + ) + map_user.s(0x00ca, 'npc buy response', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'fail'), + ], + fixed_size=3, + ) + map_user.s(0x00cb, 'npc sell response', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'fail'), + ], + fixed_size=3, + ) + map_user.s(0x00cd, 'kick status', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + map_user.r(0x00e4, 'trade request request', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + ], + fixed_size=6, + ) + map_user.s(0x00e5, 'incoming trade request', + fixed=[ + at(0, u16, 'packet id'), + at(2, char_name, 'char name'), + ], + fixed_size=26, + ) + map_user.r(0x00e6, 'incoming trade request response', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'type'), + ], + fixed_size=3, + ) + map_user.s(0x00e7, 'trade request response', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'type'), + ], + fixed_size=3, + ) + map_user.r(0x00e8, 'trade item add request', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'zeny or ioff2'), + at(4, u32, 'amount'), + ], + fixed_size=8, + ) + map_user.s(0x00e9, 'trade item add', + fixed=[ + at(0, u16, 'packet id'), + at(2, u32, 'amount'), + at(6, item_name_id, 'name id'), + at(8, u8, 'identify'), + at(9, u8, 'broken or attribute'), + at(10, u8, 'refine'), + at(11, u16, 'card0'), + at(13, u16, 'card1'), + at(15, u16, 'card2'), + at(17, u16, 'card3'), + ], + fixed_size=19, + ) + map_user.r(0x00eb, 'trade add complete', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + map_user.s(0x00ec, 'trade ok', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'fail'), + ], + fixed_size=3, + ) + map_user.r(0x00ed, 'trace cancel request', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + map_user.s(0x00ee, 'trade cancel', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + map_user.r(0x00ef, 'trade ok request', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + map_user.s(0x00f0, 'trade complete', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'fail'), + ], + fixed_size=3, + ) + map_user.s(0x00f2, 'storage status', + fixed=[ + at(0, u16, 'packet id'), + at(2, u16, 'current slots'), + at(4, u16, 'max slots'), + ], + fixed_size=6, + ) + map_user.r(0x00f3, 'move item to storage request', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + at(4, u32, 'amount'), + ], + fixed_size=8, + ) + map_user.s(0x00f4, 'move item to storage', + fixed=[ + at(0, u16, 'packet id'), + at(2, soff1, 'soff1'), + at(4, u32, 'amount'), + at(8, item_name_id, 'name id'), + at(10, u8, 'identify'), + at(11, u8, 'broken or attribute'), + at(12, u8, 'refine'), + at(13, u16, 'card0'), + at(15, u16, 'card1'), + at(17, u16, 'card2'), + at(19, u16, 'card3'), + ], + fixed_size=21, + ) + map_user.r(0x00f5, 'move item from storage request', + fixed=[ + at(0, u16, 'packet id'), + at(2, soff1, 'soff1'), + at(4, u32, 'amount'), + ], + fixed_size=8, + ) + map_user.s(0x00f6, 'remove item from storage', + fixed=[ + at(0, u16, 'packet id'), + at(2, soff1, 'soff1'), + at(4, u32, 'amount'), + ], + fixed_size=8, + ) + map_user.r(0x00f7, 'storage close request', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + map_user.s(0x00f8, 'storage closed', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + map_user.r(0x00f9, 'create party request', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_name, 'party name'), + ], + fixed_size=26, + ) + map_user.s(0x00fa, 'create party', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'flag'), + ], + fixed_size=3, + ) + map_user.s(0x00fb, 'party info', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, party_name, 'party name'), + ], + head_size=28, + repeat=[ + at(0, account_id, 'account id'), + at(4, char_name, 'char name'), + at(28, map_name, 'map name'), + at(44, u8, 'leader'), + at(45, u8, 'online'), + ], + repeat_size=46, + ) + map_user.r(0x00fc, 'party invite request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + map_user.s(0x00fd, 'party invite response', + fixed=[ + at(0, u16, 'packet id'), + at(2, char_name, 'char name'), + at(26, u8, 'flag'), + ], + fixed_size=27, + ) + map_user.s(0x00fe, 'party invite succeeded', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, party_name, 'party name'), + ], + fixed_size=30, + ) + map_user.r(0x00ff, 'party join request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u32, 'flag'), + ], + fixed_size=10, + ) + map_user.r(0x0100, 'party leave request', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + map_user.s(0x0101, 'party settings', + fixed=[ + at(0, u16, 'packet id'), + at(2, u16, 'exp'), + at(4, u16, 'item'), + ], + fixed_size=6, + ) + map_user.r(0x0102, 'party settings request', + fixed=[ + at(0, u16, 'packet id'), + at(2, u16, 'exp'), + at(4, u16, 'item'), + ], + fixed_size=6, + ) + map_user.r(0x0103, 'party kick request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, char_name, 'unused char name'), + ], + fixed_size=30, + ) + map_user.s(0x0105, 'party leave', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, char_name, 'char name'), + at(30, u8, 'flag'), + ], + fixed_size=31, + ) + map_user.s(0x0106, 'update party member hp', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u16, 'hp'), + at(8, u16, 'max hp'), + ], + fixed_size=10, + ) + map_user.s(0x0107, 'update party member coords', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u16, 'x'), + at(8, u16, 'y'), + ], + fixed_size=10, + ) + map_user.r(0x0108, 'party message request', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + map_user.s(0x0109, 'party message', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, account_id, 'account id'), + ], + head_size=8, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1 + ) + map_user.s(0x010c, 'MVP (unused)', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + ], + fixed_size=6, + ) + map_user.s(0x010e, 'raise a skill', + fixed=[ + at(0, u16, 'packet id'), + at(2, skill_id, 'skill id'), + at(4, u16, 'level'), + at(6, u16, 'sp'), + at(8, u16, 'range'), + at(10, u8, 'can raise'), + ], + fixed_size=11, + ) + map_user.s(0x010f, 'player skills', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, skill_info, 'info'), + ], + repeat_size=37, + ) + map_user.s(0x0110, 'skill failed', + fixed=[ + at(0, u16, 'packet id'), + at(2, skill_id, 'skill id'), + at(4, u16, 'btype'), + at(6, u16, 'zero1'), + at(8, u8, 'zero2'), + at(9, u8, 'type'), + ], + fixed_size=10, + ) + map_user.r(0x0112, 'request a skill lvl up', + fixed=[ + at(0, u16, 'packet id'), + at(2, skill_id, 'skill id'), + ], + fixed_size=4, + ) + map_user.r(0x0118, 'stop attack request', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + map_user.s(0x0119, 'change player status', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, opt1, 'opt1'), + at(8, opt2, 'opt2'), + at(10, option, 'option'), + at(12, u8, 'zero'), + ], + fixed_size=13, + ) + map_user.s(0x0139, 'move player to within attack range', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, u16, 'bl x'), + at(8, u16, 'bl y'), + at(10, u16, 'sd x'), + at(12, u16, 'sd y'), + at(14, u16, 'range'), + ], + fixed_size=16, + ) + map_user.s(0x013a, 'player attack range', + fixed=[ + at(0, u16, 'packet id'), + at(2, u16, 'attack range'), + ], + fixed_size=4, + ) + map_user.s(0x013b, 'player arrow message', + fixed=[ + at(0, u16, 'packet id'), + at(2, u16, 'type'), + ], + fixed_size=4, + ) + map_user.s(0x013c, 'player arrow equip', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + ], + fixed_size=4, + ) + map_user.s(0x0141, 'player stat update 3', + fixed=[ + at(0, u16, 'packet id'), + at(2, sp, 'sp type'), + at(4, u16, 'zero'), + at(6, u32, 'value status'), + at(10, u32, 'value b e'), + ], + fixed_size=14, + ) + map_user.s(0x0142, 'npc integer input', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + ], + fixed_size=6, + ) + map_user.r(0x0143, 'npc integer response', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, u32, 'input int value'), + ], + fixed_size=10, + ) + map_user.r(0x0146, 'npc close request', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + ], + fixed_size=6, + ) + map_user.s(0x0147, 'single skill info (unused)', + fixed=[ + at(0, u16, 'packet id'), + at(2, skill_info, 'info'), + ], + fixed_size=39, + ) + map_user.s(0x0148, 'being resurrected', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, u16, 'type'), + ], + fixed_size=8, + ) + map_user.r(0x014d, 'guild check master (unused)', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + map_user.r(0x018a, 'client quit', + fixed=[ + at(0, u16, 'packet id'), + at(2, u16, 'unused'), + ], + fixed_size=4, + ) + map_user.s(0x018b, 'map quit response', + fixed=[ + at(0, u16, 'packet id'), + at(2, u16, 'okay'), + ], + fixed_size=4, + ) + map_user.s(0x0195, 'guild party info (unused)', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, party_name, 'party name'), + at(30, str24, 'guild name'), + at(54, str24, 'guild pos'), + at(78, str24, 'guild pos again'), + ], + fixed_size=102, + ) + map_user.s(0x0196, 'being status change', + fixed=[ + at(0, u16, 'packet id'), + at(2, status_change, 'sc type'), + at(4, block_id, 'block id'), + at(8, u8, 'flag'), + ], + fixed_size=9, + ) + map_user.s(0x019b, 'being effect', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, u32, 'type'), + ], + fixed_size=10, + ) + map_user.s(0x01b1, 'trade item add response', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + at(4, u16, 'amount'), + at(6, u8, 'fail'), + ], + fixed_size=7, + ) + map_user.s(0x01c8, 'use inventory item succeeded', + fixed=[ + at(0, u16, 'packet id'), + at(2, ioff2, 'ioff2'), + at(4, item_name_id, 'name id'), + at(6, block_id, 'block id'), + at(10, u16, 'amount'), + at(12, u8, 'ok'), + ], + fixed_size=13, + ) + map_user.s(0x01d4, 'npc string input', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + ], + fixed_size=6, + ) + map_user.r(0x01d5, 'npc string response', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, block_id, 'block id'), + ], + head_size=8, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + map_user.s(0x01d7, 'change being appearance (unused)', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, look, 'look type'), + at(7, u16, 'weapon or name id or value'), + at(9, item_name_id, 'shield'), + ], + fixed_size=11, + ) + # very similar to, but not compatible with, 0x01d9 and 0x01da + map_user.s(0x01d8, 'player update 1', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, interval16, 'speed'), + at(8, opt1, 'opt1'), + at(10, opt2, 'opt2'), + at(12, option, 'option'), + at(14, species, 'species'), + at(16, u16, 'hair style'), + at(18, item_name_id, 'weapon'), + at(20, item_name_id, 'shield'), + at(22, item_name_id, 'head bottom'), + at(24, item_name_id, 'head top'), + at(26, item_name_id, 'head mid'), + at(28, u16, 'hair color'), + at(30, u16, 'clothes color'), + at(32, dir, 'head dir'), + at(33, u8, 'unused2'), + at(34, u32, 'guild id'), + at(38, u16, 'guild emblem id'), + at(40, u16, 'manner'), + at(42, opt3, 'opt3'), + at(44, u8, 'karma'), + at(45, sex, 'sex'), + at(46, pos1, 'pos'), + at(49, u16, 'gm bits'), + at(51, u8, 'dead sit'), + at(52, u16, 'unused'), + ], + fixed_size=54, + ) + # very similar to, but not compatible with, 0x01d8 and 0x01da + map_user.s(0x01d9, 'player update 2', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, interval16, 'speed'), + at(8, opt1, 'opt1'), + at(10, opt2, 'opt2'), + at(12, option, 'option'), + at(14, species, 'species'), + at(16, u16, 'hair style'), + at(18, item_name_id, 'weapon'), + at(20, item_name_id, 'shield'), + at(22, item_name_id, 'head bottom'), + at(24, item_name_id, 'head top'), + at(26, item_name_id, 'head mid'), + at(28, u16, 'hair color'), + at(30, u16, 'clothes color'), + at(32, dir, 'head dir'), + at(33, u8, 'unused2'), + at(34, u32, 'guild id'), + at(38, u16, 'guild emblem id'), + at(40, u16, 'manner'), + at(42, opt3, 'opt3'), + at(44, u8, 'karma'), + at(45, sex, 'sex'), + at(46, pos1, 'pos'), + at(49, u16, 'gm bits'), + at(51, u16, 'unused'), + ], + fixed_size=53, + ) + # very similar to, but not compatible with, 0x01d8 and 0x01d9 + map_user.s(0x01da, 'player move', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, interval16, 'speed'), + at(8, opt1, 'opt1'), + at(10, opt2, 'opt2'), + at(12, option, 'option'), + at(14, species, 'species'), + at(16, u16, 'hair style'), + at(18, item_name_id, 'weapon'), + at(20, item_name_id, 'shield'), + at(22, item_name_id, 'head bottom'), + at(24, tick32, 'tick'), + at(28, item_name_id, 'head top'), + at(30, item_name_id, 'head mid'), + at(32, u16, 'hair color'), + at(34, u16, 'clothes color'), + at(36, dir, 'head dir'), + at(37, u8, 'unused2'), + at(38, u32, 'guild id'), + at(42, u16, 'guild emblem id'), + at(44, u16, 'manner'), + at(46, opt3, 'opt3'), + at(48, u8, 'karma'), + at(49, sex, 'sex'), + at(50, pos2, 'pos2'), + at(55, u16, 'gm bits'), + at(57, u8, 'five'), + at(58, u16, 'unused'), + ], + fixed_size=60, + ) + map_user.s(0x01de, 'deal skill damage', + fixed=[ + at(0, u16, 'packet id'), + at(2, skill_id, 'skill id'), + at(4, block_id, 'src id'), + at(8, block_id, 'dst id'), + at(12, tick32, 'tick'), + at(16, interval32, 'sdelay'), + at(20, interval32, 'ddelay'), + at(24, u32, 'damage'), + at(28, u16, 'skill level'), + at(30, u16, 'div'), + at(32, u8, 'type or hit'), + ], + fixed_size=33, + ) + map_user.s(0x01ee, 'player inventory', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, ioff2, 'ioff2'), + at(2, item_name_id, 'name id'), + at(4, item_type, 'item type'), + at(5, u8, 'identify'), + at(6, u16, 'amount'), + at(8, epos, 'epos'), + at(10, u16, 'card0'), + at(12, u16, 'card1'), + at(14, u16, 'card2'), + at(16, u16, 'card3'), + ], + repeat_size=18, + ) + map_user.s(0x01f0, 'storage item list', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, soff1, 'soff1'), + at(2, item_name_id, 'name id'), + at(4, item_type, 'item type'), + at(5, u8, 'identify'), + at(6, u16, 'amount'), + at(8, epos, 'epos zero'), + at(10, u16, 'card0'), + at(12, u16, 'card1'), + at(14, u16, 'card2'), + at(16, u16, 'card3'), + ], + repeat_size=18, + ) + map_user.s(0x020c, 'set being ip', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'block id'), + at(6, ip4, 'ip'), + ], + fixed_size=10, + ) + map_user.s(0x0212, 'npc command', + fixed=[ + at(0, u16, 'packet id'), + at(2, block_id, 'npc id'), + at(6, u16, 'command'), + at(8, block_id, 'id'), + at(12, u16, 'x'), + at(14, u16, 'y'), + ], + fixed_size=16, + ) + + # login char + login_char.r(0x2709, 'reload gm accounts request', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + login_char.r(0x2710, 'add char server request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, account_pass, 'account pass'), + at(50, u32, 'unknown'), + at(54, ip4, 'ip'), + at(58, u16, 'port'), + at(60, server_name, 'server name'), + at(80, u16, 'unknown2'), + at(82, u16, 'maintenance'), + at(84, u16, 'is new'), + ], + fixed_size=86, + ) + login_char.s(0x2711, 'add char server result', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'code'), + ], + fixed_size=3, + ) + login_char.r(0x2712, 'account auth request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u32, 'login id1'), + at(10, u32, 'login id2'), + at(14, sex, 'sex'), + at(15, ip4, 'ip'), + ], + fixed_size=19, + ) + login_char.s(0x2713, 'account auth result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u8, 'invalid'), + at(7, account_email, 'email'), + at(47, time32, 'connect until'), + ], + fixed_size=51, + ) + login_char.r(0x2714, 'online count', + fixed=[ + at(0, u16, 'packet id'), + at(2, u32, 'users'), + ], + fixed_size=6, + ) + login_char.r(0x2716, 'email limit request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + login_char.s(0x2717, 'email limit result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_email, 'email'), + at(46, time32, 'connect until'), + ], + fixed_size=50, + ) + # 0x2b0a + login_char.r(0x2720, 'become gm request', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, account_id, 'account id'), + ], + head_size=8, + repeat=[at(0, u8, 'c')], + repeat_size=1, + ) + login_char.s(0x2721, 'become gm reply', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, gm, 'gm level'), + ], + fixed_size=10, + ) + # 0x2b0c + login_char.r(0x2722, 'account email change request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_email, 'old email'), + at(46, account_email, 'new email'), + ], + fixed_size=86, + ) + login_char.s(0x2723, 'changesex reply', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, sex, 'sex'), + ], + fixed_size=7, + ) + login_char.r(0x2724, 'block status', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u32, 'status'), + ], + fixed_size=10, + ) + login_char.r(0x2725, 'ban add', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, human_time_diff, 'ban add'), + ], + fixed_size=18, + ) + # evil packet, see also 0x794e + login_admin.s(0x2726, 'broadcast', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'unused'), + at(4, SkewLengthType(u32, 8), 'magic packet length'), + ], + head_size=8, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + login_char.r(0x2727, 'change sex request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + # 0x2b10, 0x2b11 + for (id, cat) in [ + (0x2728, login_char.r), + (0x2729, login_char.s), + ]: + cat(id, 'update account reg2', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, account_id, 'account id'), + ], + head_size=8, + repeat=[ + at(0, var_name, 'name'), + at(32, u32, 'value'), + ], + repeat_size=36, + ) + login_char.r(0x272a, 'unban request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + login_char.s(0x2730, 'account deleted', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + login_char.s(0x2731, 'status or ban changed', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u8, 'ban not status'), + at(7, time32, 'status or ban until'), + ], + fixed_size=11, + ) + login_char.s(0x2732, 'gm account list', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, account_id, 'account id'), + at(4, gm1, 'gm level'), + ], + repeat_size=5, + ) + login_char.r(0x2740, 'change password request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_pass, 'old pass'), + at(30, account_pass, 'new pass'), + ], + fixed_size=54, + ) + login_char.s(0x2741, 'change password reply', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u8, 'status'), + ], + fixed_size=7, + ) + + # char map + char_map.r(0x2af7, 'reload gm db', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + char_map.r(0x2af8, 'add map server request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, account_pass, 'account pass'), + at(50, u32, 'unused'), + at(54, ip4, 'ip'), + at(58, u16, 'port'), + ], + fixed_size=60, + ) + char_map.s(0x2af9, 'add map server result', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'code'), + ], + fixed_size=3, + ) + # wtf duplicate v + char_map.r(0x2afa, 'map list', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, map_name, 'map name'), + ], + repeat_size=16, + ) + # wtf duplicate ^ + char_map.s(0x2afa, 'itemfrob', + fixed=[ + at(0, u16, 'packet id'), + at(2, item_name_id4, 'source item id'), + at(6, item_name_id4, 'dest item id'), + ], + fixed_size=10, + ) + char_map.s(0x2afb, 'map list ack', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'unknown'), + at(3, char_name, 'whisper name'), + ], + fixed_size=27, + ) + char_map.r(0x2afc, 'character auth request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, char_id, 'char id'), + at(10, u32, 'login id1'), + at(14, u32, 'login id2'), + at(18, ip4, 'ip'), + ], + fixed_size=22, + ) + char_map.s(0x2afd, 'character auth and data', + payload=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, account_id, 'account id'), + at(8, u32, 'login id2'), + at(12, time32, 'connect until'), + at(16, u16, 'packet tmw version'), + at(18, char_key, 'char key'), + at(None, char_data, 'char data'), + ], + payload_size=None, + ) + char_map.s(0x2afe, 'character auth error', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + char_map.r(0x2aff, 'user list', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, u16, 'users'), + ], + head_size=6, + repeat=[ + at(0, char_id, 'char id'), + ], + repeat_size=4, + ) + char_map.s(0x2b00, 'total users', + fixed=[ + at(0, u16, 'packet id'), + at(2, u32, 'users'), + ], + fixed_size=6, + ) + char_map.r(0x2b01, 'character save', + payload=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, account_id, 'account id'), + at(8, char_id, 'char id'), + at(12, char_key, 'char key'), + at(None, char_data, 'char data'), + ], + payload_size=None, + ) + char_map.r(0x2b02, 'char select req', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u32, 'login id1'), + at(10, u32, 'login id2'), + at(14, ip4, 'ip'), + ], + fixed_size=18, + ) + char_map.s(0x2b03, 'char select res', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u8, 'unknown'), + ], + fixed_size=7, + ) + char_map.s(0x2b04, 'map list broadcast', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, ip4, 'ip'), + at(8, u16, 'port'), + ], + head_size=10, + repeat=[ + at(0, map_name, 'map name'), + ], + repeat_size=16, + ) + char_map.r(0x2b05, 'change map server request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u32, 'login id1'), + at(10, u32, 'login id2'), + at(14, char_id, 'char id'), + at(18, map_name, 'map name'), + at(34, u16, 'x'), + at(36, u16, 'y'), + at(38, ip4, 'map ip'), + at(42, u16, 'map port'), + at(44, sex, 'sex'), + at(45, ip4, 'client ip'), + ], + fixed_size=49, + ) + char_map.s(0x2b06, 'change map server ack', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u32, 'error'), + at(10, u32, 'unknown'), + at(14, char_id, 'char id'), + at(18, map_name, 'map name'), + at(34, u16, 'x'), + at(36, u16, 'y'), + at(38, ip4, 'map ip'), + at(42, u16, 'map port'), + ], + fixed_size=44, + ) + # 0x2720 + char_map.r(0x2b0a, 'become gm request', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, account_id, 'account id'), + ], + head_size=8, + repeat=[at(0, u8, 'c')], + repeat_size=1, + ) + char_map.s(0x2b0b, 'become gm result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, gm, 'gm level'), + ], + fixed_size=10, + ) + # 0x2722 + char_map.r(0x2b0c, 'change email request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_email, 'old email'), + at(46, account_email, 'new email'), + ], + fixed_size=86, + ) + char_map.s(0x2b0d, 'sex changed notify', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, sex, 'sex'), + ], + fixed_size=7, + ) + char_map.r(0x2b0e, 'named char operation request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, char_name, 'char name'), + at(30, u16, 'operation'), + at(32, human_time_diff, 'ban add'), + ], + fixed_size=44, + ) + char_map.r(0x2b0f, 'named char operation answer', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, char_name, 'char name'), + at(30, u16, 'operation'), + at(32, u16, 'error'), + ], + fixed_size=34, + ) + # 0x2728, 0x2729 + for (id, cat) in [ + (0x2b10, char_map.r), + (0x2b11, char_map.s), + ]: + cat(id, 'account reg2 update', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, account_id, 'account id'), + ], + head_size=8, + repeat=[ + at(0, var_name, 'name'), + at(32, u32, 'value'), + ], + repeat_size=36, + ) + char_map.s(0x2b12, 'divorce notify', + fixed=[ + at(0, u16, 'packet id'), + at(2, char_id, 'char id'), + at(6, char_id, 'partner id'), + ], + fixed_size=10, + ) + char_map.s(0x2b13, 'account delete notify', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + char_map.s(0x2b14, 'status or ban notify', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u8, 'ban not status'), + at(7, time32, 'status or ban until'), + ], + fixed_size=11, + ) + char_map.s(0x2b15, 'gm account list notify', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, account_id, 'account id'), + at(4, gm1, 'gm level'), + ], + repeat_size=5, + ) + char_map.r(0x2b16, 'divorce request', + fixed=[ + at(0, u16, 'packet id'), + at(2, char_id, 'char id'), + ], + fixed_size=6, + ) + + char_map.r(0x3000, 'gm broadcast', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + char_map.r(0x3001, 'whisper forward', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, char_name, 'from char name'), + at(28, char_name, 'to char name'), + ], + head_size=52, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + char_map.r(0x3002, 'whisper forward result', + fixed=[ + at(0, u16, 'packet id'), + at(2, char_id, 'char id'), + at(6, u8, 'flag'), + ], + fixed_size=7, + ) + # 0x3803 + char_map.r(0x3003, 'wgm forward', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, char_name, 'char name'), + at(28, gm2, 'min gm level'), + ], + head_size=30, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + # 0x3804 + char_map.r(0x3004, 'save account reg', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, account_id, 'account id'), + ], + head_size=8, + repeat=[ + at(0, var_name, 'name'), + at(32, u32, 'value'), + ], + repeat_size=36, + ) + char_map.r(0x3005, 'want account reg', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + char_map.r(0x3010, 'want storage', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + char_map.r(0x3011, 'got storage', + payload=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, account_id, 'account id'), + at(8, storage, 'storage'), + ], + payload_size=None, + ) + char_map.r(0x3020, 'create party', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, party_name, 'party name'), + at(30, char_name, 'char name'), + at(54, map_name, 'map name'), + at(70, u16, 'level'), + ], + fixed_size=72, + ) + char_map.r(0x3021, 'request party info', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_id, 'party id'), + ], + fixed_size=6, + ) + char_map.r(0x3022, 'party add member', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_id, 'party id'), + at(6, account_id, 'account id'), + at(10, char_name, 'char name'), + at(34, map_name, 'map name'), + at(50, u16, 'level'), + ], + fixed_size=52, + ) + char_map.r(0x3023, 'party change option', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_id, 'party id'), + at(6, account_id, 'account id'), + at(10, u16, 'exp'), + at(12, u16, 'item'), + ], + fixed_size=14, + ) + char_map.r(0x3024, 'party leave', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_id, 'party id'), + at(6, account_id, 'account id'), + ], + fixed_size=10, + ) + char_map.r(0x3025, 'party change map', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_id, 'party id'), + at(6, account_id, 'account id'), + at(10, map_name, 'map name'), + at(26, u8, 'online'), + at(27, u16, 'level'), + ], + fixed_size=29, + ) + char_map.r(0x3027, 'party message', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, party_id, 'party id'), + at(8, account_id, 'account id'), + ], + head_size=12, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + char_map.r(0x3028, 'party check conflict', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_id, 'party id'), + at(6, account_id, 'account id'), + at(10, char_name, 'char name'), + ], + fixed_size=34, + ) + + char_map.s(0x3800, 'gm broadcast', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + char_map.s(0x3801, 'whisper forward', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, char_id, 'whisper id'), + at(8, char_name, 'src char name'), + at(32, char_name, 'dst char name'), + ], + head_size=56, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + char_map.s(0x3802, 'whisper result', + fixed=[ + at(0, u16, 'packet id'), + at(2, char_name, 'sender char name'), + at(26, u8, 'flag'), + ], + fixed_size=27, + ) + # 0x3003 + char_map.s(0x3803, 'whisper gm', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, char_name, 'char name'), + at(28, gm2, 'min gm level'), + ], + head_size=30, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + # 0x3004 + char_map.s(0x3804, 'broadcast account reg', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, account_id, 'account id'), + ], + head_size=8, + repeat=[ + at(0, var_name, 'name'), + at(32, u32, 'value'), + ], + repeat_size=36, + ) + char_map.s(0x3810, 'load storage', + payload=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, account_id, 'account id'), + at(8, storage, 'storage'), + ], + payload_size=None, + ) + char_map.s(0x3811, 'save storage ack', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u8, 'unknown'), + ], + fixed_size=7, + ) + char_map.s(0x3820, 'party created', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, u8, 'error'), + at(7, party_id, 'party id'), + at(11, party_name, 'party name'), + ], + fixed_size=35, + ) + char_map.s(0x3821, 'party info maybe', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, party_id, 'party id'), + ], + head_size=8, + option=[ + at(0, party_most, 'party most'), + ], + option_size=None, + ) + char_map.s(0x3822, 'party member added', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_id, 'party id'), + at(6, account_id, 'account id'), + at(10, u8, 'flag'), + ], + fixed_size=11, + ) + char_map.s(0x3823, 'party option changed', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_id, 'party id'), + at(6, account_id, 'account id'), + at(10, u16, 'exp'), + at(12, u16, 'item'), + at(14, u8, 'flag'), + ], + fixed_size=15, + ) + char_map.s(0x3824, 'party member left', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_id, 'party id'), + at(6, account_id, 'account id'), + at(10, char_name, 'char name'), + ], + fixed_size=34, + ) + char_map.s(0x3825, 'party member moved', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_id, 'party id'), + at(6, account_id, 'account id'), + at(10, map_name, 'map name'), + at(26, u8, 'online'), + at(27, u16, 'level'), + ], + fixed_size=29, + ) + char_map.s(0x3826, 'party broken', + fixed=[ + at(0, u16, 'packet id'), + at(2, party_id, 'party id'), + at(6, u8, 'flag'), + ], + fixed_size=7, + ) + char_map.s(0x3827, 'party message', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + at(4, party_id, 'party id'), + at(8, account_id, 'account id'), + ], + head_size=12, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + + # any client + any_user.r(0x7530, 'version request', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + any_user.s(0x7531, 'version reply', + fixed=[ + at(0, u16, 'packet id'), + at(2, version, 'version'), + ], + fixed_size=10, + ) + any_user.r(0x7532, 'shutdown please', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + + # login admin + login_admin.r(0x7918, 'admin auth request', + fixed=[ + at(0, u16, 'packet id'), + at(2, u16, 'encryption zero'), + at(4, account_pass, 'account pass'), + ], + fixed_size=28, + ) + login_admin.s(0x7919, 'admin auth result', + fixed=[ + at(0, u16, 'packet id'), + at(2, u8, 'error'), + ], + fixed_size=3, + ) + login_admin.r(0x7920, 'account list request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'start account id'), + at(6, account_id, 'end account id'), + ], + fixed_size=10, + ) + login_admin.s(0x7921, 'account list reply', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, account_id, 'account id'), + at(4, gm1, 'gm level'), + at(5, account_name, 'account name'), + at(29, sex, 'sex'), + at(30, u32, 'login count'), + at(34, u32, 'status'), + ], + repeat_size=38, + ) + login_admin.r(0x7924, 'itemfrob', + fixed=[ + at(0, u16, 'packet id'), + at(2, item_name_id4, 'source item id'), + at(6, item_name_id4, 'dest item id'), + ], + fixed_size=10, + ) + login_admin.s(0x7925, 'itemfrob ok', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + login_admin.r(0x7930, 'account create request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, account_pass, 'password'), + at(50, sex_char, 'sex'), + at(51, account_email, 'email'), + ], + fixed_size=91, + ) + login_admin.s(0x7931, 'account create result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + ], + fixed_size=30, + ) + login_admin.r(0x7932, 'account delete request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + ], + fixed_size=26, + ) + login_admin.s(0x7933, 'account delete reply', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + ], + fixed_size=30, + ) + login_admin.r(0x7934, 'password change request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, account_pass, 'password'), + ], + fixed_size=50, + ) + login_admin.s(0x7935, 'password change result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + ], + fixed_size=30, + ) + login_admin.r(0x7936, 'account state change request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, u32, 'status'), + at(30, seconds, 'error message'), + ], + fixed_size=50, + ) + login_admin.s(0x7937, 'account state change result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + at(30, u32, 'status'), + ], + fixed_size=34, + ) + login_admin.r(0x7938, 'server list request', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + login_admin.s(0x7939, 'server list result', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'packet length'), + ], + head_size=4, + repeat=[ + at(0, ip4, 'ip'), + at(4, u16, 'port'), + at(6, server_name, 'name'), + at(26, u16, 'users'), + at(28, u16, 'maintenance'), + at(30, u16, 'is new'), + ], + repeat_size=32, + ) + login_admin.r(0x793a, 'password check request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, account_pass, 'password'), + ], + fixed_size=50, + ) + login_admin.s(0x793b, 'password check result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + ], + fixed_size=30, + ) + login_admin.r(0x793c, 'change sex request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, sex_char, 'sex'), + ], + fixed_size=27, + ) + login_admin.s(0x793d, 'change sex result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + ], + fixed_size=30, + ) + login_admin.r(0x793e, 'adjust gm level request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, gm1, 'gm level'), + ], + fixed_size=27, + ) + login_admin.s(0x793f, 'adjust gm level result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + ], + fixed_size=30, + ) + login_admin.r(0x7940, 'change email request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, account_email, 'email'), + ], + fixed_size=66, + ) + login_admin.s(0x7941, 'change email result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + ], + fixed_size=30, + ) + # this packet is insane + login_admin.r(0x7942, 'change memo request', + head=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, SkewLengthType(u16, 28), 'magic packet length'), + ], + head_size=28, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + login_admin.s(0x7943, 'change memo result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + ], + fixed_size=30, + ) + login_admin.r(0x7944, 'account id lookup request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + ], + fixed_size=26, + ) + login_admin.s(0x7945, 'account id lookup result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + ], + fixed_size=30, + ) + login_admin.r(0x7946, 'account name lookup request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + login_admin.s(0x7947, 'account name lookup result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + ], + fixed_size=30, + ) + login_admin.r(0x7948, 'validity absolute request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, time32, 'valid until'), + ], + fixed_size=30, + ) + login_admin.s(0x7949, 'validity absolute result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + at(30, time32, 'valid until'), + ], + fixed_size=34, + ) + login_admin.r(0x794a, 'ban absolute request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, time32, 'ban until'), + ], + fixed_size=30, + ) + login_admin.s(0x794b, 'ban absolute result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + at(30, time32, 'ban until'), + ], + fixed_size=34, + ) + login_admin.r(0x794c, 'ban relative request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, human_time_diff, 'ban add'), + ], + fixed_size=38, + ) + login_admin.s(0x794d, 'ban relative result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + at(30, time32, 'ban until'), + ], + fixed_size=34, + ) + # evil packet (see also 0x2726) + login_admin.r(0x794e, 'broadcast message request', + head=[ + at(0, u16, 'packet id'), + at(2, u16, 'unused'), + at(4, SkewLengthType(u32, 8), 'magic packet length'), + ], + head_size=8, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + login_admin.s(0x794f, 'broadcast message result', + fixed=[ + at(0, u16, 'packet id'), + at(2, u16, 'error'), + ], + fixed_size=4, + ) + login_admin.r(0x7950, 'validity relative request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + at(26, human_time_diff, 'valid add'), + ], + fixed_size=38, + ) + login_admin.s(0x7951, 'validity relative result', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, account_name, 'account name'), + at(30, time32, 'valid until'), + ], + fixed_size=34, + ) + login_admin.r(0x7952, 'account name info request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_name, 'account name'), + ], + fixed_size=26, + ) + # this packet is insane + login_admin.s(0x7953, 'account info result', + head=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + at(6, gm1, 'gm level'), + at(7, account_name, 'account name'), + at(31, sex, 'sex'), + at(32, u32, 'login count'), + at(36, u32, 'state'), + at(40, seconds, 'error message'), + at(60, millis, 'last login string'), + at(84, str16, 'ip string'), + at(100, account_email, 'email'), + at(140, time32, 'connect until'), + at(144, time32, 'ban until'), + at(148, SkewLengthType(u16, 150), 'magic packet length'), + ], + head_size=150, + repeat=[ + at(0, u8, 'c'), + ], + repeat_size=1, + ) + login_admin.r(0x7954, 'account id info request', + fixed=[ + at(0, u16, 'packet id'), + at(2, account_id, 'account id'), + ], + fixed_size=6, + ) + login_admin.r(0x7955, 'reload gm signal', + fixed=[ + at(0, u16, 'packet id'), + ], + fixed_size=2, + ) + + ## new-style packets + # general packets + any_user.x(0x8000, 'special hold', + payload=[ + at(0, u16, 'packet id'), + # packet 0x8000 is handled specially + at(2, u16, 'packet length'), + ], + payload_size=4, + ) + + ## teardown + ctx.dump() + +if __name__ == '__main__': + main() diff --git a/version.make b/version.make index f7d5511..73ecc83 100644 --- a/version.make +++ b/version.make @@ -1,4 +1,7 @@ +ABI_VERSION := 0 + # These lines are automatically replaced in tarballs generated by 'make dist' +# Note so you stop forgetting: export-subst attribute can't do tag-relative VERSION_FULL := $(shell git --git-dir=${SRC_DIR}/.git describe --tags HEAD) VERSION_HASH := $(shell git --git-dir=${SRC_DIR}/.git rev-parse HEAD) @@ -40,8 +43,16 @@ VENDOR_SOURCE := https://github.com/themanaworld/tmwa # Convenience VERSION_STRING := TMWA ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} dev${VERSION_DEVEL} +${VENDOR_POINT} (${VENDOR_NAME}) +VERSION_DOTS := ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_DEVEL}.${VENDOR_POINT} + +# Shared libraries +SO_SHORT := so.${ABI_VERSION} +SO_LONG := ${SO_SHORT}.${VERSION_DOTS} +# and thanks for all the fish version: @echo version '${VERSION_STRING}' @echo based on commit ${VERSION_FULL} aka ${VERSION_HASH} @echo source ${VENDOR_SOURCE} + @echo abi version ${ABI_VERSION} + @echo 'lib so -> ${SO_SHORT} -> ${SO_LONG}' |