From 8f3bff764b2d62689747ed20d90de00ca4607fff Mon Sep 17 00:00:00 2001 From: feynman Date: Sun, 14 Apr 2013 15:54:56 +0000 Subject: [PATCH] Forgot to commit the source changes in the last commit. Sorry. So, here they are. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5999 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- ModularizedTacticalAI/Doxyfile | 1792 ++ .../ModularizedTacticalAI.vcproj | 221 + .../include/AbstractPlanFactory.h | 77 + ModularizedTacticalAI/include/LegacyAIPlan.h | 32 + .../include/LegacyAIPlanFactory.h | 32 + ModularizedTacticalAI/include/NullPlan.h | 41 + .../include/NullPlanFactory.h | 46 + ModularizedTacticalAI/include/Plan.h | 52 + .../include/PlanFactoryLibrary.h | 42 + ModularizedTacticalAI/readme.txt | 27 + ModularizedTacticalAI/src/LegacyAIPlan.cpp | 28 + .../src/LegacyAIPlanFactory.cpp | 25 + ModularizedTacticalAI/src/NullPlan.cpp | 21 + ModularizedTacticalAI/src/NullPlanFactory.cpp | 25 + .../src/PlanFactoryLibrary.cpp | 84 + SaveLoadGame.cpp | 2 + SCREENS.cpp => Screens.cpp | 2 +- SCREENS.H => Screens.h | 0 Strategic/XML_CoolnessBySector.cpp | 2 - Tactical/Overhead.cpp | 16296 ++++++++-------- Tactical/Overhead.h | 402 +- Tactical/Soldier Control.cpp | 44 +- Tactical/Soldier Control.h | 17 +- Tactical/XML_Sounds.cpp | 370 +- TacticalAI/AIMain.cpp | 1708 +- ja2_VS2008.sln | 26 +- 26 files changed, 11543 insertions(+), 9871 deletions(-) create mode 100644 ModularizedTacticalAI/Doxyfile create mode 100644 ModularizedTacticalAI/ModularizedTacticalAI.vcproj create mode 100644 ModularizedTacticalAI/include/AbstractPlanFactory.h create mode 100644 ModularizedTacticalAI/include/LegacyAIPlan.h create mode 100644 ModularizedTacticalAI/include/LegacyAIPlanFactory.h create mode 100644 ModularizedTacticalAI/include/NullPlan.h create mode 100644 ModularizedTacticalAI/include/NullPlanFactory.h create mode 100644 ModularizedTacticalAI/include/Plan.h create mode 100644 ModularizedTacticalAI/include/PlanFactoryLibrary.h create mode 100644 ModularizedTacticalAI/readme.txt create mode 100644 ModularizedTacticalAI/src/LegacyAIPlan.cpp create mode 100644 ModularizedTacticalAI/src/LegacyAIPlanFactory.cpp create mode 100644 ModularizedTacticalAI/src/NullPlan.cpp create mode 100644 ModularizedTacticalAI/src/NullPlanFactory.cpp create mode 100644 ModularizedTacticalAI/src/PlanFactoryLibrary.cpp rename SCREENS.cpp => Screens.cpp (97%) rename SCREENS.H => Screens.h (100%) diff --git a/ModularizedTacticalAI/Doxyfile b/ModularizedTacticalAI/Doxyfile new file mode 100644 index 00000000..ba617d50 --- /dev/null +++ b/ModularizedTacticalAI/Doxyfile @@ -0,0 +1,1792 @@ +# Doxyfile 1.8.1.2 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "Jagged Alliance 2 Modularized AI" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../../Developer_Docs/ModularizedAI/ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. + +EXTRACT_PACKAGE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C, C++ and Fortran comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/ModularizedTacticalAI/ModularizedTacticalAI.vcproj b/ModularizedTacticalAI/ModularizedTacticalAI.vcproj new file mode 100644 index 00000000..efef7fe1 --- /dev/null +++ b/ModularizedTacticalAI/ModularizedTacticalAI.vcproj @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModularizedTacticalAI/include/AbstractPlanFactory.h b/ModularizedTacticalAI/include/AbstractPlanFactory.h new file mode 100644 index 00000000..8ef0c977 --- /dev/null +++ b/ModularizedTacticalAI/include/AbstractPlanFactory.h @@ -0,0 +1,77 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ + +#ifndef ABSTRACT_PLAN_FACTORY_H_ +#define ABSTRACT_PLAN_FACTORY_H_ + +class SOLDIERTYPE; + +namespace AI +{ + namespace tactical + { + /**@class AIInputData + * @brief Wrapper class around the environmental data required to build an AI plan + * + * At the moment, simply a wrapper around SOLDIERTYPE. Future versions might require more data; without the + * wrapper, *every* Concrete Factory ever created would need to be changed in this event. With the wrapper, no + * change is required at all. + */ + struct AIInputData + { + SOLDIERTYPE* npc_to_plan_for_; + }; + class Plan; + /**@class AbstractPlanFactory + * @brief Abstract Factory. Base class for all plan factories. + * + * The Abstract Factory design pattern is used to create instances of Plan object hierarchies. The concrete + * factories differ not necessarily in the concrete product they produce (as is otherwise the case when using + * this design pattern), but in the structure of the compositions (plans are Composites) instead. Public + * inheritance is required for two reasons: (a) several sub-class instances are packed in a container, and this + * abstract class serves as the container's data type. And (b) implementation of create_plan() and update_plan() + * is forced for concrete subclasses. + */ + class AbstractPlanFactory + { + private: + bool initialize_called_; + public: + AbstractPlanFactory() : initialize_called_(false) { } + bool initialize_called() const { return initialize_called_; } + /**@brief Used for delayed initialization of ressource-intensive initialization tasks + * + * Due to the design of the modularized AI, each factory's constructor must be called, even if the + * factory is not used. Therefore, memory- and cpu intensive tasks should not be performed in the + * constructor, but in this function instead. It will only be called if the factory is actually + * referenced in the AI.ini file. + */ + virtual void initialize() { }; + /**@brief Abstract Plan object hierarchy creation function + * + * The subclasses (i.e., Concrete Factories) implpmenting this routine contain + * the decision-making AI core. + * + * @param input A pointer to a structure containing all required input data in order for the AI + * algorithms to perform their task. At the moment, simply a wrapper around SOLDIERTYPE. Future versions + * might require other datatypes; without the wrapper, *every* Concrete Factory ever created would need + * to be changed in this event. + * @return A Plan object tree representing the produced strategy + */ + virtual Plan* create_plan(const AIInputData& input) = 0; + /**@brief Abstract Plan object hierarchy update function, called in order to update an already created + * plan + * + * @param input A pointer to a structure containing all required input data in order for the AI + * algorithms to perform their task + * @param plan_to_change The Plan object hierarchy that is to be updated + */ + virtual void update_plan(const AIInputData& input, Plan* plan_to_change) = 0; + }; + } +} + +#endif + diff --git a/ModularizedTacticalAI/include/LegacyAIPlan.h b/ModularizedTacticalAI/include/LegacyAIPlan.h new file mode 100644 index 00000000..786d9a34 --- /dev/null +++ b/ModularizedTacticalAI/include/LegacyAIPlan.h @@ -0,0 +1,32 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ + +#ifndef LEGACY_AI_PLAN_H_ +#define LEGACY_AI_PLAN_H_ + +#include "Plan.h" + +namespace AI +{ + namespace tactical + { + /**@class LegacyAIPlan + * @brief Component/Concrete Product. Generates a Plan that executes the AI as it was before modularization. + * + * A simple encapsulation of the functions TurnBasedHandleNPCAI() and RTHandleAI(), defined in + * TacticalAI/AIMain.cpp and TacticalAI/Realtime.cpp, respectively. The AI handles decisions for all kinds of + * NPCs (enemies, zombies, civilians, ...) + */ + class LegacyAIPlan: public Plan + { + private: + public: + virtual void execute(bool turn_based, PlanInputData& manipulated_object); + }; + } +} + +#endif + diff --git a/ModularizedTacticalAI/include/LegacyAIPlanFactory.h b/ModularizedTacticalAI/include/LegacyAIPlanFactory.h new file mode 100644 index 00000000..6982ac7c --- /dev/null +++ b/ModularizedTacticalAI/include/LegacyAIPlanFactory.h @@ -0,0 +1,32 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ + +#ifndef LEGACY_AI_PLAN_FACTORY_H_ +#define LEGACY_AI_PLAN_FACTORY_H_ + +#include "AbstractPlanFactory.h" +#include + +namespace AI +{ + namespace tactical + { + /**@class LegacyAIPlanFactory + * @brief Concrete Factory. Generates the LegacyAIPlan, making NPCs do exactly what it did before this AI + * modularization/re-write. + */ + class LegacyAIPlanFactory : public AbstractPlanFactory + { + private: + public: + static std::string get_name() {return "LegacyAIPlanFactory";} + virtual Plan* create_plan(const AIInputData& input); + virtual void update_plan(const AIInputData& input, Plan* plan_to_change); + }; + } +} + +#endif + diff --git a/ModularizedTacticalAI/include/NullPlan.h b/ModularizedTacticalAI/include/NullPlan.h new file mode 100644 index 00000000..8a1975ef --- /dev/null +++ b/ModularizedTacticalAI/include/NullPlan.h @@ -0,0 +1,41 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ + +#ifndef NULL_PLAN_H_ +#define NULL_PLAN_H_ + +#include "Plan.h" + +namespace AI +{ + namespace tactical + { + /**@class NullPlan + * @brief Component/Concrete Product. The NullPlan lets makes the NPC executing it do absolutely nothing. + * + * The purpose of this plan is two-fold. Firstly, it is a good starting point for new plans; to use it + * as such, perform a + + * - \c svn copy include/NullPlan.h include/YourPlan.h + * - \c svn copy src/NullPlan.cpp src/YourPlan.cpp + * + * Remember to + * + * - Adjust the include guards + * - A concrete factory using this plan is required in order for it to be used + * + * And secondly, it is a debugging tool (cf. NullPlanFactory) + */ + class NullPlan: public Plan + { + private: + public: + virtual void execute(bool turn_based, PlanInputData& manipulated_object); + }; + } +} + +#endif + diff --git a/ModularizedTacticalAI/include/NullPlanFactory.h b/ModularizedTacticalAI/include/NullPlanFactory.h new file mode 100644 index 00000000..5c370fec --- /dev/null +++ b/ModularizedTacticalAI/include/NullPlanFactory.h @@ -0,0 +1,46 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ + +#ifndef NULL_PLAN_FACTORY_H_ +#define NULL_PLAN_FACTORY_H_ + +#include "AbstractPlanFactory.h" +#include + +namespace AI +{ + namespace tactical + { + /**@class NullPlanFactory + * @brief Concrete Factory. Generates the NullPlan, making a NPC do absolutely nothing. + * + * The purpose of this factory is two-fold. Firstly, it is a good starting point for new plan factories; to use + * it as such, perform a + + * \c svn copy include/NullPlanFactory.h include/YourPlanFactory.h\n + * \c svn copy src/NullPlanFactory.cpp src/YourPlanFactory.cpp + * + * Remember to + * - Adjust the include guards + * - Adjust the string returned by get_name() + * - Add a line in PlanFactoryLibrary.cpp to create an instance of the new factory in the library's + * constructor; otherwise, it won't be accessible via the configuration file. + * + * And secondly, it is a debugging tool. Change the configuration file to use this AI factory for a certain + * AI_INDEX to have said group do... nothing (e.g. to measure performance differences). + */ + class NullPlanFactory : public AbstractPlanFactory + { + private: + public: + static std::string get_name() {return "NullPlanFactory";} + virtual Plan* create_plan(const AIInputData& input); + virtual void update_plan(const AIInputData& input, Plan* plan_to_change); + }; + } +} + +#endif + diff --git a/ModularizedTacticalAI/include/Plan.h b/ModularizedTacticalAI/include/Plan.h new file mode 100644 index 00000000..34a56528 --- /dev/null +++ b/ModularizedTacticalAI/include/Plan.h @@ -0,0 +1,52 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ + +#ifndef PLAN_H_ +#define PLAN_H_ + +class SOLDIERTYPE; + +namespace AI +{ + namespace tactical + { + /**@class PlanInputData + * @brief Wrapper class around the entity manipulated through plan execution + * + * At the moment, simply a wrapper around SOLDIERTYPE. Future versions might require other datatypes; without + * the wrapper, *every* Plan subclass ever created would need to be changed in this event. With the wrapper, no + * change is required at all. + */ + struct PlanInputData + { + SOLDIERTYPE* controlled_npc_; + }; + /**@class Plan + * @brief Composite/Abstract Product. Base class for all plan compositions and components. + * + * The Plan class provides a common interface for both plan compositions and plan components. + */ + class Plan + { + private: + public: + /** @brief Plan execution is the encapsulation of an action sequence, making up higher-level building blocks + * + * Each plan objects represents a high-level action, implemented by means of lower-level actions. These + * lower level actions can be other Plans subtypes; at some point, a Plan object has no further + * sub-plans, i.e., the objet is no composition, but a component, forming a leaf in the Plan hierarchy. + * The components' lower level actions are formed by the fundamental npc actions made available outside + * the AI framework. + * + * @param turn_based true if turn-based mode is active, false for real-time mode + * @param manipulated_object Encapsulation of around object(s) a plan may manipulate. + */ + virtual void execute(bool turn_based, PlanInputData& manipulated_object) = 0; + }; + } +} + +#endif + diff --git a/ModularizedTacticalAI/include/PlanFactoryLibrary.h b/ModularizedTacticalAI/include/PlanFactoryLibrary.h new file mode 100644 index 00000000..56a07a00 --- /dev/null +++ b/ModularizedTacticalAI/include/PlanFactoryLibrary.h @@ -0,0 +1,42 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ + +#ifndef PLAN_FACTORY_LIBRARY_H_ +#define PLAN_FACTORY_LIBRARY_H_ + +#include +#include +#include + +namespace AI +{ + namespace tactical + { + // forward declarations + class AbstractPlanFactory; + class Plan; + struct AIInputData; + + /**@class PlanFactoryLibrary + * @brief Singleton. A "library" containing all available PlanFactories, accessible via the strings returned by + * their get_name() function. + * + */ + class PlanFactoryLibrary + { + private: + static PlanFactoryLibrary* instance_; + std::map registred_factories_; + std::deque ai_index_to_factory_mapping_; + PlanFactoryLibrary(); + public: + static PlanFactoryLibrary* instance(); + Plan* create_plan(size_t index, AIInputData& input) const; + }; + } +} + +#endif + diff --git a/ModularizedTacticalAI/readme.txt b/ModularizedTacticalAI/readme.txt new file mode 100644 index 00000000..7b155e27 --- /dev/null +++ b/ModularizedTacticalAI/readme.txt @@ -0,0 +1,27 @@ +API Documentation +================= +The API documentation is available in the source code repository under +./Developer_Docs/ModularizedAI/html/index.html + + +Coding style guidelines +======================= +When modifying or adding to the code in ModularizedTacticalAI, plese adhere to +the following rules in order to keep the place tidy. + +- Do indent code blocks by 4 spaces +- Do not use tabs; they are interpreted differently on each platform, messing up the indention +- Do not #include compilation units (cpp files). Doing so will lead to you facing the firing squad. +- Do try to limit the number of include files to what is really needed. If a lot is needed, consider using the Pimpl + idiom. +- Do not use leading underscores or double underscores. They are reserved for compiler implementation. +- Do document your code using Doxygen-style comments, and update the doxygen documentation by running doxygen in the + ModularizedTacticalAI directory. +- Do use identifier names that reflect what you are doing. +- Do use CamelCase for classes, and all_lowercase_characters() for function names and attributes +- Do use one trailing underscore for class_members_ +- Do not event think about adding a global variable, goto, macros (unless absolutely needed) or other BS. +- Do follow the C++ specifications, as in ISO 14882 +- Do, if you feel that these guidelines are an impediment for your work, discuss alternatives at bears-pit.com + + diff --git a/ModularizedTacticalAI/src/LegacyAIPlan.cpp b/ModularizedTacticalAI/src/LegacyAIPlan.cpp new file mode 100644 index 00000000..e35f637e --- /dev/null +++ b/ModularizedTacticalAI/src/LegacyAIPlan.cpp @@ -0,0 +1,28 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ + +#include "../include/LegacyAIPlan.h" + +#include "../../TacticalAI/ai.h" // for EndAIGuysTurn + + +// Forward declarations for the two legacy functions called here +void RTHandleAI( SOLDIERTYPE * pSoldier ); // defined in TacticalAI/Realtime.cpp +void TurnBasedHandleNPCAI(SOLDIERTYPE *pSoldier); // defined in TacticalAI/AIMain.cpp + +namespace AI +{ + namespace tactical + { + void LegacyAIPlan::execute(bool turn_based, PlanInputData& manipulated_object) + { + if(turn_based) + TurnBasedHandleNPCAI(manipulated_object.controlled_npc_); + else + RTHandleAI(manipulated_object.controlled_npc_); + } + } +} + diff --git a/ModularizedTacticalAI/src/LegacyAIPlanFactory.cpp b/ModularizedTacticalAI/src/LegacyAIPlanFactory.cpp new file mode 100644 index 00000000..912120c1 --- /dev/null +++ b/ModularizedTacticalAI/src/LegacyAIPlanFactory.cpp @@ -0,0 +1,25 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ +#include "../include/LegacyAIPlanFactory.h" +#include "../include/LegacyAIPlan.h" + +namespace AI +{ + namespace tactical + { + Plan* LegacyAIPlanFactory::create_plan(const AIInputData& input) + { + return new LegacyAIPlan(); + } + + void LegacyAIPlanFactory::update_plan(const AIInputData& input, Plan* plan_to_change) + { + // TODO: currently, everything is handled in the LegacyAIPlan. The goal is to modularize the AI, so that in + // the end, the LegacyAIPlan is split into so many "new" AI Plan subclasses, that every case is covered. + // Then the behavior of the old AI would be implemented here. + } + } +} + diff --git a/ModularizedTacticalAI/src/NullPlan.cpp b/ModularizedTacticalAI/src/NullPlan.cpp new file mode 100644 index 00000000..7da836a0 --- /dev/null +++ b/ModularizedTacticalAI/src/NullPlan.cpp @@ -0,0 +1,21 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ + +#include "../include/NullPlan.h" + +#include "../../TacticalAI/ai.h" // for EndAIGuysTurn + +namespace AI +{ + namespace tactical + { + /// Simply end the turn for the npc passed in the manipulated_object wrapper, then return. + void NullPlan::execute(bool turn_based, PlanInputData& manipulated_object) + { + EndAIGuysTurn(manipulated_object.controlled_npc_); + } + } +} + diff --git a/ModularizedTacticalAI/src/NullPlanFactory.cpp b/ModularizedTacticalAI/src/NullPlanFactory.cpp new file mode 100644 index 00000000..d9f58437 --- /dev/null +++ b/ModularizedTacticalAI/src/NullPlanFactory.cpp @@ -0,0 +1,25 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ + +#include "../include/NullPlanFactory.h" +#include "../include/NullPlan.h" +#include "../Tactical/Soldier Control.h" + +namespace AI +{ + namespace tactical + { + Plan* NullPlanFactory::create_plan(const AIInputData& input) + { + return new NullPlan(); + } + + void NullPlanFactory::update_plan(const AIInputData& input, Plan* plan_to_change) + { + // the idea is to do nothing, so let's do it... + } + } +} + diff --git a/ModularizedTacticalAI/src/PlanFactoryLibrary.cpp b/ModularizedTacticalAI/src/PlanFactoryLibrary.cpp new file mode 100644 index 00000000..f0821132 --- /dev/null +++ b/ModularizedTacticalAI/src/PlanFactoryLibrary.cpp @@ -0,0 +1,84 @@ +/** + * @file + * @author feynman (bears-pit.com) + */ + +#include "../include/PlanFactoryLibrary.h" +#include "../include/NullPlanFactory.h" +#include "../include/LegacyAIPlanFactory.h" +// XXX Add includes for new factories here XXX + + +#include "../../Utils/INIReader.h" + +#undef max // Who the fuck writes MACROS not using CAPITAL LETTERS??? You, sir, have lost your coding license. Please hand over your compiler and leave. Now. + +#include +#include +#include +#include + +namespace AI +{ + namespace tactical + { + PlanFactoryLibrary* PlanFactoryLibrary::instance_ = 0; + + /*@brief Initialize all PlanFactories and map them to the slots defined by the configuration file + * + * This is the place where new factories need to be "registred" in order for them to be available using the + * settings in AI.ini + */ + PlanFactoryLibrary::PlanFactoryLibrary() + { + + // ================================================================================ + // XXX vv Add new factory registrations here vv XXX + + registred_factories_[NullPlanFactory::get_name()] = new NullPlanFactory(); + registred_factories_[LegacyAIPlanFactory::get_name()] = new LegacyAIPlanFactory(); + + // XXX ^^ Add new factory registrations here ^^ XXX + // ================================================================================ + + CIniReader ini_reader("AI.ini", true); + size_t num_slots = ini_reader.ReadInteger("Modularized Tactical AI", "NumFactories", 0, 0, std::numeric_limits::max()); + for(size_t i(0); i(slot_index.str().c_str()), "LegacyAIFactory"); + ai_index_to_factory_mapping_.push_back(registred_factories_[factory_name]); + if(!ai_index_to_factory_mapping_.back()->initialize_called()) + ai_index_to_factory_mapping_.back()->initialize(); + } + } + + /** @brief If no instance exists yet, create it. Return a pointer to the only existing instance of this library. + * @return Pointer to the only instance of the PlanFactoryLibrary + */ + PlanFactoryLibrary* PlanFactoryLibrary::instance() + { + if(instance_ == 0) + instance_ = new PlanFactoryLibrary(); + return instance_; + } + + /**@brief Create a plan for the given input using the factory at the given index + * @param index Index of the concrete plan factory to use, set in the constructor via ini settings + * @param input The environmental data required for a factory to plan + * @throws std::out_of_range for invalid index + * @throws std::logic_error for valid index, but undefined factory (most likely due to typo in AI.ini) + * @return Pointer to the only instance of the PlanFactoryLibrary + */ + Plan* PlanFactoryLibrary::create_plan(size_t index, AIInputData& input) const + { + if(index >= ai_index_to_factory_mapping_.size()) + throw std::out_of_range("PlanFactoryLibrary detected invalid factory index"); + if(!ai_index_to_factory_mapping_[index]) + throw std::logic_error("PlanFactoryLibrary encountered a nullptr for a valid index (typo in AI.ini?)"); + return ai_index_to_factory_mapping_[index]->create_plan(input); + } + } +} + diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 4bf375ae..cd75effa 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -2029,6 +2029,7 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile) numBytesRead = ReadFieldByField(hFile, &this->bOverTurnAPS, sizeof(bOverTurnAPS), sizeof(INT16), numBytesRead); numBytesRead = ReadFieldByField(hFile, &this->sMTActionGridNo, sizeof(sMTActionGridNo), sizeof(INT32), numBytesRead); numBytesRead = ReadFieldByField(hFile, &this->usMultiTurnAction, sizeof(usMultiTurnAction), sizeof(UINT8), numBytesRead); + numBytesRead = ReadFieldByField(hFile, &this->bAIIndex, sizeof(bAIIndex), sizeof(UINT16), numBytesRead); numBytesRead = ReadFieldByField(hFile, &this->ubFiller, sizeof(ubFiller), sizeof(UINT8), numBytesRead); } @@ -2037,6 +2038,7 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile) this->bOverTurnAPS = 0; this->sMTActionGridNo = NOWHERE; this->usMultiTurnAction = 0; + this->bAIIndex = 0; // as we added new variables, fillersize was reduced, here we account for that. We have to also read the existing fillers that now do not exist anymore const UINT8 tmp = sizeof(bOverTurnAPS) + sizeof(this->sMTActionGridNo) + sizeof(usMultiTurnAction); diff --git a/SCREENS.cpp b/Screens.cpp similarity index 97% rename from SCREENS.cpp rename to Screens.cpp index ebfe0053..68f58fa2 100644 --- a/SCREENS.cpp +++ b/Screens.cpp @@ -73,4 +73,4 @@ Screens GameScreens[MAX_SCREENS] = #endif { QuestDebugScreenInit, QuestDebugScreenHandle, QuestDebugScreenShutdown } -}; \ No newline at end of file +}; diff --git a/SCREENS.H b/Screens.h similarity index 100% rename from SCREENS.H rename to Screens.h diff --git a/Strategic/XML_CoolnessBySector.cpp b/Strategic/XML_CoolnessBySector.cpp index 6ac239f4..a51acb8c 100644 --- a/Strategic/XML_CoolnessBySector.cpp +++ b/Strategic/XML_CoolnessBySector.cpp @@ -12,8 +12,6 @@ #include "MemMan.h" #include "Debug Control.h" #include "mapscreen.h" - - #include "Soldier Create.cpp" #endif #define MAX_CHAR_DATA_LENGTH 500 diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 9f5619d1..758dcb80 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -53,7 +53,7 @@ #include "Soldier macros.h" #include "EditorMercs.h" #include "soldier tile.h" -#ifdef NETWORKED +#ifdef NETWORKED #include "Networking.h" #include "NetworkEvent.h" #endif @@ -128,13 +128,13 @@ #endif // OJW - 20090419 -UINT8 giMAXIMUM_NUMBER_OF_PLAYER_MERCS = CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS; -UINT8 giMAXIMUM_NUMBER_OF_PLAYER_VEHICLES = CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES; -UINT8 giMAXIMUM_NUMBER_OF_PLAYER_SLOTS = CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS; -UINT8 giMAXIMUM_NUMBER_OF_ENEMIES = CODE_MAXIMUM_NUMBER_OF_ENEMIES; -UINT8 giMAXIMUM_NUMBER_OF_CREATURES = CODE_MAXIMUM_NUMBER_OF_CREATURES; -UINT8 giMAXIMUM_NUMBER_OF_REBELS = CODE_MAXIMUM_NUMBER_OF_REBELS; -UINT8 giMAXIMUM_NUMBER_OF_CIVS = CODE_MAXIMUM_NUMBER_OF_CIVS; +UINT8 giMAXIMUM_NUMBER_OF_PLAYER_MERCS = CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS; +UINT8 giMAXIMUM_NUMBER_OF_PLAYER_VEHICLES = CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES; +UINT8 giMAXIMUM_NUMBER_OF_PLAYER_SLOTS = CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS; +UINT8 giMAXIMUM_NUMBER_OF_ENEMIES = CODE_MAXIMUM_NUMBER_OF_ENEMIES; +UINT8 giMAXIMUM_NUMBER_OF_CREATURES = CODE_MAXIMUM_NUMBER_OF_CREATURES; +UINT8 giMAXIMUM_NUMBER_OF_REBELS = CODE_MAXIMUM_NUMBER_OF_REBELS; +UINT8 giMAXIMUM_NUMBER_OF_CIVS = CODE_MAXIMUM_NUMBER_OF_CIVS; //forward declarations of common classes to eliminate includes @@ -143,7 +143,7 @@ class SOLDIERTYPE; extern void HandleBestSightingPositionInRealtime(); -extern UINT8 gubAICounter; +extern UINT8 gubAICounter; #include "fresh_header.h" #define RT_DELAY_BETWEEN_AI_HANDLING 50 @@ -157,27 +157,24 @@ UINT32 guiAIAwaySlotToHandle = RESET_HANDLE_OF_OFF_MAP_MERCS; #define PAUSE_ALL_AI_DELAY 1500 -BOOLEAN gfPauseAllAI = FALSE; -INT32 giPauseAllAITimer = 0; +BOOLEAN gfPauseAllAI = FALSE; +INT32 giPauseAllAITimer = 0; BOOLEAN sniperwarning; BOOLEAN biggunwarning; BOOLEAN gogglewarning; //BOOLEAN airstrikeavailable; -TacticalStatusType gTacticalStatus; +TacticalStatusType gTacticalStatus; extern void RecalculateOppCntsDueToNoLongerNeutral( SOLDIERTYPE * pSoldier ); extern void SetSoldierAniSpeed( SOLDIERTYPE *pSoldier ); -extern void HandleExplosionQueue( void ); +extern void HandleExplosionQueue( ); extern void UpdateForContOverPortrait( SOLDIERTYPE *pSoldier, BOOLEAN fOn ); extern void HandleSystemNewAISituation( SOLDIERTYPE *pSoldier, BOOLEAN fResetABC ); -//DBrot: More Rooms -//extern BOOLEAN NPCInRoom( UINT8 ubProfileID, UINT8 ubRoomID ); extern BOOLEAN NPCInRoom( UINT8 ubProfileID, UINT16 usRoomID ); -extern INT8 gbInvalidPlacementSlot[ NUM_INV_SLOTS ]; - +extern INT8 gbInvalidPlacementSlot[ NUM_INV_SLOTS ]; void ResetAllMercSpeeds( ); void HandleBloodForNewGridNo( SOLDIERTYPE *pSoldier ); @@ -188,2987 +185,2791 @@ void HandleCreatureTenseQuote( ); void RemoveSoldierFromTacticalSector( SOLDIERTYPE *pSoldier, BOOLEAN fAdjustSelected ); void HandleEndDemoInCreatureLevel( ); -void DeathTimerCallback( void ); -void CaptureTimerCallback( void ); +void DeathTimerCallback( ); +void CaptureTimerCallback( ); // HEADROCK HAM 3.6: Define now. -void MilitiaChangesSides( void ); +void MilitiaChangesSides( ); extern void CheckForAlertWhenEnemyDies( SOLDIERTYPE * pDyingSoldier ); extern void PlaySoldierFootstepSound( SOLDIERTYPE *pSoldier ); extern void HandleKilledQuote( SOLDIERTYPE *pKilledSoldier, SOLDIERTYPE *pKillerSoldier, INT32 sGridNo, INT8 bLevel ); extern UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady, BOOLEAN fHipStance ); - - extern void PlayStealthySoldierFootstepSound( SOLDIERTYPE *pSoldier ); #ifdef JA2UB BOOLEAN CanMsgBoxForPlayerToBeNotifiedOfSomeoneElseInSector(); - extern void PlayStealthySoldierFootstepSound( SOLDIERTYPE *pSoldier ); -//extern BOOLEAN gfFirstTimeInGameHeliCrash; //JA25 UB #endif extern BOOLEAN gfSurrendered; // GLOBALS -#define START_DEMO_SCENE 3 -#define NUM_RANDOM_SCENES 4 +#define START_DEMO_SCENE 3 +#define NUM_RANDOM_SCENES 4 CHAR8 gDebugStr[128]; #ifdef NETWORKED -extern BYTE gfAmIHost; -extern BOOLEAN gfAmINetworked; +extern BYTE gfAmIHost; +extern BOOLEAN gfAmINetworked; #endif -#define NEW_FADE_DELAY 60 +#define NEW_FADE_DELAY 60 // ATE: GLOBALS FOR E3 -UINT8 gubCurrentScene = 0; -CHAR8 gzLevelFilenames[ ][ 50 ] = +UINT8 gubCurrentScene = 0; +CHAR8 gzLevelFilenames[ ][ 50 ] = { - "A9.dat", - "ScotTBMines.dat", - "LindaTBCaves.dat", - "LindaRTDesert.dat", - "IanRTNight.dat", - "LindaRTCave1.dat", - "LindaRTCave2.dat" + "A9.dat", + "ScotTBMines.dat", + "LindaTBCaves.dat", + "LindaRTDesert.dat", + "IanRTNight.dat", + "LindaRTCave1.dat", + "LindaRTCave2.dat" }; -INT8 ubLevelMoveLink[ 10 ] = +INT8 ubLevelMoveLink[ 10 ] = { - 1, - 2, - 3, - 4, - 0, - 0, - 0, - 0, - 0, - 0 + 1, + 2, + 3, + 4, + 0, + 0, + 0, + 0, + 0, + 0 }; // Soldier List used for all soldier overhead interaction -SOLDIERTYPE Menptr[ TOTAL_SOLDIERS ]; -SOLDIERTYPE *MercPtrs[ TOTAL_SOLDIERS ]; +SOLDIERTYPE Menptr[ TOTAL_SOLDIERS ]; +SOLDIERTYPE* MercPtrs[ TOTAL_SOLDIERS ]; -SOLDIERTYPE *MercSlots[ TOTAL_SOLDIERS ]; -UINT32 guiNumMercSlots = 0; +SOLDIERTYPE* MercSlots[ TOTAL_SOLDIERS ]; +UINT32 guiNumMercSlots = 0; -SOLDIERTYPE *AwaySlots[ TOTAL_SOLDIERS ]; -UINT32 guiNumAwaySlots = 0; +SOLDIERTYPE* AwaySlots[ TOTAL_SOLDIERS ]; +UINT32 guiNumAwaySlots = 0; // DEF: changed to have client wait for gPlayerNum assigned from host -UINT8 gbPlayerNum = 0; +UINT8 gbPlayerNum = 0; // Global for current selected soldier -UINT16 gusSelectedSoldier = NOBODY; -INT8 gbShowEnemies = FALSE; +UINT16 gusSelectedSoldier = NOBODY; +INT8 gbShowEnemies = FALSE; +BOOLEAN gfMovingAnimation = FALSE; -BOOLEAN gfMovingAnimation = FALSE; - -CHAR8 gzAlertStr[][ 30 ] = +CHAR8 gzAlertStr[][ 30 ] = { - "GREEN", - "YELLOW", - "RED", - "BLACK" + "GREEN", + "YELLOW", + "RED", + "BLACK" }; -CHAR8 gzActionStr[][ 30 ] = +CHAR8 gzActionStr[][ 30 ] = { - "NONE", - - "RANDOM PATROL", - "SEEK FRIEND", - "SEEK OPPONENT", - "TAKE COVER", - "GET CLOSER", - - "POINT PATROL", - "LEAVE WATER GAS", - "SEEK NOISE", - "ESCORTED MOVE", - "RUN AWAY", - - "KNIFE MOVE", - "APPROACH MERC", - "TRACK", - "EAT", - "PICK UP ITEM", - - "SCHEDULE MOVE", - "WALK", - "RUN", - "WITHDRAW", - "FLANK LEFT", - "FLANK RIGHT", - "MOVE TO CLIMB", - "CHG FACING", - - "CHG STANCE", - "YELLOW ALERT", - "RED ALERT", - "CREATURE CALL", - "PULL TRIGGER", - - "USE DETONATOR", - "FIRE GUN", - "TOSS PROJECTILE", - "KNIFE STAB", - "THROW KNIFE", - - "GIVE AID", - "WAIT", - "PENDING ACTION", - "DROP ITEM", - "COWER", - - "STOP COWERING", - "OPEN/CLOSE DOOR", - "UNLOCK DOOR", - "LOCK DOOR", - "LOWER GUN", - - "ABSOLUTELY NONE", - "CLIMB ROOF", - "END TURN", - "EC&M", - "TRAVERSE DOWN", - "OFFER SURRENDER", - "RAISE GUN", + "NONE", + "RANDOM PATROL", + "SEEK FRIEND", + "SEEK OPPONENT", + "TAKE COVER", + "GET CLOSER", + "POINT PATROL", + "LEAVE WATER GAS", + "SEEK NOISE", + "ESCORTED MOVE", + "RUN AWAY", + "KNIFE MOVE", + "APPROACH MERC", + "TRACK", + "EAT", + "PICK UP ITEM", + "SCHEDULE MOVE", + "WALK", + "RUN", + "WITHDRAW", + "FLANK LEFT", + "FLANK RIGHT", + "MOVE TO CLIMB", + "CHG FACING", + "CHG STANCE", + "YELLOW ALERT", + "RED ALERT", + "CREATURE CALL", + "PULL TRIGGER", + "USE DETONATOR", + "FIRE GUN", + "TOSS PROJECTILE", + "KNIFE STAB", + "THROW KNIFE", + "GIVE AID", + "WAIT", + "PENDING ACTION", + "DROP ITEM", + "COWER", + "STOP COWERING", + "OPEN/CLOSE DOOR", + "UNLOCK DOOR", + "LOCK DOOR", + "LOWER GUN", + "ABSOLUTELY NONE", + "CLIMB ROOF", + "END TURN", + "EC&M", + "TRAVERSE DOWN", + "OFFER SURRENDER", + "RAISE GUN", }; -CHAR8 gzDirectionStr[][ 30 ] = +CHAR8 gzDirectionStr[][ 30 ] = { - "NORTHEAST", - "EAST", - "SOUTHEAST", - "SOUTH", - "SOUTHWEST", - "WEST", - "NORTHWEST", - "NORTH" + "NORTHEAST", + "EAST", + "SOUTHEAST", + "SOUTH", + "SOUTHWEST", + "WEST", + "NORTHWEST", + "NORTH" }; // TEMP VALUES FOR TEAM DEFAULT POSITIONS UINT8 bDefaultTeamRangesMP[ MAXTEAMS ][ 2 ] = { - 0, 19, //20 US - 20, 51, //32 ENEMY - 52, 52, //kulled off to make room ;) //32 CREATURE - 53, 84, //32 REBELS ( OUR GUYS ) - 85, 116, //32 CIVILIANS - 117, 119, // PLANNING SOLDIERS (reduced) - 120, 126, //1 //new sides //hayden // 7 each - 127, 133, //2 - 134, 140, //3 - 141, MAX_NUM_SOLDIERS - 1, //4 - MAX_NUM_SOLDIERS, TOTAL_SOLDIERS - 1 // PLANNING SOLDIERS + 0, 19, //20 US + 20, 51, //32 ENEMY + 52, 52, //kulled off to make room ;) //32 CREATURE + 53, 84, //32 REBELS ( OUR GUYS ) + 85, 116, //32 CIVILIANS + 117, 119, // PLANNING SOLDIERS (reduced) + 120, 126, //1 //new sides //hayden // 7 each + 127, 133, //2 + 134, 140, //3 + 141, MAX_NUM_SOLDIERS - 1, //4 + MAX_NUM_SOLDIERS, TOTAL_SOLDIERS - 1 // PLANNING SOLDIERS }; UINT8 bDefaultTeamRanges[ MAXTEAMS_SP ][ 2 ] = { - 0, - CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES-1, - CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES, - CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES-1, - CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES, - CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES+CODE_MAXIMUM_NUMBER_OF_CREATURES-1, - CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES+CODE_MAXIMUM_NUMBER_OF_CREATURES, - CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES+CODE_MAXIMUM_NUMBER_OF_CREATURES+CODE_MAXIMUM_NUMBER_OF_REBELS-1, - CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES+CODE_MAXIMUM_NUMBER_OF_CREATURES+CODE_MAXIMUM_NUMBER_OF_REBELS, - MAX_NUM_SOLDIERS -1, - MAX_NUM_SOLDIERS, - TOTAL_SOLDIERS - 1 // PLANNING SOLDIERS + 0, + CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES-1, + CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES, + CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES-1, + CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES, + CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES+CODE_MAXIMUM_NUMBER_OF_CREATURES-1, + CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES+CODE_MAXIMUM_NUMBER_OF_CREATURES, + CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES+CODE_MAXIMUM_NUMBER_OF_CREATURES+CODE_MAXIMUM_NUMBER_OF_REBELS-1, + CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS+CODE_MAXIMUM_NUMBER_OF_PLAYER_VEHICLES+CODE_MAXIMUM_NUMBER_OF_ENEMIES+CODE_MAXIMUM_NUMBER_OF_CREATURES+CODE_MAXIMUM_NUMBER_OF_REBELS, + MAX_NUM_SOLDIERS -1, + MAX_NUM_SOLDIERS, + TOTAL_SOLDIERS - 1 // PLANNING SOLDIERS }; COLORVAL bDefaultTeamColors[ MAXTEAMS ] = { - FROMRGB( 255, 255, 0 ), - FROMRGB( 255, 0, 0 ), - FROMRGB( 255, 0, 255 ), - FROMRGB( 0, 255, 0 ), - FROMRGB( 255, 255, 255 ), - FROMRGB( 0, 0, 255 ), - FROMRGB( 255, 120, 0 ), //hayden //team 1 (radar colours) // orange - FROMRGB( 62, 140, 240 ), //2 // light blue - FROMRGB( 180, 50, 255 ), //3 // violett - FROMRGB( 0, 180, 20 ) //4 // green + FROMRGB( 255, 255, 0 ), + FROMRGB( 255, 0, 0 ), + FROMRGB( 255, 0, 255 ), + FROMRGB( 0, 255, 0 ), + FROMRGB( 255, 255, 255 ), + FROMRGB( 0, 0, 255 ), + FROMRGB( 255, 120, 0 ), //hayden //team 1 (radar colours) // orange + FROMRGB( 62, 140, 240 ), //2 // light blue + FROMRGB( 180, 50, 255 ), //3 // violett + FROMRGB( 0, 180, 20 ) //4 // green }; - // UTILITY FUNCTIONS -INT8 NumActiveAndConsciousTeamMembers( UINT8 ubTeam ); -UINT8 NumEnemyInSector( ); -UINT8 NumEnemyInSectorExceptCreatures(); -UINT8 NumCapableEnemyInSector( ); +INT8 NumActiveAndConsciousTeamMembers( UINT8 ubTeam ); +UINT8 NumEnemyInSector( ); +UINT8 NumEnemyInSectorExceptCreatures(); +UINT8 NumCapableEnemyInSector( ); BOOLEAN KillIncompacitatedEnemyInSector( ); BOOLEAN CheckForLosingEndOfBattle( ); -void EndBattleWithUnconsciousGuysCallback( UINT8 bExitValue ); -UINT8 NumEnemyInSectorNotDeadOrDying( ); -UINT8 NumBloodcatsInSectorNotDeadOrDying( ); +void EndBattleWithUnconsciousGuysCallback( UINT8 bExitValue ); +UINT8 NumEnemyInSectorNotDeadOrDying( ); +UINT8 NumBloodcatsInSectorNotDeadOrDying( ); +UINT8 gubWaitingForAllMercsToExitCode = 0; +INT8 gbNumMercsUntilWaitingOver = 0; +UINT32 guiWaitingForAllMercsToExitData[3]; +UINT32 guiWaitingForAllMercsToExitTimer = 0; +BOOLEAN gfKillingGuysForLosingBattle = FALSE; -UINT8 gubWaitingForAllMercsToExitCode = 0; -INT8 gbNumMercsUntilWaitingOver = 0; -UINT32 guiWaitingForAllMercsToExitData[3]; -UINT32 guiWaitingForAllMercsToExitTimer = 0; -BOOLEAN gfKillingGuysForLosingBattle = FALSE; - -INT32 GetFreeMercSlot(void) +INT32 GetFreeMercSlot() { - UINT32 uiCount; - - for(uiCount=0; uiCount < guiNumMercSlots; uiCount++) - { - if(( MercSlots[uiCount] == NULL ) ) - return((INT32)uiCount); - } - - if(guiNumMercSlots < TOTAL_SOLDIERS ) - return((INT32)guiNumMercSlots++); - - return(-1); + UINT32 uiCount; + for(uiCount=0; uiCount < guiNumMercSlots; uiCount++) + { + if(( MercSlots[uiCount] == NULL ) ) + return((INT32)uiCount); + } + if(guiNumMercSlots < TOTAL_SOLDIERS ) + return((INT32)guiNumMercSlots++); + return(-1); } - -void RecountMercSlots(void) +// WTF? +void RecountMercSlots( ) { - INT32 iCount; - - if ( guiNumMercSlots > 0 ) - { - // set equal to 0 as a default - for (iCount = guiNumMercSlots - 1; (iCount >=0) ; iCount--) - { - if ( ( MercSlots[iCount] != NULL ) ) - { - guiNumMercSlots=(UINT32)(iCount+1); - return; - } - } - // no mercs found - guiNumMercSlots = 0; - } + INT32 iCount; + if ( guiNumMercSlots > 0 ) + { + for (iCount = guiNumMercSlots - 1; iCount >=0 ; iCount--) + { + if ( ( MercSlots[iCount] != NULL ) ) + { + guiNumMercSlots=(UINT32)(iCount+1); + return; + } + } + // no mercs found + guiNumMercSlots = 0; + } } - -INT32 AddMercSlot( SOLDIERTYPE *pSoldier ) +INT32 AddMercSlot( SOLDIERTYPE *pSoldier ) { - INT32 iMercIndex; + INT32 iMercIndex; - if( ( iMercIndex = GetFreeMercSlot() )==(-1) ) - return(-1); - - MercSlots[ iMercIndex ] = pSoldier; - - return( iMercIndex ); + if( ( iMercIndex = GetFreeMercSlot() )==(-1) ) + return(-1); + MercSlots[ iMercIndex ] = pSoldier; + return( iMercIndex ); } - BOOLEAN RemoveMercSlot( SOLDIERTYPE *pSoldier ) { - UINT32 uiCount; - - CHECKF( pSoldier != NULL ); - - for( uiCount=0; uiCount < guiNumMercSlots; uiCount++) - { - if ( MercSlots[ uiCount ] == pSoldier ) - { - MercSlots[ uiCount ] = NULL; - RecountMercSlots( ); - return( TRUE ); - } - } - - // TOLD TO DELETE NON-EXISTANT SOLDIER - return( FALSE ); + UINT32 uiCount; + CHECKF( pSoldier != NULL ); + for( uiCount=0; uiCount < guiNumMercSlots; uiCount++) + { + if ( MercSlots[ uiCount ] == pSoldier ) + { + MercSlots[ uiCount ] = NULL; + RecountMercSlots( ); + return( TRUE ); + } + } + // TOLD TO DELETE NON-EXISTANT SOLDIER + return( FALSE ); } -INT32 GetFreeAwaySlot(void) +INT32 GetFreeAwaySlot( ) { - UINT32 uiCount; - - for(uiCount=0; uiCount < guiNumAwaySlots; uiCount++) - { - if(( AwaySlots[uiCount] == NULL ) ) - return((INT32)uiCount); - } - - if(guiNumAwaySlots < TOTAL_SOLDIERS ) - return((INT32)guiNumAwaySlots++); - - return(-1); + UINT32 uiCount; + for(uiCount=0; uiCount < guiNumAwaySlots; uiCount++) + { + if(( AwaySlots[uiCount] == NULL ) ) + return((INT32)uiCount); + } + if(guiNumAwaySlots < TOTAL_SOLDIERS ) + return((INT32)guiNumAwaySlots++); + return(-1); } - -void RecountAwaySlots(void) +void RecountAwaySlots( ) { - INT32 iCount; - - if ( guiNumAwaySlots > 0 ) - { - for (iCount = guiNumAwaySlots - 1; (iCount >=0) ; iCount--) - { - if ( ( AwaySlots[iCount] != NULL ) ) - { - guiNumAwaySlots = (UINT32)(iCount + 1); - return; - } - } - // no mercs found - guiNumAwaySlots = 0; - } + INT32 iCount; + if ( guiNumAwaySlots > 0 ) + { + for (iCount = guiNumAwaySlots - 1; (iCount >=0) ; iCount--) + { + if ( ( AwaySlots[iCount] != NULL ) ) + { + guiNumAwaySlots = (UINT32)(iCount + 1); + return; + } + } + // no mercs found + guiNumAwaySlots = 0; + } } - -INT32 AddAwaySlot( SOLDIERTYPE *pSoldier ) +INT32 AddAwaySlot( SOLDIERTYPE *pSoldier ) { - INT32 iAwayIndex; - - if( ( iAwayIndex = GetFreeAwaySlot() )==(-1) ) - return(-1); - - AwaySlots[ iAwayIndex ] = pSoldier; - - return( iAwayIndex ); + INT32 iAwayIndex; + if( ( iAwayIndex = GetFreeAwaySlot() )==(-1) ) + return(-1); + AwaySlots[ iAwayIndex ] = pSoldier; + return( iAwayIndex ); } - BOOLEAN RemoveAwaySlot( SOLDIERTYPE *pSoldier ) { - UINT32 uiCount; - - CHECKF( pSoldier != NULL ); - - for( uiCount=0; uiCount < guiNumAwaySlots; uiCount++) - { - if ( AwaySlots[ uiCount ] == pSoldier ) - { - AwaySlots[ uiCount ] = NULL; - RecountAwaySlots( ); - return( TRUE ); - } - } - - // TOLD TO DELETE NON-EXISTANT SOLDIER - return( FALSE ); + UINT32 uiCount; + CHECKF( pSoldier != NULL ); + for( uiCount=0; uiCount < guiNumAwaySlots; uiCount++) + { + if ( AwaySlots[ uiCount ] == pSoldier ) + { + AwaySlots[ uiCount ] = NULL; + RecountAwaySlots( ); + return( TRUE ); + } + } + // TOLD TO DELETE NON-EXISTANT SOLDIER + return( FALSE ); } INT32 MoveSoldierFromMercToAwaySlot( SOLDIERTYPE * pSoldier ) { - BOOLEAN fRet; + BOOLEAN fRet; - fRet = RemoveMercSlot( pSoldier ); - if (!fRet) - { - return( -1 ); - } + fRet = RemoveMercSlot( pSoldier ); + if (!fRet) + { + return( -1 ); + } - if ( !(pSoldier->flags.uiStatusFlags & SOLDIER_OFF_MAP) ) - { - RemoveManFromTeam( pSoldier->bTeam ); - } + if ( !(pSoldier->flags.uiStatusFlags & SOLDIER_OFF_MAP) ) + { + RemoveManFromTeam( pSoldier->bTeam ); + } - pSoldier->bInSector = FALSE; - pSoldier->flags.uiStatusFlags |= SOLDIER_OFF_MAP; - return( AddAwaySlot( pSoldier ) ); + pSoldier->bInSector = FALSE; + pSoldier->flags.uiStatusFlags |= SOLDIER_OFF_MAP; + return( AddAwaySlot( pSoldier ) ); } - INT32 MoveSoldierFromAwayToMercSlot( SOLDIERTYPE * pSoldier ) { - BOOLEAN fRet; + BOOLEAN fRet; - fRet = RemoveAwaySlot( pSoldier ); - if (!fRet) - { - return( -1 ); - } + fRet = RemoveAwaySlot( pSoldier ); + if (!fRet) + { + return( -1 ); + } - AddManToTeam( pSoldier->bTeam ); + AddManToTeam( pSoldier->bTeam ); - pSoldier->bInSector = TRUE; - pSoldier->flags.uiStatusFlags &= (~SOLDIER_OFF_MAP); - return( AddMercSlot( pSoldier ) ); + pSoldier->bInSector = TRUE; + pSoldier->flags.uiStatusFlags &= (~SOLDIER_OFF_MAP); + return( AddMercSlot( pSoldier ) ); } - - - BOOLEAN InitTacticalEngine( ) { - // Init renderer - InitRenderParams( 0 ); - - // Init dirty queue system - InitializeBaseDirtyRectQueue( ); - - // Init Interface stuff - InitializeTacticalInterface( ); - - // Init system objects - InitializeGameVideoObjects( ); - - // Init palette system - LoadPaletteData( ); - - if( !LoadLockTable() ) - return(FALSE); - - InitInteractiveTileManagement( ); - - // init path code - if (!InitPathAI()) - { - return( FALSE ); - } - - // init AI - if (!InitAI()) - { - return( FALSE ); - } - - // Init Overhead - if ( !InitOverhead( ) ) - { - return( FALSE ); - } + InitRenderParams( 0 ); // Init renderer + InitializeBaseDirtyRectQueue( ); // Init dirty queue system + InitializeTacticalInterface( ); // Init Interface stuff + InitializeGameVideoObjects( ); // Init system objects + LoadPaletteData( ); // Init palette system + if( !LoadLockTable() ) + return(FALSE); + InitInteractiveTileManagement( ); + if (!InitPathAI()) // init path code + return( FALSE ); + if (!InitAI()) // init AI + return( FALSE ); + if ( !InitOverhead( ) ) // Init Overhead + return( FALSE ); #ifdef NETWORKED - if ( !gfAmINetworked ) - gfAmIHost = TRUE; + if ( !gfAmINetworked ) + gfAmIHost = TRUE; #endif - - return( TRUE ); + return( TRUE ); } void ShutdownTacticalEngine( ) { - DeletePaletteData( ); - - ShutdownStaticExternalNPCFaces( ); - - ShutDownPathAI(); - ShutdownInteractiveTileManagement( ); - UnLoadCarPortraits( ); - - ShutdownNPCQuotes(); - + DeletePaletteData( ); + ShutdownStaticExternalNPCFaces( ); + ShutDownPathAI(); + ShutdownInteractiveTileManagement( ); + UnLoadCarPortraits( ); + ShutdownNPCQuotes(); } BOOLEAN InitOverhead( ) { - UINT32 cnt; - UINT8 cnt2; + UINT32 cnt; + UINT8 cnt2; - //memset( MercSlots, 0, sizeof( MercSlots ) ); - //memset( AwaySlots, 0, sizeof( AwaySlots ) ); + // Set pointers list + for( cnt = 0; cnt < TOTAL_SOLDIERS; cnt++ ) + { + MercPtrs[ cnt ] = &Menptr[ cnt ]; + MercPtrs[ cnt ]->bActive = FALSE; + } + memset( &gTacticalStatus, 0, sizeof( TacticalStatusType ) ); + UINT8 maxteams; + if (!is_networked) + maxteams = MAXTEAMS_SP; + else + maxteams = MAXTEAMS; - // Set pointers list - for( cnt = 0; cnt < TOTAL_SOLDIERS; cnt++ ) - { - MercPtrs[ cnt ] = &Menptr[ cnt ]; - MercPtrs[ cnt ]->bActive = FALSE; - } + // Set team values + for( cnt = 0; cnt < maxteams; cnt++ ) + { + // For now, set hard-coded values + if (!is_networked) + { + gTacticalStatus.Team[ cnt ].bFirstID = bDefaultTeamRanges[ cnt ][0]; + gTacticalStatus.Team[ cnt ].bLastID = bDefaultTeamRanges[ cnt ][1]; + } + else + { + gTacticalStatus.Team[ cnt ].bFirstID = bDefaultTeamRangesMP[ cnt ][0]; + gTacticalStatus.Team[ cnt ].bLastID = bDefaultTeamRangesMP[ cnt ][1]; + } + // WDS - make number of mercenaries, etc. be configurable + unsigned max = 0; + switch (cnt) + { + case OUR_TEAM: + max = gGameExternalOptions.ubGameMaximumNumberOfPlayerMercs + gGameExternalOptions.ubGameMaximumNumberOfPlayerVehicles; + break; + case ENEMY_TEAM: + max = gGameExternalOptions.ubGameMaximumNumberOfEnemies; + break; + case CREATURE_TEAM: + max = gGameExternalOptions.ubGameMaximumNumberOfCreatures; + break; + case MILITIA_TEAM: + max = gGameExternalOptions.ubGameMaximumNumberOfRebels; + break; + case CIV_TEAM: + max = gGameExternalOptions.ubGameMaximumNumberOfCivilians; + break; + // Don't worry about the others + case PLAYER_PLAN: + case LAN_TEAM_ONE: + case LAN_TEAM_TWO: + case LAN_TEAM_THREE: + case LAN_TEAM_FOUR: + max = 9999; + break; + } + if (max < (unsigned)(gTacticalStatus.Team[ cnt ].bLastID - gTacticalStatus.Team[ cnt ].bFirstID + 1)) + { + gTacticalStatus.Team[ cnt ].bLastID = gTacticalStatus.Team[ cnt ].bFirstID + max - 1; + } - memset( &gTacticalStatus, 0, sizeof( TacticalStatusType ) ); + gTacticalStatus.Team[ cnt ].RadarColor = bDefaultTeamColors[ cnt ]; - UINT8 maxteams; - if (!is_networked) - maxteams = MAXTEAMS_SP; - else - maxteams = MAXTEAMS; + if ( cnt == gbPlayerNum || cnt == PLAYER_PLAN ) + { + gTacticalStatus.Team[ cnt ].bSide = 0; + gTacticalStatus.Team[ cnt ].bHuman = TRUE; + } + else + { + if (cnt == MILITIA_TEAM ) + { + // militia guys on our side! + gTacticalStatus.Team[ cnt ].bSide = 0; + } + else if ( cnt == CREATURE_TEAM ) + { + // creatures are on no one's side but their own + // NB side 2 is used for hostile rebels.... + gTacticalStatus.Team[ cnt ].bSide = 3; + } + else + { + // hostile (enemies, or civilians; civs are potentially hostile but neutral) + gTacticalStatus.Team[ cnt ].bSide = 1; + } + gTacticalStatus.Team[ cnt ].bHuman = FALSE; + } + gTacticalStatus.Team[ cnt ].ubLastMercToRadio = NOBODY; + gTacticalStatus.Team[ cnt ].bTeamActive = FALSE; + gTacticalStatus.Team[ cnt ].bAwareOfOpposition = FALSE; - // Set team values - for( cnt = 0; cnt < maxteams; cnt++ ) - { - // For now, set hard-coded values - if (!is_networked) - { - gTacticalStatus.Team[ cnt ].bFirstID = bDefaultTeamRanges[ cnt ][0]; - gTacticalStatus.Team[ cnt ].bLastID = bDefaultTeamRanges[ cnt ][1]; - } - else - { - gTacticalStatus.Team[ cnt ].bFirstID = bDefaultTeamRangesMP[ cnt ][0]; - gTacticalStatus.Team[ cnt ].bLastID = bDefaultTeamRangesMP[ cnt ][1]; - } - // WDS - make number of mercenaries, etc. be configurable - unsigned max = 0; - switch (cnt) { - case OUR_TEAM: - max = gGameExternalOptions.ubGameMaximumNumberOfPlayerMercs + gGameExternalOptions.ubGameMaximumNumberOfPlayerVehicles; - break; - case ENEMY_TEAM: - max = gGameExternalOptions.ubGameMaximumNumberOfEnemies; - break; - case CREATURE_TEAM: - max = gGameExternalOptions.ubGameMaximumNumberOfCreatures; - break; - case MILITIA_TEAM: - max = gGameExternalOptions.ubGameMaximumNumberOfRebels; - break; - case CIV_TEAM: - max = gGameExternalOptions.ubGameMaximumNumberOfCivilians; - break; - // Don't worry about the others - case PLAYER_PLAN: - case LAN_TEAM_ONE: - case LAN_TEAM_TWO: - case LAN_TEAM_THREE: - case LAN_TEAM_FOUR: - max = 9999; - break; - } - if (max < (unsigned)(gTacticalStatus.Team[ cnt ].bLastID - gTacticalStatus.Team[ cnt ].bFirstID + 1)) { - gTacticalStatus.Team[ cnt ].bLastID = gTacticalStatus.Team[ cnt ].bFirstID + max - 1; - } + // set team values in soldier structures for all who are on this team + for ( cnt2 = gTacticalStatus.Team[ cnt ].bFirstID; cnt2 <= gTacticalStatus.Team[ cnt ].bLastID; cnt2++ ) + { + MercPtrs[ cnt2 ]->bTeam = (INT8) cnt; + } + } - gTacticalStatus.Team[ cnt ].RadarColor = bDefaultTeamColors[ cnt ]; + // Zero out merc slots! + for ( cnt = 0; cnt < TOTAL_SOLDIERS; cnt++ ) + { + MercSlots[ cnt ] = NULL; + } - if ( cnt == gbPlayerNum || cnt == PLAYER_PLAN ) - { - gTacticalStatus.Team[ cnt ].bSide = 0; - gTacticalStatus.Team[ cnt ].bHuman = TRUE; - } - else - { - if (cnt == MILITIA_TEAM ) - { - // militia guys on our side! - gTacticalStatus.Team[ cnt ].bSide = 0; - } - else if ( cnt == CREATURE_TEAM ) - { - // creatures are on no one's side but their own - // NB side 2 is used for hostile rebels.... - gTacticalStatus.Team[ cnt ].bSide = 3; - } - else - { - // hostile (enemies, or civilians; civs are potentially hostile but neutral) - gTacticalStatus.Team[ cnt ].bSide = 1; - } - gTacticalStatus.Team[ cnt ].bHuman = FALSE; - } + // Set other tactical flags + gTacticalStatus.uiFlags = TURNBASED | TRANSLUCENCY_TYPE; + gTacticalStatus.sSlideTarget = NOWHERE; + gTacticalStatus.uiTimeOfLastInput = GetJA2Clock(); + gTacticalStatus.uiTimeSinceDemoOn = GetJA2Clock(); + gTacticalStatus.uiCountdownToRestart = GetJA2Clock(); + gTacticalStatus.fGoingToEnterDemo = FALSE; + gTacticalStatus.fNOTDOLASTDEMO = FALSE; - gTacticalStatus.Team[ cnt ].ubLastMercToRadio = NOBODY; - gTacticalStatus.Team[ cnt ].bTeamActive = FALSE; - gTacticalStatus.Team[ cnt ].bAwareOfOpposition = FALSE; + if (is_networked) + gTacticalStatus.fDidGameJustStart = FALSE; + else + gTacticalStatus.fDidGameJustStart = TRUE; - // set team values in soldier structures for all who are on this team - for ( cnt2 = gTacticalStatus.Team[ cnt ].bFirstID; cnt2 <= gTacticalStatus.Team[ cnt ].bLastID; cnt2++ ) - { - MercPtrs[ cnt2 ]->bTeam = (INT8) cnt; - } - } + gTacticalStatus.ubLastRequesterTargetID = NO_PROFILE; + gTacticalStatus.ubLastRequesterSurgeryTargetID = NOBODY; // SANDRO - reset surgery requester too - // Zero out merc slots! - for ( cnt = 0; cnt < TOTAL_SOLDIERS; cnt++ ) - { - MercSlots[ cnt ] = NULL; - } + for ( cnt = 0; cnt < NUM_PANIC_TRIGGERS; cnt++ ) + { + gTacticalStatus.sPanicTriggerGridNo[ cnt ] = NOWHERE; + } - // Set other tactical flags - gTacticalStatus.uiFlags = TURNBASED | TRANSLUCENCY_TYPE; - gTacticalStatus.sSlideTarget = NOWHERE; - gTacticalStatus.uiTimeOfLastInput = GetJA2Clock(); - gTacticalStatus.uiTimeSinceDemoOn = GetJA2Clock(); - gTacticalStatus.uiCountdownToRestart = GetJA2Clock(); - gTacticalStatus.fGoingToEnterDemo = FALSE; - gTacticalStatus.fNOTDOLASTDEMO = FALSE; - - if (is_networked) - gTacticalStatus.fDidGameJustStart = FALSE; //hayden - else - gTacticalStatus.fDidGameJustStart = TRUE; + gTacticalStatus.bRealtimeSpeed = MAX_REALTIME_SPEED_VAL / 2; + gfInAirRaid = FALSE; + gpCustomizableTimerCallback = NULL; - gTacticalStatus.ubLastRequesterTargetID = NO_PROFILE; - gTacticalStatus.ubLastRequesterSurgeryTargetID = NOBODY; // SANDRO - reset surgery requester too + // Reset cursor + gpItemPointer = NULL; + gpItemPointerSoldier = NULL; + memset( gbInvalidPlacementSlot, 0, sizeof( gbInvalidPlacementSlot ) ); - for ( cnt = 0; cnt < NUM_PANIC_TRIGGERS; cnt++ ) - { - gTacticalStatus.sPanicTriggerGridNo[ cnt ] = NOWHERE; - } - /* for ( cnt = 0; cnt < NUM_TOPTIONS; cnt++ ) - { - gGameSettings.fOptions[ cnt ] = 1; - } - - gGameSettings.fOptions[ TOPTION_RTCONFIRM ] = 0; - gGameSettings.fOptions[ TOPTION_HIDE_BULLETS ] = 0; - */ - gTacticalStatus.bRealtimeSpeed = MAX_REALTIME_SPEED_VAL / 2; - - gfInAirRaid = FALSE; - gpCustomizableTimerCallback = NULL; - - // Reset cursor - gpItemPointer = NULL; - gpItemPointerSoldier = NULL; - memset( gbInvalidPlacementSlot, 0, sizeof( gbInvalidPlacementSlot ) ); - - InitCivQuoteSystem( ); - - ZeroAnimSurfaceCounts( ); - - InitializeLua(); - - return( TRUE ); + InitCivQuoteSystem( ); + ZeroAnimSurfaceCounts( ); + InitializeLua(); + return( TRUE ); } BOOLEAN ShutdownOverhead( ) { - UINT32 cnt; - - ShutdownLua( ); - - // Delete any soldiers which have been created! - for( cnt = 0; cnt < TOTAL_SOLDIERS; cnt++ ) - { - if( MercPtrs[ cnt ] != NULL ) - { - if ( MercPtrs[ cnt ]->bActive ) - { - MercPtrs[ cnt ]->DeleteSoldier( ); - } - } - } - - return( TRUE ); + UINT32 cnt; + ShutdownLua( ); + // Delete any soldiers which have been created! + for( cnt = 0; cnt < TOTAL_SOLDIERS; cnt++ ) + { + if( MercPtrs[ cnt ] != NULL ) + { + if ( MercPtrs[ cnt ]->bActive ) + { + MercPtrs[ cnt ]->DeleteSoldier( ); + } + } + } + return( TRUE ); } - BOOLEAN GetSoldier( SOLDIERTYPE **ppSoldier, UINT16 usSoldierIndex ) { - // Check range of index given - *ppSoldier = NULL; - - if ( usSoldierIndex < 0 || usSoldierIndex > TOTAL_SOLDIERS-1 ) - { - // Set debug message - return( FALSE ); - } - - // Check if a guy exists here - // Does another soldier exist here? - if ( MercPtrs[ usSoldierIndex ]->bActive ) - { - // Set Existing guy - *ppSoldier = MercPtrs[ usSoldierIndex ]; - return( TRUE); - } - else - { - return( FALSE ); - } + // Check range of index given + *ppSoldier = NULL; + if ( usSoldierIndex < 0 || usSoldierIndex > TOTAL_SOLDIERS-1 ) + { + // Set debug message + return( FALSE ); + } + // Check if a guy exists here + // Does another soldier exist here? + if ( MercPtrs[ usSoldierIndex ]->bActive ) + { + // Set Existing guy + *ppSoldier = MercPtrs[ usSoldierIndex ]; + return( TRUE); + } + else + { + return( FALSE ); + } } -BOOLEAN NextAIToHandle( UINT32 uiCurrAISlot ) +BOOLEAN NextAIToHandle( UINT32 uiCurrAISlot ) { - UINT32 cnt; + UINT32 cnt; - if (uiCurrAISlot >= guiNumMercSlots) - { - // last person to handle was an off-map merc, so now we start looping at the beginning - // again - cnt = 0; - } - else - { - // continue on from the last person we handled - cnt = uiCurrAISlot + 1; - } + if (uiCurrAISlot >= guiNumMercSlots) + { + // last person to handle was an off-map merc, so now we start looping at the beginning again + cnt = 0; + } + else + { + // continue on from the last person we handled + cnt = uiCurrAISlot + 1; + } - for ( ; cnt < guiNumMercSlots; cnt++ ) - { - if ( MercSlots[ cnt ] && ( (MercSlots[ cnt ]->bTeam != gbPlayerNum) || (MercSlots[ cnt ]->flags.uiStatusFlags & SOLDIER_PCUNDERAICONTROL) ) ) - { - // aha! found an AI guy! - guiAISlotToHandle = cnt; - return( TRUE ); - } - } + for ( ; cnt < guiNumMercSlots; cnt++ ) + { + if ( MercSlots[ cnt ] && ( (MercSlots[ cnt ]->bTeam != gbPlayerNum) || (MercSlots[ cnt ]->flags.uiStatusFlags & SOLDIER_PCUNDERAICONTROL) ) ) + { + // aha! found an AI guy! + guiAISlotToHandle = cnt; + return( TRUE ); + } + } + // set so that even if there are no off-screen mercs to handle, we will loop back to + // the start of the array + guiAISlotToHandle = HANDLE_OFF_MAP_MERC; - // set so that even if there are no off-screen mercs to handle, we will loop back to - // the start of the array - guiAISlotToHandle = HANDLE_OFF_MAP_MERC; - - // didn't find an AI guy to handle after the last one handled and the # of slots - // it's time to check for an off-map merc... maybe - if (guiNumAwaySlots > 0) - { - if ( (guiAIAwaySlotToHandle + 1) >= guiNumAwaySlots) - { - // start looping from the beginning - cnt = 0; - } - else - { - // continue on from the last person we handled - cnt = guiAIAwaySlotToHandle + 1; - } - - for ( ; cnt < guiNumAwaySlots; cnt++ ) - { - if (AwaySlots[ cnt ] && AwaySlots[ cnt ]->bTeam != gbPlayerNum) - { - // aha! found an AI guy! - guiAIAwaySlotToHandle = cnt; - return( FALSE ); - } - } - - // reset awayAISlotToHandle, but DON'T loop again, away slots not that important - guiAIAwaySlotToHandle = RESET_HANDLE_OF_OFF_MAP_MERCS; - } - - return( FALSE ); + // didn't find an AI guy to handle after the last one handled and the # of slots + // it's time to check for an off-map merc... maybe + if (guiNumAwaySlots > 0) + { + if ( (guiAIAwaySlotToHandle + 1) >= guiNumAwaySlots) + { + // start looping from the beginning + cnt = 0; + } + else + { + // continue on from the last person we handled + cnt = guiAIAwaySlotToHandle + 1; + } + for ( ; cnt < guiNumAwaySlots; cnt++ ) + { + if (AwaySlots[ cnt ] && AwaySlots[ cnt ]->bTeam != gbPlayerNum) + { + // aha! found an AI guy! + guiAIAwaySlotToHandle = cnt; + return( FALSE ); + } + } + // reset awayAISlotToHandle, but DON'T loop again, away slots not that important + guiAIAwaySlotToHandle = RESET_HANDLE_OF_OFF_MAP_MERCS; + } + return( FALSE ); } -void PauseAITemporarily( void ) +void PauseAITemporarily( ) { - gfPauseAllAI = TRUE; - giPauseAllAITimer = GetJA2Clock(); + gfPauseAllAI = TRUE; + giPauseAllAITimer = GetJA2Clock(); } -void PauseAIUntilManuallyUnpaused( void ) +void PauseAIUntilManuallyUnpaused( ) { - gfPauseAllAI = TRUE; - giPauseAllAITimer = 0; + gfPauseAllAI = TRUE; + giPauseAllAITimer = 0; } -void UnPauseAI( void ) +void UnPauseAI( ) { - // overrides any timer too - gfPauseAllAI = FALSE; - giPauseAllAITimer = 0; + // overrides any timer too + gfPauseAllAI = FALSE; + giPauseAllAITimer = 0; } FLOAT gdRadiansForAngle[ ] = { - (FLOAT)PI, - (FLOAT)( 3 * PI / 4 ), - (FLOAT)( PI / 2 ), - (FLOAT)( ( PI ) / 4 ), + (FLOAT)PI, + (FLOAT)( 3 * PI / 4 ), + (FLOAT)( PI / 2 ), + (FLOAT)( ( PI ) / 4 ), - (FLOAT)0, - (FLOAT)( ( -PI ) / 4 ), - (FLOAT)( -PI / 2 ), - (FLOAT)( -3 * PI / 4 ), + (FLOAT)0, + (FLOAT)( ( -PI ) / 4 ), + (FLOAT)( -PI / 2 ), + (FLOAT)( -3 * PI / 4 ), }; - BOOLEAN ExecuteOverhead( ) { + if( !COUNTERDONE( TOVERHEAD ) ) + return TRUE; // FIXME: return value is ignored and should be void + RESETCOUNTER( TOVERHEAD ); - UINT32 cnt; - SOLDIERTYPE *pSoldier; - INT16 sAPCost; - INT16 sBPCost; - FLOAT dXPos , dYPos; - FLOAT dAngle; - BOOLEAN fKeepMoving; - INT8 bShadeLevel; - BOOLEAN fNoAPsForPendingAction; - INT32 sGridNo; - STRUCTURE *pStructure; - BOOLEAN fHandleAI = FALSE; + UINT32 cnt; + SOLDIERTYPE* pSoldier; + INT16 sAPCost; + INT16 sBPCost; + FLOAT dXPos , dYPos; + FLOAT dAngle; + BOOLEAN fKeepMoving; + INT8 bShadeLevel; + BOOLEAN fNoAPsForPendingAction; + INT32 sGridNo; + STRUCTURE *pStructure; + BOOLEAN fHandleAI = FALSE; + // Diagnostic Stuff + static INT32 iTimerTest = 0; + static INT32 iTimerVal = 0; + gfMovingAnimation = FALSE; + if(GetSoldier(&pSoldier, gusSelectedSoldier)) + { + if(pSoldier->bActive) + { + if(pSoldier->flags.uiStatusFlags&SOLDIER_GREEN_RAY) + LightShowRays((INT16)(pSoldier->dXPos/CELL_X_SIZE), (INT16)(pSoldier->dYPos/CELL_Y_SIZE), FALSE); + } + } + // Diagnostic Stuff + iTimerVal = GetJA2Clock(); + giTimerDiag = iTimerVal - iTimerTest; + iTimerTest = iTimerVal; - // Diagnostic Stuff - static INT32 iTimerTest = 0; - static INT32 iTimerVal = 0; + UpdateAniTiles( ); // ANIMATED TILE STUFF + HandleExplosionQueue(); // BOMBS!!! + HandleCreatureTenseQuote( ); + CheckHostileOrSayQuoteList(); + if ( gfPauseAllAI && giPauseAllAITimer && ( iTimerVal - giPauseAllAITimer > PAUSE_ALL_AI_DELAY ) ) + { + // ok, stop pausing the AI! + gfPauseAllAI = FALSE; + } - gfMovingAnimation = FALSE; + if (!gfPauseAllAI) + { + // AI limiting crap + gubAICounter = 0; + if (!((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT))) + { + if ((iTimerVal - giRTAILastUpdateTime ) > RT_DELAY_BETWEEN_AI_HANDLING) + { + giRTAILastUpdateTime = iTimerVal; + // figure out which AI guy to handle this time around, starting with the slot AFTER the current AI guy + fHandleAI = NextAIToHandle( guiAISlotToHandle ); + } + } + } - if(GetSoldier(&pSoldier, gusSelectedSoldier)) - { - if(pSoldier->bActive) - { - if(pSoldier->flags.uiStatusFlags&SOLDIER_GREEN_RAY) - LightShowRays((INT16)(pSoldier->dXPos/CELL_X_SIZE), (INT16)(pSoldier->dYPos/CELL_Y_SIZE), FALSE); - } - } + for ( cnt = 0; cnt < guiNumMercSlots; cnt++ ) + { + pSoldier = MercSlots[ cnt ]; + if ( pSoldier && pSoldier->bActive && (pSoldier->bTeam == OUR_TEAM) ) { + if (!gogglewarning && BadGoggles(pSoldier)) { + gogglewarning = TRUE; + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_CHECK_GOGGLES] ); + } + } + // Syncronize for upcoming soldier counters + SYNCTIMECOUNTER( ); + if ( pSoldier != NULL ) + { + HandlePanelFaceAnimations( pSoldier ); + // Handle damage counters + if ( pSoldier->flags.fDisplayDamage ) + { + if ( TIMECOUNTERDONE( pSoldier->timeCounters.DamageCounter, DAMAGE_DISPLAY_DELAY ) ) + { + pSoldier->bDisplayDamageCount++; + pSoldier->sDamageX+=1; + pSoldier->sDamageY-=1; - if ( COUNTERDONE( TOVERHEAD ) ) - { - // Reset counter - RESETCOUNTER( TOVERHEAD ); + RESETTIMECOUNTER( pSoldier->timeCounters.DamageCounter, DAMAGE_DISPLAY_DELAY ); + } - // Diagnostic Stuff - iTimerVal = GetJA2Clock(); - giTimerDiag = iTimerVal - iTimerTest; - iTimerTest = iTimerVal; + if ( pSoldier->bDisplayDamageCount >= 8 ) + { + pSoldier->bDisplayDamageCount = 0; + pSoldier->sDamage = 0; + pSoldier->flags.fDisplayDamage = FALSE; + } - // ANIMATED TILE STUFF - UpdateAniTiles( ); + } - // BOMBS!!! - HandleExplosionQueue(); + // Handle reload counters + if ( pSoldier->flags.fReloading ) + { + if ( TIMECOUNTERDONE( pSoldier->timeCounters.ReloadCounter, pSoldier->sReloadDelay ) ) + { + pSoldier->flags.fReloading = FALSE; + pSoldier->flags.fPauseAim = FALSE; + } + } +#ifdef JA2UB + //Ja25 UB + // ATE: JA25 additon - poll for getting up from start of game... + if( pSoldier->fWaitingToGetupFromJA25Start ) + { + if( !DialogueActive( ) ) + { + ///if the timer is done, AND no one is talking + if( TIMECOUNTERDONE( pSoldier->GetupFromJA25StartCounter, 0 ) ) + { + //make sure they wont say this again + pSoldier->fWaitingToGetupFromJA25Start = FALSE; - HandleCreatureTenseQuote( ); + // + //Get the soldier that should say the quote + // - CheckHostileOrSayQuoteList(); + //if the merc is one of the mercs who has Quote 80, say that + if( pSoldier->ubProfile == 58 ||//GASTON + pSoldier->ubProfile == 59 ||//STOGIE + pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__PLAYER_CHARACTER ) + { + TacticalCharacterDialogue( pSoldier, QUOTE_REPUTATION_REFUSAL ); + } + else + { + // Now make them say their curse sound + pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 ); + } - if ( gfPauseAllAI && giPauseAllAITimer && ( iTimerVal - giPauseAllAITimer > PAUSE_ALL_AI_DELAY ) ) - { - // ok, stop pausing the AI! - gfPauseAllAI = FALSE; - } + SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_MULTIPURPOSE, pSoldier->ubProfile, 0, 0, pSoldier->iFaceIndex, 0 ); + } + } + else + { + pSoldier->GetupFromJA25StartCounter += giTimerDiag; + } + } - if (!gfPauseAllAI) - { - // AI limiting crap - gubAICounter = 0; - if (!((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT))) - { - if ((iTimerVal - giRTAILastUpdateTime ) > RT_DELAY_BETWEEN_AI_HANDLING) - { - giRTAILastUpdateTime = iTimerVal; - // figure out which AI guy to handle this time around, - // starting with the slot AFTER the current AI guy - fHandleAI = NextAIToHandle( guiAISlotToHandle ); - } - } - } - - for ( cnt = 0; cnt < guiNumMercSlots; cnt++ ) - { - pSoldier = MercSlots[ cnt ]; - - if ( pSoldier && pSoldier->bActive && (pSoldier->bTeam == OUR_TEAM) ) { - if (!gogglewarning && BadGoggles(pSoldier)) { - gogglewarning = TRUE; - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_CHECK_GOGGLES] ); - } - } - - // Syncronize for upcoming soldier counters - SYNCTIMECOUNTER( ); - - if ( pSoldier != NULL ) - { - HandlePanelFaceAnimations( pSoldier ); - - // Handle damage counters - if ( pSoldier->flags.fDisplayDamage ) - { - if ( TIMECOUNTERDONE( pSoldier->timeCounters.DamageCounter, DAMAGE_DISPLAY_DELAY ) ) - { - pSoldier->bDisplayDamageCount++; - pSoldier->sDamageX+=1; - pSoldier->sDamageY-=1; - - RESETTIMECOUNTER( pSoldier->timeCounters.DamageCounter, DAMAGE_DISPLAY_DELAY ); - } - - if ( pSoldier->bDisplayDamageCount >= 8 ) - { - pSoldier->bDisplayDamageCount = 0; - pSoldier->sDamage = 0; - pSoldier->flags.fDisplayDamage = FALSE; - } - - } - - // Handle reload counters - if ( pSoldier->flags.fReloading ) - { - if ( TIMECOUNTERDONE( pSoldier->timeCounters.ReloadCounter, pSoldier->sReloadDelay ) ) - { - pSoldier->flags.fReloading = FALSE; - pSoldier->flags.fPauseAim = FALSE; - /* - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - realtime reloading") ); - FreeUpAttacker( pSoldier->ubID ); - */ - } - } -#ifdef JA2UB - //Ja25 UB - // ATE: JA25 additon - poll for getting up from start of game... - if( pSoldier->fWaitingToGetupFromJA25Start ) - { - if( !DialogueActive( ) ) - { - ///if the timer is done, AND no one is talking - if( TIMECOUNTERDONE( pSoldier->GetupFromJA25StartCounter, 0 ) ) - { - //make sure they wont say this again - pSoldier->fWaitingToGetupFromJA25Start = FALSE; - - // - //Get the soldier that should say the quote - // - - //if the merc is one of the mercs who has Quote 80, say that - if( pSoldier->ubProfile == 58 ||//GASTON - pSoldier->ubProfile == 59 ||//STOGIE - pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__PLAYER_CHARACTER ) - { - TacticalCharacterDialogue( pSoldier, QUOTE_REPUTATION_REFUSAL ); - } - else - { - // Now make them say their curse sound - pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 ); - } - - SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_MULTIPURPOSE, pSoldier->ubProfile, 0, 0, pSoldier->iFaceIndex, 0 ); - } - } - else - { - pSoldier->GetupFromJA25StartCounter += giTimerDiag; - } - } - #endif - // Checkout fading - if ( pSoldier->flags.fBeginFade ) - { - if ( TIMECOUNTERDONE( pSoldier->timeCounters.FadeCounter, NEW_FADE_DELAY ) ) - { - RESETTIMECOUNTER( pSoldier->timeCounters.FadeCounter, NEW_FADE_DELAY ); + // Checkout fading + if ( pSoldier->flags.fBeginFade ) + { + if ( TIMECOUNTERDONE( pSoldier->timeCounters.FadeCounter, NEW_FADE_DELAY ) ) + { + RESETTIMECOUNTER( pSoldier->timeCounters.FadeCounter, NEW_FADE_DELAY ); - // Fade out.... - if ( pSoldier->flags.fBeginFade == 1 ) - { - bShadeLevel = (pSoldier->ubFadeLevel&0x0f); - bShadeLevel=__min(bShadeLevel+1, SHADE_MIN); + // Fade out.... + if ( pSoldier->flags.fBeginFade == 1 ) + { + bShadeLevel = (pSoldier->ubFadeLevel&0x0f); + bShadeLevel=__min(bShadeLevel+1, SHADE_MIN); + if ( bShadeLevel >= ( SHADE_MIN - 3 ) ) + { + pSoldier->flags.fBeginFade = FALSE; + pSoldier->bVisible = -1; + // Set levelnode shade level.... + if ( pSoldier->pLevelNode ) + { + pSoldier->pLevelNode->ubShadeLevel = bShadeLevel; + } + // Set Anim speed accordingly! + SetSoldierAniSpeed( pSoldier ); + } + bShadeLevel|=(pSoldier->ubFadeLevel&0x30); + pSoldier->ubFadeLevel = bShadeLevel; + } + else if ( pSoldier->flags.fBeginFade == 2 ) + { + bShadeLevel = (pSoldier->ubFadeLevel&0x0f); + bShadeLevel = bShadeLevel-1; + if ( bShadeLevel <= 0 ) + { + bShadeLevel = 0; + } + if ( bShadeLevel <= (gpWorldLevelData[ pSoldier->sGridNo ].pLandHead->ubShadeLevel ) ) + { + bShadeLevel = (gpWorldLevelData[ pSoldier->sGridNo ].pLandHead->ubShadeLevel ); + pSoldier->flags.fBeginFade = FALSE; + // Set levelnode shade level.... + if ( pSoldier->pLevelNode ) + { + pSoldier->pLevelNode->ubShadeLevel = bShadeLevel; + } + // Set Anim speed accordingly! + SetSoldierAniSpeed( pSoldier ); + } + bShadeLevel|=(pSoldier->ubFadeLevel&0x30); + pSoldier->ubFadeLevel = bShadeLevel; + } + } + } - if ( bShadeLevel >= ( SHADE_MIN - 3 ) ) - { - pSoldier->flags.fBeginFade = FALSE; - pSoldier->bVisible = -1; + // Check if we have a new visiblity and shade accordingly down + if ( pSoldier->bLastRenderVisibleValue != pSoldier->bVisible ) + { + HandleCrowShadowVisibility( pSoldier ); + // Check for fade out.... + if ( pSoldier->bVisible == -1 && pSoldier->bLastRenderVisibleValue >= 0 ) + { + if (!TileIsOutOfBounds(pSoldier->sGridNo)) + { + pSoldier->ubFadeLevel = gpWorldLevelData[ pSoldier->sGridNo ].pLandHead->ubShadeLevel; + } + pSoldier->flags.fBeginFade = TRUE; + pSoldier->sLocationOfFadeStart = pSoldier->sGridNo; + // OK, re-evaluate guy's roof marker + HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, FALSE, FALSE ); + pSoldier->bVisible = -2; + } + // Check for fade in..... + if ( pSoldier->bVisible != -1 && pSoldier->bLastRenderVisibleValue == -1 && pSoldier->bTeam != gbPlayerNum ) + { + pSoldier->ubFadeLevel = ( SHADE_MIN - 3 ); + pSoldier->flags.fBeginFade = 2; + pSoldier->sLocationOfFadeStart = pSoldier->sGridNo; - // Set levelnode shade level.... - if ( pSoldier->pLevelNode ) - { - pSoldier->pLevelNode->ubShadeLevel = bShadeLevel; - } + // OK, re-evaluate guy's roof marker + HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, TRUE, FALSE ); + } + } + pSoldier->bLastRenderVisibleValue = pSoldier->bVisible; - // Set Anim speed accordingly! - SetSoldierAniSpeed( pSoldier ); - } + // Handle stationary polling... + if ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_STATIONARY ) || pSoldier->flags.fNoAPToFinishMove ) + { + // Are are stationary.... + // Were we once moving...? + if ( pSoldier->flags.fSoldierWasMoving && pSoldier->bVisible > -1 ) + { + pSoldier->flags.fSoldierWasMoving = FALSE; - bShadeLevel|=(pSoldier->ubFadeLevel&0x30); - pSoldier->ubFadeLevel = bShadeLevel; - } - else if ( pSoldier->flags.fBeginFade == 2 ) - { - bShadeLevel = (pSoldier->ubFadeLevel&0x0f); - //ubShadeLevel =__max(ubShadeLevel-1, gpWorldLevelData[ pSoldier->sGridNo ].pLandHead->ubShadeLevel ); + HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, TRUE, FALSE ); - bShadeLevel = bShadeLevel-1; + if ( !gGameSettings.fOptions[ TOPTION_MERC_ALWAYS_LIGHT_UP ] ) + { + pSoldier->DeleteSoldierLight( ); + pSoldier->SetCheckSoldierLightFlag( ); + } + } + } + else + { + // We are moving.... + // Were we once stationary? + if ( !pSoldier->flags.fSoldierWasMoving ) + { + pSoldier->flags.fSoldierWasMoving = TRUE; + HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, FALSE, FALSE ); + } + } - if ( bShadeLevel <= 0 ) - { - bShadeLevel = 0; - } - - if ( bShadeLevel <= (gpWorldLevelData[ pSoldier->sGridNo ].pLandHead->ubShadeLevel ) ) - { - bShadeLevel = (gpWorldLevelData[ pSoldier->sGridNo ].pLandHead->ubShadeLevel ); - - pSoldier->flags.fBeginFade = FALSE; - //pSoldier->bVisible = -1; - //pSoldier->ubFadeLevel = gpWorldLevelData[ pSoldier->sGridNo ].pLandHead->ubShadeLevel; - - // Set levelnode shade level.... - if ( pSoldier->pLevelNode ) - { - pSoldier->pLevelNode->ubShadeLevel = bShadeLevel; - } - - // Set Anim speed accordingly! - SetSoldierAniSpeed( pSoldier ); - } - - bShadeLevel|=(pSoldier->ubFadeLevel&0x30); - pSoldier->ubFadeLevel = bShadeLevel; - } - } - } - - // Check if we have a new visiblity and shade accordingly down - if ( pSoldier->bLastRenderVisibleValue != pSoldier->bVisible ) - { - HandleCrowShadowVisibility( pSoldier ); - - // Check for fade out.... - if ( pSoldier->bVisible == -1 && pSoldier->bLastRenderVisibleValue >= 0 ) - { - if (!TileIsOutOfBounds(pSoldier->sGridNo)) - { - pSoldier->ubFadeLevel = gpWorldLevelData[ pSoldier->sGridNo ].pLandHead->ubShadeLevel; - } - - pSoldier->flags.fBeginFade = TRUE; - pSoldier->sLocationOfFadeStart = pSoldier->sGridNo; - - // OK, re-evaluate guy's roof marker - HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, FALSE, FALSE ); - - pSoldier->bVisible = -2; - } - - // Check for fade in..... - if ( pSoldier->bVisible != -1 && pSoldier->bLastRenderVisibleValue == -1 && pSoldier->bTeam != gbPlayerNum ) - { - pSoldier->ubFadeLevel = ( SHADE_MIN - 3 ); - pSoldier->flags.fBeginFade = 2; - pSoldier->sLocationOfFadeStart = pSoldier->sGridNo; - - // OK, re-evaluate guy's roof marker - HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, TRUE, FALSE ); - } - - } - pSoldier->bLastRenderVisibleValue = pSoldier->bVisible; - - - // Handle stationary polling... - if ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_STATIONARY ) || pSoldier->flags.fNoAPToFinishMove ) - { - // Are are stationary.... - // Were we once moving...? - if ( pSoldier->flags.fSoldierWasMoving && pSoldier->bVisible > -1 ) - { - pSoldier->flags.fSoldierWasMoving = FALSE; - - HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, TRUE, FALSE ); - - if ( !gGameSettings.fOptions[ TOPTION_MERC_ALWAYS_LIGHT_UP ] ) - { - pSoldier->DeleteSoldierLight( ); - - pSoldier->SetCheckSoldierLightFlag( ); - } - } - } - else - { - // We are moving.... - // Were we once stationary? - if ( !pSoldier->flags.fSoldierWasMoving ) - { - pSoldier->flags.fSoldierWasMoving = TRUE; - - HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, FALSE, FALSE ); - } - } - - // Handle animation update counters - // ATE: Added additional check here for special value of anispeed that pauses all updates - { + // Handle animation update counters + // ATE: Added additional check here for special value of anispeed that pauses all updates #ifndef BOUNDS_CHECKER - if ( TIMECOUNTERDONE( pSoldier->timeCounters.UpdateCounter, pSoldier->sAniDelay ) && pSoldier->sAniDelay != 10000 ) + if ( TIMECOUNTERDONE( pSoldier->timeCounters.UpdateCounter, pSoldier->sAniDelay ) && pSoldier->sAniDelay != 10000 ) #endif - { + { +#ifdef NETWORKED + // DEF: + // Check for TIMING delay here only if in Realtime + if( gTacticalStatus.uiFlags & REALTIME) + if ( pSoldier->flags.fIsSoldierMoving ) + CheckForSlowSoldier( pSoldier ); +#endif + + // Check if we need to look for items + if ( pSoldier->flags.uiStatusFlags & SOLDIER_LOOKFOR_ITEMS ) + { + RevealRoofsAndItems(pSoldier, TRUE, FALSE, pSoldier->pathing.bLevel, FALSE ); + pSoldier->flags.uiStatusFlags &= (~SOLDIER_LOOKFOR_ITEMS); + } + + + // Check if we need to reposition light.... + if ( pSoldier->flags.uiStatusFlags & SOLDIER_RECHECKLIGHT ) + { + pSoldier->PositionSoldierLight( ); + pSoldier->flags.uiStatusFlags &= (~SOLDIER_RECHECKLIGHT); + } + + RESETTIMECOUNTER( pSoldier->timeCounters.UpdateCounter, pSoldier->sAniDelay ); + + fNoAPsForPendingAction = FALSE; #ifdef NETWORKED - // DEF: - // Check for TIMING delay here only if in Realtime - if( gTacticalStatus.uiFlags & REALTIME) - if ( pSoldier->flags.fIsSoldierMoving ) - CheckForSlowSoldier( pSoldier ); + // Get the path update, if there is 1 + if (pSoldier->flags.fSoldierUpdatedFromNetwork) + UpdateSoldierFromNetwork(pSoldier); #endif - // Check if we need to look for items - if ( pSoldier->flags.uiStatusFlags & SOLDIER_LOOKFOR_ITEMS ) - { - RevealRoofsAndItems(pSoldier, TRUE, FALSE, pSoldier->pathing.bLevel, FALSE ); - pSoldier->flags.uiStatusFlags &= (~SOLDIER_LOOKFOR_ITEMS); - } + // Check if we are moving and we deduct points and we have no points + if ( !( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_MOVING | ANIM_SPECIALMOVE ) ) && pSoldier->flags.fNoAPToFinishMove ) && !pSoldier->flags.fPauseAllAnimation ) + { + if ( !AdjustToNextAnimationFrame( pSoldier ) ) + { + continue; + } + if ( !( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_SPECIALMOVE ) ) + { + HandleNextTileWaiting( pSoldier ); // Check if we are waiting for an opened path + } + // Update world data with new position, etc + // Determine gameworld cells corrds of guy + if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_MOVING | ANIM_SPECIALMOVE ) && !( pSoldier->flags.uiStatusFlags & SOLDIER_PAUSEANIMOVE ) ) + { + fKeepMoving = TRUE; - // Check if we need to reposition light.... - if ( pSoldier->flags.uiStatusFlags & SOLDIER_RECHECKLIGHT ) - { - pSoldier->PositionSoldierLight( ); - pSoldier->flags.uiStatusFlags &= (~SOLDIER_RECHECKLIGHT); - } + pSoldier->flags.fPausedMove = FALSE; - RESETTIMECOUNTER( pSoldier->timeCounters.UpdateCounter, pSoldier->sAniDelay ); + // CHECK TO SEE IF WE'RE ON A MIDDLE TILE + if ( pSoldier->flags.fPastXDest && pSoldier->flags.fPastYDest ) + { + pSoldier->flags.fPastXDest = pSoldier->flags.fPastYDest = FALSE; + // assign X/Y values back to make sure we are at the center of the tile + // (to prevent mercs from going through corners of tiles and producing + // structure data complaints) - fNoAPsForPendingAction = FALSE; + //pSoldier->dXPos = pSoldier->pathing.sDestXPos; + //pSoldier->dYPos = pSoldier->pathing.sDestYPos; + HandleBloodForNewGridNo( pSoldier ); + if ( !( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_SPECIALMOVE ) && pSoldier->sGridNo != pSoldier->pathing.sFinalDestination) ) + { + //OK, we're at the MIDDLE of a new tile... + HandleAtNewGridNo( pSoldier, &fKeepMoving ); + } + if ( gTacticalStatus.bBoxingState != NOT_BOXING && (gTacticalStatus.bBoxingState == BOXING_WAITING_FOR_PLAYER || + gTacticalStatus.bBoxingState == PRE_BOXING || gTacticalStatus.bBoxingState == BOXING) ) + { + BoxingMovementCheck( pSoldier ); + } + // Are we at our final destination? + if ( pSoldier->pathing.sFinalDestination == pSoldier->sGridNo ) + { + // Cancel path.... + pSoldier->pathing.usPathIndex = pSoldier->pathing.usPathDataSize = 0; + // Cancel reverse + pSoldier->bReverse = FALSE; + BOOLEAN fAimAfterMove = FALSE; + if ( pSoldier->usAnimState == WALKING_ALTERNATIVE_RDY || pSoldier->usAnimState == SIDE_STEP_ALTERNATIVE_RDY ) + { + fAimAfterMove = TRUE; + pSoldier->usPendingAnimation = AIM_ALTERNATIVE_STAND; + pSoldier->ubPendingDirection = pSoldier->ubDirection; + } + else if ( pSoldier->usAnimState == SIDE_STEP_WEAPON_RDY || pSoldier->usAnimState == WALKING_WEAPON_RDY ) + { + fAimAfterMove = TRUE; + pSoldier->usPendingAnimation = AIM_RIFLE_STAND; + pSoldier->ubPendingDirection = pSoldier->ubDirection; + } + else if ( pSoldier->usAnimState == SIDE_STEP_DUAL_RDY || pSoldier->usAnimState == WALKING_DUAL_RDY ) + { + fAimAfterMove = TRUE; + pSoldier->usPendingAnimation = AIM_DUAL_STAND; + pSoldier->ubPendingDirection = pSoldier->ubDirection; + } + // OK, if we are the selected soldier, refresh some UI stuff + if ( pSoldier->ubID == (UINT8)gusSelectedSoldier ) + { + gfUIRefreshArrows = TRUE; + } + // ATE: Play landing sound..... + if ( pSoldier->usAnimState == JUMP_OVER_BLOCKING_PERSON || pSoldier->usAnimState == LONG_JUMP ) + { + PlaySoldierFootstepSound( pSoldier ); + } + // If we are a robot, play stop sound... + if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT ) + { + PlaySoldierJA2Sample( pSoldier->ubID, ROBOT_STOP, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE ); + } + + // Update to middle if we're on destination + dXPos = pSoldier->pathing.sDestXPos; + dYPos = pSoldier->pathing.sDestYPos; + pSoldier->EVENT_SetSoldierPosition( dXPos, dYPos ); #ifdef NETWORKED - // Get the path update, if there is 1 - if (pSoldier->flags.fSoldierUpdatedFromNetwork) - UpdateSoldierFromNetwork(pSoldier); + // DEF: Test Code + StopSoldierMovementTime(pSoldier); #endif + // CHECK IF WE HAVE A PENDING ANIMATION + if ( pSoldier->usPendingAnimation != NO_PENDING_ANIMATION ) + { + pSoldier->ChangeSoldierState( pSoldier->usPendingAnimation, 0 , FALSE ); + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; - // Check if we are moving and we deduct points and we have no points - if ( !( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_MOVING | ANIM_SPECIALMOVE ) ) && pSoldier->flags.fNoAPToFinishMove ) && !pSoldier->flags.fPauseAllAnimation ) - { - if ( !AdjustToNextAnimationFrame( pSoldier ) ) - { - continue; - } - //hayden - holt at scheduled grid - - //if (is_networked) - //{ - // if(pSoldier->sGridNo==pSoldier->sScheduledStop) - // { - // pSoldier->HaultSoldierFromSighting( 1 ); - // pSoldier->sScheduledStop=NULL; - // } - //} + if ( pSoldier->ubPendingDirection != NO_PENDING_DIRECTION ) + { + pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubPendingDirection ); + pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; + } - if ( !( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_SPECIALMOVE ) ) - { - // Check if we are waiting for an opened path - HandleNextTileWaiting( pSoldier ); - } + } - // Update world data with new position, etc - // Determine gameworld cells corrds of guy - if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_MOVING | ANIM_SPECIALMOVE ) && !( pSoldier->flags.uiStatusFlags & SOLDIER_PAUSEANIMOVE ) ) - { - fKeepMoving = TRUE; + // CHECK IF WE HAVE A PENDING ACTION + if ( pSoldier->ubWaitActionToDo ) + { + if ( pSoldier->ubWaitActionToDo == 2 ) + { + pSoldier->ubWaitActionToDo = 1; - pSoldier->flags.fPausedMove = FALSE; + if ( gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALKOFF_SCREEN ) + { + pSoldier->pathing.usPathIndex--; // ATE wanted this line here... + AdjustSoldierPathToGoOffEdge( pSoldier, pSoldier->sGridNo, (UINT8)pSoldier->aiData.uiPendingActionData1 ); + continue; + } + } + else if ( pSoldier->ubWaitActionToDo == 1 ) + { + pSoldier->ubWaitActionToDo = 0; + gbNumMercsUntilWaitingOver--; + pSoldier->SoldierGotoStationaryStance( ); + // If we are at an exit-grid, make disappear..... + if ( gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO ) + { + RemoveSoldierFromTacticalSector( pSoldier, TRUE ); // Remove! + } + } + } + else if ( pSoldier->aiData.ubPendingAction != NO_PENDING_ACTION ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("We are inside the IF PENDING Animation with soldier #%d", pSoldier->ubID) ); - // CHECK TO SEE IF WE'RE ON A MIDDLE TILE - if ( pSoldier->flags.fPastXDest && pSoldier->flags.fPastYDest ) - { - pSoldier->flags.fPastXDest = pSoldier->flags.fPastYDest = FALSE; - // assign X/Y values back to make sure we are at the center of the tile - // (to prevent mercs from going through corners of tiles and producing - // structure data complaints) + if ( pSoldier->aiData.ubPendingAction == MERC_OPENDOOR || pSoldier->aiData.ubPendingAction == MERC_OPENSTRUCT ) + { + sGridNo = pSoldier->aiData.sPendingActionData2; + //usStructureID = (UINT16)pSoldier->aiData.uiPendingActionData1; + //pStructure = FindStructureByID( sGridNo, usStructureID ); - //pSoldier->dXPos = pSoldier->pathing.sDestXPos; - //pSoldier->dYPos = pSoldier->pathing.sDestYPos; + // LOOK FOR STRUCT OPENABLE + pStructure = FindStructure( sGridNo, STRUCTURE_OPENABLE ); - HandleBloodForNewGridNo( pSoldier ); - - if ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_SPECIALMOVE ) && pSoldier->sGridNo != pSoldier->pathing.sFinalDestination ) - { - - } - else - { - //OK, we're at the MIDDLE of a new tile... - HandleAtNewGridNo( pSoldier, &fKeepMoving ); - } - - if ( gTacticalStatus.bBoxingState != NOT_BOXING && (gTacticalStatus.bBoxingState == BOXING_WAITING_FOR_PLAYER || gTacticalStatus.bBoxingState == PRE_BOXING || gTacticalStatus.bBoxingState == BOXING) ) - { - BoxingMovementCheck( pSoldier ); - } - - // Are we at our final destination? - if ( pSoldier->pathing.sFinalDestination == pSoldier->sGridNo ) - { - // Cancel path.... - pSoldier->pathing.usPathIndex = pSoldier->pathing.usPathDataSize = 0; - - // Cancel reverse - pSoldier->bReverse = FALSE; - - BOOLEAN fAimAfterMove = FALSE; - if ( pSoldier->usAnimState == WALKING_ALTERNATIVE_RDY || pSoldier->usAnimState == SIDE_STEP_ALTERNATIVE_RDY ) - { - fAimAfterMove = TRUE; - pSoldier->usPendingAnimation = AIM_ALTERNATIVE_STAND; - pSoldier->ubPendingDirection = pSoldier->ubDirection; - } - else if ( pSoldier->usAnimState == SIDE_STEP_WEAPON_RDY || pSoldier->usAnimState == WALKING_WEAPON_RDY ) - { - fAimAfterMove = TRUE; - pSoldier->usPendingAnimation = AIM_RIFLE_STAND; - pSoldier->ubPendingDirection = pSoldier->ubDirection; - } - else if ( pSoldier->usAnimState == SIDE_STEP_DUAL_RDY || pSoldier->usAnimState == WALKING_DUAL_RDY ) - { - fAimAfterMove = TRUE; - pSoldier->usPendingAnimation = AIM_DUAL_STAND; - pSoldier->ubPendingDirection = pSoldier->ubDirection; - } - - // OK, if we are the selected soldier, refresh some UI stuff - if ( pSoldier->ubID == (UINT8)gusSelectedSoldier ) - { - gfUIRefreshArrows = TRUE; - } - - // ATE: Play landing sound..... - if ( pSoldier->usAnimState == JUMP_OVER_BLOCKING_PERSON || pSoldier->usAnimState == LONG_JUMP ) - { - PlaySoldierFootstepSound( pSoldier ); - } - - // If we are a robot, play stop sound... - if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT ) - { - PlaySoldierJA2Sample( pSoldier->ubID, ROBOT_STOP, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE ); - } - - // Update to middle if we're on destination - dXPos = pSoldier->pathing.sDestXPos; - dYPos = pSoldier->pathing.sDestYPos; - pSoldier->EVENT_SetSoldierPosition( dXPos, dYPos ); -#ifdef NETWORKED - // DEF: Test Code - StopSoldierMovementTime(pSoldier); -#endif - - // Handle New sight - //HandleSight(pSoldier,SIGHT_LOOK | SIGHT_RADIO ); - - // CHECK IF WE HAVE A PENDING ANIMATION - if ( pSoldier->usPendingAnimation != NO_PENDING_ANIMATION ) - { - pSoldier->ChangeSoldierState( pSoldier->usPendingAnimation, 0 , FALSE ); - pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; - - if ( pSoldier->ubPendingDirection != NO_PENDING_DIRECTION ) - { - pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubPendingDirection ); - pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; - } - - } - - // CHECK IF WE HAVE A PENDING ACTION - if ( pSoldier->ubWaitActionToDo ) - { - if ( pSoldier->ubWaitActionToDo == 2 ) - { - pSoldier->ubWaitActionToDo = 1; - - if ( gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALKOFF_SCREEN ) - { - // ATE wanted this line here... - pSoldier->pathing.usPathIndex--; - AdjustSoldierPathToGoOffEdge( pSoldier, pSoldier->sGridNo, (UINT8)pSoldier->aiData.uiPendingActionData1 ); - continue; - } - } - else if ( pSoldier->ubWaitActionToDo == 1 ) - { - pSoldier->ubWaitActionToDo = 0; - - gbNumMercsUntilWaitingOver--; - - pSoldier->SoldierGotoStationaryStance( ); - - // If we are at an exit-grid, make disappear..... - if ( gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO ) - { - // Remove! - RemoveSoldierFromTacticalSector( pSoldier, TRUE ); - } - } - } - else if ( pSoldier->aiData.ubPendingAction != NO_PENDING_ACTION ) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("We are inside the IF PENDING Animation with soldier #%d", pSoldier->ubID) ); - - if ( pSoldier->aiData.ubPendingAction == MERC_OPENDOOR || pSoldier->aiData.ubPendingAction == MERC_OPENSTRUCT ) - { - sGridNo = pSoldier->aiData.sPendingActionData2; - //usStructureID = (UINT16)pSoldier->aiData.uiPendingActionData1; - //pStructure = FindStructureByID( sGridNo, usStructureID ); - - // LOOK FOR STRUCT OPENABLE - pStructure = FindStructure( sGridNo, STRUCTURE_OPENABLE ); - - if ( pStructure == NULL ) - { + if ( pStructure == NULL ) + { #ifdef JA2BETAVERSION - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Told to open struct at %d and none was found", sGridNo ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Told to open struct at %d and none was found", sGridNo ); #endif - fKeepMoving = FALSE; - } - else - { - CalcInteractiveObjectAPs( pSoldier, sGridNo, pStructure, &sAPCost, &sBPCost ); // SANDRO - added argument + fKeepMoving = FALSE; + } + else + { + CalcInteractiveObjectAPs( pSoldier, sGridNo, pStructure, &sAPCost, &sBPCost ); // SANDRO - added argument - if ( EnoughPoints( pSoldier, sAPCost, sBPCost , TRUE ) ) - { - InteractWithInteractiveObject( pSoldier, pStructure, pSoldier->aiData.bPendingActionData3 ); - } - else - { - fNoAPsForPendingAction = TRUE; - } - } - } - if ( pSoldier->aiData.ubPendingAction == MERC_PICKUPITEM ) - { - sGridNo = pSoldier->aiData.sPendingActionData2; + if ( EnoughPoints( pSoldier, sAPCost, sBPCost , TRUE ) ) + { + InteractWithInteractiveObject( pSoldier, pStructure, pSoldier->aiData.bPendingActionData3 ); + } + else + { + fNoAPsForPendingAction = TRUE; + } + } + } + if ( pSoldier->aiData.ubPendingAction == MERC_PICKUPITEM ) + { + sGridNo = pSoldier->aiData.sPendingActionData2; - if ( sGridNo == pSoldier->sGridNo ) - { - // OK, now, if in realtime - if ( !( gTacticalStatus.uiFlags & INCOMBAT ) ) - { - // If the two gridnos are not the same, check to see if we can - // now go into it - if ( sGridNo != (pSoldier->aiData.uiPendingActionData4 )) - { - if ( NewOKDestination( pSoldier, pSoldier->aiData.uiPendingActionData4, TRUE, pSoldier->pathing.bLevel ) ) - { - // GOTO NEW TILE! - SoldierPickupItem( pSoldier, pSoldier->aiData.uiPendingActionData1, pSoldier->aiData.uiPendingActionData4, pSoldier->aiData.bPendingActionData3 ); - continue; - } - } - } + if ( sGridNo == pSoldier->sGridNo ) + { + // OK, now, if in realtime + if ( !( gTacticalStatus.uiFlags & INCOMBAT ) ) + { + // If the two gridnos are not the same, check to see if we can + // now go into it + if ( sGridNo != (pSoldier->aiData.uiPendingActionData4 )) + { + if ( NewOKDestination( pSoldier, pSoldier->aiData.uiPendingActionData4, TRUE, pSoldier->pathing.bLevel ) ) + { + // GOTO NEW TILE! + SoldierPickupItem( pSoldier, pSoldier->aiData.uiPendingActionData1, pSoldier->aiData.uiPendingActionData4, pSoldier->aiData.bPendingActionData3 ); + continue; + } + } + } - // OK MORON, DOUBLE CHECK THAT THE ITEM EXISTS HERE... - if ( pSoldier->aiData.uiPendingActionData1 != ITEM_PICKUP_ACTION_ALL ) - { - //if ( ItemExistsAtLocation( (INT16)( pSoldier->aiData.uiPendingActionData4 ), pSoldier->aiData.uiPendingActionData1, pSoldier->pathing.bLevel ) ) - { - PickPickupAnimation( pSoldier, pSoldier->aiData.uiPendingActionData1, pSoldier->aiData.uiPendingActionData4, pSoldier->aiData.bPendingActionData3 ); - } - } - else - { - PickPickupAnimation( pSoldier, pSoldier->aiData.uiPendingActionData1, pSoldier->aiData.uiPendingActionData4, pSoldier->aiData.bPendingActionData3 ); - } - } - else - { - pSoldier->SoldierGotoStationaryStance( ); - } - } - else if ( pSoldier->aiData.ubPendingAction == MERC_PUNCH ) - { - // for the benefit of the AI - pSoldier->aiData.bAction = AI_ACTION_KNIFE_STAB; + // OK MORON, DOUBLE CHECK THAT THE ITEM EXISTS HERE... + if ( pSoldier->aiData.uiPendingActionData1 != ITEM_PICKUP_ACTION_ALL ) + { + PickPickupAnimation( pSoldier, pSoldier->aiData.uiPendingActionData1, pSoldier->aiData.uiPendingActionData4, pSoldier->aiData.bPendingActionData3 ); + } + else + { + PickPickupAnimation( pSoldier, pSoldier->aiData.uiPendingActionData1, pSoldier->aiData.uiPendingActionData4, pSoldier->aiData.bPendingActionData3 ); + } + } + else + { + pSoldier->SoldierGotoStationaryStance( ); + } + } + else if ( pSoldier->aiData.ubPendingAction == MERC_PUNCH ) + { + // for the benefit of the AI + pSoldier->aiData.bAction = AI_ACTION_KNIFE_STAB; - pSoldier->EVENT_SoldierBeginPunchAttack( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_TALK ) - { - pSoldier->PlayerSoldierStartTalking( (UINT8)pSoldier->aiData.uiPendingActionData1, TRUE ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_DROPBOMB ) - { - pSoldier->EVENT_SoldierBeginDropBomb( ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_STEAL ) - { - //pSoldier->pathing.bDesiredDirection = pSoldier->aiData.bPendingActionData3; - pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->aiData.bPendingActionData3 ); - // if we are crouching or prone, use steal in crouch - if ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE || gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_CROUCH ) - { - pSoldier->EVENT_InitNewSoldierAnim( STEAL_ITEM_CROUCHED, 0 , FALSE ); - } - else // otherwise determine our target position - { - SOLDIERTYPE *pTarget; - UINT16 usSoldierIndex; - usSoldierIndex = WhoIsThere2( pSoldier->aiData.sPendingActionData2, pSoldier->pathing.bLevel ); - if ( usSoldierIndex != NOBODY ) - { - pTarget = MercPtrs[ usSoldierIndex ]; + pSoldier->EVENT_SoldierBeginPunchAttack( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_TALK ) + { + pSoldier->PlayerSoldierStartTalking( (UINT8)pSoldier->aiData.uiPendingActionData1, TRUE ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_DROPBOMB ) + { + pSoldier->EVENT_SoldierBeginDropBomb( ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_STEAL ) + { + //pSoldier->pathing.bDesiredDirection = pSoldier->aiData.bPendingActionData3; + pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->aiData.bPendingActionData3 ); + // if we are crouching or prone, use steal in crouch + if ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE || gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_CROUCH ) + { + pSoldier->EVENT_InitNewSoldierAnim( STEAL_ITEM_CROUCHED, 0 , FALSE ); + } + else // otherwise determine our target position + { + SOLDIERTYPE *pTarget; + UINT16 usSoldierIndex; + usSoldierIndex = WhoIsThere2( pSoldier->aiData.sPendingActionData2, pSoldier->pathing.bLevel ); + if ( usSoldierIndex != NOBODY ) + { + pTarget = MercPtrs[ usSoldierIndex ]; - // we always need to crouch to prone target - if ( gAnimControl[ pTarget->usAnimState ].ubEndHeight == ANIM_PRONE ) - pSoldier->EVENT_InitNewSoldierAnim( STEAL_ITEM_CROUCHED, 0 , FALSE ); - else - pSoldier->EVENT_InitNewSoldierAnim( STEAL_ITEM, 0 , FALSE ); - } - else // strange things can happe?? - { - pSoldier->EVENT_InitNewSoldierAnim( STEAL_ITEM, 0 , FALSE ); - } + // we always need to crouch to prone target + if ( gAnimControl[ pTarget->usAnimState ].ubEndHeight == ANIM_PRONE ) + pSoldier->EVENT_InitNewSoldierAnim( STEAL_ITEM_CROUCHED, 0 , FALSE ); + else + pSoldier->EVENT_InitNewSoldierAnim( STEAL_ITEM, 0 , FALSE ); + } + else // strange things can happe?? + { + pSoldier->EVENT_InitNewSoldierAnim( STEAL_ITEM, 0 , FALSE ); + } - } - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_KNIFEATTACK) - { - // for the benefit of the AI - pSoldier->aiData.bAction = AI_ACTION_KNIFE_STAB; + } + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_KNIFEATTACK) + { + // for the benefit of the AI + pSoldier->aiData.bAction = AI_ACTION_KNIFE_STAB; - pSoldier->EVENT_SoldierBeginBladeAttack( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_GIVEAID ) - { - pSoldier->EVENT_SoldierBeginFirstAid( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_REPAIR ) - { - pSoldier->EVENT_SoldierBeginRepair( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_FUEL_VEHICLE ) - { - pSoldier->EVENT_SoldierBeginRefuel( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_RELOADROBOT ) - { - pSoldier->EVENT_SoldierBeginReloadRobot( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3, (INT8)pSoldier->aiData.uiPendingActionData1 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_TAKEBLOOD ) - { - pSoldier->EVENT_SoldierBeginTakeBlood( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_ATTACH_CAN ) - { - pSoldier->EVENT_SoldierBeginAttachCan( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_ENTER_VEHICLE ) - { - pSoldier->EVENT_SoldierEnterVehicle( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - continue; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_CUTFFENCE ) - { - pSoldier->EVENT_SoldierBeginCutFence( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_BUILD_FORTIFICATION ) - { - pSoldier->EVENT_SoldierBuildStructure( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_HANDCUFF_PERSON ) - { - pSoldier->EVENT_SoldierHandcuffPerson( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_APPLYITEM ) - { - pSoldier->EVENT_SoldierApplyItemToPerson( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else if ( pSoldier->aiData.ubPendingAction == MERC_GIVEITEM ) - { - pSoldier->EVENT_SoldierBeginGiveItem( ); - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } + pSoldier->EVENT_SoldierBeginBladeAttack( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_GIVEAID ) + { + pSoldier->EVENT_SoldierBeginFirstAid( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_REPAIR ) + { + pSoldier->EVENT_SoldierBeginRepair( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_FUEL_VEHICLE ) + { + pSoldier->EVENT_SoldierBeginRefuel( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_RELOADROBOT ) + { + pSoldier->EVENT_SoldierBeginReloadRobot( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3, (INT8)pSoldier->aiData.uiPendingActionData1 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_TAKEBLOOD ) + { + pSoldier->EVENT_SoldierBeginTakeBlood( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_ATTACH_CAN ) + { + pSoldier->EVENT_SoldierBeginAttachCan( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_ENTER_VEHICLE ) + { + pSoldier->EVENT_SoldierEnterVehicle( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + continue; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_CUTFFENCE ) + { + pSoldier->EVENT_SoldierBeginCutFence( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_BUILD_FORTIFICATION ) + { + pSoldier->EVENT_SoldierBuildStructure( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_HANDCUFF_PERSON ) + { + pSoldier->EVENT_SoldierHandcuffPerson( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_APPLYITEM ) + { + pSoldier->EVENT_SoldierApplyItemToPerson( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else if ( pSoldier->aiData.ubPendingAction == MERC_GIVEITEM ) + { + pSoldier->EVENT_SoldierBeginGiveItem( ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } - if ( fNoAPsForPendingAction ) - { - // Change status of guy to waiting - HaltMoveForSoldierOutOfPoints( pSoldier ); - fKeepMoving = FALSE; - pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; - pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; - } + if ( fNoAPsForPendingAction ) + { + // Change status of guy to waiting + HaltMoveForSoldierOutOfPoints( pSoldier ); + fKeepMoving = FALSE; + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; + } - } - else - { - // OK, ADJUST TO STANDING, WE ARE DONE - // DO NOTHING IF WE ARE UNCONSCIOUS - if ( pSoldier->stats.bLife >= OKLIFE ) - { - if ( pSoldier->ubBodyType == CROW ) - { - // If we are flying, don't stop! - if ( pSoldier->sHeightAdjustment == 0 ) - { - pSoldier->SoldierGotoStationaryStance( ); - } - } - else - { - UnSetUIBusy( pSoldier->ubID ); + } + else + { + // OK, ADJUST TO STANDING, WE ARE DONE + // DO NOTHING IF WE ARE UNCONSCIOUS + if ( pSoldier->stats.bLife >= OKLIFE ) + { + if ( pSoldier->ubBodyType == CROW ) + { + // If we are flying, don't stop! + if ( pSoldier->sHeightAdjustment == 0 ) + { + pSoldier->SoldierGotoStationaryStance( ); + } + } + else + { + UnSetUIBusy( pSoldier->ubID ); - if ( !fAimAfterMove ) // SANDRO - don't do this after movement with weapon raised - { - // Flugente: if in turnbased combat and option is selected, do not go to standing animation - // By this, we wont have to spend additional APs when we continue to run - if ( gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT && gGameExternalOptions.fNoStandingAnimAdjustInCombat && !pSoldier->bCollapsed && !pSoldier->bBreathCollapsed ) - { - // Flugente: We have to decide depending on the animation we have, otherwise we canc ause bugs if we do this after being hit by an explosion etc. - BOOLEAN dontadjustanim = FALSE; - switch ( pSoldier->usAnimState ) - { - case WALKING: - case CROUCHING: - case SWATTING: - case RUNNING: - case CRAWLING: - case END_HURT_WALKING: - case SWAT_BACKWARDS: - case SWATTING_WK: - case SWAT_BACKWARDS_WK: - case SWAT_BACKWARDS_NOTHING: - case RUNNING_W_PISTOL: - case SIDE_STEP_WEAPON_RDY: - case SIDE_STEP_DUAL_RDY: - case WALKING_WEAPON_RDY: - case WALKING_DUAL_RDY: - case WALKING_ALTERNATIVE_RDY: - case SIDE_STEP_ALTERNATIVE_RDY: - dontadjustanim = TRUE; - break; - } + if ( !fAimAfterMove ) // SANDRO - don't do this after movement with weapon raised + { + // Flugente: if in turnbased combat and option is selected, do not go to standing animation + // By this, we wont have to spend additional APs when we continue to run + if ( gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT && gGameExternalOptions.fNoStandingAnimAdjustInCombat && + !pSoldier->bCollapsed && !pSoldier->bBreathCollapsed ) + { + // Flugente: We have to decide depending on the animation we have, otherwise we canc ause bugs if we do this after being hit by an explosion etc. + BOOLEAN dontadjustanim = FALSE; + switch ( pSoldier->usAnimState ) + { + case WALKING: + case CROUCHING: + case SWATTING: + case RUNNING: + case CRAWLING: + case END_HURT_WALKING: + case SWAT_BACKWARDS: + case SWATTING_WK: + case SWAT_BACKWARDS_WK: + case SWAT_BACKWARDS_NOTHING: + case RUNNING_W_PISTOL: + case SIDE_STEP_WEAPON_RDY: + case SIDE_STEP_DUAL_RDY: + case WALKING_WEAPON_RDY: + case WALKING_DUAL_RDY: + case WALKING_ALTERNATIVE_RDY: + case SIDE_STEP_ALTERNATIVE_RDY: + dontadjustanim = TRUE; + break; + } - if ( dontadjustanim ) - { - pSoldier->AdjustNoAPToFinishMove( TRUE ); + if ( dontadjustanim ) + { + pSoldier->AdjustNoAPToFinishMove( TRUE ); - pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; - pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } - else - pSoldier->SoldierGotoStationaryStance( ); - } - else - pSoldier->SoldierGotoStationaryStance( ); - } - } - } - } + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } + else + pSoldier->SoldierGotoStationaryStance( ); + } + else + pSoldier->SoldierGotoStationaryStance( ); + } + } + } + } - // RESET MOVE FAST FLAG - if ( (pSoldier->ubProfile == NO_PROFILE) ) - { - pSoldier->flags.fUIMovementFast = FALSE; - } + // RESET MOVE FAST FLAG + if ( (pSoldier->ubProfile == NO_PROFILE) ) + { + pSoldier->flags.fUIMovementFast = FALSE; + } - // if AI moving and waiting to process something at end of - // move, have them handled the very next frame - if (pSoldier->ubQuoteActionID == QUOTE_ACTION_ID_CHECKFORDEST) - { - pSoldier->aiData.fAIFlags |= AI_HANDLE_EVERY_FRAME; - } + // if AI moving and waiting to process something at end of + // move, have them handled the very next frame + if (pSoldier->ubQuoteActionID == QUOTE_ACTION_ID_CHECKFORDEST) + { + pSoldier->aiData.fAIFlags |= AI_HANDLE_EVERY_FRAME; + } - fKeepMoving = FALSE; - } - else if ( !pSoldier->flags.fNoAPToFinishMove ) - { - // Increment path.... - pSoldier->pathing.usPathIndex++; + fKeepMoving = FALSE; + } + else if ( !pSoldier->flags.fNoAPToFinishMove ) + { + // Increment path.... + pSoldier->pathing.usPathIndex++; - if ( pSoldier->pathing.usPathIndex > pSoldier->pathing.usPathDataSize ) - { - pSoldier->pathing.usPathIndex = pSoldier->pathing.usPathDataSize; - } + if ( pSoldier->pathing.usPathIndex > pSoldier->pathing.usPathDataSize ) + { + pSoldier->pathing.usPathIndex = pSoldier->pathing.usPathDataSize; + } - // Are we at the end? - if ( pSoldier->pathing.usPathIndex == pSoldier->pathing.usPathDataSize ) - { - // ATE: Pop up warning.... - if ( pSoldier->pathing.usPathDataSize != MAX_PATH_LIST_SIZE ) - { + // Are we at the end? + if ( pSoldier->pathing.usPathIndex == pSoldier->pathing.usPathDataSize ) + { + // ATE: Pop up warning.... + if ( pSoldier->pathing.usPathDataSize != MAX_PATH_LIST_SIZE ) + { #ifdef JA2BETAVERSION - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Path for %s ( %d ) did not make merc get to dest (%d spaces away).", pSoldier->GetName(), pSoldier->ubID, PythSpacesAway( pSoldier->pathing.sFinalDestination, pSoldier->sGridNo) ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Path for %s ( %d ) did not make merc get to dest (%d spaces away).", + pSoldier->GetName(), pSoldier->ubID, PythSpacesAway( pSoldier->pathing.sFinalDestination, pSoldier->sGridNo) ); #endif - } + } - // In case this is an AI person with the path-stored flag set, - // turn it OFF since we have exhausted our stored path - pSoldier->pathing.bPathStored = FALSE; - if (!TileIsOutOfBounds(pSoldier->sAbsoluteFinalDestination)) - { - // We have not made it to our dest... but it's better to let the AI handle this itself, - // on the very next fram - pSoldier->aiData.fAIFlags |= AI_HANDLE_EVERY_FRAME; - } - else - { - // ATE: Added this to fcalilitate the fact - // that our final dest may now have people on it.... - // 0verhaul: But what if this is turn-based? The soldier may be waiting forever for - // the other one to leave the position, but since it's turn-based he never will. - // Is that an issue here? - // Yes, I think it is. I found a situation where the soldier's path led through another - // soldier. The other soldier wasn't even at the destination but his path invariably - // led through that soldier. Since this was set up to allow that, he ended up deadlocked - // in "take cover" mode waiting for the soldier right next to him to leave. - // So in turn-based mode, we will just allow the soldier to re-think his next move. - if ( gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) - { - ActionDone( pSoldier); - pSoldier->SoldierGotoStationaryStance( ); - continue; - } - else - { - if ( FindBestPath( pSoldier, pSoldier->pathing.sFinalDestination, pSoldier->pathing.bLevel, pSoldier->usUIMovementMode, NO_COPYROUTE, PATH_THROUGH_PEOPLE ) != 0 ) - { - INT32 sNewGridNo; + // In case this is an AI person with the path-stored flag set, + // turn it OFF since we have exhausted our stored path + pSoldier->pathing.bPathStored = FALSE; + if (!TileIsOutOfBounds(pSoldier->sAbsoluteFinalDestination)) + { + // We have not made it to our dest... but it's better to let the AI handle this itself, + // on the very next fram + pSoldier->aiData.fAIFlags |= AI_HANDLE_EVERY_FRAME; + } + else + { + // ATE: Added this to fcalilitate the fact + // that our final dest may now have people on it.... + // 0verhaul: But what if this is turn-based? The soldier may be waiting forever for + // the other one to leave the position, but since it's turn-based he never will. + // Is that an issue here? + // Yes, I think it is. I found a situation where the soldier's path led through another + // soldier. The other soldier wasn't even at the destination but his path invariably + // led through that soldier. Since this was set up to allow that, he ended up deadlocked + // in "take cover" mode waiting for the soldier right next to him to leave. + // So in turn-based mode, we will just allow the soldier to re-think his next move. + if ( gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) + { + ActionDone( pSoldier); + pSoldier->SoldierGotoStationaryStance( ); + continue; + } + else + { + if ( FindBestPath( pSoldier, pSoldier->pathing.sFinalDestination, pSoldier->pathing.bLevel, pSoldier->usUIMovementMode, + NO_COPYROUTE, PATH_THROUGH_PEOPLE ) != 0 ) + { + INT32 sNewGridNo; + sNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( (UINT8)guiPathingData[ 0 ] ) ); + SetDelayedTileWaiting( pSoldier, sNewGridNo, 1 ); + } - sNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( (UINT8)guiPathingData[ 0 ] ) ); + // We have not made it to our dest... set flag that we are waiting.... + if ( !pSoldier->EVENT_InternalGetNewSoldierPath( pSoldier->pathing.sFinalDestination, pSoldier->usUIMovementMode, 2, FALSE ) ) + { + // ATE: To do here.... we could not get path, so we have to stop + // 0verhaul: May also need to clear the action type so that the soldier will know + // to re-think another move instead of waiting for nothing to finish happening. + pSoldier->SoldierGotoStationaryStance( ); + continue; + } + } + } + } + else + { + // OK, Now find another dest grindo.... + if ( !( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_SPECIALMOVE ) ) + { + // OK, now we want to see if we can continue to another tile... + if ( !HandleGotoNewGridNo( pSoldier, &fKeepMoving, FALSE, pSoldier->usAnimState ) ) + { + continue; + } + } + else + { + // Change desired direction + // Just change direction + pSoldier->EVENT_InternalSetSoldierDestination( (UINT8) pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ], FALSE, pSoldier->usAnimState ); + } - SetDelayedTileWaiting( pSoldier, sNewGridNo, 1 ); - } + if ( gTacticalStatus.bBoxingState != NOT_BOXING && (gTacticalStatus.bBoxingState == BOXING_WAITING_FOR_PLAYER || + gTacticalStatus.bBoxingState == PRE_BOXING || gTacticalStatus.bBoxingState == BOXING) ) + { + BoxingMovementCheck( pSoldier ); + } + } + } + } - // We have not made it to our dest... set flag that we are waiting.... - if ( !pSoldier->EVENT_InternalGetNewSoldierPath( pSoldier->pathing.sFinalDestination, pSoldier->usUIMovementMode, 2, FALSE ) ) - { - // ATE: To do here.... we could not get path, so we have to stop - // 0verhaul: May also need to clear the action type so that the soldier will know - // to re-think another move instead of waiting for nothing to finish happening. - pSoldier->SoldierGotoStationaryStance( ); - continue; - } - } - } - } - else - { - // OK, Now find another dest grindo.... - if ( !( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_SPECIALMOVE ) ) - { - // OK, now we want to see if we can continue to another tile... - if ( !HandleGotoNewGridNo( pSoldier, &fKeepMoving, FALSE, pSoldier->usAnimState ) ) - { - continue; - } - } - else - { - // Change desired direction - // Just change direction - pSoldier->EVENT_InternalSetSoldierDestination( (UINT8) pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ], FALSE, pSoldier->usAnimState ); - } + if ( ( pSoldier->flags.uiStatusFlags & SOLDIER_PAUSEANIMOVE ) ) + { + fKeepMoving = FALSE; + } - if ( gTacticalStatus.bBoxingState != NOT_BOXING && (gTacticalStatus.bBoxingState == BOXING_WAITING_FOR_PLAYER || gTacticalStatus.bBoxingState == PRE_BOXING || gTacticalStatus.bBoxingState == BOXING) ) - { - BoxingMovementCheck( pSoldier ); - } - } - } - } + BOOLEAN executeCondition = FALSE; - if ( ( pSoldier->flags.uiStatusFlags & SOLDIER_PAUSEANIMOVE ) ) - { - fKeepMoving = FALSE; - } + if (is_networked) + { + if ( !pSoldier->flags.fPausedMove && fKeepMoving && !pSoldier->flags.fNoAPToFinishMove ) + executeCondition = TRUE; + } + else + { + if ( !pSoldier->flags.fPausedMove && fKeepMoving ) + executeCondition = TRUE; + } - BOOLEAN executeCondition = FALSE; + // DO WALKING + if ( executeCondition ) + { + // Determine deltas + // dDeltaX = pSoldier->pathing.sDestXPos - pSoldier->dXPos; + //dDeltaY = pSoldier->pathing.sDestYPos - pSoldier->dYPos; - if (is_networked) - { - if ( !pSoldier->flags.fPausedMove && fKeepMoving && !pSoldier->flags.fNoAPToFinishMove ) - executeCondition = TRUE; - } - else - { - if ( !pSoldier->flags.fPausedMove && fKeepMoving ) - executeCondition = TRUE; - } + // Determine angle + // dAngle = (FLOAT)atan2( dDeltaX, dDeltaY ); + dAngle = gdRadiansForAngle[ pSoldier->bMovementDirection ]; - // DO WALKING - if ( executeCondition ) - { - // Determine deltas - // dDeltaX = pSoldier->pathing.sDestXPos - pSoldier->dXPos; - //dDeltaY = pSoldier->pathing.sDestYPos - pSoldier->dYPos; + // For walking, base it on body type! + if ( pSoldier->usAnimState == WALKING || + pSoldier->usAnimState == WALKING_WEAPON_RDY || + pSoldier->usAnimState == WALKING_DUAL_RDY || + pSoldier->usAnimState == WALKING_ALTERNATIVE_RDY ) + { + pSoldier->MoveMerc( gubAnimWalkSpeeds[ pSoldier->ubBodyType ].dMovementChange, dAngle, TRUE ); - // Determine angle - // dAngle = (FLOAT)atan2( dDeltaX, dDeltaY ); - - - dAngle = gdRadiansForAngle[ pSoldier->bMovementDirection ]; - - // For walking, base it on body type! - if ( pSoldier->usAnimState == WALKING || - pSoldier->usAnimState == WALKING_WEAPON_RDY || - pSoldier->usAnimState == WALKING_DUAL_RDY || - pSoldier->usAnimState == WALKING_ALTERNATIVE_RDY ) - { - pSoldier->MoveMerc( gubAnimWalkSpeeds[ pSoldier->ubBodyType ].dMovementChange, dAngle, TRUE ); - - } - else - { - pSoldier->MoveMerc( gAnimControl[ pSoldier->usAnimState ].dMovementChange, dAngle, TRUE ); - } - } - - } - - // Check for direction change - if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_TURNING ) - { - pSoldier->TurnSoldier( ); - } - } + } + else + { + pSoldier->MoveMerc( gAnimControl[ pSoldier->usAnimState ].dMovementChange, dAngle, TRUE ); + } + } + } + // Check for direction change + if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_TURNING ) + { + pSoldier->TurnSoldier( ); + } + } #ifdef NETWORKED - if(!pSoldier->flags.fNoAPToFinishMove ) - pSoldier->usLastUpdateTime = GetJA2Clock(); - if (pSoldier->flags.fSoldierUpdatedFromNetwork) - UpdateSoldierFromNetwork(pSoldier); + if(!pSoldier->flags.fNoAPToFinishMove ) + pSoldier->usLastUpdateTime = GetJA2Clock(); + if (pSoldier->flags.fSoldierUpdatedFromNetwork) + UpdateSoldierFromNetwork(pSoldier); #endif -//haydens network soldier update ->> - if(is_client)UpdateSoldierToNetwork ( pSoldier ); -// - } + //haydens network soldier update ->> + if(is_client) + UpdateSoldierToNetwork ( pSoldier ); + } - } - if ( !gfPauseAllAI && - ( ((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) || (fHandleAI && guiAISlotToHandle == cnt) || (pSoldier->aiData.fAIFlags & AI_HANDLE_EVERY_FRAME) || gTacticalStatus.fAutoBandageMode ) ) - { - HandleSoldierAI( pSoldier ); - if ( !((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) ) - { - if (GetJA2Clock() - iTimerVal > RT_AI_TIMESLICE) - { - // don't do any more AI this time! - fHandleAI = FALSE; - } - else - { - // we still have time to handle AI; skip to the next person - fHandleAI = NextAIToHandle( guiAISlotToHandle ); - } - } - } + if ( !gfPauseAllAI && + ( ((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) || + (fHandleAI && guiAISlotToHandle == cnt) || (pSoldier->aiData.fAIFlags & AI_HANDLE_EVERY_FRAME) || gTacticalStatus.fAutoBandageMode ) ) + { + HandleSoldierAI( pSoldier ); + if ( !((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) ) + { + if (GetJA2Clock() - iTimerVal > RT_AI_TIMESLICE) + { + // don't do any more AI this time! + fHandleAI = FALSE; + } + else + { + // we still have time to handle AI; skip to the next person + fHandleAI = NextAIToHandle( guiAISlotToHandle ); + } + } + } + } + } - } + if ( guiNumAwaySlots > 0 && !gfPauseAllAI && !(gTacticalStatus.uiFlags & INCOMBAT) && guiAISlotToHandle == HANDLE_OFF_MAP_MERC && guiAIAwaySlotToHandle != RESET_HANDLE_OF_OFF_MAP_MERCS ) + { + pSoldier = AwaySlots[ guiAIAwaySlotToHandle ]; - } + // Syncronize for upcoming soldier counters + SYNCTIMECOUNTER( ); - if ( guiNumAwaySlots > 0 && !gfPauseAllAI && !(gTacticalStatus.uiFlags & INCOMBAT) && guiAISlotToHandle == HANDLE_OFF_MAP_MERC && guiAIAwaySlotToHandle != RESET_HANDLE_OF_OFF_MAP_MERCS ) - { - pSoldier = AwaySlots[ guiAIAwaySlotToHandle ]; + if ( pSoldier != NULL ) + { + // the ONLY thing to do with away soldiers is process their schedule if they have one + // and there is an action for them to do (like go on-sector) + if (pSoldier->aiData.fAIFlags & AI_CHECK_SCHEDULE) + { + HandleSoldierAI( pSoldier ); + } + } + } - // Syncronize for upcoming soldier counters - SYNCTIMECOUNTER( ); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // SANDRO - hack! - resolve possible pending interrupt + if(GetSoldier(&pSoldier, gusSelectedSoldier) && gGameOptions.fImprovedInterruptSystem ) + { + if ( pSoldier->bActive ) + { + if ( ResolvePendingInterrupt( pSoldier, UNDEFINED_INTERRUPT ) ) + { + fKeepMoving = FALSE; + pSoldier->AdjustNoAPToFinishMove( TRUE ); + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; - if ( pSoldier != NULL ) - { - // the ONLY thing to do with away soldiers is process their schedule if they have one - // and there is an action for them to do (like go on-sector) - if (pSoldier->aiData.fAIFlags & AI_CHECK_SCHEDULE) - { - HandleSoldierAI( pSoldier ); - } - } - } + // "artificially" set lock ui flag in this case + if (pSoldier->bTeam == gbPlayerNum) + { + //AddTopMessage( COMPUTER_INTERRUPT_MESSAGE, Message[STR_INTERRUPT] ); + guiPendingOverrideEvent = LU_BEGINUILOCK; + HandleTacticalUI( ); + } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // SANDRO - hack! - resolve possible pending interrupt - if(GetSoldier(&pSoldier, gusSelectedSoldier) && gGameOptions.fImprovedInterruptSystem ) - { - if ( pSoldier->bActive ) - { - if ( ResolvePendingInterrupt( pSoldier, UNDEFINED_INTERRUPT ) ) - { - fKeepMoving = FALSE; - pSoldier->AdjustNoAPToFinishMove( TRUE ); - pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; - pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; + // return early + gubNPCAPBudget = 0; + gubNPCDistLimit = 0; - // "artificially" set lock ui flag in this case - if (pSoldier->bTeam == gbPlayerNum) - { - //AddTopMessage( COMPUTER_INTERRUPT_MESSAGE, Message[STR_INTERRUPT] ); - guiPendingOverrideEvent = LU_BEGINUILOCK; - HandleTacticalUI( ); - } + return( TRUE ); + } + } + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // return early - gubNPCAPBudget = 0; - gubNPCDistLimit = 0; + // Turn off auto bandage if we need to... + if ( gTacticalStatus.fAutoBandageMode ) + { + if ( !CanAutoBandage( TRUE) ) + { + SetAutoBandageComplete( ); + } + } - return( TRUE ); - } - } - } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - // Turn off auto bandage if we need to... - if ( gTacticalStatus.fAutoBandageMode ) - { - if ( !CanAutoBandage( TRUE) ) - { - SetAutoBandageComplete( ); - } - } - - // Check if we should be doing a special event once guys get to a location... - if ( gubWaitingForAllMercsToExitCode != 0 ) - { - // Check if we have gone past our time... - if ( ( GetJA2Clock( ) - guiWaitingForAllMercsToExitTimer ) > 2500 ) - { - // OK, set num waiting to 0 + // Check if we should be doing a special event once guys get to a location... + if ( gubWaitingForAllMercsToExitCode != 0 ) + { + // Check if we have gone past our time... + if ( ( GetJA2Clock( ) - guiWaitingForAllMercsToExitTimer ) > 2500 ) + { + // OK, set num waiting to 0 #ifdef JA2BETAVERSION - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_DEBUG, L"Waiting too long for Mercs to exit...forcing entry." ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_DEBUG, L"Waiting too long for Mercs to exit...forcing entry." ); #endif - gbNumMercsUntilWaitingOver = 0; + gbNumMercsUntilWaitingOver = 0; - // Reset all waitng codes - for ( cnt = 0; cnt < guiNumMercSlots; cnt++ ) - { - pSoldier = MercSlots[ cnt ]; - if ( pSoldier != NULL ) - { - pSoldier->ubWaitActionToDo = 0; - } - } + // Reset all waitng codes + for ( cnt = 0; cnt < guiNumMercSlots; cnt++ ) + { + pSoldier = MercSlots[ cnt ]; + if ( pSoldier != NULL ) + { + pSoldier->ubWaitActionToDo = 0; + } + } + } + } - } - } - - if ( gbNumMercsUntilWaitingOver == 0 ) - { - // ATE: Unset flag to ignore sight... - gTacticalStatus.uiFlags &= ( ~DISALLOW_SIGHT ); + if ( gbNumMercsUntilWaitingOver == 0 ) + { + // ATE: Unset flag to ignore sight... + gTacticalStatus.uiFlags &= ( ~DISALLOW_SIGHT ); - // OK cheif, do something here.... - switch( gubWaitingForAllMercsToExitCode ) - { - case WAIT_FOR_MERCS_TO_WALKOFF_SCREEN: + // OK cheif, do something here.... + switch( gubWaitingForAllMercsToExitCode ) + { + case WAIT_FOR_MERCS_TO_WALKOFF_SCREEN: - if ( ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) ) - { - guiPendingOverrideEvent = LU_ENDUILOCK; - HandleTacticalUI( ); - } - AllMercsHaveWalkedOffSector( ); - break; + if ( ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) ) + { + guiPendingOverrideEvent = LU_ENDUILOCK; + HandleTacticalUI( ); + } + AllMercsHaveWalkedOffSector( ); + break; - case WAIT_FOR_MERCS_TO_WALKON_SCREEN: + case WAIT_FOR_MERCS_TO_WALKON_SCREEN: - // OK, unset UI - if ( ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) ) - { - guiPendingOverrideEvent = LU_ENDUILOCK; - HandleTacticalUI( ); - } - break; + // OK, unset UI + if ( ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) ) + { + guiPendingOverrideEvent = LU_ENDUILOCK; + HandleTacticalUI( ); + } + break; - case WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO: + case WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO: - // OK, unset UI - if ( ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) ) - { - guiPendingOverrideEvent = LU_ENDUILOCK; - HandleTacticalUI( ); - } - AllMercsWalkedToExitGrid( ); - break; + // OK, unset UI + if ( ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) ) + { + guiPendingOverrideEvent = LU_ENDUILOCK; + HandleTacticalUI( ); + } + AllMercsWalkedToExitGrid( ); + break; - } + } - // ATE; Turn off tactical status flag... - gTacticalStatus.uiFlags &= ( ~IGNORE_ALL_OBSTACLES ); + // ATE; Turn off tactical status flag... + gTacticalStatus.uiFlags &= ( ~IGNORE_ALL_OBSTACLES ); - gubWaitingForAllMercsToExitCode = 0; - } - } - - - // reset these AI-related global variables to 0 to ensure they don't interfere with the UI - gubNPCAPBudget = 0; - gubNPCDistLimit = 0; - - return( TRUE ); + gubWaitingForAllMercsToExitCode = 0; + } + // reset these AI-related global variables to 0 to ensure they don't interfere with the UI + gubNPCAPBudget = 0; + gubNPCDistLimit = 0; + return( TRUE ); } void HaltGuyFromNewGridNoBecauseOfNoAPs( SOLDIERTYPE *pSoldier ) { - HaltMoveForSoldierOutOfPoints( pSoldier ); - pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; - pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - - UnMarkMovementReserved( pSoldier ); - - // Display message if our merc... - if ( pSoldier->bTeam == gbPlayerNum && ( gTacticalStatus.uiFlags & INCOMBAT ) ) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ GUY_HAS_RUN_OUT_OF_APS_STR ], pSoldier->GetName() ); - } - - UnSetUIBusy( pSoldier->ubID ); - - // OK, Unset engaged in CONV, something changed... - UnSetEngagedInConvFromPCAction( pSoldier ); - + HaltMoveForSoldierOutOfPoints( pSoldier ); + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + UnMarkMovementReserved( pSoldier ); + // Display message if our merc... + if ( pSoldier->bTeam == gbPlayerNum && ( gTacticalStatus.uiFlags & INCOMBAT ) ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ GUY_HAS_RUN_OUT_OF_APS_STR ], pSoldier->GetName() ); + } + UnSetUIBusy( pSoldier->ubID ); + // OK, Unset engaged in CONV, something changed... + UnSetEngagedInConvFromPCAction( pSoldier ); } - void HandleLocateToGuyAsHeWalks( SOLDIERTYPE *pSoldier ) { - // Our guys if option set, - if ( pSoldier->bTeam == gbPlayerNum ) - { - // IF tracking on, center on guy.... - if ( gGameSettings.fOptions[ TOPTION_TRACKING_MODE ] ) - { - LocateSoldier( pSoldier->ubID, FALSE ); - } - } - else - { - // Others if visible... - if ( pSoldier->bVisible != -1 ) - { - // ATE: If we are visible, and have not already removed roofs, goforit - if ( pSoldier->pathing.bLevel > 0 ) - { - if ( !( gTacticalStatus.uiFlags & SHOW_ALL_ROOFS ) ) - { - gTacticalStatus.uiFlags |= SHOW_ALL_ROOFS; - SetRenderFlags( RENDER_FLAG_FULL ); - } - } + // Our guys if option set, + if ( pSoldier->bTeam == gbPlayerNum ) + { + // IF tracking on, center on guy.... + if ( gGameSettings.fOptions[ TOPTION_TRACKING_MODE ] ) + { + LocateSoldier( pSoldier->ubID, FALSE ); + } + } + else + { + // Others if visible... + if ( pSoldier->bVisible != -1 ) + { + // ATE: If we are visible, and have not already removed roofs, goforit + if ( pSoldier->pathing.bLevel > 0 ) + { + if ( !( gTacticalStatus.uiFlags & SHOW_ALL_ROOFS ) ) + { + gTacticalStatus.uiFlags |= SHOW_ALL_ROOFS; + SetRenderFlags( RENDER_FLAG_FULL ); + } + } - LocateSoldier( pSoldier->ubID, FALSE ); - } - } + LocateSoldier( pSoldier->ubID, FALSE ); + } + } } #pragma optimize("gpt",on) -__forceinline + __forceinline BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLEAN fInitialMove, UINT16 usAnimState ) { - INT16 sAPCost; - INT16 sBPCost; - INT32 usNewGridNo, sOverFenceGridNo, sMineGridNo; + INT16 sAPCost; + INT16 sBPCost; + INT32 usNewGridNo, sOverFenceGridNo, sMineGridNo; - if (gTacticalStatus.uiFlags & INCOMBAT && fInitialMove ) - { - HandleLocateToGuyAsHeWalks( pSoldier ); - } + if (gTacticalStatus.uiFlags & INCOMBAT && fInitialMove ) + { + HandleLocateToGuyAsHeWalks( pSoldier ); + } - // Default to TRUE - (*pfKeepMoving ) = TRUE; + // Default to TRUE + (*pfKeepMoving ) = TRUE; - // Check for good breath.... - // if ( pSoldier->bBreath < OKBREATH && !fInitialMove ) - if ( pSoldier->bBreath < OKBREATH ) - { - // OK, first check for b== 0 - // If our currentd state is moving already....( this misses the first tile, so the user - // Sees some change in their click, but just one tile - if ( pSoldier->bBreath == 0 ) - { - // Collapse! - pSoldier->bBreathCollapsed = TRUE; - pSoldier->bEndDoorOpenCode = FALSE; + // Check for good breath.... + // if ( pSoldier->bBreath < OKBREATH && !fInitialMove ) + if ( pSoldier->bBreath < OKBREATH ) + { + // OK, first check for b== 0 + // If our currentd state is moving already....( this misses the first tile, so the user + // Sees some change in their click, but just one tile + if ( pSoldier->bBreath == 0 ) + { + // Collapse! + pSoldier->bBreathCollapsed = TRUE; + pSoldier->bEndDoorOpenCode = FALSE; - if ( fInitialMove ) - { - UnSetUIBusy( pSoldier->ubID ); - } + if ( fInitialMove ) + { + UnSetUIBusy( pSoldier->ubID ); + } - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: Out of Breath") ); - return( FALSE ); - } + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: Out of Breath") ); + return( FALSE ); + } - // OK, if we are collapsed now, check for OK breath instead... - if ( pSoldier->bCollapsed ) - { - // Collapse! - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: Has Collapsed") ); - pSoldier->bBreathCollapsed = TRUE; - pSoldier->bEndDoorOpenCode = FALSE; - return( FALSE ); - } + // OK, if we are collapsed now, check for OK breath instead... + if ( pSoldier->bCollapsed ) + { + // Collapse! + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: Has Collapsed") ); + pSoldier->bBreathCollapsed = TRUE; + pSoldier->bEndDoorOpenCode = FALSE; + return( FALSE ); + } - } + } - usNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ) ); + usNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ) ); - // OK, check if this is a fence cost.... - if ( gubWorldMovementCosts[ usNewGridNo ][ (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ][ pSoldier->pathing.bLevel ] == TRAVELCOST_FENCE ) - { - // We have been told to jump fence.... + // OK, check if this is a fence cost.... + if ( gubWorldMovementCosts[ usNewGridNo ][ (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ][ pSoldier->pathing.bLevel ] == TRAVELCOST_FENCE ) + { + // We have been told to jump fence.... - // Do we have APs? - // CHRISL: Added penalty for jumping a fence while wearing a backpack - // Do we have APs? - // SANDRO - changed the static values to precise calculation here - if((UsingNewInventorySystem() == true) && pSoldier->inv[BPACKPOCKPOS].exists() == true) - { - sAPCost = GetAPsToJumpFence( pSoldier, TRUE ); - sBPCost = GetBPsToJumpFence( pSoldier, TRUE ); - } - else - { - sAPCost = GetAPsToJumpFence( pSoldier, FALSE ); - sBPCost = GetBPsToJumpFence( pSoldier, FALSE ); - } + // Do we have APs? + // CHRISL: Added penalty for jumping a fence while wearing a backpack + // Do we have APs? + // SANDRO - changed the static values to precise calculation here + if((UsingNewInventorySystem() == true) && pSoldier->inv[BPACKPOCKPOS].exists() == true) + { + sAPCost = GetAPsToJumpFence( pSoldier, TRUE ); + sBPCost = GetBPsToJumpFence( pSoldier, TRUE ); + } + else + { + sAPCost = GetAPsToJumpFence( pSoldier, FALSE ); + sBPCost = GetBPsToJumpFence( pSoldier, FALSE ); + } - if ( EnoughPoints( pSoldier, sAPCost, sBPCost, FALSE ) ) - { - // ATE: Check for tile being clear.... - sOverFenceGridNo = NewGridNo( usNewGridNo, DirectionInc( (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex + 1 ] ) ); + if ( EnoughPoints( pSoldier, sAPCost, sBPCost, FALSE ) ) + { + // ATE: Check for tile being clear.... + sOverFenceGridNo = NewGridNo( usNewGridNo, DirectionInc( (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex + 1 ] ) ); - if ( HandleNextTile( pSoldier, (INT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex + 1 ], sOverFenceGridNo, pSoldier->pathing.sFinalDestination ) ) - { - // We do, adjust path data.... - pSoldier->pathing.usPathIndex++; - // We go two, because we really want to start moving towards the NEXT gridno, - // if we have any... + if ( HandleNextTile( pSoldier, (INT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex + 1 ], sOverFenceGridNo, pSoldier->pathing.sFinalDestination ) ) + { + // We do, adjust path data.... + pSoldier->pathing.usPathIndex++; + // We go two, because we really want to start moving towards the NEXT gridno, + // if we have any... - // LOCK PENDING ACTION COUNTER - pSoldier->flags.uiStatusFlags |= SOLDIER_LOCKPENDINGACTIONCOUNTER; + // LOCK PENDING ACTION COUNTER + pSoldier->flags.uiStatusFlags |= SOLDIER_LOCKPENDINGACTIONCOUNTER; - pSoldier->SoldierGotoStationaryStance( ); + pSoldier->SoldierGotoStationaryStance( ); - // OK, jump! - pSoldier->BeginSoldierClimbFence( ); + // OK, jump! + pSoldier->BeginSoldierClimbFence( ); - pSoldier->flags.fContinueMoveAfterStanceChange = 2; - } + pSoldier->flags.fContinueMoveAfterStanceChange = 2; + } - } - else - { - HaltGuyFromNewGridNoBecauseOfNoAPs( pSoldier ); - (*pfKeepMoving ) = FALSE; - } + } + else + { + HaltGuyFromNewGridNoBecauseOfNoAPs( pSoldier ); + (*pfKeepMoving ) = FALSE; + } - return( FALSE ); - } - else if ( InternalDoorTravelCost( pSoldier, usNewGridNo, gubWorldMovementCosts[ usNewGridNo ][ (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ][ pSoldier->pathing.bLevel ], (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), NULL, TRUE ) == TRAVELCOST_DOOR ) - { - STRUCTURE * pStructure; - INT8 bDirection; - INT32 sDoorGridNo; + return( FALSE ); + } + else if ( InternalDoorTravelCost( pSoldier, usNewGridNo, gubWorldMovementCosts[ usNewGridNo ][ (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ][ pSoldier->pathing.bLevel ], (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), NULL, TRUE ) == TRAVELCOST_DOOR ) + { + STRUCTURE * pStructure; + INT8 bDirection; + INT32 sDoorGridNo; - // OK, if we are here, we have been told to get a pth through a door. + // OK, if we are here, we have been told to get a pth through a door. - // No need to check if for AI + // No need to check if for AI - // No need to check for right key ( since the path checks for that? ) + // No need to check for right key ( since the path checks for that? ) - // Just for now play the $&&% animation - bDirection = (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ]; + // Just for now play the $&&% animation + bDirection = (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ]; - // OK, based on the direction, get door gridno - if ( bDirection == NORTH || bDirection == WEST ) - { - sDoorGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ) ); - } - else if ( bDirection == SOUTH || bDirection == EAST ) - { - sDoorGridNo = pSoldier->sGridNo; - } - else - { + // OK, based on the direction, get door gridno + if ( bDirection == NORTH || bDirection == WEST ) + { + sDoorGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ) ); + } + else if ( bDirection == SOUTH || bDirection == EAST ) + { + sDoorGridNo = pSoldier->sGridNo; + } + else + { #ifdef JA2TESTVERSION - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"ERROR: Invalid Direction to approach door. (Soldier loc: %d, dir: %d).", pSoldier->sGridNo, bDirection ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"ERROR: Invalid Direction to approach door. (Soldier loc: %d, dir: %d).", pSoldier->sGridNo, bDirection ); #endif - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: Open door - invalid approach direction") ); + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: Open door - invalid approach direction") ); - HaltGuyFromNewGridNoBecauseOfNoAPs( pSoldier ); - pSoldier->bEndDoorOpenCode = FALSE; - (*pfKeepMoving ) = FALSE; - return( FALSE ); - } + HaltGuyFromNewGridNoBecauseOfNoAPs( pSoldier ); + pSoldier->bEndDoorOpenCode = FALSE; + (*pfKeepMoving ) = FALSE; + return( FALSE ); + } - // Get door - pStructure = FindStructure( sDoorGridNo, STRUCTURE_ANYDOOR ); + // Get door + pStructure = FindStructure( sDoorGridNo, STRUCTURE_ANYDOOR ); - if ( pStructure == NULL ) - { + if ( pStructure == NULL ) + { #ifdef JA2TESTVERSION - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"ERROR: Told to open door that does not exist at %d.", sDoorGridNo ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"ERROR: Told to open door that does not exist at %d.", sDoorGridNo ); #endif - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: Door does not exist") ); - HaltGuyFromNewGridNoBecauseOfNoAPs( pSoldier ); - pSoldier->bEndDoorOpenCode = FALSE; - (*pfKeepMoving ) = FALSE; - return( FALSE ); - } + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: Door does not exist") ); + HaltGuyFromNewGridNoBecauseOfNoAPs( pSoldier ); + pSoldier->bEndDoorOpenCode = FALSE; + (*pfKeepMoving ) = FALSE; + return( FALSE ); + } - // OK, open! - StartInteractiveObject( sDoorGridNo, pStructure->usStructureID, pSoldier, bDirection ); - InteractWithInteractiveObject( pSoldier, pStructure, bDirection ); + // OK, open! + StartInteractiveObject( sDoorGridNo, pStructure->usStructureID, pSoldier, bDirection ); + InteractWithInteractiveObject( pSoldier, pStructure, bDirection ); - // One needs to walk after.... - if ( (pSoldier->bTeam != gbPlayerNum) || (gTacticalStatus.fAutoBandageMode) || ( pSoldier->flags.uiStatusFlags & SOLDIER_PCUNDERAICONTROL ) ) - { - pSoldier->bEndDoorOpenCode = 1; - pSoldier->sEndDoorOpenCodeData = sDoorGridNo; - } - (*pfKeepMoving ) = FALSE; - return( FALSE ); - } + // One needs to walk after.... + if ( (pSoldier->bTeam != gbPlayerNum) || (gTacticalStatus.fAutoBandageMode) || ( pSoldier->flags.uiStatusFlags & SOLDIER_PCUNDERAICONTROL ) ) + { + pSoldier->bEndDoorOpenCode = 1; + pSoldier->sEndDoorOpenCodeData = sDoorGridNo; + } + (*pfKeepMoving ) = FALSE; + return( FALSE ); + } - // Find out how much it takes to move here! - sAPCost = ActionPointCost( pSoldier, usNewGridNo, (INT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ], usAnimState ); - sBPCost = TerrainBreathPoints( pSoldier, usNewGridNo, (INT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ], usAnimState ); - // SANDRO: add BP cost for weapon holding (additional for APBPConstants[BP_MOVEMENT_READY]), this one is specifically based on the weapon itself - if ( gGameExternalOptions.ubEnergyCostForWeaponWeight ) - sBPCost += sAPCost * GetBPCostPer10APsForGunHolding( pSoldier ) / 10; + // Find out how much it takes to move here! + sAPCost = ActionPointCost( pSoldier, usNewGridNo, (INT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ], usAnimState ); + sBPCost = TerrainBreathPoints( pSoldier, usNewGridNo, (INT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ], usAnimState ); + // SANDRO: add BP cost for weapon holding (additional for APBPConstants[BP_MOVEMENT_READY]), this one is specifically based on the weapon itself + if ( gGameExternalOptions.ubEnergyCostForWeaponWeight ) + sBPCost += sAPCost * GetBPCostPer10APsForGunHolding( pSoldier ) / 10; - // CHECK IF THIS TILE IS A GOOD ONE! - if ( !HandleNextTile( pSoldier, (INT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ], usNewGridNo, pSoldier->pathing.sFinalDestination ) ) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "HandleGotoNewGridNo() Failed: Tile %d Was blocked", sNewGridNo ) ); + // CHECK IF THIS TILE IS A GOOD ONE! + if ( !HandleNextTile( pSoldier, (INT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ], usNewGridNo, pSoldier->pathing.sFinalDestination ) ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "HandleGotoNewGridNo() Failed: Tile %d Was blocked", sNewGridNo ) ); - // ATE: If our own guy and an initial move.. display message - //if ( fInitialMove && pSoldier->bTeam == gbPlayerNum ) - //{ - // ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ NO_PATH_FOR_MERC ], pSoldier->GetName() ); - //} + // ATE: If our own guy and an initial move.. display message + //if ( fInitialMove && pSoldier->bTeam == gbPlayerNum ) + //{ + // ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ NO_PATH_FOR_MERC ], pSoldier->GetName() ); + //} - pSoldier->bEndDoorOpenCode = FALSE; - // GO on to next guy! - return( FALSE ); - } + pSoldier->bEndDoorOpenCode = FALSE; + // GO on to next guy! + return( FALSE ); + } - // just check the tile we're going to walk into - if ( NearbyGroundSeemsWrong( pSoldier, usNewGridNo, FALSE, &sMineGridNo ) ) - { - if ( pSoldier->flags.uiStatusFlags & SOLDIER_PC ) - { - // NearbyGroundSeemsWrong returns true with gridno NOWHERE if - // we find something by metal detector... we should definitely stop - // but we won't place a locator or say anything + // just check the tile we're going to walk into + if ( NearbyGroundSeemsWrong( pSoldier, usNewGridNo, FALSE, &sMineGridNo ) ) + { + if ( pSoldier->flags.uiStatusFlags & SOLDIER_PC ) + { + // NearbyGroundSeemsWrong returns true with gridno NOWHERE if + // we find something by metal detector... we should definitely stop + // but we won't place a locator or say anything - // IF not in combat, stop them all - if ( !( gTacticalStatus.uiFlags & INCOMBAT ) ) - { - INT32 cnt2; - SOLDIERTYPE *pSoldier2; + // IF not in combat, stop them all + if ( !( gTacticalStatus.uiFlags & INCOMBAT ) ) + { + INT32 cnt2; + SOLDIERTYPE *pSoldier2; - cnt2 = gTacticalStatus.Team[ gbPlayerNum ].bLastID; + cnt2 = gTacticalStatus.Team[ gbPlayerNum ].bLastID; - // look for all mercs on the same team, - for ( pSoldier2 = MercPtrs[ cnt2 ]; cnt2 >= gTacticalStatus.Team[ gbPlayerNum ].bFirstID; cnt2-- ,pSoldier2-- ) - { - if ( pSoldier2->bActive ) - { - pSoldier2->EVENT_StopMerc( pSoldier2->sGridNo, pSoldier2->ubDirection ); - } - } - } - else - { - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - } + // look for all mercs on the same team, + for ( pSoldier2 = MercPtrs[ cnt2 ]; cnt2 >= gTacticalStatus.Team[ gbPlayerNum ].bFirstID; cnt2-- ,pSoldier2-- ) + { + if ( pSoldier2->bActive ) + { + pSoldier2->EVENT_StopMerc( pSoldier2->sGridNo, pSoldier2->ubDirection ); + } + } + } + else + { + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + } - (*pfKeepMoving) = FALSE; + (*pfKeepMoving) = FALSE; - if (!TileIsOutOfBounds(sMineGridNo)) - { - LocateGridNo( sMineGridNo ); - // we reuse the boobytrap gridno variable here - gsBoobyTrapGridNo = sMineGridNo; - gpBoobyTrapSoldier = pSoldier; - // silversurfer: if TRUE the merc won't comment that he found a mine, otherwise old behaviour - if (gGameExternalOptions.fMineSpottedNoTalk ) - MineSpottedDialogueCallBack (); - else - { - SetStopTimeQuoteCallback( MineSpottedDialogueCallBack ); - TacticalCharacterDialogue( pSoldier, QUOTE_SUSPICIOUS_GROUND ); - } - } - } - else - { - if (!TileIsOutOfBounds(sMineGridNo)) - { - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - (*pfKeepMoving) = FALSE; + if (!TileIsOutOfBounds(sMineGridNo)) + { + LocateGridNo( sMineGridNo ); + // we reuse the boobytrap gridno variable here + gsBoobyTrapGridNo = sMineGridNo; + gpBoobyTrapSoldier = pSoldier; + // silversurfer: if TRUE the merc won't comment that he found a mine, otherwise old behaviour + if (gGameExternalOptions.fMineSpottedNoTalk ) + MineSpottedDialogueCallBack (); + else + { + SetStopTimeQuoteCallback( MineSpottedDialogueCallBack ); + TacticalCharacterDialogue( pSoldier, QUOTE_SUSPICIOUS_GROUND ); + } + } + } + else + { + if (!TileIsOutOfBounds(sMineGridNo)) + { + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + (*pfKeepMoving) = FALSE; - if (pSoldier->bSide != 0) - { - gpWorldLevelData[ sMineGridNo ].uiFlags |= MAPELEMENT_ENEMY_MINE_PRESENT; - } - else - { - gpWorldLevelData[ sMineGridNo ].uiFlags |= MAPELEMENT_PLAYER_MINE_PRESENT; - } + if (pSoldier->bSide != 0) + { + gpWorldLevelData[ sMineGridNo ].uiFlags |= MAPELEMENT_ENEMY_MINE_PRESENT; + } + else + { + gpWorldLevelData[ sMineGridNo ].uiFlags |= MAPELEMENT_PLAYER_MINE_PRESENT; + } - // better stop and reconsider what to do... - SetNewSituation( pSoldier ); - ActionDone( pSoldier ); - // HEADROCK HAM 3.6: Militia can now place flags when they spot landmines. - if (gGameExternalOptions.fMilitiaPlaceBlueFlags && - pSoldier->bTeam == MILITIA_TEAM) - { - // This line causes the screen to focus on the gridno if it is not currently visible. - // Is it desirable when militia spot mines? Probably not. Turned off for now. - //LocateGridNo( sMineGridNo ); + // better stop and reconsider what to do... + SetNewSituation( pSoldier ); + ActionDone( pSoldier ); + // HEADROCK HAM 3.6: Militia can now place flags when they spot landmines. + if (gGameExternalOptions.fMilitiaPlaceBlueFlags && + pSoldier->bTeam == MILITIA_TEAM) + { + // This line causes the screen to focus on the gridno if it is not currently visible. + // Is it desirable when militia spot mines? Probably not. Turned off for now. + //LocateGridNo( sMineGridNo ); - // Flash gridno - ITEM_POOL *pItemPool = NULL; - GetItemPool( sMineGridNo, &pItemPool, 0 ); - SetItemPoolLocator( pItemPool ); - // Add flag - AddBlueFlag(sMineGridNo,1); - } - } - } - } + // Flash gridno + ITEM_POOL *pItemPool = NULL; + GetItemPool( sMineGridNo, &pItemPool, 0 ); + SetItemPoolLocator( pItemPool ); + // Add flag + AddBlueFlag(sMineGridNo,1); + } + } + } + } - // ATE: Check if we have sighted anyone, if so, don't do anything else... - // IN other words, we have stopped from sighting... - if ( pSoldier->flags.fNoAPToFinishMove && !fInitialMove ) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: No APs to finish move set") ); - pSoldier->bEndDoorOpenCode = FALSE; - (*pfKeepMoving ) = FALSE; - } - else if ( pSoldier->pathing.usPathIndex == pSoldier->pathing.usPathDataSize && pSoldier->pathing.usPathDataSize == 0 ) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: No Path") ); - pSoldier->bEndDoorOpenCode = FALSE; - (*pfKeepMoving ) = FALSE; - } - //else if ( gTacticalStatus.fEnemySightingOnTheirTurn ) - //{ - // Hault guy! - // pSoldier->AdjustNoAPToFinishMove( TRUE ); - // (*pfKeepMoving ) = FALSE; - //} - else if ( EnoughPoints( pSoldier, sAPCost, 0, FALSE ) ) - { - BOOLEAN fDontContinue = FALSE; + // ATE: Check if we have sighted anyone, if so, don't do anything else... + // IN other words, we have stopped from sighting... + if ( pSoldier->flags.fNoAPToFinishMove && !fInitialMove ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: No APs to finish move set") ); + pSoldier->bEndDoorOpenCode = FALSE; + (*pfKeepMoving ) = FALSE; + } + else if ( pSoldier->pathing.usPathIndex == pSoldier->pathing.usPathDataSize && pSoldier->pathing.usPathDataSize == 0 ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: No Path") ); + pSoldier->bEndDoorOpenCode = FALSE; + (*pfKeepMoving ) = FALSE; + } + //else if ( gTacticalStatus.fEnemySightingOnTheirTurn ) + //{ + // Hault guy! + // pSoldier->AdjustNoAPToFinishMove( TRUE ); + // (*pfKeepMoving ) = FALSE; + //} + else if ( EnoughPoints( pSoldier, sAPCost, 0, FALSE ) ) + { + BOOLEAN fDontContinue = FALSE; - if ( pSoldier->pathing.usPathIndex > 0 ) - { - // check for running into gas + if ( pSoldier->pathing.usPathIndex > 0 ) + { + // check for running into gas - // note: this will have to use the minimum types of structures for tear/creature gas - // since there isn't a way to retrieve the smoke effect structure - if ( (gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & ANY_SMOKE_EFFECT && PreRandom( 4 ) == 0 ) || gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_BURNABLEGAS ) - { - EXPLOSIVETYPE * pExplosive = NULL; - INT8 bPosOfMask; + // note: this will have to use the minimum types of structures for tear/creature gas + // since there isn't a way to retrieve the smoke effect structure + if ( (gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & ANY_SMOKE_EFFECT && PreRandom( 4 ) == 0 ) || gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_BURNABLEGAS ) + { + EXPLOSIVETYPE * pExplosive = NULL; + INT8 bPosOfMask; - bPosOfMask = FindGasMask (pSoldier); + bPosOfMask = FindGasMask (pSoldier); - if(!DoesSoldierWearGasMask(pSoldier))//dnl ch40 200909 - bPosOfMask = NO_SLOT; + if(!DoesSoldierWearGasMask(pSoldier))//dnl ch40 200909 + bPosOfMask = NO_SLOT; - // WANNE: Only apply the following code for soldiers and not the ROBOT!! - // TODO: Madd: This next section is pretty lame because it can't figure out which explosive was used to actually cause a gas effect - // so for now, the first explosive to use a gas effect decides the health and breath damage for all of the gasses of that type - // (this was hard coded before by the developers - i guess they figured they didn't need to look for the actual explosion item, - // since they only had one of each gas item?!?) - // anyway, it means that we can only have one set of health/breath damage values for each gas type, until someone has time - // to dig into this further and actually make it find the original item that caused the gas - if ( !AM_A_ROBOT( pSoldier ) ) - { + // WANNE: Only apply the following code for soldiers and not the ROBOT!! + // TODO: Madd: This next section is pretty lame because it can't figure out which explosive was used to actually cause a gas effect + // so for now, the first explosive to use a gas effect decides the health and breath damage for all of the gasses of that type + // (this was hard coded before by the developers - i guess they figured they didn't need to look for the actual explosion item, + // since they only had one of each gas item?!?) + // anyway, it means that we can only have one set of health/breath damage values for each gas type, until someone has time + // to dig into this further and actually make it find the original item that caused the gas + if ( !AM_A_ROBOT( pSoldier ) ) + { - if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_SMOKE ) - { - if ( bPosOfMask == NO_SLOT && !(pSoldier->flags.fHitByGasFlags & HIT_BY_SMOKEGAS) )//dnl ch40 200909 - { - pExplosive = &( Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_SMOKE) ].ubClassIndex ]); - } - } + if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_SMOKE ) + { + if ( bPosOfMask == NO_SLOT && !(pSoldier->flags.fHitByGasFlags & HIT_BY_SMOKEGAS) )//dnl ch40 200909 + { + pExplosive = &( Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_SMOKE) ].ubClassIndex ]); + } + } - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pExplosive: %d", pExplosive->ubType ); - if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_TEARGAS ) - { - if ( !(pSoldier->flags.fHitByGasFlags & HIT_BY_TEARGAS) && bPosOfMask == NO_SLOT ) - { - pExplosive = &( Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_TEARGAS) ].ubClassIndex ]); - } - } + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pExplosive: %d", pExplosive->ubType ); + if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_TEARGAS ) + { + if ( !(pSoldier->flags.fHitByGasFlags & HIT_BY_TEARGAS) && bPosOfMask == NO_SLOT ) + { + pExplosive = &( Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_TEARGAS) ].ubClassIndex ]); + } + } - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pExplosive: %d", pExplosive->ubType ); - if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_MUSTARDGAS ) - { - if ( !(pSoldier->flags.fHitByGasFlags & HIT_BY_MUSTARDGAS) && bPosOfMask == NO_SLOT ) - { - pExplosive = &(Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_MUSTGAS) ].ubClassIndex ]); - } - } - - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pExplosive: %d", pExplosive->ubType ); - if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_CREATUREGAS ) - { - if ( !(pSoldier->flags.fHitByGasFlags & HIT_BY_CREATUREGAS) ) // gas mask doesn't help vs creaturegas - { - pExplosive = &(Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_CREATUREGAS) ].ubClassIndex ]); - } - } + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pExplosive: %d", pExplosive->ubType ); + if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_MUSTARDGAS ) + { + if ( !(pSoldier->flags.fHitByGasFlags & HIT_BY_MUSTARDGAS) && bPosOfMask == NO_SLOT ) + { + pExplosive = &(Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_MUSTGAS) ].ubClassIndex ]); + } + } - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pExplosive: %d", pExplosive->ubType ); - if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_BURNABLEGAS ) - { - if ( !(pSoldier->flags.fHitByGasFlags & HIT_BY_BURNABLEGAS) ) - { - pExplosive = &(Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_BURNABLEGAS) ].ubClassIndex ]); - } - } + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pExplosive: %d", pExplosive->ubType ); + if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_CREATUREGAS ) + { + if ( !(pSoldier->flags.fHitByGasFlags & HIT_BY_CREATUREGAS) ) // gas mask doesn't help vs creaturegas + { + pExplosive = &(Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_CREATUREGAS) ].ubClassIndex ]); + } + } - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pSoldier->flags.fHitByGasFlags: %d", pSoldier->flags.fHitByGasFlags ); - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pExplosive: %d", pExplosive->ubType ); + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pExplosive: %d", pExplosive->ubType ); + if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_BURNABLEGAS ) + { + if ( !(pSoldier->flags.fHitByGasFlags & HIT_BY_BURNABLEGAS) ) + { + pExplosive = &(Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_BURNABLEGAS) ].ubClassIndex ]); + } + } - if ( !(gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_SMOKE )) - { - if ( pExplosive ) - { - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - fDontContinue = TRUE; + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pSoldier->flags.fHitByGasFlags: %d", pSoldier->flags.fHitByGasFlags ); + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pExplosive: %d", pExplosive->ubType ); - DishOutGasDamage( pSoldier, pExplosive, TRUE, FALSE, - (INT16) (pExplosive->ubDamage + (UINT8)PreRandom( pExplosive->ubDamage ) ), - (INT16) (100 * ( pExplosive->ubStunDamage + (INT16)PreRandom( ( pExplosive->ubStunDamage / 2 ) ) ) ), NOBODY ); - } - } - } - } + if ( !(gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_SMOKE )) + { + if ( pExplosive ) + { + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + fDontContinue = TRUE; - if ( !fDontContinue ) - { + DishOutGasDamage( pSoldier, pExplosive, TRUE, FALSE, + (INT16) (pExplosive->ubDamage + (UINT8)PreRandom( pExplosive->ubDamage ) ), + (INT16) (100 * ( pExplosive->ubStunDamage + (INT16)PreRandom( ( pExplosive->ubStunDamage / 2 ) ) ) ), NOBODY ); + } + } + } + } - if ( (pSoldier->bOverTerrainType == FLAT_FLOOR || pSoldier->bOverTerrainType == PAVED_ROAD) && pSoldier->pathing.bLevel == 0 ) - { - INT32 iMarblesIndex; + if ( !fDontContinue ) + { - if ( MarblesExistAtLocation( pSoldier->sGridNo, 0, &iMarblesIndex ) ) - { - // Slip on marbles! - pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 ); - if ( pSoldier->bTeam == gbPlayerNum ) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, Message[ STR_SLIPPED_MARBLES ], pSoldier->name ); - } - RemoveItemFromPool( pSoldier->sGridNo, iMarblesIndex, 0 ); - SoldierCollapse( pSoldier ); - if (pSoldier->bActionPoints > 0) - { - pSoldier->bActionPoints -= (INT8) (Random( pSoldier->bActionPoints ) + 1); - } - return( FALSE ); - } - } + if ( (pSoldier->bOverTerrainType == FLAT_FLOOR || pSoldier->bOverTerrainType == PAVED_ROAD) && pSoldier->pathing.bLevel == 0 ) + { + INT32 iMarblesIndex; - if ( (pSoldier->bBlindedCounter > 0) && (pSoldier->usAnimState == RUNNING) && (Random( 5 ) == 0) && - OKFallDirection( pSoldier, (pSoldier->sGridNo + DirectionInc( pSoldier->ubDirection ) ), pSoldier->pathing.bLevel, pSoldier->ubDirection, pSoldier->usAnimState ) ) - { - // 20% chance of falling over! - pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 ); - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[ 37 ], pSoldier->GetName() ); - SoldierCollapse( pSoldier ); - if (pSoldier->bActionPoints > 0) - { - pSoldier->bActionPoints -= (INT8) (Random( pSoldier->bActionPoints ) + 1); - } - return( FALSE ); - } - else if ( ( GetDrunkLevel( pSoldier ) == DRUNK ) && (Random( 5 ) == 0) && - OKFallDirection( pSoldier, (pSoldier->sGridNo + DirectionInc( pSoldier->ubDirection ) ), pSoldier->pathing.bLevel, pSoldier->ubDirection, pSoldier->usAnimState ) ) - { - // 20% chance of falling over! - pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 ); - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[ 37 ], pSoldier->GetName() ); - SoldierCollapse( pSoldier ); - if (pSoldier->bActionPoints > 0) - { - pSoldier->bActionPoints -= (INT8) (Random( pSoldier->bActionPoints ) + 1); - } - return( FALSE ); - } - else - // ATE; First check for profile - // Forgetful guy might forget his path - if ( (pSoldier->bTeam == gbPlayerNum) && ( pSoldier->ubProfile != NO_PROFILE ) && gMercProfiles[pSoldier->ubProfile].bDisability == FORGETFUL ) - { - if ( pSoldier->ubNumTilesMovesSinceLastForget < 255 ) - { - pSoldier->ubNumTilesMovesSinceLastForget++; - } + if ( MarblesExistAtLocation( pSoldier->sGridNo, 0, &iMarblesIndex ) ) + { + // Slip on marbles! + pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 ); + if ( pSoldier->bTeam == gbPlayerNum ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, Message[ STR_SLIPPED_MARBLES ], pSoldier->name ); + } + RemoveItemFromPool( pSoldier->sGridNo, iMarblesIndex, 0 ); + SoldierCollapse( pSoldier ); + if (pSoldier->bActionPoints > 0) + { + pSoldier->bActionPoints -= (INT8) (Random( pSoldier->bActionPoints ) + 1); + } + return( FALSE ); + } + } - if ( pSoldier->pathing.usPathIndex > 2 && (Random( 100 ) == 0) && pSoldier->ubNumTilesMovesSinceLastForget > 200 ) - { - pSoldier->ubNumTilesMovesSinceLastForget = 0; + if ( (pSoldier->bBlindedCounter > 0) && (pSoldier->usAnimState == RUNNING) && (Random( 5 ) == 0) && + OKFallDirection( pSoldier, (pSoldier->sGridNo + DirectionInc( pSoldier->ubDirection ) ), pSoldier->pathing.bLevel, pSoldier->ubDirection, pSoldier->usAnimState ) ) + { + // 20% chance of falling over! + pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[ 37 ], pSoldier->GetName() ); + SoldierCollapse( pSoldier ); + if (pSoldier->bActionPoints > 0) + { + pSoldier->bActionPoints -= (INT8) (Random( pSoldier->bActionPoints ) + 1); + } + return( FALSE ); + } + else if ( ( GetDrunkLevel( pSoldier ) == DRUNK ) && (Random( 5 ) == 0) && + OKFallDirection( pSoldier, (pSoldier->sGridNo + DirectionInc( pSoldier->ubDirection ) ), pSoldier->pathing.bLevel, pSoldier->ubDirection, pSoldier->usAnimState ) ) + { + // 20% chance of falling over! + pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[ 37 ], pSoldier->GetName() ); + SoldierCollapse( pSoldier ); + if (pSoldier->bActionPoints > 0) + { + pSoldier->bActionPoints -= (INT8) (Random( pSoldier->bActionPoints ) + 1); + } + return( FALSE ); + } + else + // ATE; First check for profile + // Forgetful guy might forget his path + if ( (pSoldier->bTeam == gbPlayerNum) && ( pSoldier->ubProfile != NO_PROFILE ) && gMercProfiles[pSoldier->ubProfile].bDisability == FORGETFUL ) + { + if ( pSoldier->ubNumTilesMovesSinceLastForget < 255 ) + { + pSoldier->ubNumTilesMovesSinceLastForget++; + } - TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT ); - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - if (pSoldier->bActionPoints > 0) - { - pSoldier->bActionPoints -= (INT8) (Random( pSoldier->bActionPoints ) + 1); - } + if ( pSoldier->pathing.usPathIndex > 2 && (Random( 100 ) == 0) && pSoldier->ubNumTilesMovesSinceLastForget > 200 ) + { + pSoldier->ubNumTilesMovesSinceLastForget = 0; - fDontContinue = TRUE; + TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT ); + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + if (pSoldier->bActionPoints > 0) + { + pSoldier->bActionPoints -= (INT8) (Random( pSoldier->bActionPoints ) + 1); + } - UnSetUIBusy( pSoldier->ubID ); - } - } + fDontContinue = TRUE; - } - } + UnSetUIBusy( pSoldier->ubID ); + } + } - if ( !fDontContinue ) - { - // Don't apply the first deduction in points... - if ( usAnimState == CRAWLING && pSoldier->flags.bTurningFromPronePosition > TURNING_FROM_PRONE_ON ) - { - } - else - { - // Adjust AP/Breathing points to move - DeductPoints( pSoldier, sAPCost, sBPCost, MOVEMENT_INTERRUPT ); - } + } + } - // OK, let's check for monsters.... - if (pSoldier->flags.uiStatusFlags & SOLDIER_MONSTER) - { - if ( !ValidCreatureTurn( pSoldier, ( INT8 ) ( pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ) ) ) - { - if ( !pSoldier->bReverse ) - { - pSoldier->bReverse = TRUE; + if ( !fDontContinue ) + { + // Don't apply the first deduction in points... + if ( usAnimState == CRAWLING && pSoldier->flags.bTurningFromPronePosition > TURNING_FROM_PRONE_ON ) + { + } + else + { + // Adjust AP/Breathing points to move + DeductPoints( pSoldier, sAPCost, sBPCost, MOVEMENT_INTERRUPT ); + } - if ( pSoldier->ubBodyType == INFANT_MONSTER ) - { - pSoldier->ChangeSoldierState( WALK_BACKWARDS, 1, TRUE ); - } - else - { - pSoldier->ChangeSoldierState( MONSTER_WALK_BACKWARDS, 1, TRUE ); - } - } - } - else - { - pSoldier->bReverse = FALSE; - } - } + // OK, let's check for monsters.... + if (pSoldier->flags.uiStatusFlags & SOLDIER_MONSTER) + { + if ( !ValidCreatureTurn( pSoldier, ( INT8 ) ( pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ) ) ) + { + if ( !pSoldier->bReverse ) + { + pSoldier->bReverse = TRUE; - // OK, let's check for monsters.... - if (pSoldier->ubBodyType == BLOODCAT ) - { - if ( !ValidCreatureTurn( pSoldier, ( INT8 ) ( pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ) ) ) - { - if ( !pSoldier->bReverse ) - { - pSoldier->bReverse = TRUE; - pSoldier->ChangeSoldierState( BLOODCAT_WALK_BACKWARDS, 1, TRUE ); - } - } - else - { - pSoldier->bReverse = FALSE; - } - } + if ( pSoldier->ubBodyType == INFANT_MONSTER ) + { + pSoldier->ChangeSoldierState( WALK_BACKWARDS, 1, TRUE ); + } + else + { + pSoldier->ChangeSoldierState( MONSTER_WALK_BACKWARDS, 1, TRUE ); + } + } + } + else + { + pSoldier->bReverse = FALSE; + } + } - // Change desired direction - pSoldier->EVENT_InternalSetSoldierDestination( (UINT8) pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ], fInitialMove, usAnimState ); + // OK, let's check for monsters.... + if (pSoldier->ubBodyType == BLOODCAT ) + { + if ( !ValidCreatureTurn( pSoldier, ( INT8 ) ( pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ) ) ) + { + if ( !pSoldier->bReverse ) + { + pSoldier->bReverse = TRUE; + pSoldier->ChangeSoldierState( BLOODCAT_WALK_BACKWARDS, 1, TRUE ); + } + } + else + { + pSoldier->bReverse = FALSE; + } + } - // CONTINUE - // IT'S SAVE TO GO AGAIN, REFRESH flag - pSoldier->AdjustNoAPToFinishMove( FALSE ); - } - } - else - { - // HALT GUY HERE - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: No APs %d %d", sAPCost, pSoldier->bActionPoints ) ); - HaltGuyFromNewGridNoBecauseOfNoAPs( pSoldier ); - pSoldier->bEndDoorOpenCode = FALSE; - (*pfKeepMoving ) = FALSE; - } + // Change desired direction + pSoldier->EVENT_InternalSetSoldierDestination( (UINT8) pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ], fInitialMove, usAnimState ); - return( TRUE ); + // CONTINUE + // IT'S SAVE TO GO AGAIN, REFRESH flag + pSoldier->AdjustNoAPToFinishMove( FALSE ); + } + } + else + { + // HALT GUY HERE + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HandleGotoNewGridNo() Failed: No APs %d %d", sAPCost, pSoldier->bActionPoints ) ); + HaltGuyFromNewGridNoBecauseOfNoAPs( pSoldier ); + pSoldier->bEndDoorOpenCode = FALSE; + (*pfKeepMoving ) = FALSE; + } + + return( TRUE ); } void HandleMaryArrival( SOLDIERTYPE * pSoldier ) { - INT32 sDist; + INT32 sDist; - if ( !pSoldier ) - { - pSoldier = FindSoldierByProfileID( MARY, TRUE ); - if ( !pSoldier ) - { - return; - } - } + if ( !pSoldier ) + { + pSoldier = FindSoldierByProfileID( MARY, TRUE ); + if ( !pSoldier ) + { + return; + } + } - if ( CheckFact( FACT_JOHN_ALIVE, 0 ) ) - { - return; - } - // new requirements: player close by + if ( CheckFact( FACT_JOHN_ALIVE, 0 ) ) + { + return; + } + // new requirements: player close by - // TODO.WANNE: Hardcoded grid number - else if (PythSpacesAway( pSoldier->sGridNo, 8228 ) < 40) - { - if ( !TileIsOutOfBounds(ClosestPC( pSoldier, &sDist )) && sDist > NPC_TALK_RADIUS * 2 ) - { - // too far away - return; - } + // TODO.WANNE: Hardcoded grid number + else if (PythSpacesAway( pSoldier->sGridNo, 8228 ) < 40) + { + if ( !TileIsOutOfBounds(ClosestPC( pSoldier, &sDist )) && sDist > NPC_TALK_RADIUS * 2 ) + { + // too far away + return; + } - // Mary has arrived - SetFactTrue( FACT_MARY_OR_JOHN_ARRIVED ); + // Mary has arrived + SetFactTrue( FACT_MARY_OR_JOHN_ARRIVED ); - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - TriggerNPCRecord( MARY, 13 ); - } + TriggerNPCRecord( MARY, 13 ); + } } void HandleJohnArrival( SOLDIERTYPE * pSoldier ) { - SOLDIERTYPE * pSoldier2 = NULL; - INT32 sDist; + SOLDIERTYPE * pSoldier2 = NULL; + INT32 sDist; - if ( !pSoldier ) - { - pSoldier = FindSoldierByProfileID( JOHN, TRUE ); - if ( !pSoldier ) - { - return; - } - } - - // TODO.WANNE: Hardcoded grid number - if (PythSpacesAway( pSoldier->sGridNo, 8228 ) < 40) - { - if (!TileIsOutOfBounds(ClosestPC( pSoldier, &sDist )) && sDist > NPC_TALK_RADIUS * 2 ) - { - // too far away - return; - } + if ( !pSoldier ) + { + pSoldier = FindSoldierByProfileID( JOHN, TRUE ); + if ( !pSoldier ) + { + return; + } + } - if ( CheckFact( FACT_MARY_ALIVE, 0 ) ) - { - pSoldier2 = FindSoldierByProfileID( MARY, FALSE ); - if ( pSoldier2 ) - { - if ( PythSpacesAway( pSoldier->sGridNo, pSoldier2->sGridNo ) > 8 ) - { - // too far away! - return; - } - } - } + // TODO.WANNE: Hardcoded grid number + if (PythSpacesAway( pSoldier->sGridNo, 8228 ) < 40) + { + if (!TileIsOutOfBounds(ClosestPC( pSoldier, &sDist )) && sDist > NPC_TALK_RADIUS * 2 ) + { + // too far away + return; + } - SetFactTrue( FACT_MARY_OR_JOHN_ARRIVED ); + if ( CheckFact( FACT_MARY_ALIVE, 0 ) ) + { + pSoldier2 = FindSoldierByProfileID( MARY, FALSE ); + if ( pSoldier2 ) + { + if ( PythSpacesAway( pSoldier->sGridNo, pSoldier2->sGridNo ) > 8 ) + { + // too far away! + return; + } + } + } - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + SetFactTrue( FACT_MARY_OR_JOHN_ARRIVED ); - // if Mary is alive/dead - if ( pSoldier2 ) - { - pSoldier2->EVENT_StopMerc( pSoldier2->sGridNo, pSoldier2->ubDirection ); - TriggerNPCRecord( JOHN, 13 ); - } - else - { - TriggerNPCRecord( JOHN, 12 ); - } - } + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + + // if Mary is alive/dead + if ( pSoldier2 ) + { + pSoldier2->EVENT_StopMerc( pSoldier2->sGridNo, pSoldier2->ubDirection ); + TriggerNPCRecord( JOHN, 13 ); + } + else + { + TriggerNPCRecord( JOHN, 12 ); + } + } } BOOLEAN HandleAtNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving ) { - INT32 sMineGridNo; - UINT8 ubVolume; + INT32 sMineGridNo; + UINT8 ubVolume; - //uses Lua - PROFILLUA_sSectorX = pSoldier->sSectorX; - PROFILLUA_sSectorY = pSoldier->sSectorY; - PROFILLUA_bSectorZ = pSoldier->bSectorZ; - PROFILLUA_Level = pSoldier->pathing.bLevel; - PROFILLUA_ubID = pSoldier->ubID; - PROFILLUA_sGridNo = pSoldier->sGridNo; - PROFILLUA_ubDirectiono = pSoldier->ubDirection; - PROFILLUA_bTeam = pSoldier->bTeam; - - // ATE; Handle bad guys, as they fade, to cancel it if - // too long... - // ONLY if fading IN! - if ( pSoldier->flags.fBeginFade == 1 ) - { - if ( pSoldier->sLocationOfFadeStart != pSoldier->sGridNo ) - { - // Turn off - pSoldier->flags.fBeginFade = FALSE; + //uses Lua + PROFILLUA_sSectorX = pSoldier->sSectorX; + PROFILLUA_sSectorY = pSoldier->sSectorY; + PROFILLUA_bSectorZ = pSoldier->bSectorZ; + PROFILLUA_Level = pSoldier->pathing.bLevel; + PROFILLUA_ubID = pSoldier->ubID; + PROFILLUA_sGridNo = pSoldier->sGridNo; + PROFILLUA_ubDirectiono = pSoldier->ubDirection; + PROFILLUA_bTeam = pSoldier->bTeam; - if ( pSoldier->pathing.bLevel > 0 && gpWorldLevelData[pSoldier->sGridNo].pRoofHead != NULL ) - { - pSoldier->ubFadeLevel = gpWorldLevelData[ pSoldier->sGridNo ].pRoofHead->ubShadeLevel; - } - else - { - pSoldier->ubFadeLevel = gpWorldLevelData[ pSoldier->sGridNo ].pLandHead->ubShadeLevel; - } + // ATE; Handle bad guys, as they fade, to cancel it if + // too long... + // ONLY if fading IN! + if ( pSoldier->flags.fBeginFade == 1 ) + { + if ( pSoldier->sLocationOfFadeStart != pSoldier->sGridNo ) + { + // Turn off + pSoldier->flags.fBeginFade = FALSE; - // Set levelnode shade level.... - if ( pSoldier->pLevelNode ) - { - pSoldier->pLevelNode->ubShadeLevel = pSoldier->ubFadeLevel; - } - pSoldier->bVisible = -1; + if ( pSoldier->pathing.bLevel > 0 && gpWorldLevelData[pSoldier->sGridNo].pRoofHead != NULL ) + { + pSoldier->ubFadeLevel = gpWorldLevelData[ pSoldier->sGridNo ].pRoofHead->ubShadeLevel; + } + else + { + pSoldier->ubFadeLevel = gpWorldLevelData[ pSoldier->sGridNo ].pLandHead->ubShadeLevel; + } - } - } + // Set levelnode shade level.... + if ( pSoldier->pLevelNode ) + { + pSoldier->pLevelNode->ubShadeLevel = pSoldier->ubFadeLevel; + } + pSoldier->bVisible = -1; - if (gTacticalStatus.uiFlags & INCOMBAT ) - { - HandleLocateToGuyAsHeWalks( pSoldier ); - } + } + } - // Default to TRUE - (*pfKeepMoving ) = TRUE; + if (gTacticalStatus.uiFlags & INCOMBAT ) + { + HandleLocateToGuyAsHeWalks( pSoldier ); + } - pSoldier->bTilesMoved++; - if ( pSoldier->usAnimState == RUNNING ) - { - // count running as double - pSoldier->bTilesMoved++; - } + // Default to TRUE + (*pfKeepMoving ) = TRUE; - // First if we are in realtime combat or noncombat - if ( (gTacticalStatus.uiFlags & REALTIME) || !(gTacticalStatus.uiFlags & INCOMBAT ) ) - { - // Update value for RT breath update - pSoldier->ubTilesMovedPerRTBreathUpdate++; - // Update last anim - pSoldier->usLastMovementAnimPerRTBreathUpdate = pSoldier->usAnimState; - } + pSoldier->bTilesMoved++; + if ( pSoldier->usAnimState == RUNNING ) + { + // count running as double + pSoldier->bTilesMoved++; + } - // Update path if showing path in RT - if ( gGameSettings.fOptions[ TOPTION_ALWAYS_SHOW_MOVEMENT_PATH ] ) - { - if ( !(gTacticalStatus.uiFlags & INCOMBAT ) ) - { - gfPlotNewMovement = TRUE; - } - } + // First if we are in realtime combat or noncombat + if ( (gTacticalStatus.uiFlags & REALTIME) || !(gTacticalStatus.uiFlags & INCOMBAT ) ) + { + // Update value for RT breath update + pSoldier->ubTilesMovedPerRTBreathUpdate++; + // Update last anim + pSoldier->usLastMovementAnimPerRTBreathUpdate = pSoldier->usAnimState; + } - // ATE: Put some stuff in here to not handle certain things if we are - // trversing... - if ( gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALKOFF_SCREEN || gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO ) - { - return( TRUE ); - } + // Update path if showing path in RT + if ( gGameSettings.fOptions[ TOPTION_ALWAYS_SHOW_MOVEMENT_PATH ] ) + { + if ( !(gTacticalStatus.uiFlags & INCOMBAT ) ) + { + gfPlotNewMovement = TRUE; + } + } - // Check if they are out of breath - if ( pSoldier->CheckForBreathCollapse( ) ) - { - (*pfKeepMoving ) = TRUE; - return( FALSE ); - } + // ATE: Put some stuff in here to not handle certain things if we are + // trversing... + if ( gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALKOFF_SCREEN || gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO ) + { + return( TRUE ); + } - // see if a mine gets set off... - if (SetOffBombsInGridNo( pSoldier->ubID, pSoldier->sGridNo, FALSE, pSoldier->pathing.bLevel ) ) - { - (*pfKeepMoving) = FALSE; - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - return( FALSE ); - } + // Check if they are out of breath + if ( pSoldier->CheckForBreathCollapse( ) ) + { + (*pfKeepMoving ) = TRUE; + return( FALSE ); + } + + // see if a mine gets set off... + if (SetOffBombsInGridNo( pSoldier->ubID, pSoldier->sGridNo, FALSE, pSoldier->pathing.bLevel ) ) + { + (*pfKeepMoving) = FALSE; + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + return( FALSE ); + } - // Set "interrupt occurred" flag to false so that we will know whether *this - // particular call* to HandleSight caused an interrupt - gTacticalStatus.fInterruptOccurred = FALSE; + // Set "interrupt occurred" flag to false so that we will know whether *this + // particular call* to HandleSight caused an interrupt + gTacticalStatus.fInterruptOccurred = FALSE; - if ( !(gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) ) - { - ubVolume = MovementNoise( pSoldier ); - if (ubVolume > 0) - { - MakeNoise( pSoldier->ubID, pSoldier->sGridNo, pSoldier->pathing.bLevel, pSoldier->bOverTerrainType, ubVolume, NOISE_MOVEMENT ); - if ( (pSoldier->flags.uiStatusFlags & SOLDIER_PC) && (pSoldier->bStealthMode) ) - { - PlayStealthySoldierFootstepSound( pSoldier ); - } - } - } + if ( !(gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) ) + { + ubVolume = MovementNoise( pSoldier ); + if (ubVolume > 0) + { + MakeNoise( pSoldier->ubID, pSoldier->sGridNo, pSoldier->pathing.bLevel, pSoldier->bOverTerrainType, ubVolume, NOISE_MOVEMENT ); + if ( (pSoldier->flags.uiStatusFlags & SOLDIER_PC) && (pSoldier->bStealthMode) ) + { + PlayStealthySoldierFootstepSound( pSoldier ); + } + } + } - // ATE: Make sure we don't make another interrupt... - if ( !gTacticalStatus.fInterruptOccurred ) - { - // Handle New sight - HandleSight(pSoldier,SIGHT_LOOK | SIGHT_RADIO | SIGHT_INTERRUPT); - } + // ATE: Make sure we don't make another interrupt... + if ( !gTacticalStatus.fInterruptOccurred ) + { + // Handle New sight + HandleSight(pSoldier,SIGHT_LOOK | SIGHT_RADIO | SIGHT_INTERRUPT); + } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // SANDRO - if pending interrupt flag was set for movement type of interupt, resolve it here - if ( gGameOptions.fImprovedInterruptSystem ) - { - if ( ResolvePendingInterrupt( pSoldier, MOVEMENT_INTERRUPT ) ) - { - //AddTopMessage( COMPUTER_INTERRUPT_MESSAGE, Message[STR_INTERRUPT] ); - } - } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - // ATE: Check if we have sighted anyone, if so, don't do anything else... - // IN other words, we have stopped from sighting... - if (gTacticalStatus.fInterruptOccurred) - { - // Unset no APs value - pSoldier->AdjustNoAPToFinishMove( TRUE ); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // SANDRO - if pending interrupt flag was set for movement type of interupt, resolve it here + if ( gGameOptions.fImprovedInterruptSystem ) + { + if ( ResolvePendingInterrupt( pSoldier, MOVEMENT_INTERRUPT ) ) + { + //AddTopMessage( COMPUTER_INTERRUPT_MESSAGE, Message[STR_INTERRUPT] ); + } + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - (*pfKeepMoving ) = FALSE; - pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; - pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; + // ATE: Check if we have sighted anyone, if so, don't do anything else... + // IN other words, we have stopped from sighting... + if (gTacticalStatus.fInterruptOccurred) + { + // Unset no APs value + pSoldier->AdjustNoAPToFinishMove( TRUE ); - // ATE: Cancel only if our final destination - if ( pSoldier->sGridNo == pSoldier->pathing.sFinalDestination ) - { - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - } + (*pfKeepMoving ) = FALSE; + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; - // this flag is set only to halt the currently moving guy; reset it now - gTacticalStatus.fInterruptOccurred = FALSE; + // ATE: Cancel only if our final destination + if ( pSoldier->sGridNo == pSoldier->pathing.sFinalDestination ) + { + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } - // ATE: Remove this if we were stopped.... - if ( gTacticalStatus.fEnemySightingOnTheirTurn ) - { - if ( gTacticalStatus.ubEnemySightingOnTheirTurnEnemyID == pSoldier->ubID ) - { - pSoldier->flags.fPauseAllAnimation = FALSE; - gTacticalStatus.fEnemySightingOnTheirTurn = FALSE; - } - } - } - else if ( pSoldier->flags.fNoAPToFinishMove ) - { - (*pfKeepMoving ) = FALSE; - } - else if ( pSoldier->pathing.usPathIndex == pSoldier->pathing.usPathDataSize && pSoldier->pathing.usPathDataSize == 0 ) - { - (*pfKeepMoving ) = FALSE; - } - else if ( gTacticalStatus.fEnemySightingOnTheirTurn ) - { - // Hault guy! - pSoldier->AdjustNoAPToFinishMove( TRUE ); - (*pfKeepMoving ) = FALSE; - } + // this flag is set only to halt the currently moving guy; reset it now + gTacticalStatus.fInterruptOccurred = FALSE; - // OK, check for other stuff like mines... - if (NearbyGroundSeemsWrong( pSoldier, pSoldier->sGridNo, TRUE, &sMineGridNo )) - { - if (pSoldier->flags.uiStatusFlags & SOLDIER_PC) - { - // NearbyGroundSeemsWrong returns true with gridno NOWHERE if - // we find something by metal detector... we should definitely stop - // but we won't place a locator or say anything + // ATE: Remove this if we were stopped.... + if ( gTacticalStatus.fEnemySightingOnTheirTurn ) + { + if ( gTacticalStatus.ubEnemySightingOnTheirTurnEnemyID == pSoldier->ubID ) + { + pSoldier->flags.fPauseAllAnimation = FALSE; + gTacticalStatus.fEnemySightingOnTheirTurn = FALSE; + } + } + } + else if ( pSoldier->flags.fNoAPToFinishMove ) + { + (*pfKeepMoving ) = FALSE; + } + else if ( pSoldier->pathing.usPathIndex == pSoldier->pathing.usPathDataSize && pSoldier->pathing.usPathDataSize == 0 ) + { + (*pfKeepMoving ) = FALSE; + } + else if ( gTacticalStatus.fEnemySightingOnTheirTurn ) + { + // Hault guy! + pSoldier->AdjustNoAPToFinishMove( TRUE ); + (*pfKeepMoving ) = FALSE; + } - // IF not in combat, stop them all - if ( !( gTacticalStatus.uiFlags & INCOMBAT ) ) - { - INT32 cnt2; - SOLDIERTYPE *pSoldier2; + // OK, check for other stuff like mines... + if (NearbyGroundSeemsWrong( pSoldier, pSoldier->sGridNo, TRUE, &sMineGridNo )) + { + if (pSoldier->flags.uiStatusFlags & SOLDIER_PC) + { + // NearbyGroundSeemsWrong returns true with gridno NOWHERE if + // we find something by metal detector... we should definitely stop + // but we won't place a locator or say anything - cnt2 = gTacticalStatus.Team[ gbPlayerNum ].bLastID; + // IF not in combat, stop them all + if ( !( gTacticalStatus.uiFlags & INCOMBAT ) ) + { + INT32 cnt2; + SOLDIERTYPE *pSoldier2; - // look for all mercs on the same team, - for ( pSoldier2 = MercPtrs[ cnt2 ]; cnt2 >= gTacticalStatus.Team[ gbPlayerNum ].bFirstID; cnt2-- ,pSoldier2-- ) - { - if ( pSoldier2->bActive ) - { - pSoldier2->EVENT_StopMerc( pSoldier2->sGridNo, pSoldier2->ubDirection ); - } - } - } - else - { - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - } + cnt2 = gTacticalStatus.Team[ gbPlayerNum ].bLastID; - (*pfKeepMoving) = FALSE; - - if (!TileIsOutOfBounds(sMineGridNo)) - { - LocateGridNo( sMineGridNo ); - // we reuse the boobytrap gridno variable here - gsBoobyTrapGridNo = sMineGridNo; - gpBoobyTrapSoldier = pSoldier; - // silversurfer: if TRUE the merc won't comment that he found a mine, otherwise old behaviour - if (gGameExternalOptions.fMineSpottedNoTalk ) - MineSpottedDialogueCallBack (); - else - { - SetStopTimeQuoteCallback( MineSpottedDialogueCallBack ); - TacticalCharacterDialogue( pSoldier, QUOTE_SUSPICIOUS_GROUND ); - } - } - } - else - { - if (!TileIsOutOfBounds(sMineGridNo)) - { + // look for all mercs on the same team, + for ( pSoldier2 = MercPtrs[ cnt2 ]; cnt2 >= gTacticalStatus.Team[ gbPlayerNum ].bFirstID; cnt2-- ,pSoldier2-- ) + { + if ( pSoldier2->bActive ) + { + pSoldier2->EVENT_StopMerc( pSoldier2->sGridNo, pSoldier2->ubDirection ); + } + } + } + else + { + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + } - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - (*pfKeepMoving) = FALSE; + (*pfKeepMoving) = FALSE; - gpWorldLevelData[ sMineGridNo ].uiFlags |= MAPELEMENT_ENEMY_MINE_PRESENT; + if (!TileIsOutOfBounds(sMineGridNo)) + { + LocateGridNo( sMineGridNo ); + // we reuse the boobytrap gridno variable here + gsBoobyTrapGridNo = sMineGridNo; + gpBoobyTrapSoldier = pSoldier; + // silversurfer: if TRUE the merc won't comment that he found a mine, otherwise old behaviour + if (gGameExternalOptions.fMineSpottedNoTalk ) + MineSpottedDialogueCallBack (); + else + { + SetStopTimeQuoteCallback( MineSpottedDialogueCallBack ); + TacticalCharacterDialogue( pSoldier, QUOTE_SUSPICIOUS_GROUND ); + } + } + } + else + { + if (!TileIsOutOfBounds(sMineGridNo)) + { - // better stop and reconsider what to do... - SetNewSituation( pSoldier ); - ActionDone( pSoldier ); - } - } - } + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + (*pfKeepMoving) = FALSE; + + gpWorldLevelData[ sMineGridNo ].uiFlags |= MAPELEMENT_ENEMY_MINE_PRESENT; + + // better stop and reconsider what to do... + SetNewSituation( pSoldier ); + ActionDone( pSoldier ); + } + } + } + + HandleSystemNewAISituation( pSoldier, FALSE ); - HandleSystemNewAISituation( pSoldier, FALSE ); - #ifdef LUA_OVERHEAD - LetLuaMyCustomHandleAtNewGridNo(NULL,pSoldier->ubProfile, 0); + LetLuaMyCustomHandleAtNewGridNo(NULL,pSoldier->ubProfile, 0); #else - //----------------Lua------------------------ - - - if ( pSoldier->bTeam == gbPlayerNum ) - { - if ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__EPC) - { - // are we there yet? - if (pSoldier->sSectorX == 13 && pSoldier->sSectorY == MAP_ROW_B && pSoldier->bSectorZ == 0) - { - switch( pSoldier->ubProfile ) - { - case SKYRIDER: - if (PythSpacesAway( pSoldier->sGridNo, 8842 ) < 11) - { - // Skyrider has arrived! - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - SetFactTrue( FACT_SKYRIDER_CLOSE_TO_CHOPPER ); - TriggerNPCRecord( SKYRIDER, 15 ); - SetUpHelicopterForPlayer( 13, MAP_ROW_B, gNewVehicle[ HELICOPTER ].NewPilot, HELICOPTER ); - } - break; + //----------------Lua------------------------ - case MARY: - HandleMaryArrival( pSoldier ); - break; - case JOHN: - HandleJohnArrival( pSoldier ); - break; - } - } - else if ( pSoldier->ubProfile == MARIA && (pSoldier->sSectorX == 6 && pSoldier->sSectorY == MAP_ROW_C && pSoldier->bSectorZ == 0) && CheckFact( FACT_MARIA_ESCORTED_AT_LEATHER_SHOP, MARIA ) == TRUE ) - { - // check that Angel is there! - if ( NPCInRoom( ANGEL, 2 ) ) // room 2 is leather shop - { - // UnRecruitEPC( MARIA ); - TriggerNPCRecord( ANGEL, 12 ); - } - } - else if ( ( pSoldier->ubProfile == JOEY ) && (pSoldier->sSectorX == 8 && pSoldier->sSectorY == MAP_ROW_G && pSoldier->bSectorZ == 0 ) ) - { - // if Joey walks near Martha then trigger Martha record 7 - if ( CheckFact( FACT_JOEY_NEAR_MARTHA, 0 ) ) - { - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - TriggerNPCRecord( JOEY, 9 ); - } - } + if ( pSoldier->bTeam == gbPlayerNum ) + { + if ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__EPC) + { + // are we there yet? + if (pSoldier->sSectorX == 13 && pSoldier->sSectorY == MAP_ROW_B && pSoldier->bSectorZ == 0) + { + switch( pSoldier->ubProfile ) + { + case SKYRIDER: + if (PythSpacesAway( pSoldier->sGridNo, 8842 ) < 11) + { + // Skyrider has arrived! + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + SetFactTrue( FACT_SKYRIDER_CLOSE_TO_CHOPPER ); + TriggerNPCRecord( SKYRIDER, 15 ); + SetUpHelicopterForPlayer( 13, MAP_ROW_B, gNewVehicle[ HELICOPTER ].NewPilot, HELICOPTER ); + } + break; - } - // Drassen stuff for John & Mary - else if ( gubQuest[ QUEST_ESCORT_TOURISTS ] == QUESTINPROGRESS && pSoldier->sSectorX == 13 && pSoldier->sSectorY == MAP_ROW_B && pSoldier->bSectorZ == 0 ) - { - if ( CheckFact( FACT_JOHN_ALIVE, 0 ) ) - { - HandleJohnArrival( NULL ); - } - else - { - HandleMaryArrival( NULL ); - } - } + case MARY: + HandleMaryArrival( pSoldier ); + break; - } - else if ( pSoldier->bTeam == CIV_TEAM && pSoldier->IsAssassin() && pSoldier->aiData.bNeutral ) - { - INT32 sDesiredMercDist; - - if (!TileIsOutOfBounds(ClosestPC( pSoldier, &sDesiredMercDist ))) - { - if ( sDesiredMercDist <= NPC_TALK_RADIUS * 2 ) - { - // stop - CancelAIAction( pSoldier, TRUE ); - // aaaaaaaaaaaaaaaaaaaaatttaaaack!!!! - AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID ); - //MakeCivHostile( pSoldier, 2 ); - //TriggerNPCWithIHateYouQuote( pSoldier->ubProfile ); - } - } - } + case JOHN: + HandleJohnArrival( pSoldier ); + break; + } + } + else if ( pSoldier->ubProfile == MARIA && (pSoldier->sSectorX == 6 && pSoldier->sSectorY == MAP_ROW_C && pSoldier->bSectorZ == 0) && CheckFact( FACT_MARIA_ESCORTED_AT_LEATHER_SHOP, MARIA ) == TRUE ) + { + // check that Angel is there! + if ( NPCInRoom( ANGEL, 2 ) ) // room 2 is leather shop + { + // UnRecruitEPC( MARIA ); + TriggerNPCRecord( ANGEL, 12 ); + } + } + else if ( ( pSoldier->ubProfile == JOEY ) && (pSoldier->sSectorX == 8 && pSoldier->sSectorY == MAP_ROW_G && pSoldier->bSectorZ == 0 ) ) + { + // if Joey walks near Martha then trigger Martha record 7 + if ( CheckFact( FACT_JOEY_NEAR_MARTHA, 0 ) ) + { + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + TriggerNPCRecord( JOEY, 9 ); + } + } + + } + // Drassen stuff for John & Mary + else if ( gubQuest[ QUEST_ESCORT_TOURISTS ] == QUESTINPROGRESS && pSoldier->sSectorX == 13 && pSoldier->sSectorY == MAP_ROW_B && pSoldier->bSectorZ == 0 ) + { + if ( CheckFact( FACT_JOHN_ALIVE, 0 ) ) + { + HandleJohnArrival( NULL ); + } + else + { + HandleMaryArrival( NULL ); + } + } + + } + else if ( pSoldier->bTeam == CIV_TEAM && pSoldier->IsAssassin() && pSoldier->aiData.bNeutral ) + { + INT32 sDesiredMercDist; + + if (!TileIsOutOfBounds(ClosestPC( pSoldier, &sDesiredMercDist ))) + { + if ( sDesiredMercDist <= NPC_TALK_RADIUS * 2 ) + { + // stop + CancelAIAction( pSoldier, TRUE ); + // aaaaaaaaaaaaaaaaaaaaatttaaaack!!!! + AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID ); + //MakeCivHostile( pSoldier, 2 ); + //TriggerNPCWithIHateYouQuote( pSoldier->ubProfile ); + } + } + } #endif - return( TRUE ); + return( TRUE ); } void SelectNextAvailSoldier( SOLDIERTYPE *pSoldier ) { - INT32 cnt; - SOLDIERTYPE *pTeamSoldier; - BOOLEAN fSoldierFound = FALSE; - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SelectNextAvailSoldier")); + INT32 cnt; + SOLDIERTYPE *pTeamSoldier; + BOOLEAN fSoldierFound = FALSE; + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SelectNextAvailSoldier")); - // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED! - cnt = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID; + // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED! + cnt = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID; - // look for all mercs on the same team, - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; cnt++,pTeamSoldier++) - { - if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) ) - { - fSoldierFound = TRUE; - break; - } - } + // look for all mercs on the same team, + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; cnt++,pTeamSoldier++) + { + if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) ) + { + fSoldierFound = TRUE; + break; + } + } - if ( fSoldierFound ) - { - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SelectNextAvailSoldier: selectsoldier")); - SelectSoldier( (INT16)cnt, FALSE, FALSE ); - } - else - { - gusSelectedSoldier = NOBODY; - // Change UI mode to reflact that we are selected - guiPendingOverrideEvent = I_ON_TERRAIN; - } + if ( fSoldierFound ) + { + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SelectNextAvailSoldier: selectsoldier")); + SelectSoldier( (INT16)cnt, FALSE, FALSE ); + } + else + { + gusSelectedSoldier = NOBODY; + // Change UI mode to reflact that we are selected + guiPendingOverrideEvent = I_ON_TERRAIN; + } - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SelectNextAvailSoldier: done")); + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SelectNextAvailSoldier: done")); } @@ -3176,183 +2977,183 @@ void SelectNextAvailSoldier( SOLDIERTYPE *pSoldier ) void InternalSelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fForceReselect, BOOLEAN fFromUI ) { - SOLDIERTYPE *pSoldier, *pOldSoldier; + SOLDIERTYPE *pSoldier, *pOldSoldier; - // ARM: can't call SelectSoldier() in mapscreen, that will initialize interface panels!!! - // ATE: Adjusted conditions a bit ( sometimes were not getting selected ) - if ( guiCurrentScreen == LAPTOP_SCREEN || guiCurrentScreen == MAP_SCREEN ) - { - return; - } + // ARM: can't call SelectSoldier() in mapscreen, that will initialize interface panels!!! + // ATE: Adjusted conditions a bit ( sometimes were not getting selected ) + if ( guiCurrentScreen == LAPTOP_SCREEN || guiCurrentScreen == MAP_SCREEN ) + { + return; + } - if ( usSoldierID == NOBODY ) - { - return; - } + if ( usSoldierID == NOBODY ) + { + return; + } - //if we are in the shop keeper interface - if( guiTacticalInterfaceFlags & INTERFACE_SHOPKEEP_INTERFACE ) - { - //dont allow the player to change the selected merc - return; - } + //if we are in the shop keeper interface + if( guiTacticalInterfaceFlags & INTERFACE_SHOPKEEP_INTERFACE ) + { + //dont allow the player to change the selected merc + return; + } - // Get guy - pSoldier = MercPtrs[ usSoldierID ]; + // Get guy + pSoldier = MercPtrs[ usSoldierID ]; - // If we are dead, ignore - if ( !OK_CONTROLLABLE_MERC( pSoldier) ) - { - return; - } + // If we are dead, ignore + if ( !OK_CONTROLLABLE_MERC( pSoldier) ) + { + return; + } - // Don't do it if we don't have an interrupt - if ( !OK_INTERRUPT_MERC( pSoldier ) ) - { - // OK, we want to display message that we can't.... - if ( fFromUI ) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ MERC_IS_UNAVAILABLE_STR ], pSoldier->GetName() ); - } - return; - } + // Don't do it if we don't have an interrupt + if ( !OK_INTERRUPT_MERC( pSoldier ) ) + { + // OK, we want to display message that we can't.... + if ( fFromUI ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ MERC_IS_UNAVAILABLE_STR ], pSoldier->GetName() ); + } + return; + } - if ( pSoldier->ubID == gusSelectedSoldier ) - { - if ( !fForceReselect ) - { - return; - } - } + if ( pSoldier->ubID == gusSelectedSoldier ) + { + if ( !fForceReselect ) + { + return; + } + } - // CANCEL FROM PLANNING MODE! - if ( InUIPlanMode( ) ) - { - EndUIPlan( ); - } + // CANCEL FROM PLANNING MODE! + if ( InUIPlanMode( ) ) + { + EndUIPlan( ); + } - // Unselect old selected guy - if ( gusSelectedSoldier != NOBODY ) - { - // Get guy - pOldSoldier = MercPtrs[ gusSelectedSoldier ]; - pOldSoldier->flags.fShowLocator = FALSE; - pOldSoldier->flags.fFlashLocator = FALSE; + // Unselect old selected guy + if ( gusSelectedSoldier != NOBODY ) + { + // Get guy + pOldSoldier = MercPtrs[ gusSelectedSoldier ]; + pOldSoldier->flags.fShowLocator = FALSE; + pOldSoldier->flags.fFlashLocator = FALSE; - // DB This used to say pSoldier... I fixed it - if ( pOldSoldier->pathing.bLevel == 0 ) - { - //ConcealWalls((INT16)(pSoldier->dXPos/CELL_X_SIZE), (INT16)(pSoldier->dYPos/CELL_Y_SIZE), REVEAL_WALLS_RADIUS); - // ApplyTranslucencyToWalls((INT16)(pOldSoldier->dXPos/CELL_X_SIZE), (INT16)(pOldSoldier->dYPos/CELL_Y_SIZE)); - //LightHideTrees((INT16)(pOldSoldier->dXPos/CELL_X_SIZE), (INT16)(pOldSoldier->dYPos/CELL_Y_SIZE)); - } - //DeleteSoldierLight( pOldSoldier ); + // DB This used to say pSoldier... I fixed it + if ( pOldSoldier->pathing.bLevel == 0 ) + { + //ConcealWalls((INT16)(pSoldier->dXPos/CELL_X_SIZE), (INT16)(pSoldier->dYPos/CELL_Y_SIZE), REVEAL_WALLS_RADIUS); + // ApplyTranslucencyToWalls((INT16)(pOldSoldier->dXPos/CELL_X_SIZE), (INT16)(pOldSoldier->dYPos/CELL_Y_SIZE)); + //LightHideTrees((INT16)(pOldSoldier->dXPos/CELL_X_SIZE), (INT16)(pOldSoldier->dYPos/CELL_Y_SIZE)); + } + //DeleteSoldierLight( pOldSoldier ); - if(pOldSoldier->flags.uiStatusFlags&SOLDIER_GREEN_RAY) - { - LightHideRays((INT16)(pOldSoldier->dXPos/CELL_X_SIZE), (INT16)(pOldSoldier->dYPos/CELL_Y_SIZE)); - pOldSoldier->flags.uiStatusFlags &= (~SOLDIER_GREEN_RAY); - } + if(pOldSoldier->flags.uiStatusFlags&SOLDIER_GREEN_RAY) + { + LightHideRays((INT16)(pOldSoldier->dXPos/CELL_X_SIZE), (INT16)(pOldSoldier->dYPos/CELL_Y_SIZE)); + pOldSoldier->flags.uiStatusFlags &= (~SOLDIER_GREEN_RAY); + } - UpdateForContOverPortrait( pOldSoldier, FALSE ); - } + UpdateForContOverPortrait( pOldSoldier, FALSE ); + } - gusSelectedSoldier = (UINT16)usSoldierID; + gusSelectedSoldier = (UINT16)usSoldierID; - // find which squad this guy is, then set selected squad to this guy - SetCurrentSquad( pSoldier -> bAssignment, FALSE ); + // find which squad this guy is, then set selected squad to this guy + SetCurrentSquad( pSoldier -> bAssignment, FALSE ); - if ( pSoldier->pathing.bLevel == 0 ) - { - //RevealWalls((INT16)(pSoldier->dXPos/CELL_X_SIZE), (INT16)(pSoldier->dYPos/CELL_Y_SIZE), REVEAL_WALLS_RADIUS); - // CalcTranslucentWalls((INT16)(pSoldier->dXPos/CELL_X_SIZE), (INT16)(pSoldier->dYPos/CELL_Y_SIZE)); - //LightTranslucentTrees((INT16)(pSoldier->dXPos/CELL_X_SIZE), (INT16)(pSoldier->dYPos/CELL_Y_SIZE)); - } + if ( pSoldier->pathing.bLevel == 0 ) + { + //RevealWalls((INT16)(pSoldier->dXPos/CELL_X_SIZE), (INT16)(pSoldier->dYPos/CELL_Y_SIZE), REVEAL_WALLS_RADIUS); + // CalcTranslucentWalls((INT16)(pSoldier->dXPos/CELL_X_SIZE), (INT16)(pSoldier->dYPos/CELL_Y_SIZE)); + //LightTranslucentTrees((INT16)(pSoldier->dXPos/CELL_X_SIZE), (INT16)(pSoldier->dYPos/CELL_Y_SIZE)); + } - //pSoldier->SetCheckSoldierLightFlag( ); + //pSoldier->SetCheckSoldierLightFlag( ); - // Set interface to reflect new selection! - SetCurrentTacticalPanelCurrentMerc( (UINT8)usSoldierID ); + // Set interface to reflect new selection! + SetCurrentTacticalPanelCurrentMerc( (UINT8)usSoldierID ); - // PLay ATTN SOUND - if ( fAcknowledge ) - { - if( !gGameSettings.fOptions[ TOPTION_MUTE_CONFIRMATIONS ] ) - pSoldier->DoMercBattleSound( BATTLE_SOUND_ATTN1 ); - } + // PLay ATTN SOUND + if ( fAcknowledge ) + { + if( !gGameSettings.fOptions[ TOPTION_MUTE_CONFIRMATIONS ] ) + pSoldier->DoMercBattleSound( BATTLE_SOUND_ATTN1 ); + } - // Change UI mode to reflact that we are selected - // NOT if we are locked inthe UI - if ( gTacticalStatus.ubCurrentTeam == OUR_TEAM && gCurrentUIMode != LOCKUI_MODE && gCurrentUIMode != LOCKOURTURN_UI_MODE ) - { - guiPendingOverrideEvent = M_ON_TERRAIN; - } + // Change UI mode to reflact that we are selected + // NOT if we are locked inthe UI + if ( gTacticalStatus.ubCurrentTeam == OUR_TEAM && gCurrentUIMode != LOCKUI_MODE && gCurrentUIMode != LOCKOURTURN_UI_MODE ) + { + guiPendingOverrideEvent = M_ON_TERRAIN; + } - ChangeInterfaceLevel( pSoldier->pathing.bLevel ); + ChangeInterfaceLevel( pSoldier->pathing.bLevel ); - if( pSoldier->flags.fMercAsleep ) - { - PutMercInAwakeState( pSoldier ); - } + if( pSoldier->flags.fMercAsleep ) + { + PutMercInAwakeState( pSoldier ); + } - // possibly say personality quote - if ( (pSoldier->bTeam == gbPlayerNum) && (pSoldier->ubProfile != NO_PROFILE && pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__PLAYER_CHARACTER) && !( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_PERSONALITY) ) - { - switch ( gMercProfiles[ pSoldier->ubProfile ].bDisability ) - { - case PSYCHO: - if ( Random( 50 ) == 0 ) - { - TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT ); - pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY; - } - break; - default: - // Flugente: drugs can temporarily cause a merc to go psycho - if ( MercUnderTheInfluence(pSoldier, DRUG_TYPE_PSYCHO) ) - { - if ( Random( 50 ) == 0 ) - { - TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT ); - pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY; - } - } - break; - } - } + // possibly say personality quote + if ( (pSoldier->bTeam == gbPlayerNum) && (pSoldier->ubProfile != NO_PROFILE && pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__PLAYER_CHARACTER) && !( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_PERSONALITY) ) + { + switch ( gMercProfiles[ pSoldier->ubProfile ].bDisability ) + { + case PSYCHO: + if ( Random( 50 ) == 0 ) + { + TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT ); + pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY; + } + break; + default: + // Flugente: drugs can temporarily cause a merc to go psycho + if ( MercUnderTheInfluence(pSoldier, DRUG_TYPE_PSYCHO) ) + { + if ( Random( 50 ) == 0 ) + { + TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT ); + pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY; + } + } + break; + } + } - UpdateForContOverPortrait( pSoldier, TRUE ); + UpdateForContOverPortrait( pSoldier, TRUE ); - // Remove any interactive tiles we could be over! - BeginCurInteractiveTileCheck( INTILE_CHECK_SELECTIVE ); + // Remove any interactive tiles we could be over! + BeginCurInteractiveTileCheck( INTILE_CHECK_SELECTIVE ); } void SelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fForceReselect ) { - InternalSelectSoldier( usSoldierID, fAcknowledge, fForceReselect, FALSE ); + InternalSelectSoldier( usSoldierID, fAcknowledge, fForceReselect, FALSE ); } -BOOLEAN ResetAllAnimationCache( ) +BOOLEAN ResetAllAnimationCache( ) { - UINT32 cnt; - SOLDIERTYPE *pSoldier; + UINT32 cnt; + SOLDIERTYPE *pSoldier; - // Loop through all mercs and make go - for ( pSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pSoldier++, cnt++ ) - { - if ( pSoldier != NULL ) - { - InitAnimationCache( (UINT16)cnt, &(pSoldier->AnimCache) ); + // Loop through all mercs and make go + for ( pSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pSoldier++, cnt++ ) + { + if ( pSoldier != NULL ) + { + InitAnimationCache( (UINT16)cnt, &(pSoldier->AnimCache) ); - } + } - } + } - return( TRUE ); + return( TRUE ); } @@ -3360,1136 +3161,1136 @@ BOOLEAN ResetAllAnimationCache( ) void LocateSoldier( UINT16 usID, BOOLEAN fSetLocator) { - SOLDIERTYPE *pSoldier; - INT16 sNewCenterWorldX, sNewCenterWorldY; + SOLDIERTYPE *pSoldier; + INT16 sNewCenterWorldX, sNewCenterWorldY; - //if (!bCenter && SoldierOnScreen(usID)) - //return; + //if (!bCenter && SoldierOnScreen(usID)) + //return; - // do we need to move the screen? - //ATE: Force this baby to locate if told to - if (!SoldierOnScreen(usID) || fSetLocator == 10 ) - { - // Get pointer of soldier - pSoldier = MercPtrs[ usID ]; + // do we need to move the screen? + //ATE: Force this baby to locate if told to + if (!SoldierOnScreen(usID) || fSetLocator == 10 ) + { + // Get pointer of soldier + pSoldier = MercPtrs[ usID ]; - // Center on guy - sNewCenterWorldX = (INT16)pSoldier->dXPos; - sNewCenterWorldY = (INT16)pSoldier->dYPos; + // Center on guy + sNewCenterWorldX = (INT16)pSoldier->dXPos; + sNewCenterWorldY = (INT16)pSoldier->dYPos; - SetRenderCenter( sNewCenterWorldX, sNewCenterWorldY ); + SetRenderCenter( sNewCenterWorldX, sNewCenterWorldY ); - // Plot new path! - gfPlotNewMovement = TRUE; - } + // Plot new path! + gfPlotNewMovement = TRUE; + } - // do we flash the name & health bars/health string above? - if (fSetLocator) - { - if ( fSetLocator == SETLOCATOR || fSetLocator == 10 ) - { - ShowRadioLocator((UINT8)usID, SHOW_LOCATOR_NORMAL ); - } - else - { - ShowRadioLocator((UINT8)usID, SHOW_LOCATOR_FAST ); - } - } + // do we flash the name & health bars/health string above? + if (fSetLocator) + { + if ( fSetLocator == SETLOCATOR || fSetLocator == 10 ) + { + ShowRadioLocator((UINT8)usID, SHOW_LOCATOR_NORMAL ); + } + else + { + ShowRadioLocator((UINT8)usID, SHOW_LOCATOR_FAST ); + } + } } void InternalLocateGridNo( INT32 sGridNo, BOOLEAN fForce ) { - INT16 sNewCenterWorldX, sNewCenterWorldY; + INT16 sNewCenterWorldX, sNewCenterWorldY; - ConvertGridNoToCenterCellXY( sGridNo, &sNewCenterWorldX, &sNewCenterWorldY ); + ConvertGridNoToCenterCellXY( sGridNo, &sNewCenterWorldX, &sNewCenterWorldY ); - // FIRST CHECK IF WE ARE ON SCREEN - if ( GridNoOnScreen( sGridNo ) && !fForce ) - { - return; - } + // FIRST CHECK IF WE ARE ON SCREEN + if ( GridNoOnScreen( sGridNo ) && !fForce ) + { + return; + } - SetRenderCenter( sNewCenterWorldX, sNewCenterWorldY ); + SetRenderCenter( sNewCenterWorldX, sNewCenterWorldY ); } void LocateGridNo( INT32 sGridNo ) { - InternalLocateGridNo( sGridNo, FALSE ); + InternalLocateGridNo( sGridNo, FALSE ); } void SlideTo(INT32 sGridNo, UINT16 usSoldierID , UINT16 usReasonID, BOOLEAN fSetLocator) { - INT32 cnt; + INT32 cnt; - if ( usSoldierID == NOBODY ) - { - return; - } + if ( usSoldierID == NOBODY ) + { + return; + } - if ( fSetLocator == SETANDREMOVEPREVIOUSLOCATOR ) - { - for ( cnt = 0; cnt < TOTAL_SOLDIERS; cnt++ ) - { - if ( MercPtrs[ cnt ]->bActive && MercPtrs[ cnt ]->bInSector ) - { - // Remove all existing locators... - MercPtrs[ cnt ]->flags.fFlashLocator = FALSE; - } - } - } + if ( fSetLocator == SETANDREMOVEPREVIOUSLOCATOR ) + { + for ( cnt = 0; cnt < TOTAL_SOLDIERS; cnt++ ) + { + if ( MercPtrs[ cnt ]->bActive && MercPtrs[ cnt ]->bInSector ) + { + // Remove all existing locators... + MercPtrs[ cnt ]->flags.fFlashLocator = FALSE; + } + } + } - // Locate even if on screen - if (fSetLocator) - ShowRadioLocator((UINT8) usSoldierID, SHOW_LOCATOR_NORMAL ); + // Locate even if on screen + if (fSetLocator) + ShowRadioLocator((UINT8) usSoldierID, SHOW_LOCATOR_NORMAL ); - // FIRST CHECK IF WE ARE ON SCREEN - if ( GridNoOnScreen( MercPtrs[ usSoldierID ]->sGridNo ) ) - { - return; - } + // FIRST CHECK IF WE ARE ON SCREEN + if ( GridNoOnScreen( MercPtrs[ usSoldierID ]->sGridNo ) ) + { + return; + } - // sGridNo here for DG compatibility - gTacticalStatus.sSlideTarget = MercPtrs[ usSoldierID ]->sGridNo; - gTacticalStatus.sSlideReason = usReasonID; + // sGridNo here for DG compatibility + gTacticalStatus.sSlideTarget = MercPtrs[ usSoldierID ]->sGridNo; + gTacticalStatus.sSlideReason = usReasonID; - // Plot new path! - gfPlotNewMovement = TRUE; + // Plot new path! + gfPlotNewMovement = TRUE; } void SlideToLocation( UINT16 usReasonID, INT32 sDestGridNo ) -{ - if (TileIsOutOfBounds(sDestGridNo)) - { - return; - } +{ + if (TileIsOutOfBounds(sDestGridNo)) + { + return; + } - // FIRST CHECK IF WE ARE ON SCREEN - if ( GridNoOnScreen( sDestGridNo ) ) - { - return; - } + // FIRST CHECK IF WE ARE ON SCREEN + if ( GridNoOnScreen( sDestGridNo ) ) + { + return; + } - // sGridNo here for DG compatibility - gTacticalStatus.sSlideTarget = sDestGridNo; - gTacticalStatus.sSlideReason = usReasonID; + // sGridNo here for DG compatibility + gTacticalStatus.sSlideTarget = sDestGridNo; + gTacticalStatus.sSlideReason = usReasonID; - // Plot new path! - gfPlotNewMovement = TRUE; + // Plot new path! + gfPlotNewMovement = TRUE; } void RebuildAllSoldierShadeTables( ) { - UINT32 cnt; - SOLDIERTYPE *pSoldier; + UINT32 cnt; + SOLDIERTYPE *pSoldier; - // Loop through all mercs and make go - for ( pSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pSoldier++, cnt++ ) - { - if ( pSoldier->bActive ) - { - pSoldier->CreateSoldierPalettes( ); - } - } + // Loop through all mercs and make go + for ( pSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pSoldier++, cnt++ ) + { + if ( pSoldier->bActive ) + { + pSoldier->CreateSoldierPalettes( ); + } + } } void HandlePlayerTeamMemberDeath( SOLDIERTYPE *pSoldier ) { - INT32 cnt; - INT32 iNewSelectedSoldier = -1; - SOLDIERTYPE *pTeamSoldier; - BOOLEAN fMissionFailed = TRUE; - INT8 bBuddyIndex; + INT32 cnt; + INT32 iNewSelectedSoldier = -1; + SOLDIERTYPE *pTeamSoldier; + BOOLEAN fMissionFailed = TRUE; + INT8 bBuddyIndex; - VerifyPublicOpplistDueToDeath( pSoldier ); + VerifyPublicOpplistDueToDeath( pSoldier ); - pSoldier->ReceivingSoldierCancelServices( ); + pSoldier->ReceivingSoldierCancelServices( ); - // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED! - cnt = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID; + // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED! + cnt = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID; - // look for all mercs on the same team, - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; cnt++,pTeamSoldier++) - { - if ( pTeamSoldier->stats.bLife >= OKLIFE && pTeamSoldier->bActive && pTeamSoldier->bInSector ) - { - iNewSelectedSoldier = cnt; - fMissionFailed = FALSE; - break; - } - } + // look for all mercs on the same team, + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; cnt++,pTeamSoldier++) + { + if ( pTeamSoldier->stats.bLife >= OKLIFE && pTeamSoldier->bActive && pTeamSoldier->bInSector ) + { + iNewSelectedSoldier = cnt; + fMissionFailed = FALSE; + break; + } + } - if ( !fMissionFailed ) - { - if (gTacticalStatus.fAutoBandageMode) - { - if ( pSoldier->ubAutoBandagingMedic != NOBODY ) - { - CancelAIAction( MercPtrs[ pSoldier->ubAutoBandagingMedic ], TRUE ); - } - } + if ( !fMissionFailed ) + { + if (gTacticalStatus.fAutoBandageMode) + { + if ( pSoldier->ubAutoBandagingMedic != NOBODY ) + { + CancelAIAction( MercPtrs[ pSoldier->ubAutoBandagingMedic ], TRUE ); + } + } - // see if this was the friend of a living merc - cnt = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID; - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; cnt++,pTeamSoldier++) - { - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife >= OKLIFE ) - { - bBuddyIndex = WhichBuddy( pTeamSoldier->ubProfile, pSoldier->ubProfile ); - switch( bBuddyIndex ) - { - case 0: - // buddy #1 died! - TacticalCharacterDialogue( pTeamSoldier, QUOTE_BUDDY_ONE_KILLED ); - break; - case 1: - // buddy #2 died! - TacticalCharacterDialogue( pTeamSoldier, QUOTE_BUDDY_TWO_KILLED ); - break; - case 2: - // learn to like buddy died! - TacticalCharacterDialogue( pTeamSoldier, QUOTE_LEARNED_TO_LIKE_MERC_KILLED ); - break; - default: - break; - } - } - } + // see if this was the friend of a living merc + cnt = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID; + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; cnt++,pTeamSoldier++) + { + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife >= OKLIFE ) + { + bBuddyIndex = WhichBuddy( pTeamSoldier->ubProfile, pSoldier->ubProfile ); + switch( bBuddyIndex ) + { + case 0: + // buddy #1 died! + TacticalCharacterDialogue( pTeamSoldier, QUOTE_BUDDY_ONE_KILLED ); + break; + case 1: + // buddy #2 died! + TacticalCharacterDialogue( pTeamSoldier, QUOTE_BUDDY_TWO_KILLED ); + break; + case 2: + // learn to like buddy died! + TacticalCharacterDialogue( pTeamSoldier, QUOTE_LEARNED_TO_LIKE_MERC_KILLED ); + break; + default: + break; + } + } + } - // handle stuff for Carmen if Slay is killed - switch( pSoldier->ubProfile ) - { + // handle stuff for Carmen if Slay is killed + switch( pSoldier->ubProfile ) + { #ifdef JA2UB -//Ja25 No carmen + //Ja25 No carmen #else - case SLAY: - pTeamSoldier = FindSoldierByProfileID( CARMEN, FALSE ); - if (pTeamSoldier && pTeamSoldier->aiData.bAttitude == ATTACKSLAYONLY && !TileIsOutOfBounds(ClosestPC( pTeamSoldier, NULL )) ) - { - // Carmen now becomes friendly again - TriggerNPCRecord( CARMEN, 29 ); - } - break; + case SLAY: + pTeamSoldier = FindSoldierByProfileID( CARMEN, FALSE ); + if (pTeamSoldier && pTeamSoldier->aiData.bAttitude == ATTACKSLAYONLY && !TileIsOutOfBounds(ClosestPC( pTeamSoldier, NULL )) ) + { + // Carmen now becomes friendly again + TriggerNPCRecord( CARMEN, 29 ); + } + break; #endif - case ROBOT: - if (CheckFact( FACT_FIRST_ROBOT_DESTROYED, 0 ) == FALSE ) - { - SetFactTrue( FACT_FIRST_ROBOT_DESTROYED ); - SetFactFalse( FACT_ROBOT_READY ); - } - else - { - SetFactTrue( FACT_SECOND_ROBOT_DESTROYED ); - } - break; - } + case ROBOT: + if (CheckFact( FACT_FIRST_ROBOT_DESTROYED, 0 ) == FALSE ) + { + SetFactTrue( FACT_FIRST_ROBOT_DESTROYED ); + SetFactFalse( FACT_ROBOT_READY ); + } + else + { + SetFactTrue( FACT_SECOND_ROBOT_DESTROYED ); + } + break; + } - } + } - //Make a call to handle the strategic things, such as Life Insurance, record it in history file etc. - StrategicHandlePlayerTeamMercDeath( pSoldier ); + //Make a call to handle the strategic things, such as Life Insurance, record it in history file etc. + StrategicHandlePlayerTeamMercDeath( pSoldier ); - CheckForEndOfBattle( FALSE ); + CheckForEndOfBattle( FALSE ); - if ( gusSelectedSoldier == pSoldier->ubID ) - { - if ( !fMissionFailed ) - { - SelectSoldier( (INT16)iNewSelectedSoldier, FALSE, FALSE ); - } - else - { - gusSelectedSoldier = NOBODY; - // Change UI mode to reflact that we are selected - guiPendingOverrideEvent = I_ON_TERRAIN; - } + if ( gusSelectedSoldier == pSoldier->ubID ) + { + if ( !fMissionFailed ) + { + SelectSoldier( (INT16)iNewSelectedSoldier, FALSE, FALSE ); + } + else + { + gusSelectedSoldier = NOBODY; + // Change UI mode to reflact that we are selected + guiPendingOverrideEvent = I_ON_TERRAIN; + } - } + } } void HandleNPCTeamMemberDeath( SOLDIERTYPE *pSoldierOld ) { - SOLDIERTYPE *pKiller = NULL; - BOOLEAN bVisible; + SOLDIERTYPE *pKiller = NULL; + BOOLEAN bVisible; - pSoldierOld->flags.uiStatusFlags |= SOLDIER_DEAD; - bVisible = pSoldierOld->bVisible; + pSoldierOld->flags.uiStatusFlags |= SOLDIER_DEAD; + bVisible = pSoldierOld->bVisible; - VerifyPublicOpplistDueToDeath( pSoldierOld ); + VerifyPublicOpplistDueToDeath( pSoldierOld ); - if ( pSoldierOld->ubProfile != NO_PROFILE ) - { - // mark as dead! - gMercProfiles[ pSoldierOld->ubProfile ].bMercStatus = MERC_IS_DEAD; - // - gMercProfiles[ pSoldierOld->ubProfile ].bLife = 0; + if ( pSoldierOld->ubProfile != NO_PROFILE ) + { + // mark as dead! + gMercProfiles[ pSoldierOld->ubProfile ].bMercStatus = MERC_IS_DEAD; + // + gMercProfiles[ pSoldierOld->ubProfile ].bLife = 0; - if ( !(pSoldierOld->flags.uiStatusFlags & SOLDIER_VEHICLE) && !TANK( pSoldierOld) ) - { - if ( pSoldierOld->ubAttackerID != NOBODY ) - { - pKiller = MercPtrs[ pSoldierOld->ubAttackerID ]; - } - if( pKiller && pKiller->bTeam == OUR_TEAM ) - { - AddHistoryToPlayersLog( HISTORY_MERC_KILLED_CHARACTER, pSoldierOld->ubProfile, GetWorldTotalMin(), gWorldSectorX, gWorldSectorY ); - } - else - { - AddHistoryToPlayersLog( HISTORY_NPC_KILLED, pSoldierOld->ubProfile, GetWorldTotalMin(), gWorldSectorX, gWorldSectorY ); - } - } - } + if ( !(pSoldierOld->flags.uiStatusFlags & SOLDIER_VEHICLE) && !TANK( pSoldierOld) ) + { + if ( pSoldierOld->ubAttackerID != NOBODY ) + { + pKiller = MercPtrs[ pSoldierOld->ubAttackerID ]; + } + if( pKiller && pKiller->bTeam == OUR_TEAM ) + { + AddHistoryToPlayersLog( HISTORY_MERC_KILLED_CHARACTER, pSoldierOld->ubProfile, GetWorldTotalMin(), gWorldSectorX, gWorldSectorY ); + } + else + { + AddHistoryToPlayersLog( HISTORY_NPC_KILLED, pSoldierOld->ubProfile, GetWorldTotalMin(), gWorldSectorX, gWorldSectorY ); + } + } + } - if (pSoldierOld->bTeam == CIV_TEAM ) - { - #ifdef JA2UB - #else - SOLDIERTYPE * pOther; - #endif - // ATE: Added string to player - if ( bVisible != -1 && pSoldierOld->ubProfile != NO_PROFILE ) - { - ScreenMsg( FONT_RED, MSG_INTERFACE, pMercDeadString[ 0 ], pSoldierOld->GetName() ); - } - - switch( pSoldierOld->ubProfile ) - { + if (pSoldierOld->bTeam == CIV_TEAM ) + { #ifdef JA2UB - case 75: //MORRIS - { - INT8 bSoldierID; +#else + SOLDIERTYPE * pOther; +#endif + // ATE: Added string to player + if ( bVisible != -1 && pSoldierOld->ubProfile != NO_PROFILE ) + { + ScreenMsg( FONT_RED, MSG_INTERFACE, pMercDeadString[ 0 ], pSoldierOld->GetName() ); + } - //Geta a random soldier ID - bSoldierID = RandomSoldierIdFromNewMercsOnPlayerTeam(); + switch( pSoldierOld->ubProfile ) + { +#ifdef JA2UB + case 75: //MORRIS + { + INT8 bSoldierID; - //if there is any - if( bSoldierID != -1 ) - { - //say the MORRIS dead quote - TacticalCharacterDialogue( &Menptr[ bSoldierID ], QUOTE_LEARNED_TO_HATE_MERC_1_ON_TEAM_WONT_RENEW ); - } - } - break; + //Geta a random soldier ID + bSoldierID = RandomSoldierIdFromNewMercsOnPlayerTeam(); + + //if there is any + if( bSoldierID != -1 ) + { + //say the MORRIS dead quote + TacticalCharacterDialogue( &Menptr[ bSoldierID ], QUOTE_LEARNED_TO_HATE_MERC_1_ON_TEAM_WONT_RENEW ); + } + } + break; #else //Ja25: none of these characters are in the exp. - case BRENDA: - SetFactTrue( FACT_BRENDA_DEAD ); - { - pOther = FindSoldierByProfileID( HANS, FALSE ); - if (pOther && pOther->stats.bLife >= OKLIFE && pOther->aiData.bNeutral && (SpacesAway( pSoldierOld->sGridNo, pOther->sGridNo ) <= 12) ) - { + case BRENDA: + SetFactTrue( FACT_BRENDA_DEAD ); + { + pOther = FindSoldierByProfileID( HANS, FALSE ); + if (pOther && pOther->stats.bLife >= OKLIFE && pOther->aiData.bNeutral && (SpacesAway( pSoldierOld->sGridNo, pOther->sGridNo ) <= 12) ) + { - TriggerNPCRecord( HANS, 10 ); - } - } - break; - case PABLO: - AddFutureDayStrategicEvent( EVENT_SECOND_AIRPORT_ATTENDANT_ARRIVED, 480 + Random( 60 ), 0, 1 ); - break; - case ROBOT: - if (CheckFact( FACT_FIRST_ROBOT_DESTROYED, 0 ) == FALSE ) - { - SetFactTrue( FACT_FIRST_ROBOT_DESTROYED ); - } - else - { - SetFactTrue( FACT_SECOND_ROBOT_DESTROYED ); - } - break; - case DRUGGIST: - case SLAY: - case ANNIE: - case CHRIS: - case TIFFANY: - case T_REX: - MakeRemainingTerroristsTougher(); - if ( pSoldierOld->ubProfile == DRUGGIST ) - { - pOther = FindSoldierByProfileID( MANNY, 0 ); - if (pOther && pOther->bActive && pOther->bInSector && pOther->stats.bLife >= OKLIFE ) - { - // try to make sure he isn't cowering etc - pOther->aiData.sNoiseGridno = NOWHERE; - pOther->aiData.bAlertStatus = STATUS_GREEN; - TriggerNPCRecord( MANNY, 10 ); - } - } - break; - case JIM: - case JACK: - case OLAF: - case RAY: - case OLGA: - case TYRONE: - MakeRemainingAssassinsTougher(); - break; + TriggerNPCRecord( HANS, 10 ); + } + } + break; + case PABLO: + AddFutureDayStrategicEvent( EVENT_SECOND_AIRPORT_ATTENDANT_ARRIVED, 480 + Random( 60 ), 0, 1 ); + break; + case ROBOT: + if (CheckFact( FACT_FIRST_ROBOT_DESTROYED, 0 ) == FALSE ) + { + SetFactTrue( FACT_FIRST_ROBOT_DESTROYED ); + } + else + { + SetFactTrue( FACT_SECOND_ROBOT_DESTROYED ); + } + break; + case DRUGGIST: + case SLAY: + case ANNIE: + case CHRIS: + case TIFFANY: + case T_REX: + MakeRemainingTerroristsTougher(); + if ( pSoldierOld->ubProfile == DRUGGIST ) + { + pOther = FindSoldierByProfileID( MANNY, 0 ); + if (pOther && pOther->bActive && pOther->bInSector && pOther->stats.bLife >= OKLIFE ) + { + // try to make sure he isn't cowering etc + pOther->aiData.sNoiseGridno = NOWHERE; + pOther->aiData.bAlertStatus = STATUS_GREEN; + TriggerNPCRecord( MANNY, 10 ); + } + } + break; + case JIM: + case JACK: + case OLAF: + case RAY: + case OLGA: + case TYRONE: + MakeRemainingAssassinsTougher(); + break; - case ELDIN: - // the security guard... Results in an extra loyalty penalty for Balime (in addition to civilian murder) + case ELDIN: + // the security guard... Results in an extra loyalty penalty for Balime (in addition to civilian murder) - /* Delayed loyalty effects elimininated. Sep.12/98. ARM - // create the event value, for town BALIME - uiLoyaltyValue = BuildLoyaltyEventValue( BALIME, LOYALTY_PENALTY_ELDIN_KILLED, FALSE ); - // post the event, 30 minute delay - AddStrategicEvent( EVENT_TOWN_LOYALTY_UPDATE, GetWorldTotalMin() + 30, uiLoyaltyValue ); - */ - DecrementTownLoyalty( BALIME, LOYALTY_PENALTY_ELDIN_KILLED ); - break; - case JOEY: - // check to see if Martha can see this - pOther = FindSoldierByProfileID( MARTHA, FALSE ); - if ( pOther && (PythSpacesAway( pOther->sGridNo, pSoldierOld->sGridNo ) < 10 || SoldierToSoldierLineOfSightTest( pOther, pSoldierOld, TRUE ) != 0 ) ) - { - // Martha has a heart attack and croaks - TriggerNPCRecord( MARTHA, 17 ); + /* Delayed loyalty effects elimininated. Sep.12/98. ARM + // create the event value, for town BALIME + uiLoyaltyValue = BuildLoyaltyEventValue( BALIME, LOYALTY_PENALTY_ELDIN_KILLED, FALSE ); + // post the event, 30 minute delay + AddStrategicEvent( EVENT_TOWN_LOYALTY_UPDATE, GetWorldTotalMin() + 30, uiLoyaltyValue ); + */ + DecrementTownLoyalty( BALIME, LOYALTY_PENALTY_ELDIN_KILLED ); + break; + case JOEY: + // check to see if Martha can see this + pOther = FindSoldierByProfileID( MARTHA, FALSE ); + if ( pOther && (PythSpacesAway( pOther->sGridNo, pSoldierOld->sGridNo ) < 10 || SoldierToSoldierLineOfSightTest( pOther, pSoldierOld, TRUE ) != 0 ) ) + { + // Martha has a heart attack and croaks + TriggerNPCRecord( MARTHA, 17 ); - /* Delayed loyalty effects elimininated. Sep.12/98. ARM - // create the event value, for town CAMBRIA - uiLoyaltyValue = BuildLoyaltyEventValue( CAMBRIA, LOYALTY_PENALTY_MARTHA_HEART_ATTACK, FALSE ); - // post the event, 30 minute delay - AddStrategicEvent( EVENT_TOWN_LOYALTY_UPDATE, GetWorldTotalMin() + 30, uiLoyaltyValue ); - */ - DecrementTownLoyalty( CAMBRIA, LOYALTY_PENALTY_MARTHA_HEART_ATTACK ); - } - else // Martha doesn't see it. She lives, but Joey is found a day or so later anyways - { - /* - // create the event value, for town CAMBRIA - uiLoyaltyValue = BuildLoyaltyEventValue( CAMBRIA, LOYALTY_PENALTY_JOEY_KILLED, FALSE ); - // post the event, 30 minute delay - AddStrategicEvent( EVENT_TOWN_LOYALTY_UPDATE, GetWorldTotalMin() + ( ( 12 + Random(13)) * 60 ), uiLoyaltyValue ); - */ - DecrementTownLoyalty( CAMBRIA, LOYALTY_PENALTY_JOEY_KILLED ); - } - break; - case DYNAMO: - // check to see if dynamo quest is on - if ( gubQuest[ QUEST_FREE_DYNAMO ] == QUESTINPROGRESS) - { - // SANDRO - quest failed if Dynamo is killed - InternalEndQuest( QUEST_FREE_DYNAMO, pSoldierOld->sSectorX, pSoldierOld->sSectorY, FALSE ); - } - break; - // SANDRO - if we kill Carmen with Slay in our team, end the terrorists quest - case CARMEN : - // Carmen must have seen Slay, to finish the quest properly, he must know we betrayd him - if ( pSoldierOld->aiData.bAttitude == ATTACKSLAYONLY ) - { - pOther = FindSoldierByProfileID( SLAY, FALSE ); - if (pOther && pOther->stats.bLife && pOther->bTeam == gbPlayerNum && - pSoldierOld->sSectorX == pOther->sSectorX && pSoldierOld->sSectorY == pOther->sSectorY) - { - // Slay is in sector and alive, Carmen dead, end quest, award some exp - EndQuest( QUEST_KILL_TERRORISTS, pSoldierOld->sSectorX, pSoldierOld->sSectorY ); - } - } - break; - case KINGPIN: - // check to see if Kingpin money quest is on - if ( gubQuest[ QUEST_KINGPIN_MONEY ] == QUESTINPROGRESS) - { - EndQuest( QUEST_KINGPIN_MONEY, pSoldierOld->sSectorX, pSoldierOld->sSectorY ); - HandleNPCDoAction( KINGPIN, NPC_ACTION_GRANT_EXPERIENCE_3, 0 ); - } - SetFactTrue( FACT_KINGPIN_DEAD ); - ExecuteStrategicAIAction( STRATEGIC_AI_ACTION_KINGPIN_DEAD, 0, 0 ); - break; - case DOREEN: - // Doreen's dead - if ( CheckFact( FACT_DOREEN_HAD_CHANGE_OF_HEART, 0 ) ) - { - // tsk tsk, player killed her after getting her to reconsider, lose the bonus for sparing her - DecrementTownLoyalty( DRASSEN, LOYALTY_BONUS_CHILDREN_FREED_DOREEN_SPARED ); - } // then get the points for freeing the kids though killing her - IncrementTownLoyalty( DRASSEN, LOYALTY_BONUS_CHILDREN_FREED_DOREEN_KILLED ); - // set the fact true so we have a universal check for whether the kids can go - SetFactTrue( FACT_DOREEN_HAD_CHANGE_OF_HEART ); - EndQuest( QUEST_FREE_CHILDREN, gWorldSectorX, gWorldSectorY ); - if ( CheckFact( FACT_KIDS_ARE_FREE , 0 ) == FALSE ) - { - HandleNPCDoAction( DOREEN, NPC_ACTION_FREE_KIDS, 0 ); - } - break; - #endif + /* Delayed loyalty effects elimininated. Sep.12/98. ARM + // create the event value, for town CAMBRIA + uiLoyaltyValue = BuildLoyaltyEventValue( CAMBRIA, LOYALTY_PENALTY_MARTHA_HEART_ATTACK, FALSE ); + // post the event, 30 minute delay + AddStrategicEvent( EVENT_TOWN_LOYALTY_UPDATE, GetWorldTotalMin() + 30, uiLoyaltyValue ); + */ + DecrementTownLoyalty( CAMBRIA, LOYALTY_PENALTY_MARTHA_HEART_ATTACK ); + } + else // Martha doesn't see it. She lives, but Joey is found a day or so later anyways + { + /* + // create the event value, for town CAMBRIA + uiLoyaltyValue = BuildLoyaltyEventValue( CAMBRIA, LOYALTY_PENALTY_JOEY_KILLED, FALSE ); + // post the event, 30 minute delay + AddStrategicEvent( EVENT_TOWN_LOYALTY_UPDATE, GetWorldTotalMin() + ( ( 12 + Random(13)) * 60 ), uiLoyaltyValue ); + */ + DecrementTownLoyalty( CAMBRIA, LOYALTY_PENALTY_JOEY_KILLED ); + } + break; + case DYNAMO: + // check to see if dynamo quest is on + if ( gubQuest[ QUEST_FREE_DYNAMO ] == QUESTINPROGRESS) + { + // SANDRO - quest failed if Dynamo is killed + InternalEndQuest( QUEST_FREE_DYNAMO, pSoldierOld->sSectorX, pSoldierOld->sSectorY, FALSE ); + } + break; + // SANDRO - if we kill Carmen with Slay in our team, end the terrorists quest + case CARMEN : + // Carmen must have seen Slay, to finish the quest properly, he must know we betrayd him + if ( pSoldierOld->aiData.bAttitude == ATTACKSLAYONLY ) + { + pOther = FindSoldierByProfileID( SLAY, FALSE ); + if (pOther && pOther->stats.bLife && pOther->bTeam == gbPlayerNum && + pSoldierOld->sSectorX == pOther->sSectorX && pSoldierOld->sSectorY == pOther->sSectorY) + { + // Slay is in sector and alive, Carmen dead, end quest, award some exp + EndQuest( QUEST_KILL_TERRORISTS, pSoldierOld->sSectorX, pSoldierOld->sSectorY ); + } + } + break; + case KINGPIN: + // check to see if Kingpin money quest is on + if ( gubQuest[ QUEST_KINGPIN_MONEY ] == QUESTINPROGRESS) + { + EndQuest( QUEST_KINGPIN_MONEY, pSoldierOld->sSectorX, pSoldierOld->sSectorY ); + HandleNPCDoAction( KINGPIN, NPC_ACTION_GRANT_EXPERIENCE_3, 0 ); + } + SetFactTrue( FACT_KINGPIN_DEAD ); + ExecuteStrategicAIAction( STRATEGIC_AI_ACTION_KINGPIN_DEAD, 0, 0 ); + break; + case DOREEN: + // Doreen's dead + if ( CheckFact( FACT_DOREEN_HAD_CHANGE_OF_HEART, 0 ) ) + { + // tsk tsk, player killed her after getting her to reconsider, lose the bonus for sparing her + DecrementTownLoyalty( DRASSEN, LOYALTY_BONUS_CHILDREN_FREED_DOREEN_SPARED ); + } // then get the points for freeing the kids though killing her + IncrementTownLoyalty( DRASSEN, LOYALTY_BONUS_CHILDREN_FREED_DOREEN_KILLED ); + // set the fact true so we have a universal check for whether the kids can go + SetFactTrue( FACT_DOREEN_HAD_CHANGE_OF_HEART ); + EndQuest( QUEST_FREE_CHILDREN, gWorldSectorX, gWorldSectorY ); + if ( CheckFact( FACT_KIDS_ARE_FREE , 0 ) == FALSE ) + { + HandleNPCDoAction( DOREEN, NPC_ACTION_FREE_KIDS, 0 ); + } + break; +#endif #ifdef JA2UB #else - // SANDRO - Check if queen bitch is dead - case QUEEN: - // Muhahahahaaa, QUEST COMPLETED! Give us everything!! Exp, glory, fame! - EndQuest( QUEST_KILL_DEIDRANNA, pSoldierOld->sSectorX, pSoldierOld->sSectorY ); - break; + // SANDRO - Check if queen bitch is dead + case QUEEN: + // Muhahahahaaa, QUEST COMPLETED! Give us everything!! Exp, glory, fame! + EndQuest( QUEST_KILL_DEIDRANNA, pSoldierOld->sSectorX, pSoldierOld->sSectorY ); + break; #endif - - } + + } #ifdef JA2UB -// Ja25no queen + // Ja25no queen #else - // Are we looking at the queen? - if ( pSoldierOld->ubProfile == QUEEN ) - { - if ( pSoldierOld->ubAttackerID != NOBODY ) - { - pKiller = MercPtrs[ pSoldierOld->ubAttackerID ]; - } + // Are we looking at the queen? + if ( pSoldierOld->ubProfile == QUEEN ) + { + if ( pSoldierOld->ubAttackerID != NOBODY ) + { + pKiller = MercPtrs[ pSoldierOld->ubAttackerID ]; + } - BeginHandleDeidrannaDeath( pKiller, pSoldierOld->sGridNo, pSoldierOld->pathing.bLevel ); - } + BeginHandleDeidrannaDeath( pKiller, pSoldierOld->sGridNo, pSoldierOld->pathing.bLevel ); + } #endif - // crows/cows are on the civilian team, but none of the following applies to them - if ( ( pSoldierOld->ubBodyType != CROW ) && ( pSoldierOld->ubBodyType != COW ) ) - { - // If the civilian's killer is known - if ( pSoldierOld->ubAttackerID != NOBODY ) - { - // handle death of civilian..and if it was intentional - HandleMurderOfCivilian( pSoldierOld, pSoldierOld->flags.fIntendedTarget ); - } - } + // crows/cows are on the civilian team, but none of the following applies to them + if ( ( pSoldierOld->ubBodyType != CROW ) && ( pSoldierOld->ubBodyType != COW ) ) + { + // If the civilian's killer is known + if ( pSoldierOld->ubAttackerID != NOBODY ) + { + // handle death of civilian..and if it was intentional + HandleMurderOfCivilian( pSoldierOld, pSoldierOld->flags.fIntendedTarget ); + } + } - // Flugente: if this was a prisoner of war, reduce their sector count by 1 - if ( pSoldierOld->bSoldierFlagMask & SOLDIER_POW_PRISON ) - { - // get sector - SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ]; - if ( pSector ) - pSector->uiNumberOfPrisonersOfWar = max(0, pSector->uiNumberOfPrisonersOfWar - 1); - } - } - else if ( pSoldierOld->bTeam == MILITIA_TEAM ) - { - INT8 bMilitiaRank; + // Flugente: if this was a prisoner of war, reduce their sector count by 1 + if ( pSoldierOld->bSoldierFlagMask & SOLDIER_POW_PRISON ) + { + // get sector + SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ]; + if ( pSector ) + pSector->uiNumberOfPrisonersOfWar = max(0, pSector->uiNumberOfPrisonersOfWar - 1); + } + } + else if ( pSoldierOld->bTeam == MILITIA_TEAM ) + { + INT8 bMilitiaRank; - bMilitiaRank = SoldierClassToMilitiaRank( pSoldierOld->ubSoldierClass ); + bMilitiaRank = SoldierClassToMilitiaRank( pSoldierOld->ubSoldierClass ); - if (bMilitiaRank != -1) - { - BOOLEAN NeedReset = gfStrategicMilitiaChangesMade; - // remove this militia from the strategic records - StrategicRemoveMilitiaFromSector( gWorldSectorX, gWorldSectorY, bMilitiaRank, 1 ); - gfStrategicMilitiaChangesMade = NeedReset; - } + if (bMilitiaRank != -1) + { + BOOLEAN NeedReset = gfStrategicMilitiaChangesMade; + // remove this militia from the strategic records + StrategicRemoveMilitiaFromSector( gWorldSectorX, gWorldSectorY, bMilitiaRank, 1 ); + gfStrategicMilitiaChangesMade = NeedReset; + } - // If the militia's killer is known - // silversurfer: did the player team kill the militia? If not, militia shouldn't become hostile towards the player. - if ( pSoldierOld->ubAttackerID != NOBODY && MercPtrs[ pSoldierOld->ubAttackerID ]->bTeam == OUR_TEAM ) - { - // also treat this as murder - but player will never be blamed for militia death he didn't cause - // HEADROCK HAM 3.6: Actually this function never runs for militia (see function for details) - //HandleMurderOfCivilian( pSoldierOld, pSoldierOld->flags.fIntendedTarget ); + // If the militia's killer is known + // silversurfer: did the player team kill the militia? If not, militia shouldn't become hostile towards the player. + if ( pSoldierOld->ubAttackerID != NOBODY && MercPtrs[ pSoldierOld->ubAttackerID ]->bTeam == OUR_TEAM ) + { + // also treat this as murder - but player will never be blamed for militia death he didn't cause + // HEADROCK HAM 3.6: Actually this function never runs for militia (see function for details) + //HandleMurderOfCivilian( pSoldierOld, pSoldierOld->flags.fIntendedTarget ); - // HEADROCK HAM 3.6: INI setting can cause militia to turn ONLY of they are killed intentionally - if (pSoldierOld->flags.fIntendedTarget // Must be intentional - && gGameExternalOptions.ubCanMilitiaBecomeHostile > 0 // INI setting - && pSoldierOld->bSide == gbPlayerNum // Must not be hostile by now - ) - { - MilitiaChangesSides(); // Militia turn on you. - } - } + // HEADROCK HAM 3.6: INI setting can cause militia to turn ONLY of they are killed intentionally + if (pSoldierOld->flags.fIntendedTarget // Must be intentional + && gGameExternalOptions.ubCanMilitiaBecomeHostile > 0 // INI setting + && pSoldierOld->bSide == gbPlayerNum // Must not be hostile by now + ) + { + MilitiaChangesSides(); // Militia turn on you. + } + } + + HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_NATIVE_KILLED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + } + else // enemies and creatures... should any of this stuff not be called if a creature dies? + { - HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_NATIVE_KILLED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - } - else // enemies and creatures... should any of this stuff not be called if a creature dies? - { - #ifdef JA2UB -//no queen, or queen monster + //no queen, or queen monster #else - if ( pSoldierOld->ubBodyType == QUEENMONSTER ) - { - SOLDIERTYPE *pKiller = NULL; + if ( pSoldierOld->ubBodyType == QUEENMONSTER ) + { + SOLDIERTYPE *pKiller = NULL; - if ( pSoldierOld->ubAttackerID != NOBODY ) - { - pKiller = MercPtrs[ pSoldierOld->ubAttackerID ]; + if ( pSoldierOld->ubAttackerID != NOBODY ) + { + pKiller = MercPtrs[ pSoldierOld->ubAttackerID ]; - BeginHandleQueenBitchDeath( pKiller, pSoldierOld->sGridNo, pSoldierOld->pathing.bLevel ); - } - } + BeginHandleQueenBitchDeath( pKiller, pSoldierOld->sGridNo, pSoldierOld->pathing.bLevel ); + } + } #endif - if ( pSoldierOld->bTeam == ENEMY_TEAM ) - { - gTacticalStatus.ubArmyGuysKilled++; - TrackEnemiesKilled( ENEMY_KILLED_IN_TACTICAL, pSoldierOld->ubSoldierClass ); - } - // If enemy guy was killed by the player, give morale boost to player's team! - if (pSoldierOld->ubAttackerID != NOBODY && MercPtrs[ pSoldierOld->ubAttackerID ]->bTeam == gbPlayerNum ) - { - HandleMoraleEvent( MercPtrs[pSoldierOld->ubAttackerID], MORALE_KILLED_ENEMY, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - } + if ( pSoldierOld->bTeam == ENEMY_TEAM ) + { + gTacticalStatus.ubArmyGuysKilled++; + TrackEnemiesKilled( ENEMY_KILLED_IN_TACTICAL, pSoldierOld->ubSoldierClass ); + } + // If enemy guy was killed by the player, give morale boost to player's team! + if (pSoldierOld->ubAttackerID != NOBODY && MercPtrs[ pSoldierOld->ubAttackerID ]->bTeam == gbPlayerNum ) + { + HandleMoraleEvent( MercPtrs[pSoldierOld->ubAttackerID], MORALE_KILLED_ENEMY, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + } - HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_ENEMY_KILLED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_ENEMY_KILLED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - CheckForAlertWhenEnemyDies( pSoldierOld ); + CheckForAlertWhenEnemyDies( pSoldierOld ); - if ( gTacticalStatus.ubTheChosenOne == pSoldierOld->ubID ) - { - // reset the chosen one! - gTacticalStatus.ubTheChosenOne = NOBODY; - } + if ( gTacticalStatus.ubTheChosenOne == pSoldierOld->ubID ) + { + // reset the chosen one! + gTacticalStatus.ubTheChosenOne = NOBODY; + } #ifdef JA2UB -//no queen, or queen monster + //no queen, or queen monster #else - if ( pSoldierOld->ubProfile == QUEEN ) - { - HandleMoraleEvent( NULL, MORALE_DEIDRANNA_KILLED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - MaximizeLoyaltyForDeidrannaKilled( ); - } - else if ( pSoldierOld->ubBodyType == QUEENMONSTER ) - { - HandleMoraleEvent( NULL, MORALE_MONSTER_QUEEN_KILLED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - IncrementTownLoyaltyEverywhere( LOYALTY_BONUS_KILL_QUEEN_MONSTER ); + if ( pSoldierOld->ubProfile == QUEEN ) + { + HandleMoraleEvent( NULL, MORALE_DEIDRANNA_KILLED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + MaximizeLoyaltyForDeidrannaKilled( ); + } + else if ( pSoldierOld->ubBodyType == QUEENMONSTER ) + { + HandleMoraleEvent( NULL, MORALE_MONSTER_QUEEN_KILLED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + IncrementTownLoyaltyEverywhere( LOYALTY_BONUS_KILL_QUEEN_MONSTER ); - // Grant experience gain..... - HandleNPCDoAction( 0, NPC_ACTION_GRANT_EXPERIENCE_5, 0 ); + // Grant experience gain..... + HandleNPCDoAction( 0, NPC_ACTION_GRANT_EXPERIENCE_5, 0 ); - } + } #endif - } + } - // killing crows/cows is not worth any experience! - if ( ( pSoldierOld->ubBodyType != CROW ) && ( pSoldierOld->ubBodyType != COW ) ) //&& pSoldierOld->ubLastDamageReason != TAKE_DAMAGE_BLOODLOSS ) // SANDRO - why not give exp for bleeding out? - { - UINT8 ubAssister = NOBODY; + // killing crows/cows is not worth any experience! + if ( ( pSoldierOld->ubBodyType != CROW ) && ( pSoldierOld->ubBodyType != COW ) ) //&& pSoldierOld->ubLastDamageReason != TAKE_DAMAGE_BLOODLOSS ) // SANDRO - why not give exp for bleeding out? + { + UINT8 ubAssister = NOBODY; - // if it was a kill by a player's merc - if (pSoldierOld->ubAttackerID != NOBODY && MercPtrs[ pSoldierOld->ubAttackerID ]->bTeam == gbPlayerNum ) - { - // SANDRO - for special NPCs, you gain more experiences - UINT16 usNumExpChances = ( 10 * pSoldierOld->stats.bExpLevel ); // basic value - switch( pSoldierOld->ubProfile ) - { - case CARMEN: - case QUEEN: - case JOE: - case ANNIE: - case CHRIS: - case KINGPIN: - case TIFFANY: - case T_REX: - case DRUGGIST: - case GENERAL: - case JIM: - case JACK: - case OLAF: - case RAY: - case OLGA: - case TYRONE: - case MIKE: - usNumExpChances *= 2; // make it double for special guys - if( gGameExternalOptions.usSpecialNPCStronger > 0 ) // if set stronger, adjust the value - { - usNumExpChances += (usNumExpChances * gGameExternalOptions.usSpecialNPCStronger / 100); - } - break; - } - // EXPERIENCE CLASS GAIN: Earned a kill - StatChange( MercPtrs[ pSoldierOld->ubAttackerID ], EXPERAMT, usNumExpChances, FALSE ); - } + // if it was a kill by a player's merc + if (pSoldierOld->ubAttackerID != NOBODY && MercPtrs[ pSoldierOld->ubAttackerID ]->bTeam == gbPlayerNum ) + { + // SANDRO - for special NPCs, you gain more experiences + UINT16 usNumExpChances = ( 10 * pSoldierOld->stats.bExpLevel ); // basic value + switch( pSoldierOld->ubProfile ) + { + case CARMEN: + case QUEEN: + case JOE: + case ANNIE: + case CHRIS: + case KINGPIN: + case TIFFANY: + case T_REX: + case DRUGGIST: + case GENERAL: + case JIM: + case JACK: + case OLAF: + case RAY: + case OLGA: + case TYRONE: + case MIKE: + usNumExpChances *= 2; // make it double for special guys + if( gGameExternalOptions.usSpecialNPCStronger > 0 ) // if set stronger, adjust the value + { + usNumExpChances += (usNumExpChances * gGameExternalOptions.usSpecialNPCStronger / 100); + } + break; + } + // EXPERIENCE CLASS GAIN: Earned a kill + StatChange( MercPtrs[ pSoldierOld->ubAttackerID ], EXPERAMT, usNumExpChances, FALSE ); + } - // JA2 Gold: if previous and current attackers are the same, the next-to-previous attacker gets the assist - if (pSoldierOld->ubPreviousAttackerID == pSoldierOld->ubAttackerID) - { - if (pSoldierOld->ubNextToPreviousAttackerID != pSoldierOld->ubAttackerID ) // SANDRO - carefully with this, if we are still one person don't do this - ubAssister = pSoldierOld->ubNextToPreviousAttackerID; - } - else - { - ubAssister = pSoldierOld->ubPreviousAttackerID; - } + // JA2 Gold: if previous and current attackers are the same, the next-to-previous attacker gets the assist + if (pSoldierOld->ubPreviousAttackerID == pSoldierOld->ubAttackerID) + { + if (pSoldierOld->ubNextToPreviousAttackerID != pSoldierOld->ubAttackerID ) // SANDRO - carefully with this, if we are still one person don't do this + ubAssister = pSoldierOld->ubNextToPreviousAttackerID; + } + else + { + ubAssister = pSoldierOld->ubPreviousAttackerID; + } - // if it was assisted by a player's merc - if (ubAssister != NOBODY && MercPtrs[ ubAssister ]->bTeam == gbPlayerNum ) - { - // EXPERIENCE CLASS GAIN: Earned an assist - StatChange( MercPtrs[ ubAssister ], EXPERAMT, (UINT16)( 5 * pSoldierOld->stats.bExpLevel ), FALSE ); - } - } + // if it was assisted by a player's merc + if (ubAssister != NOBODY && MercPtrs[ ubAssister ]->bTeam == gbPlayerNum ) + { + // EXPERIENCE CLASS GAIN: Earned an assist + StatChange( MercPtrs[ ubAssister ], EXPERAMT, (UINT16)( 5 * pSoldierOld->stats.bExpLevel ), FALSE ); + } + } - if (pSoldierOld->ubAttackerID != NOBODY && MercPtrs[ pSoldierOld->ubAttackerID ]->bTeam == MILITIA_TEAM ) - { - MercPtrs[ pSoldierOld->ubAttackerID ]->ubMilitiaKills++; - } + if (pSoldierOld->ubAttackerID != NOBODY && MercPtrs[ pSoldierOld->ubAttackerID ]->bTeam == MILITIA_TEAM ) + { + MercPtrs[ pSoldierOld->ubAttackerID ]->ubMilitiaKills++; + } + + //if the NPC is a dealer, add the dealers items to the ground + AddDeadArmsDealerItemsToWorld( pSoldierOld->ubProfile ); - //if the NPC is a dealer, add the dealers items to the ground - AddDeadArmsDealerItemsToWorld( pSoldierOld->ubProfile ); - #ifdef JA2UB - HandleDeathInPowerGenSector( pSoldierOld ); //ja25 ub - HandleWhenCertainPercentageOfEnemiesDie(); //ja25 ub + HandleDeathInPowerGenSector( pSoldierOld ); //ja25 ub + HandleWhenCertainPercentageOfEnemiesDie(); //ja25 ub #endif - //The queen AI layer must process the event by subtracting forces, etc. - ProcessQueenCmdImplicationsOfDeath( pSoldierOld ); + //The queen AI layer must process the event by subtracting forces, etc. + ProcessQueenCmdImplicationsOfDeath( pSoldierOld ); #ifdef JA2UB - //------------------- ja25 ub ------------------------- - //if the person was Raul, and we are to say the blown up quotes - if( pSoldierOld->ubProfile == PERKO /*RAUL */ && IsJa25GeneralFlagSet( JA_GF__RAUL_BLOW_HIMSELF_UP ) ) - { - UINT8 SoldierId1; - UINT8 SoldierId2; + //------------------- ja25 ub ------------------------- + //if the person was Raul, and we are to say the blown up quotes + if( pSoldierOld->ubProfile == PERKO /*RAUL */ && IsJa25GeneralFlagSet( JA_GF__RAUL_BLOW_HIMSELF_UP ) ) + { + UINT8 SoldierId1; + UINT8 SoldierId2; - //Get some random Soldier ID's of the valid mercs - if( Get3RandomQualifiedMercs( &SoldierId1, &SoldierId2, NULL ) != 0 ) - { - //Say the "he blew himself up quote" - TacticalCharacterDialogue( &Menptr[SoldierId1], QUOTE_GREETING ); + //Get some random Soldier ID's of the valid mercs + if( Get3RandomQualifiedMercs( &SoldierId1, &SoldierId2, NULL ) != 0 ) + { + //Say the "he blew himself up quote" + TacticalCharacterDialogue( &Menptr[SoldierId1], QUOTE_GREETING ); - //if there isnt a second soldier - if( SoldierId2 == NOBODY ) - { - SoldierId2 = SoldierId1; - } + //if there isnt a second soldier + if( SoldierId2 == NOBODY ) + { + SoldierId2 = SoldierId1; + } - //say the "darn he took the inventoruy with him" - TacticalCharacterDialogue( &Menptr[SoldierId2], QUOTE_SMALL_TALK ); - } - } + //say the "darn he took the inventoruy with him" + TacticalCharacterDialogue( &Menptr[SoldierId2], QUOTE_SMALL_TALK ); + } + } #endif - // OK, check for existence of any more badguys! - CheckForEndOfBattle( FALSE ); + // OK, check for existence of any more badguys! + CheckForEndOfBattle( FALSE ); } UINT8 LastActiveTeamMember( UINT8 ubTeam ) { - INT32 cnt; - SOLDIERTYPE *pSoldier; + INT32 cnt; + SOLDIERTYPE *pSoldier; - cnt = gTacticalStatus.Team[ ubTeam ].bLastID; + cnt = gTacticalStatus.Team[ ubTeam ].bLastID; - // look for all mercs on the same team, - for ( pSoldier = MercPtrs[ cnt ]; cnt >= gTacticalStatus.Team[ ubTeam ].bFirstID; cnt-- ,pSoldier--) - { - if ( pSoldier->bActive ) - { - return( (INT8)cnt ); - } - } + // look for all mercs on the same team, + for ( pSoldier = MercPtrs[ cnt ]; cnt >= gTacticalStatus.Team[ ubTeam ].bFirstID; cnt-- ,pSoldier--) + { + if ( pSoldier->bActive ) + { + return( (INT8)cnt ); + } + } - return( gTacticalStatus.Team[ ubTeam ].bLastID ); + return( gTacticalStatus.Team[ ubTeam ].bLastID ); } void CheckForPotentialAddToBattleIncrement( SOLDIERTYPE *pSoldier ) { - //UINT16 iCounter2; - // Check if we are a threat! - if ( !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum ) ) - { - //if ( FindObjClass( pSoldier, IC_WEAPON ) != NO_SLOT ) - // We need to exclude cases where a kid is not neutral anymore, but is defenceless! - if ( pSoldier->bTeam == CIV_TEAM ) - { - /* // maybe increment num enemy attacked - switch ( pSoldier->ubCivilianGroup ) - { - case REBEL_CIV_GROUP: - case KINGPIN_CIV_GROUP: - case HICKS_CIV_GROUP: - if ( FindObjClass( pSoldier, IC_WEAPON ) != NO_SLOT ) - { - gTacticalStatus.bNumFoughtInBattle[ pSoldier->bTeam ]++; - } - break; - default: - // nope! - break; - } - - //New Group by Jazz - for( iCounter2 = UNNAMED_CIV_GROUP_15; iCounter2 < NUM_CIV_GROUPS; iCounter2++ ) - { - if (pSoldier->ubCivilianGroup == iCounter2) - { - if ( FindObjClass( pSoldier, IC_WEAPON ) != NO_SLOT ) - { - gTacticalStatus.bNumFoughtInBattle[ pSoldier->bTeam ]++; - } - - } - } - */ - - //New Group by Jazz - if ( FindObjClass( pSoldier, IC_WEAPON ) != NO_SLOT && pSoldier->ubCivilianGroup >= REBEL_CIV_GROUP && pSoldier->ubCivilianGroup < NUM_CIV_GROUPS ) - { - if ( zCivGroupName[pSoldier->ubCivilianGroup].AddToBattle == TRUE ) - { - gTacticalStatus.bNumFoughtInBattle[ pSoldier->bTeam ]++; - } - } - } - else - { - // Increment num enemy attacked - gTacticalStatus.bNumFoughtInBattle[ pSoldier->bTeam ]++; - } - } + //UINT16 iCounter2; + // Check if we are a threat! + if ( !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum ) ) + { + //if ( FindObjClass( pSoldier, IC_WEAPON ) != NO_SLOT ) + // We need to exclude cases where a kid is not neutral anymore, but is defenceless! + if ( pSoldier->bTeam == CIV_TEAM ) + { + /* // maybe increment num enemy attacked + switch ( pSoldier->ubCivilianGroup ) + { + case REBEL_CIV_GROUP: + case KINGPIN_CIV_GROUP: + case HICKS_CIV_GROUP: + if ( FindObjClass( pSoldier, IC_WEAPON ) != NO_SLOT ) + { + gTacticalStatus.bNumFoughtInBattle[ pSoldier->bTeam ]++; + } + break; + default: + // nope! + break; + } + + //New Group by Jazz + for( iCounter2 = UNNAMED_CIV_GROUP_15; iCounter2 < NUM_CIV_GROUPS; iCounter2++ ) + { + if (pSoldier->ubCivilianGroup == iCounter2) + { + if ( FindObjClass( pSoldier, IC_WEAPON ) != NO_SLOT ) + { + gTacticalStatus.bNumFoughtInBattle[ pSoldier->bTeam ]++; + } + + } + } + */ + + //New Group by Jazz + if ( FindObjClass( pSoldier, IC_WEAPON ) != NO_SLOT && pSoldier->ubCivilianGroup >= REBEL_CIV_GROUP && pSoldier->ubCivilianGroup < NUM_CIV_GROUPS ) + { + if ( zCivGroupName[pSoldier->ubCivilianGroup].AddToBattle == TRUE ) + { + gTacticalStatus.bNumFoughtInBattle[ pSoldier->bTeam ]++; + } + } + } + else + { + // Increment num enemy attacked + gTacticalStatus.bNumFoughtInBattle[ pSoldier->bTeam ]++; + } + } } // internal function for turning neutral to FALSE void SetSoldierNonNeutral( SOLDIERTYPE * pSoldier ) { - pSoldier->aiData.bNeutral = FALSE; + pSoldier->aiData.bNeutral = FALSE; - if ( gTacticalStatus.bBoxingState == NOT_BOXING ) - { - // Special code for strategic implications - CalculateNonPersistantPBIInfo(); - } + if ( gTacticalStatus.bBoxingState == NOT_BOXING ) + { + // Special code for strategic implications + CalculateNonPersistantPBIInfo(); + } } // internal function for turning neutral to TRUE void SetSoldierNeutral( SOLDIERTYPE * pSoldier ) { - pSoldier->aiData.bNeutral = TRUE; + pSoldier->aiData.bNeutral = TRUE; - if ( gTacticalStatus.bBoxingState == NOT_BOXING ) - { - // Special code for strategic implications - // search through civ team looking for non-neutral civilian! - if ( !HostileCiviliansPresent() ) - { - CalculateNonPersistantPBIInfo(); - } - } + if ( gTacticalStatus.bBoxingState == NOT_BOXING ) + { + // Special code for strategic implications + // search through civ team looking for non-neutral civilian! + if ( !HostileCiviliansPresent() ) + { + CalculateNonPersistantPBIInfo(); + } + } } void MakeCivHostile( SOLDIERTYPE *pSoldier, INT8 bNewSide ) { - if ( pSoldier->ubBodyType == COW ) - { - return; - } + if ( pSoldier->ubBodyType == COW ) + { + return; + } - // override passed-in value; default is hostile to player, allied to army - bNewSide = 1; + // override passed-in value; default is hostile to player, allied to army + bNewSide = 1; - switch( pSoldier->ubProfile ) - { + switch( pSoldier->ubProfile ) + { #ifdef JA2UB -//Ja25 No Ira, miguel, etc + //Ja25 No Ira, miguel, etc #else - case IRA: - case DIMITRI: - case MIGUEL: - case CARLOS: -#endif - case MADLAB: - case DYNAMO: - case SHANK: - // rebels and rebel sympathizers become hostile to player and enemy - bNewSide = 2; - break; - case MARIA: - case ANGEL: - if ( gubQuest[ QUEST_RESCUE_MARIA ] == QUESTINPROGRESS || gubQuest[ QUEST_RESCUE_MARIA ] == QUESTDONE ) - { - bNewSide = 2; - } - break; - default: - switch( pSoldier->ubCivilianGroup ) - { - case REBEL_CIV_GROUP: - bNewSide = 2; - break; - default: - break; - } - break; - } + case IRA: + case DIMITRI: + case MIGUEL: + case CARLOS: +#endif + case MADLAB: + case DYNAMO: + case SHANK: + // rebels and rebel sympathizers become hostile to player and enemy + bNewSide = 2; + break; + case MARIA: + case ANGEL: + if ( gubQuest[ QUEST_RESCUE_MARIA ] == QUESTINPROGRESS || gubQuest[ QUEST_RESCUE_MARIA ] == QUESTDONE ) + { + bNewSide = 2; + } + break; + default: + switch( pSoldier->ubCivilianGroup ) + { + case REBEL_CIV_GROUP: + bNewSide = 2; + break; + default: + break; + } + break; + } - if ( !pSoldier->aiData.bNeutral && bNewSide == pSoldier->bSide ) - { - // already hostile! - return; - } + if ( !pSoldier->aiData.bNeutral && bNewSide == pSoldier->bSide ) + { + // already hostile! + return; + } - if (pSoldier->ubProfile == CONRAD || pSoldier->ubProfile == GENERAL) - { - // change to enemy team - SetSoldierNonNeutral( pSoldier ); - pSoldier->bSide = bNewSide; - pSoldier = ChangeSoldierTeam( pSoldier, ENEMY_TEAM ); - } - else - { - if ( pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP ) - { - // if Maria is in the sector and escorted, set fact that the escape has - // been noticed - if ( gubQuest[ QUEST_RESCUE_MARIA ] == QUESTINPROGRESS && gTacticalStatus.bBoxingState == NOT_BOXING ) - { - SOLDIERTYPE * pMaria = FindSoldierByProfileID( MARIA, FALSE ); - if ( pMaria && pMaria->bActive && pMaria->bInSector ) - { - SetFactTrue( FACT_MARIA_ESCAPE_NOTICED ); - } - } - } - if (pSoldier->ubProfile == BILLY) - { - // change orders - pSoldier->aiData.bOrders = FARPATROL; - } - if (bNewSide != -1) - { - pSoldier->bSide = bNewSide; - } - if ( pSoldier->aiData.bNeutral ) - { - // HEADROCK HAM 3.6: INI Setting decides whether non-combat civs can become hostile - if (gGameExternalOptions.fCanTrueCiviliansBecomeHostile || - !IS_CIV_BODY_TYPE(pSoldier)) - { - SetSoldierNonNeutral( pSoldier ); - } - RecalculateOppCntsDueToNoLongerNeutral( pSoldier ); - } - } + if (pSoldier->ubProfile == CONRAD || pSoldier->ubProfile == GENERAL) + { + // change to enemy team + SetSoldierNonNeutral( pSoldier ); + pSoldier->bSide = bNewSide; + pSoldier = ChangeSoldierTeam( pSoldier, ENEMY_TEAM ); + } + else + { + if ( pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP ) + { + // if Maria is in the sector and escorted, set fact that the escape has + // been noticed + if ( gubQuest[ QUEST_RESCUE_MARIA ] == QUESTINPROGRESS && gTacticalStatus.bBoxingState == NOT_BOXING ) + { + SOLDIERTYPE * pMaria = FindSoldierByProfileID( MARIA, FALSE ); + if ( pMaria && pMaria->bActive && pMaria->bInSector ) + { + SetFactTrue( FACT_MARIA_ESCAPE_NOTICED ); + } + } + } + if (pSoldier->ubProfile == BILLY) + { + // change orders + pSoldier->aiData.bOrders = FARPATROL; + } + if (bNewSide != -1) + { + pSoldier->bSide = bNewSide; + } + if ( pSoldier->aiData.bNeutral ) + { + // HEADROCK HAM 3.6: INI Setting decides whether non-combat civs can become hostile + if (gGameExternalOptions.fCanTrueCiviliansBecomeHostile || + !IS_CIV_BODY_TYPE(pSoldier)) + { + SetSoldierNonNeutral( pSoldier ); + } + RecalculateOppCntsDueToNoLongerNeutral( pSoldier ); + } + } - // If we are already in combat... - if ( ( gTacticalStatus.uiFlags & INCOMBAT ) ) - { - CheckForPotentialAddToBattleIncrement( pSoldier ); - } - + // If we are already in combat... + if ( ( gTacticalStatus.uiFlags & INCOMBAT ) ) + { + CheckForPotentialAddToBattleIncrement( pSoldier ); + } - //uses Lua - PROFILLUA2_ubProfile = pSoldier->ubProfile; - PROFILLUA2_sSectorX = pSoldier->sSectorX; - PROFILLUA2_sSectorY = pSoldier->sSectorY; - PROFILLUA2_bSectorZ = pSoldier->bSectorZ; - PROFILLUA2_sGridNo = pSoldier->sGridNo; - - //LetLuaMyCustomHandleAtNewGridNo(bNewSide,NULL, 1); + + //uses Lua + PROFILLUA2_ubProfile = pSoldier->ubProfile; + PROFILLUA2_sSectorX = pSoldier->sSectorX; + PROFILLUA2_sSectorY = pSoldier->sSectorY; + PROFILLUA2_bSectorZ = pSoldier->bSectorZ; + PROFILLUA2_sGridNo = pSoldier->sGridNo; + + //LetLuaMyCustomHandleAtNewGridNo(bNewSide,NULL, 1); } UINT8 CivilianGroupMembersChangeSidesWithinProximity( SOLDIERTYPE * pAttacked ) { - SOLDIERTYPE * pSoldier; - UINT8 ubFirstProfile = NO_PROFILE; - UINT8 cnt; + SOLDIERTYPE * pSoldier; + UINT8 ubFirstProfile = NO_PROFILE; + UINT8 cnt; - if ( pAttacked->ubCivilianGroup == NON_CIV_GROUP ) - { - return( pAttacked->ubProfile ); - } + if ( pAttacked->ubCivilianGroup == NON_CIV_GROUP ) + { + return( pAttacked->ubProfile ); + } - cnt = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; - for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; cnt++ ,pSoldier++ ) - { - if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife && pSoldier->aiData.bNeutral ) - { - if ( pSoldier->ubCivilianGroup == pAttacked->ubCivilianGroup && pSoldier->ubBodyType != COW ) - { - // if in LOS of this guy's attacker - if ( (pAttacked->ubAttackerID != NOBODY && pSoldier->aiData.bOppList[pAttacked->ubAttackerID] == SEEN_CURRENTLY) - || ( PythSpacesAway( pSoldier->sGridNo, pAttacked->sGridNo ) < pAttacked->GetMaxDistanceVisible(pSoldier->sGridNo, pSoldier->pathing.bLevel) ) - || ( pAttacked->ubAttackerID != NOBODY && PythSpacesAway( pSoldier->sGridNo, MercPtrs[ pAttacked->ubAttackerID ]->sGridNo ) < pAttacked->GetMaxDistanceVisible(MercPtrs[ pAttacked->ubAttackerID ]->sGridNo, MercPtrs[ pAttacked->ubAttackerID ]->pathing.bLevel) ) ) - { - MakeCivHostile( pSoldier, 2 ); - if ( pSoldier->aiData.bOppCnt > 0 ) - { - AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID ); - } + cnt = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; + for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; cnt++ ,pSoldier++ ) + { + if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife && pSoldier->aiData.bNeutral ) + { + if ( pSoldier->ubCivilianGroup == pAttacked->ubCivilianGroup && pSoldier->ubBodyType != COW ) + { + // if in LOS of this guy's attacker + if ( (pAttacked->ubAttackerID != NOBODY && pSoldier->aiData.bOppList[pAttacked->ubAttackerID] == SEEN_CURRENTLY) + || ( PythSpacesAway( pSoldier->sGridNo, pAttacked->sGridNo ) < pAttacked->GetMaxDistanceVisible(pSoldier->sGridNo, pSoldier->pathing.bLevel) ) + || ( pAttacked->ubAttackerID != NOBODY && PythSpacesAway( pSoldier->sGridNo, MercPtrs[ pAttacked->ubAttackerID ]->sGridNo ) < pAttacked->GetMaxDistanceVisible(MercPtrs[ pAttacked->ubAttackerID ]->sGridNo, MercPtrs[ pAttacked->ubAttackerID ]->pathing.bLevel) ) ) + { + MakeCivHostile( pSoldier, 2 ); + if ( pSoldier->aiData.bOppCnt > 0 ) + { + AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID ); + } - if ( pSoldier->ubProfile != NO_PROFILE && pSoldier->aiData.bOppCnt > 0 && ( ubFirstProfile == NO_PROFILE || Random( 2 ) ) ) - { - ubFirstProfile = pSoldier->ubProfile; - } - } + if ( pSoldier->ubProfile != NO_PROFILE && pSoldier->aiData.bOppCnt > 0 && ( ubFirstProfile == NO_PROFILE || Random( 2 ) ) ) + { + ubFirstProfile = pSoldier->ubProfile; + } + } - } - } - } + } + } + } - return( ubFirstProfile ); + return( ubFirstProfile ); } SOLDIERTYPE * CivilianGroupMemberChangesSides( SOLDIERTYPE * pAttacked ) { - SOLDIERTYPE * pNew; - SOLDIERTYPE * pNewAttacked = pAttacked; - SOLDIERTYPE * pSoldier; - UINT8 cnt; - UINT8 ubFirstProfile = NO_PROFILE; + SOLDIERTYPE * pNew; + SOLDIERTYPE * pNewAttacked = pAttacked; + SOLDIERTYPE * pSoldier; + UINT8 cnt; + UINT8 ubFirstProfile = NO_PROFILE; - if ( pAttacked->ubCivilianGroup == NON_CIV_GROUP ) - { - // abort - return( pNewAttacked ); - } + if ( pAttacked->ubCivilianGroup == NON_CIV_GROUP ) + { + // abort + return( pNewAttacked ); + } - // remove anyone (rebels) on our team and put them back in the civ team - cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; - for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++ ,pSoldier++) - { - if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife) - { - if (pSoldier->ubCivilianGroup == pAttacked->ubCivilianGroup) - { - // should become hostile - if ( pSoldier->ubProfile != NO_PROFILE && ( ubFirstProfile == NO_PROFILE || Random( 2 ) ) ) - { - ubFirstProfile = pSoldier->ubProfile; - } + // remove anyone (rebels) on our team and put them back in the civ team + cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; + for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++ ,pSoldier++) + { + if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife) + { + if (pSoldier->ubCivilianGroup == pAttacked->ubCivilianGroup) + { + // should become hostile + if ( pSoldier->ubProfile != NO_PROFILE && ( ubFirstProfile == NO_PROFILE || Random( 2 ) ) ) + { + ubFirstProfile = pSoldier->ubProfile; + } - pNew = ChangeSoldierTeam( pSoldier, CIV_TEAM ); - if ( pSoldier == pAttacked ) - { - pNewAttacked = pNew; - } + pNew = ChangeSoldierTeam( pSoldier, CIV_TEAM ); + if ( pSoldier == pAttacked ) + { + pNewAttacked = pNew; + } - } - } - } + } + } + } - // now change sides for anyone on the civ team within proximity - if ( ubFirstProfile == NO_PROFILE ) - { - // get first profile value - ubFirstProfile = CivilianGroupMembersChangeSidesWithinProximity( pNewAttacked ); - } - else - { - // just call - CivilianGroupMembersChangeSidesWithinProximity( pNewAttacked ); - } + // now change sides for anyone on the civ team within proximity + if ( ubFirstProfile == NO_PROFILE ) + { + // get first profile value + ubFirstProfile = CivilianGroupMembersChangeSidesWithinProximity( pNewAttacked ); + } + else + { + // just call + CivilianGroupMembersChangeSidesWithinProximity( pNewAttacked ); + } - /* - if ( ubFirstProfile != NO_PROFILE ) - { - TriggerFriendWithHostileQuote( ubFirstProfile ); - } - */ + /* + if ( ubFirstProfile != NO_PROFILE ) + { + TriggerFriendWithHostileQuote( ubFirstProfile ); + } + */ - if ( gTacticalStatus.fCivGroupHostile[ pNewAttacked->ubCivilianGroup ] == CIV_GROUP_NEUTRAL ) - { - // if the civilian group turning hostile is the Rebels - if (pAttacked->ubCivilianGroup == REBEL_CIV_GROUP) - { - // we haven't already reduced the loyalty back when we first set the flag to BECOME hostile - ReduceLoyaltyForRebelsBetrayed(); - } + if ( gTacticalStatus.fCivGroupHostile[ pNewAttacked->ubCivilianGroup ] == CIV_GROUP_NEUTRAL ) + { + // if the civilian group turning hostile is the Rebels + if (pAttacked->ubCivilianGroup == REBEL_CIV_GROUP) + { + // we haven't already reduced the loyalty back when we first set the flag to BECOME hostile + ReduceLoyaltyForRebelsBetrayed(); + } - AddStrategicEvent( EVENT_MAKE_CIV_GROUP_HOSTILE_ON_NEXT_SECTOR_ENTRANCE, GetWorldTotalMin() + 300, pNewAttacked->ubCivilianGroup ); - gTacticalStatus.fCivGroupHostile[ pNewAttacked->ubCivilianGroup ] = CIV_GROUP_WILL_EVENTUALLY_BECOME_HOSTILE; - } + AddStrategicEvent( EVENT_MAKE_CIV_GROUP_HOSTILE_ON_NEXT_SECTOR_ENTRANCE, GetWorldTotalMin() + 300, pNewAttacked->ubCivilianGroup ); + gTacticalStatus.fCivGroupHostile[ pNewAttacked->ubCivilianGroup ] = CIV_GROUP_WILL_EVENTUALLY_BECOME_HOSTILE; + } - // HEADROCK HAM 3.6: If this sector has affiliated bloodcats, make them all hostile. - if ( gBloodcatPlacements[SECTOR(pNewAttacked->sSectorX,pNewAttacked->sSectorY)][0].PlacementType == BLOODCAT_PLACEMENT_STATIC && - gBloodcatPlacements[SECTOR(pNewAttacked->sSectorX,pNewAttacked->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation == pNewAttacked->ubCivilianGroup ) - { - MakeBloodcatsHostile(); - } + // HEADROCK HAM 3.6: If this sector has affiliated bloodcats, make them all hostile. + if ( gBloodcatPlacements[SECTOR(pNewAttacked->sSectorX,pNewAttacked->sSectorY)][0].PlacementType == BLOODCAT_PLACEMENT_STATIC && + gBloodcatPlacements[SECTOR(pNewAttacked->sSectorX,pNewAttacked->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation == pNewAttacked->ubCivilianGroup ) + { + MakeBloodcatsHostile(); + } - return( pNewAttacked ); + return( pNewAttacked ); } void CivilianGroupChangesSides( UINT8 ubCivilianGroup ) { - // change civ group side due to external event (wall blowing up) - INT32 cnt; - SOLDIERTYPE * pSoldier; + // change civ group side due to external event (wall blowing up) + INT32 cnt; + SOLDIERTYPE * pSoldier; - gTacticalStatus.fCivGroupHostile[ ubCivilianGroup ] = CIV_GROUP_HOSTILE; + gTacticalStatus.fCivGroupHostile[ ubCivilianGroup ] = CIV_GROUP_HOSTILE; - // now change sides for anyone on the civ team - cnt = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; - for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; cnt++ ,pSoldier++) - { - if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife && pSoldier->aiData.bNeutral) - { - if ( pSoldier->ubCivilianGroup == ubCivilianGroup && pSoldier->ubBodyType != COW ) - { - MakeCivHostile( pSoldier, 2 ); - if ( pSoldier->aiData.bOppCnt > 0 ) - { - AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID ); - } - /* - if ( (pSoldier->ubProfile != NO_PROFILE) && (pSoldier->aiData.bOppCnt > 0) && ( ubFirstProfile == NO_PROFILE || Random( 2 ) ) ) - { - ubFirstProfile = pSoldier->ubProfile; - } - */ - } - } - } + // now change sides for anyone on the civ team + cnt = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; + for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; cnt++ ,pSoldier++) + { + if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife && pSoldier->aiData.bNeutral) + { + if ( pSoldier->ubCivilianGroup == ubCivilianGroup && pSoldier->ubBodyType != COW ) + { + MakeCivHostile( pSoldier, 2 ); + if ( pSoldier->aiData.bOppCnt > 0 ) + { + AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID ); + } + /* + if ( (pSoldier->ubProfile != NO_PROFILE) && (pSoldier->aiData.bOppCnt > 0) && ( ubFirstProfile == NO_PROFILE || Random( 2 ) ) ) + { + ubFirstProfile = pSoldier->ubProfile; + } + */ + } + } + } - /* - if ( ubFirstProfile != NO_PROFILE ) - { - TriggerFriendWithHostileQuote( ubFirstProfile ); - } - */ + /* + if ( ubFirstProfile != NO_PROFILE ) + { + TriggerFriendWithHostileQuote( ubFirstProfile ); + } + */ } void HickCowAttacked( SOLDIERTYPE * pNastyGuy, SOLDIERTYPE * pTarget ) { - INT32 cnt; - SOLDIERTYPE * pSoldier; + INT32 cnt; + SOLDIERTYPE * pSoldier; - // now change sides for anyone on the civ team - cnt = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; - for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; cnt++ ,pSoldier++) - { - if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife && pSoldier->aiData.bNeutral && pSoldier->ubCivilianGroup == HICKS_CIV_GROUP ) - { - if ( SoldierToSoldierLineOfSightTest( pSoldier, pNastyGuy, TRUE ) ) - { - CivilianGroupMemberChangesSides( pSoldier ); - break; - } - } - } + // now change sides for anyone on the civ team + cnt = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; + for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; cnt++ ,pSoldier++) + { + if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife && pSoldier->aiData.bNeutral && pSoldier->ubCivilianGroup == HICKS_CIV_GROUP ) + { + if ( SoldierToSoldierLineOfSightTest( pSoldier, pNastyGuy, TRUE ) ) + { + CivilianGroupMemberChangesSides( pSoldier ); + break; + } + } + } } -void MilitiaChangesSides( void ) +void MilitiaChangesSides( ) { - // make all the militia change sides + // make all the militia change sides - INT32 cnt; - SOLDIERTYPE * pSoldier; + INT32 cnt; + SOLDIERTYPE * pSoldier; - if ( gTacticalStatus.Team[ MILITIA_TEAM ].bMenInSector == 0 ) - { - return; - } + if ( gTacticalStatus.Team[ MILITIA_TEAM ].bMenInSector == 0 ) + { + return; + } - // remove anyone (rebels) on our team and put them back in the civ team - cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; - for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++ ,pSoldier++) - { - if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife) - { - if ( (gWorldSectorX ==0 && gWorldSectorY == 0) || !NumEnemiesInSector( gWorldSectorX, gWorldSectorY ) ) - MakeCivHostile( pSoldier, 2 ); - RecalculateOppCntsDueToNoLongerNeutral( pSoldier ); - } - } + // remove anyone (rebels) on our team and put them back in the civ team + cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; + for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++ ,pSoldier++) + { + if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife) + { + if ( (gWorldSectorX ==0 && gWorldSectorY == 0) || !NumEnemiesInSector( gWorldSectorX, gWorldSectorY ) ) + MakeCivHostile( pSoldier, 2 ); + RecalculateOppCntsDueToNoLongerNeutral( pSoldier ); + } + } } /* -void MakePotentiallyHostileCivGroupsHostile( void ) -{ -UINT8 ubLoop; + void MakePotentiallyHostileCivGroupsHostile( ) + { + UINT8 ubLoop; // loop through all civ groups that might become hostile and set them // to hostile @@ -4501,304 +4302,304 @@ gTacticalStatus.fCivGroupHostile[ ubLoop ] = CIV_GROUP_HOSTILE; } } } -*/ + */ INT8 NumActiveAndConsciousTeamMembers( UINT8 ubTeam ) { - INT32 cnt; - SOLDIERTYPE *pSoldier; - UINT8 ubCount = 0; + INT32 cnt; + SOLDIERTYPE *pSoldier; + UINT8 ubCount = 0; - cnt = gTacticalStatus.Team[ ubTeam ].bFirstID; + cnt = gTacticalStatus.Team[ ubTeam ].bFirstID; - // look for all mercs on the same team, - for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ ubTeam ].bLastID; cnt++,pSoldier++) - { - if ( OK_CONTROLLABLE_MERC( pSoldier) ) - { - ubCount++; - } - } + // look for all mercs on the same team, + for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ ubTeam ].bLastID; cnt++,pSoldier++) + { + if ( OK_CONTROLLABLE_MERC( pSoldier) ) + { + ubCount++; + } + } - return( ubCount ); + return( ubCount ); } UINT8 FindNextActiveAndAliveMerc( SOLDIERTYPE *pSoldier, BOOLEAN fGoodForLessOKLife, BOOLEAN fOnlyRegularMercs ) { - UINT8 bLastTeamID; - INT32 cnt; - SOLDIERTYPE *pTeamSoldier; + UINT8 bLastTeamID; + INT32 cnt; + SOLDIERTYPE *pTeamSoldier; - cnt = pSoldier->ubID + 1; - bLastTeamID = gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; + cnt = pSoldier->ubID + 1; + bLastTeamID = gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; - // look for all mercs on the same team, - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= bLastTeamID; cnt++,pTeamSoldier++) - { - if ( fOnlyRegularMercs ) - { - if ( pTeamSoldier->bActive && ( AM_AN_EPC( pTeamSoldier ) || AM_A_ROBOT( pTeamSoldier ) ) ) - { - continue; - } - } + // look for all mercs on the same team, + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= bLastTeamID; cnt++,pTeamSoldier++) + { + if ( fOnlyRegularMercs ) + { + if ( pTeamSoldier->bActive && ( AM_AN_EPC( pTeamSoldier ) || AM_A_ROBOT( pTeamSoldier ) ) ) + { + continue; + } + } - if ( fGoodForLessOKLife ) - { - if ( pTeamSoldier->stats.bLife > 0 && pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == gbPlayerNum && pTeamSoldier->bAssignment < ON_DUTY && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) - { - return( (UINT8)cnt ); - } - } - else - { - if ( OK_CONTROLLABLE_MERC( pTeamSoldier) && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) - { - return( (UINT8)cnt ); - } - } - } + if ( fGoodForLessOKLife ) + { + if ( pTeamSoldier->stats.bLife > 0 && pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == gbPlayerNum && pTeamSoldier->bAssignment < ON_DUTY && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) + { + return( (UINT8)cnt ); + } + } + else + { + if ( OK_CONTROLLABLE_MERC( pTeamSoldier) && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) + { + return( (UINT8)cnt ); + } + } + } - // none found, - // Now loop back - cnt = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID; - bLastTeamID = pSoldier->ubID; + // none found, + // Now loop back + cnt = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID; + bLastTeamID = pSoldier->ubID; - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= bLastTeamID; cnt++,pTeamSoldier++) - { - if ( fOnlyRegularMercs ) - { - if ( pTeamSoldier->bActive && ( AM_AN_EPC( pTeamSoldier ) || AM_A_ROBOT( pTeamSoldier ) ) ) - { - continue; - } - } + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= bLastTeamID; cnt++,pTeamSoldier++) + { + if ( fOnlyRegularMercs ) + { + if ( pTeamSoldier->bActive && ( AM_AN_EPC( pTeamSoldier ) || AM_A_ROBOT( pTeamSoldier ) ) ) + { + continue; + } + } - if ( fGoodForLessOKLife ) - { - if ( pTeamSoldier->stats.bLife > 0 && pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == gbPlayerNum && pTeamSoldier->bAssignment < ON_DUTY && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) - { - return( (UINT8)cnt ); - } - } - else - { - if ( OK_CONTROLLABLE_MERC( pTeamSoldier) && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) - { - return( (UINT8)cnt ); - } - } - } + if ( fGoodForLessOKLife ) + { + if ( pTeamSoldier->stats.bLife > 0 && pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == gbPlayerNum && pTeamSoldier->bAssignment < ON_DUTY && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) + { + return( (UINT8)cnt ); + } + } + else + { + if ( OK_CONTROLLABLE_MERC( pTeamSoldier) && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) + { + return( (UINT8)cnt ); + } + } + } - // IF we are here, keep as we always were! - return( pSoldier->ubID ); + // IF we are here, keep as we always were! + return( pSoldier->ubID ); } SOLDIERTYPE *FindNextActiveSquad( SOLDIERTYPE *pSoldier ) { - INT32 cnt, cnt2; + INT32 cnt, cnt2; - for( cnt = pSoldier->bAssignment + 1 ; cnt < NUMBER_OF_SQUADS; cnt++ ) - { - for( cnt2 =0; cnt2 < NUMBER_OF_SOLDIERS_PER_SQUAD; cnt2++ ) - { - if ( Squad[ cnt ][ cnt2 ] != NULL && Squad[ cnt ][ cnt2 ]->bInSector && OK_INTERRUPT_MERC( Squad[ cnt ][ cnt2 ] ) && OK_CONTROLLABLE_MERC( Squad[ cnt ][ cnt2 ] ) && !(Squad[ cnt ][ cnt2 ]->flags.uiStatusFlags & SOLDIER_VEHICLE) ) - { - return( Squad[ cnt ][ cnt2 ] ); - } - } - } + for( cnt = pSoldier->bAssignment + 1 ; cnt < NUMBER_OF_SQUADS; cnt++ ) + { + for( cnt2 =0; cnt2 < NUMBER_OF_SOLDIERS_PER_SQUAD; cnt2++ ) + { + if ( Squad[ cnt ][ cnt2 ] != NULL && Squad[ cnt ][ cnt2 ]->bInSector && OK_INTERRUPT_MERC( Squad[ cnt ][ cnt2 ] ) && OK_CONTROLLABLE_MERC( Squad[ cnt ][ cnt2 ] ) && !(Squad[ cnt ][ cnt2 ]->flags.uiStatusFlags & SOLDIER_VEHICLE) ) + { + return( Squad[ cnt ][ cnt2 ] ); + } + } + } - // none found, - // Now loop back - for( cnt = 0; cnt <= pSoldier->bAssignment; cnt++ ) - { - for( cnt2 =0; cnt2 < NUMBER_OF_SOLDIERS_PER_SQUAD; cnt2++ ) - { - if ( Squad[ cnt ][ cnt2 ] != NULL && Squad[ cnt ][ cnt2 ]->bInSector && OK_INTERRUPT_MERC( Squad[ cnt ][ cnt2 ] ) && OK_CONTROLLABLE_MERC( Squad[ cnt ][ cnt2 ] ) && !(Squad[ cnt ][ cnt2 ]->flags.uiStatusFlags & SOLDIER_VEHICLE) ) - { - return( Squad[ cnt ][ cnt2 ] ); - } - } - } + // none found, + // Now loop back + for( cnt = 0; cnt <= pSoldier->bAssignment; cnt++ ) + { + for( cnt2 =0; cnt2 < NUMBER_OF_SOLDIERS_PER_SQUAD; cnt2++ ) + { + if ( Squad[ cnt ][ cnt2 ] != NULL && Squad[ cnt ][ cnt2 ]->bInSector && OK_INTERRUPT_MERC( Squad[ cnt ][ cnt2 ] ) && OK_CONTROLLABLE_MERC( Squad[ cnt ][ cnt2 ] ) && !(Squad[ cnt ][ cnt2 ]->flags.uiStatusFlags & SOLDIER_VEHICLE) ) + { + return( Squad[ cnt ][ cnt2 ] ); + } + } + } - // IF we are here, keep as we always were! - return( pSoldier ); + // IF we are here, keep as we always were! + return( pSoldier ); } -UINT8 FindPrevActiveAndAliveMerc( SOLDIERTYPE *pSoldier, BOOLEAN fGoodForLessOKLife, BOOLEAN fOnlyRegularMercs ) +UINT8 FindPrevActiveAndAliveMerc( SOLDIERTYPE *pSoldier, BOOLEAN fGoodForLessOKLife, BOOLEAN fOnlyRegularMercs ) { - UINT8 bLastTeamID; - INT32 cnt; - SOLDIERTYPE *pTeamSoldier; + UINT8 bLastTeamID; + INT32 cnt; + SOLDIERTYPE *pTeamSoldier; - // loop back - bLastTeamID = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID; - cnt = pSoldier->ubID - 1; + // loop back + bLastTeamID = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID; + cnt = pSoldier->ubID - 1; - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt >= bLastTeamID; cnt--,pTeamSoldier-- ) - { - if ( fOnlyRegularMercs ) - { - if ( AM_AN_EPC( pTeamSoldier ) || AM_A_ROBOT( pTeamSoldier ) ) - { - continue; - } - } + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt >= bLastTeamID; cnt--,pTeamSoldier-- ) + { + if ( fOnlyRegularMercs ) + { + if ( AM_AN_EPC( pTeamSoldier ) || AM_A_ROBOT( pTeamSoldier ) ) + { + continue; + } + } - if ( fGoodForLessOKLife ) - { - // Check for bLife > 0 - if ( pTeamSoldier->stats.bLife > 0 && pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == gbPlayerNum && pTeamSoldier->bAssignment < ON_DUTY && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) - { - return( (UINT8)cnt ); - } - } - else - { - if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) - { - return( (UINT8)cnt ); - } - } - } + if ( fGoodForLessOKLife ) + { + // Check for bLife > 0 + if ( pTeamSoldier->stats.bLife > 0 && pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == gbPlayerNum && pTeamSoldier->bAssignment < ON_DUTY && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) + { + return( (UINT8)cnt ); + } + } + else + { + if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) + { + return( (UINT8)cnt ); + } + } + } - bLastTeamID = pSoldier->ubID; - cnt = gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; + bLastTeamID = pSoldier->ubID; + cnt = gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; - // look for all mercs on the same team, - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt >= bLastTeamID; cnt--,pTeamSoldier-- ) - { - if ( fOnlyRegularMercs ) - { - if ( AM_AN_EPC( pTeamSoldier ) || AM_A_ROBOT( pTeamSoldier ) ) - { - continue; - } - } + // look for all mercs on the same team, + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt >= bLastTeamID; cnt--,pTeamSoldier-- ) + { + if ( fOnlyRegularMercs ) + { + if ( AM_AN_EPC( pTeamSoldier ) || AM_A_ROBOT( pTeamSoldier ) ) + { + continue; + } + } - if ( fGoodForLessOKLife ) - { - if ( pTeamSoldier->stats.bLife > 0 && pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == gbPlayerNum && pTeamSoldier->bAssignment < ON_DUTY && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) - { - return( (UINT8)cnt ); - } - } - else - { - if ( OK_CONTROLLABLE_MERC( pTeamSoldier) && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) - { - return( (UINT8)cnt ); - } - } - } + if ( fGoodForLessOKLife ) + { + if ( pTeamSoldier->stats.bLife > 0 && pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == gbPlayerNum && pTeamSoldier->bAssignment < ON_DUTY && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) + { + return( (UINT8)cnt ); + } + } + else + { + if ( OK_CONTROLLABLE_MERC( pTeamSoldier) && OK_INTERRUPT_MERC( pTeamSoldier ) && pSoldier->bAssignment == pTeamSoldier->bAssignment ) + { + return( (UINT8)cnt ); + } + } + } - // none found, - // IF we are here, keep as we always were! - return( pSoldier->ubID ); + // none found, + // IF we are here, keep as we always were! + return( pSoldier->ubID ); } BOOLEAN CheckForPlayerTeamInMissionExit( ) { - INT32 cnt; - SOLDIERTYPE *pSoldier; - UINT8 bGuysIn = 0; + INT32 cnt; + SOLDIERTYPE *pSoldier; + UINT8 bGuysIn = 0; - // End the turn of player charactors - cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; + // End the turn of player charactors + cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; - // look for all mercs on the same team, - for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++) - { - if ( pSoldier->bActive && pSoldier->stats.bLife >= OKLIFE ) - { - if ( pSoldier->flags.fInMissionExitNode ) - { - bGuysIn++; - } - } - } + // look for all mercs on the same team, + for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++) + { + if ( pSoldier->bActive && pSoldier->stats.bLife >= OKLIFE ) + { + if ( pSoldier->flags.fInMissionExitNode ) + { + bGuysIn++; + } + } + } - if ( bGuysIn == 0 ) - { - return( FALSE ); - } + if ( bGuysIn == 0 ) + { + return( FALSE ); + } - if ( NumActiveAndConsciousTeamMembers( gbPlayerNum ) == 0 ) - { - return( FALSE ); - } + if ( NumActiveAndConsciousTeamMembers( gbPlayerNum ) == 0 ) + { + return( FALSE ); + } - if ( bGuysIn == NumActiveAndConsciousTeamMembers( gbPlayerNum ) ) - { - return( TRUE ); - } + if ( bGuysIn == NumActiveAndConsciousTeamMembers( gbPlayerNum ) ) + { + return( TRUE ); + } - return( FALSE ); + return( FALSE ); } void EndTacticalDemo( ) { - gTacticalStatus.uiFlags &= (~DEMOMODE ); - gTacticalStatus.fGoingToEnterDemo = FALSE; + gTacticalStatus.uiFlags &= (~DEMOMODE ); + gTacticalStatus.fGoingToEnterDemo = FALSE; } UINT32 EnterTacticalDemoMode() { - UINT8 ubNewScene = gubCurrentScene; - UINT8 ubNumScenes = NUM_RANDOM_SCENES; + UINT8 ubNewScene = gubCurrentScene; + UINT8 ubNumScenes = NUM_RANDOM_SCENES; - gTacticalStatus.uiTimeOfLastInput = GetJA2Clock(); + gTacticalStatus.uiTimeOfLastInput = GetJA2Clock(); - // REMOVE ALL EVENTS! - DequeAllGameEvents( FALSE ); + // REMOVE ALL EVENTS! + DequeAllGameEvents( FALSE ); - // Switch into realtime/demo - gTacticalStatus.uiFlags |= ( REALTIME | DEMOMODE ); - gTacticalStatus.uiFlags &= (~TURNBASED); - gTacticalStatus.uiFlags &= (~NPC_TEAM_DEAD); - gTacticalStatus.uiFlags &= (~PLAYER_TEAM_DEAD); + // Switch into realtime/demo + gTacticalStatus.uiFlags |= ( REALTIME | DEMOMODE ); + gTacticalStatus.uiFlags &= (~TURNBASED); + gTacticalStatus.uiFlags &= (~NPC_TEAM_DEAD); + gTacticalStatus.uiFlags &= (~PLAYER_TEAM_DEAD); - // Force load of guys - SetLoadOverrideParams( TRUE, FALSE, NULL ); + // Force load of guys + SetLoadOverrideParams( TRUE, FALSE, NULL ); - // Load random level - // Dont't do first three levels - if ( gTacticalStatus.fNOTDOLASTDEMO ) - { - ubNumScenes--; - } + // Load random level + // Dont't do first three levels + if ( gTacticalStatus.fNOTDOLASTDEMO ) + { + ubNumScenes--; + } - do - { - ubNewScene = START_DEMO_SCENE + (UINT8)Random( ubNumScenes ); + do + { + ubNewScene = START_DEMO_SCENE + (UINT8)Random( ubNumScenes ); - } while( ubNewScene == gubCurrentScene ); + } while( ubNewScene == gubCurrentScene ); - gubCurrentScene = ubNewScene; + gubCurrentScene = ubNewScene; - // Set demo timer - gTacticalStatus.uiTimeSinceDemoOn = GetJA2Clock(); + // Set demo timer + gTacticalStatus.uiTimeSinceDemoOn = GetJA2Clock(); - gfSGPInputReceived = FALSE; + gfSGPInputReceived = FALSE; - gTacticalStatus.fGoingToEnterDemo = FALSE; + gTacticalStatus.fGoingToEnterDemo = FALSE; - return( INIT_SCREEN ); + return( INIT_SCREEN ); } -CHAR8 *GetSceneFilename( ) +CHAR8 *GetSceneFilename( ) { - return( gzLevelFilenames[ gubCurrentScene ] ); + return( gzLevelFilenames[ gubCurrentScene ] ); } extern BOOLEAN InternalOkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_STRUCTURE_REF * pDBStructureRef, INT16 sExclusionID, BOOLEAN fIgnorePeople ); @@ -4806,252 +4607,252 @@ extern BOOLEAN InternalOkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel // NB if making changes don't forget to update NewOKDestinationAndDirection INT16 NewOKDestination( SOLDIERTYPE * pCurrSoldier, INT32 sGridNo, BOOLEAN fPeopleToo, INT8 bLevel ) { - UINT8 bPerson; - STRUCTURE * pStructure; - INT16 sDesiredLevel; - BOOLEAN fOKCheckStruct; + UINT8 bPerson; + STRUCTURE * pStructure; + INT16 sDesiredLevel; + BOOLEAN fOKCheckStruct; - if ( !GridNoOnVisibleWorldTile( sGridNo ) ) - { - return( TRUE ); - } + if ( !GridNoOnVisibleWorldTile( sGridNo ) ) + { + return( TRUE ); + } - if (fPeopleToo && ( bPerson = WhoIsThere2( sGridNo, bLevel ) ) != NOBODY ) - { - // we could be multitiled... if the person there is us, and the gridno is not - // our base gridno, skip past these checks - if ( ! (bPerson == pCurrSoldier->ubID && sGridNo != pCurrSoldier->sGridNo) ) - { - if ( pCurrSoldier->bTeam == gbPlayerNum ) - { - if ( ( Menptr[ bPerson ].bVisible >= 0) || ( gTacticalStatus.uiFlags & SHOW_ALL_MERCS ) ) - return( FALSE ); // if someone there it's NOT OK - } - else - { - return( FALSE ); // if someone there it's NOT OK - } - } - } + if (fPeopleToo && ( bPerson = WhoIsThere2( sGridNo, bLevel ) ) != NOBODY ) + { + // we could be multitiled... if the person there is us, and the gridno is not + // our base gridno, skip past these checks + if ( ! (bPerson == pCurrSoldier->ubID && sGridNo != pCurrSoldier->sGridNo) ) + { + if ( pCurrSoldier->bTeam == gbPlayerNum ) + { + if ( ( Menptr[ bPerson ].bVisible >= 0) || ( gTacticalStatus.uiFlags & SHOW_ALL_MERCS ) ) + return( FALSE ); // if someone there it's NOT OK + } + else + { + return( FALSE ); // if someone there it's NOT OK + } + } + } - // Check structure database - if ( (pCurrSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE) && !(gfEstimatePath) ) - { - UINT16 usAnimSurface; - STRUCTURE_FILE_REF * pStructureFileRef; - BOOLEAN fOk; - INT8 bLoop; - UINT16 usStructureID = INVALID_STRUCTURE_ID; + // Check structure database + if ( (pCurrSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE) && !(gfEstimatePath) ) + { + UINT16 usAnimSurface; + STRUCTURE_FILE_REF * pStructureFileRef; + BOOLEAN fOk; + INT8 bLoop; + UINT16 usStructureID = INVALID_STRUCTURE_ID; - // this could be kinda slow... + // this could be kinda slow... - // Get animation surface... - usAnimSurface = DetermineSoldierAnimationSurface( pCurrSoldier, pCurrSoldier->usUIMovementMode ); - // Get structure ref... - pStructureFileRef = GetAnimationStructureRef( pCurrSoldier->ubID, usAnimSurface, pCurrSoldier->usUIMovementMode ); + // Get animation surface... + usAnimSurface = DetermineSoldierAnimationSurface( pCurrSoldier, pCurrSoldier->usUIMovementMode ); + // Get structure ref... + pStructureFileRef = GetAnimationStructureRef( pCurrSoldier->ubID, usAnimSurface, pCurrSoldier->usUIMovementMode ); - // opposite directions should be mirrors, so only check 4 - if ( pStructureFileRef ) - { - // if ANY direction is valid, consider moving here valid - for (bLoop = 0; bLoop < NUM_WORLD_DIRECTIONS; bLoop++) - { - // ATE: Only if we have a levelnode... - if ( pCurrSoldier->pLevelNode != NULL && pCurrSoldier->pLevelNode->pStructureData != NULL ) - { - usStructureID = pCurrSoldier->pLevelNode->pStructureData->usStructureID; - } - else - { - usStructureID = INVALID_STRUCTURE_ID; - } + // opposite directions should be mirrors, so only check 4 + if ( pStructureFileRef ) + { + // if ANY direction is valid, consider moving here valid + for (bLoop = 0; bLoop < NUM_WORLD_DIRECTIONS; bLoop++) + { + // ATE: Only if we have a levelnode... + if ( pCurrSoldier->pLevelNode != NULL && pCurrSoldier->pLevelNode->pStructureData != NULL ) + { + usStructureID = pCurrSoldier->pLevelNode->pStructureData->usStructureID; + } + else + { + usStructureID = INVALID_STRUCTURE_ID; + } - fOk = InternalOkayToAddStructureToWorld( sGridNo, bLevel, &(pStructureFileRef->pDBStructureRef[bLoop]), usStructureID, (BOOLEAN)!fPeopleToo ); - if (fOk) - { - return( TRUE ); - } - } - } - return( FALSE ); - } - else - { - // quick test - if ( gpWorldLevelData[ sGridNo ].pStructureHead != NULL ) - { - // Something is here, check obstruction in future - if ( bLevel == 0) - { - sDesiredLevel = STRUCTURE_ON_GROUND; - } - else - { - sDesiredLevel = STRUCTURE_ON_ROOF; - } + fOk = InternalOkayToAddStructureToWorld( sGridNo, bLevel, &(pStructureFileRef->pDBStructureRef[bLoop]), usStructureID, (BOOLEAN)!fPeopleToo ); + if (fOk) + { + return( TRUE ); + } + } + } + return( FALSE ); + } + else + { + // quick test + if ( gpWorldLevelData[ sGridNo ].pStructureHead != NULL ) + { + // Something is here, check obstruction in future + if ( bLevel == 0) + { + sDesiredLevel = STRUCTURE_ON_GROUND; + } + else + { + sDesiredLevel = STRUCTURE_ON_ROOF; + } - pStructure = FindStructure( sGridNo, STRUCTURE_BLOCKSMOVES ); + pStructure = FindStructure( sGridNo, STRUCTURE_BLOCKSMOVES ); - // ATE: If we are trying to get a path to an exit grid AND - // we are a cave....still allow this.. - //if ( pStructure && gfPlotPathToExitGrid && pStructure->fFlags & STRUCTURE_CAVEWALL ) - if ( pStructure && gfPlotPathToExitGrid ) - { - pStructure = NULL; - } + // ATE: If we are trying to get a path to an exit grid AND + // we are a cave....still allow this.. + //if ( pStructure && gfPlotPathToExitGrid && pStructure->fFlags & STRUCTURE_CAVEWALL ) + if ( pStructure && gfPlotPathToExitGrid ) + { + pStructure = NULL; + } - while (pStructure != NULL) - { - if (!(pStructure->fFlags & STRUCTURE_PASSABLE) ) - { - fOKCheckStruct = TRUE; + while (pStructure != NULL) + { + if (!(pStructure->fFlags & STRUCTURE_PASSABLE) ) + { + fOKCheckStruct = TRUE; - // Check if this is a multi-tile - if ( ( pStructure->fFlags & STRUCTURE_MOBILE ) && ( pCurrSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE ) ) - { - // Check IDs with soldier's ID - if ( pCurrSoldier->pLevelNode != NULL && pCurrSoldier->pLevelNode->pStructureData != NULL && pCurrSoldier->pLevelNode->pStructureData->usStructureID == pStructure->usStructureID ) - { - fOKCheckStruct = FALSE; - } - } + // Check if this is a multi-tile + if ( ( pStructure->fFlags & STRUCTURE_MOBILE ) && ( pCurrSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE ) ) + { + // Check IDs with soldier's ID + if ( pCurrSoldier->pLevelNode != NULL && pCurrSoldier->pLevelNode->pStructureData != NULL && pCurrSoldier->pLevelNode->pStructureData->usStructureID == pStructure->usStructureID ) + { + fOKCheckStruct = FALSE; + } + } - if ( fOKCheckStruct ) - { - if (pStructure->sCubeOffset == sDesiredLevel) - { - return( FALSE ); - } - } - } + if ( fOKCheckStruct ) + { + if (pStructure->sCubeOffset == sDesiredLevel) + { + return( FALSE ); + } + } + } - pStructure = FindNextStructure( pStructure, STRUCTURE_BLOCKSMOVES ); - } - } - } - return( TRUE ); + pStructure = FindNextStructure( pStructure, STRUCTURE_BLOCKSMOVES ); + } + } + } + return( TRUE ); } // NB if making changes don't forget to update NewOKDestination INT16 NewOKDestinationAndDirection( SOLDIERTYPE * pCurrSoldier, INT32 sGridNo, INT8 bDirection, BOOLEAN fPeopleToo, INT8 bLevel ) { - UINT8 bPerson; - STRUCTURE * pStructure; - INT16 sDesiredLevel; - BOOLEAN fOKCheckStruct; + UINT8 bPerson; + STRUCTURE * pStructure; + INT16 sDesiredLevel; + BOOLEAN fOKCheckStruct; - if (fPeopleToo && ( bPerson = WhoIsThere2( sGridNo, bLevel ) ) != NOBODY ) - { - // we could be multitiled... if the person there is us, and the gridno is not - // our base gridno, skip past these checks - if ( ! (bPerson == pCurrSoldier->ubID && sGridNo != pCurrSoldier->sGridNo) ) - { - if ( pCurrSoldier->bTeam == gbPlayerNum ) - { - if ( ( Menptr[ bPerson ].bVisible >= 0) || ( gTacticalStatus.uiFlags & SHOW_ALL_MERCS ) ) - return( FALSE ); // if someone there it's NOT OK - } - else - { - return( FALSE ); // if someone there it's NOT OK - } - } - } + if (fPeopleToo && ( bPerson = WhoIsThere2( sGridNo, bLevel ) ) != NOBODY ) + { + // we could be multitiled... if the person there is us, and the gridno is not + // our base gridno, skip past these checks + if ( ! (bPerson == pCurrSoldier->ubID && sGridNo != pCurrSoldier->sGridNo) ) + { + if ( pCurrSoldier->bTeam == gbPlayerNum ) + { + if ( ( Menptr[ bPerson ].bVisible >= 0) || ( gTacticalStatus.uiFlags & SHOW_ALL_MERCS ) ) + return( FALSE ); // if someone there it's NOT OK + } + else + { + return( FALSE ); // if someone there it's NOT OK + } + } + } - // Check structure database - if ( ( pCurrSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE ) && !(gfEstimatePath) ) - { - UINT16 usAnimSurface; - STRUCTURE_FILE_REF * pStructureFileRef; - BOOLEAN fOk; - INT8 bLoop; - UINT16 usStructureID = INVALID_STRUCTURE_ID; + // Check structure database + if ( ( pCurrSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE ) && !(gfEstimatePath) ) + { + UINT16 usAnimSurface; + STRUCTURE_FILE_REF * pStructureFileRef; + BOOLEAN fOk; + INT8 bLoop; + UINT16 usStructureID = INVALID_STRUCTURE_ID; - // this could be kinda slow... + // this could be kinda slow... - // Get animation surface... - usAnimSurface = DetermineSoldierAnimationSurface( pCurrSoldier, pCurrSoldier->usUIMovementMode ); - // Get structure ref... - pStructureFileRef = GetAnimationStructureRef( pCurrSoldier->ubID, usAnimSurface, pCurrSoldier->usUIMovementMode ); + // Get animation surface... + usAnimSurface = DetermineSoldierAnimationSurface( pCurrSoldier, pCurrSoldier->usUIMovementMode ); + // Get structure ref... + pStructureFileRef = GetAnimationStructureRef( pCurrSoldier->ubID, usAnimSurface, pCurrSoldier->usUIMovementMode ); - if ( pStructureFileRef ) - { + if ( pStructureFileRef ) + { - // use the specified direction for checks - bLoop = bDirection; + // use the specified direction for checks + bLoop = bDirection; - { - // ATE: Only if we have a levelnode... - if ( pCurrSoldier->pLevelNode != NULL && pCurrSoldier->pLevelNode->pStructureData != NULL ) - { - usStructureID = pCurrSoldier->pLevelNode->pStructureData->usStructureID; - } + { + // ATE: Only if we have a levelnode... + if ( pCurrSoldier->pLevelNode != NULL && pCurrSoldier->pLevelNode->pStructureData != NULL ) + { + usStructureID = pCurrSoldier->pLevelNode->pStructureData->usStructureID; + } - fOk = InternalOkayToAddStructureToWorld( sGridNo, pCurrSoldier->pathing.bLevel, &(pStructureFileRef->pDBStructureRef[ gOneCDirection[ bLoop ] ]), usStructureID, (BOOLEAN)!fPeopleToo ); - if (fOk) - { - return( TRUE ); - } - } + fOk = InternalOkayToAddStructureToWorld( sGridNo, pCurrSoldier->pathing.bLevel, &(pStructureFileRef->pDBStructureRef[ gOneCDirection[ bLoop ] ]), usStructureID, (BOOLEAN)!fPeopleToo ); + if (fOk) + { + return( TRUE ); + } + } - } - return( FALSE ); - } - else - { - // quick test - if ( gpWorldLevelData[ sGridNo ].pStructureHead != NULL ) - { - // Something is here, check obstruction in future - if ( bLevel == 0) - { - sDesiredLevel = STRUCTURE_ON_GROUND; - } - else - { - sDesiredLevel = STRUCTURE_ON_ROOF; - } + } + return( FALSE ); + } + else + { + // quick test + if ( gpWorldLevelData[ sGridNo ].pStructureHead != NULL ) + { + // Something is here, check obstruction in future + if ( bLevel == 0) + { + sDesiredLevel = STRUCTURE_ON_GROUND; + } + else + { + sDesiredLevel = STRUCTURE_ON_ROOF; + } - pStructure = FindStructure( sGridNo, STRUCTURE_BLOCKSMOVES ); + pStructure = FindStructure( sGridNo, STRUCTURE_BLOCKSMOVES ); - // ATE: If we are trying to get a path to an exit grid AND - // we are a cave....still allow this.. - //if ( pStructure && gfPlotPathToExitGrid && pStructure->fFlags & STRUCTURE_CAVEWALL ) - if ( pStructure && gfPlotPathToExitGrid ) - { - pStructure = NULL; - } + // ATE: If we are trying to get a path to an exit grid AND + // we are a cave....still allow this.. + //if ( pStructure && gfPlotPathToExitGrid && pStructure->fFlags & STRUCTURE_CAVEWALL ) + if ( pStructure && gfPlotPathToExitGrid ) + { + pStructure = NULL; + } - while (pStructure != NULL) - { - if (!(pStructure->fFlags & STRUCTURE_PASSABLE) ) - { - fOKCheckStruct = TRUE; + while (pStructure != NULL) + { + if (!(pStructure->fFlags & STRUCTURE_PASSABLE) ) + { + fOKCheckStruct = TRUE; - // Check if this is a multi-tile - if ( ( pStructure->fFlags & STRUCTURE_MOBILE ) && ( pCurrSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE ) ) - { - // Check IDs with soldier's ID - if ( pCurrSoldier->pLevelNode != NULL && pCurrSoldier->pLevelNode->pStructureData != NULL && pCurrSoldier->pLevelNode->pStructureData->usStructureID == pStructure->usStructureID ) - { - fOKCheckStruct = FALSE; - } - } + // Check if this is a multi-tile + if ( ( pStructure->fFlags & STRUCTURE_MOBILE ) && ( pCurrSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE ) ) + { + // Check IDs with soldier's ID + if ( pCurrSoldier->pLevelNode != NULL && pCurrSoldier->pLevelNode->pStructureData != NULL && pCurrSoldier->pLevelNode->pStructureData->usStructureID == pStructure->usStructureID ) + { + fOKCheckStruct = FALSE; + } + } - if ( fOKCheckStruct ) - { - if (pStructure->sCubeOffset == sDesiredLevel) - { - return( FALSE ); - } - } - } + if ( fOKCheckStruct ) + { + if (pStructure->sCubeOffset == sDesiredLevel) + { + return( FALSE ); + } + } + } - pStructure = FindNextStructure( pStructure, STRUCTURE_BLOCKSMOVES ); - } - } - } - return( TRUE ); + pStructure = FindNextStructure( pStructure, STRUCTURE_BLOCKSMOVES ); + } + } + } + return( TRUE ); } @@ -5059,1111 +4860,1111 @@ INT16 NewOKDestinationAndDirection( SOLDIERTYPE * pCurrSoldier, INT32 sGridNo, I //Kris: BOOLEAN FlatRoofAboveGridNo( INT32 iMapIndex ) { - LEVELNODE *pRoof; - UINT32 uiTileType; - pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead; - while( pRoof ) - { - if( pRoof->usIndex != NO_TILE ) - { - GetTileType( pRoof->usIndex, &uiTileType ); - if( uiTileType >= FIRSTROOF && uiTileType <= LASTROOF ) - return TRUE; - } - pRoof = pRoof->pNext; - } - return FALSE; + LEVELNODE *pRoof; + UINT32 uiTileType; + pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead; + while( pRoof ) + { + if( pRoof->usIndex != NO_TILE ) + { + GetTileType( pRoof->usIndex, &uiTileType ); + if( uiTileType >= FIRSTROOF && uiTileType <= LASTROOF ) + return TRUE; + } + pRoof = pRoof->pNext; + } + return FALSE; } //Kris: -//ASSUMPTION: This function assumes that we are checking on behalf of a single tiled merc. This function -// should not be used for checking on behalf of multi-tiled "things". -//I wrote this function for editor use. I don't personally care about multi-tiled stuff. All I want -//to know is whether or not I can put a merc here. In most cases, I won't be dealing with multi-tiled -//mercs, and the rarity doesn't justify the needs. I just wrote this to be quick and dirty, and I don't +//ASSUMPTION: This function assumes that we are checking on behalf of a single tiled merc. This function +// should not be used for checking on behalf of multi-tiled "things". +//I wrote this function for editor use. I don't personally care about multi-tiled stuff. All I want +//to know is whether or not I can put a merc here. In most cases, I won't be dealing with multi-tiled +//mercs, and the rarity doesn't justify the needs. I just wrote this to be quick and dirty, and I don't //expect it to perform perfectly in all situations. BOOLEAN IsLocationSittable( INT32 iMapIndex, BOOLEAN fOnRoof ) { - STRUCTURE *pStructure; - INT16 sDesiredLevel; - if( WhoIsThere2( iMapIndex, 0 ) != NOBODY ) - return FALSE; - //Locations on roofs without a roof is not possible, so - //we convert the onroof intention to ground. - if( fOnRoof && !FlatRoofAboveGridNo( iMapIndex ) ) - fOnRoof = FALSE; - // Check structure database - if( gpWorldLevelData[ iMapIndex ].pStructureHead ) - { - // Something is here, check obstruction in future - sDesiredLevel = fOnRoof ? STRUCTURE_ON_ROOF : STRUCTURE_ON_GROUND; - pStructure = FindStructure( iMapIndex, STRUCTURE_BLOCKSMOVES ); - while( pStructure ) - { - if( !(pStructure->fFlags & STRUCTURE_PASSABLE) && pStructure->sCubeOffset == sDesiredLevel ) - return FALSE; - pStructure = FindNextStructure( pStructure, STRUCTURE_BLOCKSMOVES ); - } - } - return TRUE; + STRUCTURE *pStructure; + INT16 sDesiredLevel; + if( WhoIsThere2( iMapIndex, 0 ) != NOBODY ) + return FALSE; + //Locations on roofs without a roof is not possible, so + //we convert the onroof intention to ground. + if( fOnRoof && !FlatRoofAboveGridNo( iMapIndex ) ) + fOnRoof = FALSE; + // Check structure database + if( gpWorldLevelData[ iMapIndex ].pStructureHead ) + { + // Something is here, check obstruction in future + sDesiredLevel = fOnRoof ? STRUCTURE_ON_ROOF : STRUCTURE_ON_GROUND; + pStructure = FindStructure( iMapIndex, STRUCTURE_BLOCKSMOVES ); + while( pStructure ) + { + if( !(pStructure->fFlags & STRUCTURE_PASSABLE) && pStructure->sCubeOffset == sDesiredLevel ) + return FALSE; + pStructure = FindNextStructure( pStructure, STRUCTURE_BLOCKSMOVES ); + } + } + return TRUE; } BOOLEAN IsLocationSittableExcludingPeople( INT32 iMapIndex, BOOLEAN fOnRoof ) { - STRUCTURE *pStructure; - INT16 sDesiredLevel; + STRUCTURE *pStructure; + INT16 sDesiredLevel; - //Locations on roofs without a roof is not possible, so - //we convert the onroof intention to ground. - if( fOnRoof && !FlatRoofAboveGridNo( iMapIndex ) ) - fOnRoof = FALSE; - // Check structure database - if( gpWorldLevelData[ iMapIndex ].pStructureHead ) - { - // Something is here, check obstruction in future - sDesiredLevel = fOnRoof ? STRUCTURE_ON_ROOF : STRUCTURE_ON_GROUND; - pStructure = FindStructure( iMapIndex, STRUCTURE_BLOCKSMOVES ); - while( pStructure ) - { - if( !(pStructure->fFlags & STRUCTURE_PASSABLE) && pStructure->sCubeOffset == sDesiredLevel ) - return FALSE; - pStructure = FindNextStructure( pStructure, STRUCTURE_BLOCKSMOVES ); - } - } - return TRUE; + //Locations on roofs without a roof is not possible, so + //we convert the onroof intention to ground. + if( fOnRoof && !FlatRoofAboveGridNo( iMapIndex ) ) + fOnRoof = FALSE; + // Check structure database + if( gpWorldLevelData[ iMapIndex ].pStructureHead ) + { + // Something is here, check obstruction in future + sDesiredLevel = fOnRoof ? STRUCTURE_ON_ROOF : STRUCTURE_ON_GROUND; + pStructure = FindStructure( iMapIndex, STRUCTURE_BLOCKSMOVES ); + while( pStructure ) + { + if( !(pStructure->fFlags & STRUCTURE_PASSABLE) && pStructure->sCubeOffset == sDesiredLevel ) + return FALSE; + pStructure = FindNextStructure( pStructure, STRUCTURE_BLOCKSMOVES ); + } + } + return TRUE; } BOOLEAN TeamMemberNear(INT8 bTeam, INT32 sGridNo, INT32 iRange) { - UINT8 bLoop; - SOLDIERTYPE * pSoldier; + UINT8 bLoop; + SOLDIERTYPE * pSoldier; - for (bLoop=gTacticalStatus.Team[bTeam].bFirstID, pSoldier=MercPtrs[bLoop]; bLoop <= gTacticalStatus.Team[bTeam].bLastID; bLoop++, pSoldier++) - { - if (pSoldier->bActive && pSoldier->bInSector && (pSoldier->stats.bLife >= OKLIFE) && !( pSoldier->flags.uiStatusFlags & SOLDIER_GASSED ) ) - { - if (PythSpacesAway(pSoldier->sGridNo,sGridNo) <= iRange) - { - return(TRUE); - } - } - } + for (bLoop=gTacticalStatus.Team[bTeam].bFirstID, pSoldier=MercPtrs[bLoop]; bLoop <= gTacticalStatus.Team[bTeam].bLastID; bLoop++, pSoldier++) + { + if (pSoldier->bActive && pSoldier->bInSector && (pSoldier->stats.bLife >= OKLIFE) && !( pSoldier->flags.uiStatusFlags & SOLDIER_GASSED ) ) + { + if (PythSpacesAway(pSoldier->sGridNo,sGridNo) <= iRange) + { + return(TRUE); + } + } + } - return(FALSE); + return(FALSE); } INT32 FindAdjacentGridEx( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 *pubDirection, INT32 *psAdjustedGridNo, BOOLEAN fForceToPerson, BOOLEAN fDoor ) { - // psAdjustedGridNo gets the original gridno or the new one if updated - // It will ONLY be updated IF we were over a merc, ( it's updated to their gridno ) - // pubDirection gets the direction to the final gridno - // fForceToPerson: forces the grid under consideration to be the one occupiedby any target - // in that location, because we could be passed a gridno based on the overlap of soldier's graphic - // fDoor determines whether special door-handling code should be used (for interacting with doors) + // psAdjustedGridNo gets the original gridno or the new one if updated + // It will ONLY be updated IF we were over a merc, ( it's updated to their gridno ) + // pubDirection gets the direction to the final gridno + // fForceToPerson: forces the grid under consideration to be the one occupiedby any target + // in that location, because we could be passed a gridno based on the overlap of soldier's graphic + // fDoor determines whether special door-handling code should be used (for interacting with doors) - INT32 sFourGrids[4], sDistance=0; - static const UINT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST }; - //INT32 cnt; - //INT32 sClosest=NOWHERE, sSpot, sOkTest; - INT32 sClosest = MAX_MAP_POS, sSpot, sOkTest; //Lalien: changed to ensure compability with new definition of NOWHERE - //INT32 sCloseGridNo=NOWHERE; - INT32 sCloseGridNo = MAX_MAP_POS; //Lalien: changed to ensure compability with new definition of NOWHERE - UINT32 uiMercFlags; - UINT16 usSoldierIndex; - UINT8 ubDir; - STRUCTURE *pDoor; - //STRUCTURE *pWall; - UINT8 ubWallOrientation; - BOOLEAN fCheckGivenGridNo = TRUE; - UINT8 ubTestDirection; - EXITGRID ExitGrid; + INT32 sFourGrids[4], sDistance=0; + static const UINT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST }; + //INT32 cnt; + //INT32 sClosest=NOWHERE, sSpot, sOkTest; + INT32 sClosest = MAX_MAP_POS, sSpot, sOkTest; //Lalien: changed to ensure compability with new definition of NOWHERE + //INT32 sCloseGridNo=NOWHERE; + INT32 sCloseGridNo = MAX_MAP_POS; //Lalien: changed to ensure compability with new definition of NOWHERE + UINT32 uiMercFlags; + UINT16 usSoldierIndex; + UINT8 ubDir; + STRUCTURE *pDoor; + //STRUCTURE *pWall; + UINT8 ubWallOrientation; + BOOLEAN fCheckGivenGridNo = TRUE; + UINT8 ubTestDirection; + EXITGRID ExitGrid; - // Set default direction - if (pubDirection) - { - *pubDirection = pSoldier->ubDirection; - } + // Set default direction + if (pubDirection) + { + *pubDirection = pSoldier->ubDirection; + } - // CHECK IF WE WANT TO FORCE GRIDNO TO PERSON - if ( psAdjustedGridNo != NULL ) - { - *psAdjustedGridNo = sGridNo; - } + // CHECK IF WE WANT TO FORCE GRIDNO TO PERSON + if ( psAdjustedGridNo != NULL ) + { + *psAdjustedGridNo = sGridNo; + } - // CHECK IF IT'S THE SAME ONE AS WE'RE ON, IF SO, RETURN THAT! - if ( pSoldier->sGridNo == sGridNo && !FindStructure( sGridNo, ( STRUCTURE_SWITCH ) ) ) - { - // OK, if we are looking for a door, it may be in the same tile as us, so find the direction we - // have to face to get to the door, not just our initial direction... - // If we are in the same tile as a switch, we can NEVER pull it.... - if( fDoor ) - { - // This can only happen if a door was to the south to east of us! + // CHECK IF IT'S THE SAME ONE AS WE'RE ON, IF SO, RETURN THAT! + if ( pSoldier->sGridNo == sGridNo && !FindStructure( sGridNo, ( STRUCTURE_SWITCH ) ) ) + { + // OK, if we are looking for a door, it may be in the same tile as us, so find the direction we + // have to face to get to the door, not just our initial direction... + // If we are in the same tile as a switch, we can NEVER pull it.... + if( fDoor ) + { + // This can only happen if a door was to the south to east of us! - // Do south! - //sSpot = NewGridNo( sGridNo, DirectionInc( SOUTH ) ); + // Do south! + //sSpot = NewGridNo( sGridNo, DirectionInc( SOUTH ) ); - // ATE: Added: Switch behave EXACTLY like doors - pDoor = FindStructure( sGridNo, ( STRUCTURE_ANYDOOR ) ); + // ATE: Added: Switch behave EXACTLY like doors + pDoor = FindStructure( sGridNo, ( STRUCTURE_ANYDOOR ) ); - if ( pDoor != NULL ) - { - // Get orinetation - ubWallOrientation = pDoor->ubWallOrientation; + if ( pDoor != NULL ) + { + // Get orinetation + ubWallOrientation = pDoor->ubWallOrientation; - if ( ubWallOrientation == OUTSIDE_TOP_LEFT || ubWallOrientation == INSIDE_TOP_LEFT ) - { - // To the south! - sSpot = NewGridNo( sGridNo, DirectionInc( SOUTH ) ); - if (pubDirection) - { - (*pubDirection) = (UINT8)GetDirectionFromGridNo( sSpot, pSoldier ); - } - } + if ( ubWallOrientation == OUTSIDE_TOP_LEFT || ubWallOrientation == INSIDE_TOP_LEFT ) + { + // To the south! + sSpot = NewGridNo( sGridNo, DirectionInc( SOUTH ) ); + if (pubDirection) + { + (*pubDirection) = (UINT8)GetDirectionFromGridNo( sSpot, pSoldier ); + } + } - if ( ubWallOrientation == OUTSIDE_TOP_RIGHT || ubWallOrientation == INSIDE_TOP_RIGHT ) - { - // TO the east! - sSpot = NewGridNo( sGridNo, DirectionInc( EAST ) ); - if (pubDirection) - { - (*pubDirection) = (UINT8)GetDirectionFromGridNo( sSpot, pSoldier ); - } - } - } - } + if ( ubWallOrientation == OUTSIDE_TOP_RIGHT || ubWallOrientation == INSIDE_TOP_RIGHT ) + { + // TO the east! + sSpot = NewGridNo( sGridNo, DirectionInc( EAST ) ); + if (pubDirection) + { + (*pubDirection) = (UINT8)GetDirectionFromGridNo( sSpot, pSoldier ); + } + } + } + } - // Use soldier's direction - return( sGridNo ); - } + // Use soldier's direction + return( sGridNo ); + } - // Look for a door! - if (fDoor) - { - pDoor = FindStructure( sGridNo, ( STRUCTURE_ANYDOOR | STRUCTURE_SWITCH ) ); - } - else - { - pDoor = NULL; - } + // Look for a door! + if (fDoor) + { + pDoor = FindStructure( sGridNo, ( STRUCTURE_ANYDOOR | STRUCTURE_SWITCH ) ); + } + else + { + pDoor = NULL; + } - if ( fForceToPerson ) - { - if ( FindSoldier( sGridNo, &usSoldierIndex, &uiMercFlags, FIND_SOLDIER_GRIDNO ) ) - { - sGridNo = MercPtrs[ usSoldierIndex ]->sGridNo; - if ( psAdjustedGridNo != NULL ) - { - *psAdjustedGridNo = sGridNo; + if ( fForceToPerson ) + { + if ( FindSoldier( sGridNo, &usSoldierIndex, &uiMercFlags, FIND_SOLDIER_GRIDNO ) ) + { + sGridNo = MercPtrs[ usSoldierIndex ]->sGridNo; + if ( psAdjustedGridNo != NULL ) + { + *psAdjustedGridNo = sGridNo; - // Use direction to this guy! - if (pubDirection) - { - (*pubDirection) = (UINT8)GetDirectionFromGridNo( sGridNo, pSoldier ); - } - } - } - } + // Use direction to this guy! + if (pubDirection) + { + (*pubDirection) = (UINT8)GetDirectionFromGridNo( sGridNo, pSoldier ); + } + } + } + } - if ( ( sOkTest = NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->pathing.bLevel ) ) > 0) // no problem going there! nobody on it! - { - // OK, if we are looking to goto a switch, ignore this.... - if ( pDoor ) - { - if ( pDoor->fFlags & STRUCTURE_SWITCH ) - { - // Don't continuel - fCheckGivenGridNo = FALSE; - } - } + if ( ( sOkTest = NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->pathing.bLevel ) ) > 0) // no problem going there! nobody on it! + { + // OK, if we are looking to goto a switch, ignore this.... + if ( pDoor ) + { + if ( pDoor->fFlags & STRUCTURE_SWITCH ) + { + // Don't continuel + fCheckGivenGridNo = FALSE; + } + } - // If there is an exit grid.... - if ( GetExitGrid( sGridNo, &ExitGrid ) ) - { - // Don't continuel - fCheckGivenGridNo = FALSE; - } + // If there is an exit grid.... + if ( GetExitGrid( sGridNo, &ExitGrid ) ) + { + // Don't continuel + fCheckGivenGridNo = FALSE; + } - if ( fCheckGivenGridNo ) - { - sDistance = PlotPath( pSoldier, sGridNo, NO_COPYROUTE, NO_PLOT, TEMPORARY, (INT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ); + if ( fCheckGivenGridNo ) + { + sDistance = PlotPath( pSoldier, sGridNo, NO_COPYROUTE, NO_PLOT, TEMPORARY, (INT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ); - if ( sDistance > 0 ) - { + if ( sDistance > 0 ) + { - if ( sDistance < sClosest ) - { - sClosest = sDistance; - sCloseGridNo = sGridNo; - } - } - } - } + if ( sDistance < sClosest ) + { + sClosest = sDistance; + sCloseGridNo = sGridNo; + } + } + } + } - for (INT8 cnt = 0; cnt < 4; cnt++) - { - // MOVE OUT TWO DIRECTIONS - sFourGrids[cnt] = sSpot = NewGridNo( sGridNo, DirectionInc( sDirs[ cnt ] ) ); + for (INT8 cnt = 0; cnt < 4; cnt++) + { + // MOVE OUT TWO DIRECTIONS + sFourGrids[cnt] = sSpot = NewGridNo( sGridNo, DirectionInc( sDirs[ cnt ] ) ); - ubTestDirection = sDirs[ cnt ]; + ubTestDirection = sDirs[ cnt ]; - // For switches, ALLOW them to walk through walls to reach it.... - if ( pDoor && pDoor->fFlags & STRUCTURE_SWITCH ) - { - ubTestDirection = gOppositeDirection[ ubTestDirection ]; - } + // For switches, ALLOW them to walk through walls to reach it.... + if ( pDoor && pDoor->fFlags & STRUCTURE_SWITCH ) + { + ubTestDirection = gOppositeDirection[ ubTestDirection ]; + } - if( fDoor ) - { - if ( gubWorldMovementCosts[ sSpot ][ ubTestDirection ][ pSoldier->pathing.bLevel ] >= TRAVELCOST_BLOCKED ) - { - // obstacle or wall there! - continue; - } - } - else - { - // this function returns original MP cost if not a door cost - if ( DoorTravelCost( pSoldier, sSpot, gubWorldMovementCosts[ sSpot ][ ubTestDirection ][ pSoldier->pathing.bLevel ], FALSE, NULL ) >= TRAVELCOST_BLOCKED ) - { - // obstacle or wall there! - continue; - } - } + if( fDoor ) + { + if ( gubWorldMovementCosts[ sSpot ][ ubTestDirection ][ pSoldier->pathing.bLevel ] >= TRAVELCOST_BLOCKED ) + { + // obstacle or wall there! + continue; + } + } + else + { + // this function returns original MP cost if not a door cost + if ( DoorTravelCost( pSoldier, sSpot, gubWorldMovementCosts[ sSpot ][ ubTestDirection ][ pSoldier->pathing.bLevel ], FALSE, NULL ) >= TRAVELCOST_BLOCKED ) + { + // obstacle or wall there! + continue; + } + } - // Eliminate some directions if we are looking at doors! - if ( pDoor != NULL ) - { - // Get orinetation - ubWallOrientation = pDoor->ubWallOrientation; + // Eliminate some directions if we are looking at doors! + if ( pDoor != NULL ) + { + // Get orinetation + ubWallOrientation = pDoor->ubWallOrientation; - // Refuse the south and north and west directions if our orientation is top-right - if ( ubWallOrientation == OUTSIDE_TOP_RIGHT || ubWallOrientation == INSIDE_TOP_RIGHT ) - { - if ( sDirs[ cnt ] == NORTH || sDirs[ cnt ] == WEST || sDirs[ cnt ] == SOUTH ) - continue; - } + // Refuse the south and north and west directions if our orientation is top-right + if ( ubWallOrientation == OUTSIDE_TOP_RIGHT || ubWallOrientation == INSIDE_TOP_RIGHT ) + { + if ( sDirs[ cnt ] == NORTH || sDirs[ cnt ] == WEST || sDirs[ cnt ] == SOUTH ) + continue; + } - // Refuse the north and west and east directions if our orientation is top-right - if ( ubWallOrientation == OUTSIDE_TOP_LEFT || ubWallOrientation == INSIDE_TOP_LEFT ) - { - if ( sDirs[ cnt ] == NORTH || sDirs[ cnt ] == WEST || sDirs[ cnt ] == EAST ) - continue; - } - } + // Refuse the north and west and east directions if our orientation is top-right + if ( ubWallOrientation == OUTSIDE_TOP_LEFT || ubWallOrientation == INSIDE_TOP_LEFT ) + { + if ( sDirs[ cnt ] == NORTH || sDirs[ cnt ] == WEST || sDirs[ cnt ] == EAST ) + continue; + } + } - // If this spot is our soldier's gridno use that! - if ( sSpot == pSoldier->sGridNo ) - { - // Use default diurection ) soldier's direction ) + // If this spot is our soldier's gridno use that! + if ( sSpot == pSoldier->sGridNo ) + { + // Use default diurection ) soldier's direction ) - // OK, at least get direction to face...... - // Defaults to soldier's facing dir unless we change it! - //if ( pDoor != NULL ) - { - // Use direction to the door! - if (pubDirection) - { - (*pubDirection) = (UINT8)GetDirectionFromGridNo( sGridNo, pSoldier ); - } - } - return( sSpot ); - } + // OK, at least get direction to face...... + // Defaults to soldier's facing dir unless we change it! + //if ( pDoor != NULL ) + { + // Use direction to the door! + if (pubDirection) + { + (*pubDirection) = (UINT8)GetDirectionFromGridNo( sGridNo, pSoldier ); + } + } + return( sSpot ); + } - // don't store path, just measure it - ubDir = (UINT8)GetDirectionToGridNoFromGridNo( sSpot, sGridNo ); + // don't store path, just measure it + ubDir = (UINT8)GetDirectionToGridNoFromGridNo( sSpot, sGridNo ); - if ( ( NewOKDestinationAndDirection( pSoldier, sSpot, ubDir, TRUE, pSoldier->pathing.bLevel ) > 0 ) && - ( ( sDistance = PlotPath( pSoldier, sSpot, NO_COPYROUTE, NO_PLOT, TEMPORARY, (INT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ) ) > 0 ) ) - { - if ( sDistance < sClosest ) - { - sClosest = sDistance; - sCloseGridNo = sSpot; - } - } - } - - if ( !TileIsOutOfBounds( sClosest ) ) - { - // Take last direction and use opposite! - // This will be usefull for ours and AI mercs + if ( ( NewOKDestinationAndDirection( pSoldier, sSpot, ubDir, TRUE, pSoldier->pathing.bLevel ) > 0 ) && + ( ( sDistance = PlotPath( pSoldier, sSpot, NO_COPYROUTE, NO_PLOT, TEMPORARY, (INT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ) ) > 0 ) ) + { + if ( sDistance < sClosest ) + { + sClosest = sDistance; + sCloseGridNo = sSpot; + } + } + } - // If our gridno is the same ( which can be if we are look at doors ) - if ( sGridNo == sCloseGridNo ) - { - if (pubDirection) - { - // ATE: Only if we have a valid door! - if ( pDoor ) - { - switch( pDoor->pDBStructureRef->pDBStructure->ubWallOrientation ) - { - case OUTSIDE_TOP_LEFT: - case INSIDE_TOP_LEFT: + if ( !TileIsOutOfBounds( sClosest ) ) + { + // Take last direction and use opposite! + // This will be usefull for ours and AI mercs - *pubDirection = SOUTH; - break; + // If our gridno is the same ( which can be if we are look at doors ) + if ( sGridNo == sCloseGridNo ) + { + if (pubDirection) + { + // ATE: Only if we have a valid door! + if ( pDoor ) + { + switch( pDoor->pDBStructureRef->pDBStructure->ubWallOrientation ) + { + case OUTSIDE_TOP_LEFT: + case INSIDE_TOP_LEFT: - case OUTSIDE_TOP_RIGHT: - case INSIDE_TOP_RIGHT: + *pubDirection = SOUTH; + break; - *pubDirection = EAST; - break; - } - } - } - } - else - { - // Calculate direction if our gridno is different.... - ubDir = (UINT8)GetDirectionToGridNoFromGridNo( sCloseGridNo, sGridNo ); - if (pubDirection) - { - *pubDirection = ubDir; - } - } - //if ( psAdjustedGridNo != NULL ) - //{ - // (*psAdjustedGridNo) = sCloseGridNo; - //} - if ( TileIsOutOfBounds( sCloseGridNo ) ) - { - return( -1 ); - } - return( sCloseGridNo ); - } - else - return( -1 ); + case OUTSIDE_TOP_RIGHT: + case INSIDE_TOP_RIGHT: + + *pubDirection = EAST; + break; + } + } + } + } + else + { + // Calculate direction if our gridno is different.... + ubDir = (UINT8)GetDirectionToGridNoFromGridNo( sCloseGridNo, sGridNo ); + if (pubDirection) + { + *pubDirection = ubDir; + } + } + //if ( psAdjustedGridNo != NULL ) + //{ + // (*psAdjustedGridNo) = sCloseGridNo; + //} + if ( TileIsOutOfBounds( sCloseGridNo ) ) + { + return( -1 ); + } + return( sCloseGridNo ); + } + else + return( -1 ); } INT32 FindNextToAdjacentGridEx( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 *pubDirection, INT32 *psAdjustedGridNo, BOOLEAN fForceToPerson, BOOLEAN fDoor ) { - // This function works in a similar way as FindAdjacentGridEx, but looks for a location 2 tiles away + // This function works in a similar way as FindAdjacentGridEx, but looks for a location 2 tiles away - // psAdjustedGridNo gets the original gridno or the new one if updated - // pubDirection gets the direction to the final gridno - // fForceToPerson: forces the grid under consideration to be the one occupiedby any target - // in that location, because we could be passed a gridno based on the overlap of soldier's graphic - // fDoor determines whether special door-handling code should be used (for interacting with doors) + // psAdjustedGridNo gets the original gridno or the new one if updated + // pubDirection gets the direction to the final gridno + // fForceToPerson: forces the grid under consideration to be the one occupiedby any target + // in that location, because we could be passed a gridno based on the overlap of soldier's graphic + // fDoor determines whether special door-handling code should be used (for interacting with doors) - INT32 sFourGrids[4], sDistance=0; - static const UINT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST }; - //INT32 cnt; - INT32 sClosest=WORLD_MAX, sSpot, sSpot2, sOkTest; - INT32 sCloseGridNo=NOWHERE; - UINT32 uiMercFlags; - UINT16 usSoldierIndex; - UINT8 ubDir; - STRUCTURE *pDoor; - UINT8 ubWallOrientation; - BOOLEAN fCheckGivenGridNo = TRUE; - UINT8 ubTestDirection; - UINT8 ubWhoIsThere; + INT32 sFourGrids[4], sDistance=0; + static const UINT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST }; + //INT32 cnt; + INT32 sClosest=WORLD_MAX, sSpot, sSpot2, sOkTest; + INT32 sCloseGridNo=NOWHERE; + UINT32 uiMercFlags; + UINT16 usSoldierIndex; + UINT8 ubDir; + STRUCTURE *pDoor; + UINT8 ubWallOrientation; + BOOLEAN fCheckGivenGridNo = TRUE; + UINT8 ubTestDirection; + UINT8 ubWhoIsThere; - // CHECK IF WE WANT TO FORCE GRIDNO TO PERSON - if ( psAdjustedGridNo != NULL ) - { - *psAdjustedGridNo = sGridNo; - } + // CHECK IF WE WANT TO FORCE GRIDNO TO PERSON + if ( psAdjustedGridNo != NULL ) + { + *psAdjustedGridNo = sGridNo; + } - // CHECK IF IT'S THE SAME ONE AS WE'RE ON, IF SO, RETURN THAT! - if ( pSoldier->sGridNo == sGridNo ) - { - *pubDirection = pSoldier->ubDirection; - return( sGridNo ); - } + // CHECK IF IT'S THE SAME ONE AS WE'RE ON, IF SO, RETURN THAT! + if ( pSoldier->sGridNo == sGridNo ) + { + *pubDirection = pSoldier->ubDirection; + return( sGridNo ); + } - // Look for a door! - if (fDoor) - { - pDoor = FindStructure( sGridNo, ( STRUCTURE_ANYDOOR | STRUCTURE_SWITCH ) ); - } - else - { - pDoor = NULL; - } + // Look for a door! + if (fDoor) + { + pDoor = FindStructure( sGridNo, ( STRUCTURE_ANYDOOR | STRUCTURE_SWITCH ) ); + } + else + { + pDoor = NULL; + } - if ( fForceToPerson ) - { - if ( FindSoldier( sGridNo, &usSoldierIndex, &uiMercFlags, FIND_SOLDIER_GRIDNO ) ) - { - sGridNo = MercPtrs[ usSoldierIndex ]->sGridNo; - if ( psAdjustedGridNo != NULL ) - { - *psAdjustedGridNo = sGridNo; - } - } - } + if ( fForceToPerson ) + { + if ( FindSoldier( sGridNo, &usSoldierIndex, &uiMercFlags, FIND_SOLDIER_GRIDNO ) ) + { + sGridNo = MercPtrs[ usSoldierIndex ]->sGridNo; + if ( psAdjustedGridNo != NULL ) + { + *psAdjustedGridNo = sGridNo; + } + } + } - if ( ( sOkTest = NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->pathing.bLevel ) ) > 0) // no problem going there! nobody on it! - { - // OK, if we are looking to goto a switch, ignore this.... - if ( pDoor ) - { - if ( pDoor->fFlags & STRUCTURE_SWITCH ) - { - // Don't continuel - fCheckGivenGridNo = FALSE; - } - } + if ( ( sOkTest = NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->pathing.bLevel ) ) > 0) // no problem going there! nobody on it! + { + // OK, if we are looking to goto a switch, ignore this.... + if ( pDoor ) + { + if ( pDoor->fFlags & STRUCTURE_SWITCH ) + { + // Don't continuel + fCheckGivenGridNo = FALSE; + } + } - if ( fCheckGivenGridNo ) - { - sDistance = PlotPath( pSoldier, sGridNo, NO_COPYROUTE, NO_PLOT, TEMPORARY, (INT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ); + if ( fCheckGivenGridNo ) + { + sDistance = PlotPath( pSoldier, sGridNo, NO_COPYROUTE, NO_PLOT, TEMPORARY, (INT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ); - if ( sDistance > 0 ) - { + if ( sDistance > 0 ) + { - if ( sDistance < sClosest ) - { - sClosest = sDistance; - sCloseGridNo = sGridNo; - } - } - } - } + if ( sDistance < sClosest ) + { + sClosest = sDistance; + sCloseGridNo = sGridNo; + } + } + } + } - for (INT8 cnt = 0; cnt < 4; cnt++) - { - // MOVE OUT TWO DIRECTIONS - sFourGrids[cnt] = sSpot = NewGridNo( sGridNo, DirectionInc( sDirs[ cnt ] ) ); + for (INT8 cnt = 0; cnt < 4; cnt++) + { + // MOVE OUT TWO DIRECTIONS + sFourGrids[cnt] = sSpot = NewGridNo( sGridNo, DirectionInc( sDirs[ cnt ] ) ); - ubTestDirection = sDirs[ cnt ]; + ubTestDirection = sDirs[ cnt ]; - if ( pDoor && pDoor->fFlags & STRUCTURE_SWITCH ) - { - ubTestDirection = gOppositeDirection[ ubTestDirection ]; - } + if ( pDoor && pDoor->fFlags & STRUCTURE_SWITCH ) + { + ubTestDirection = gOppositeDirection[ ubTestDirection ]; + } - if ( gubWorldMovementCosts[ sSpot ][ ubTestDirection ][ pSoldier->pathing.bLevel ] >= TRAVELCOST_BLOCKED ) - { - // obstacle or wall there! - continue; - } + if ( gubWorldMovementCosts[ sSpot ][ ubTestDirection ][ pSoldier->pathing.bLevel ] >= TRAVELCOST_BLOCKED ) + { + // obstacle or wall there! + continue; + } - ubWhoIsThere = WhoIsThere2( sSpot, pSoldier->pathing.bLevel ); - if ( ubWhoIsThere != NOBODY && ubWhoIsThere != pSoldier->ubID ) - { - // skip this direction b/c it's blocked by another merc! - continue; - } + ubWhoIsThere = WhoIsThere2( sSpot, pSoldier->pathing.bLevel ); + if ( ubWhoIsThere != NOBODY && ubWhoIsThere != pSoldier->ubID ) + { + // skip this direction b/c it's blocked by another merc! + continue; + } - // Eliminate some directions if we are looking at doors! - if ( pDoor != NULL ) - { - // Get orinetation - ubWallOrientation = pDoor->ubWallOrientation; + // Eliminate some directions if we are looking at doors! + if ( pDoor != NULL ) + { + // Get orinetation + ubWallOrientation = pDoor->ubWallOrientation; - // Refuse the south and north and west directions if our orientation is top-right - if ( ubWallOrientation == OUTSIDE_TOP_RIGHT || ubWallOrientation == INSIDE_TOP_RIGHT ) - { - if ( sDirs[ cnt ] == NORTH || sDirs[ cnt ] == WEST || sDirs[ cnt ] == SOUTH ) - continue; - } + // Refuse the south and north and west directions if our orientation is top-right + if ( ubWallOrientation == OUTSIDE_TOP_RIGHT || ubWallOrientation == INSIDE_TOP_RIGHT ) + { + if ( sDirs[ cnt ] == NORTH || sDirs[ cnt ] == WEST || sDirs[ cnt ] == SOUTH ) + continue; + } - // Refuse the north and west and east directions if our orientation is top-right - if ( ubWallOrientation == OUTSIDE_TOP_LEFT || ubWallOrientation == INSIDE_TOP_LEFT ) - { - if ( sDirs[ cnt ] == NORTH || sDirs[ cnt ] == WEST || sDirs[ cnt ] == EAST ) - continue; - } - } + // Refuse the north and west and east directions if our orientation is top-right + if ( ubWallOrientation == OUTSIDE_TOP_LEFT || ubWallOrientation == INSIDE_TOP_LEFT ) + { + if ( sDirs[ cnt ] == NORTH || sDirs[ cnt ] == WEST || sDirs[ cnt ] == EAST ) + continue; + } + } - // first tile is okay, how about the second? - sSpot2 = NewGridNo( sSpot, DirectionInc( sDirs[ cnt ] ) ); - if ( gubWorldMovementCosts[ sSpot2 ][ sDirs[cnt] ][ pSoldier->pathing.bLevel ] >= TRAVELCOST_BLOCKED || - DoorTravelCost( pSoldier, sSpot2, gubWorldMovementCosts[ sSpot2 ][ sDirs[cnt] ][ pSoldier->pathing.bLevel ], (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), NULL ) == TRAVELCOST_DOOR ) // closed door blocks! - { - // obstacle or wall there! - continue; - } + // first tile is okay, how about the second? + sSpot2 = NewGridNo( sSpot, DirectionInc( sDirs[ cnt ] ) ); + if ( gubWorldMovementCosts[ sSpot2 ][ sDirs[cnt] ][ pSoldier->pathing.bLevel ] >= TRAVELCOST_BLOCKED || + DoorTravelCost( pSoldier, sSpot2, gubWorldMovementCosts[ sSpot2 ][ sDirs[cnt] ][ pSoldier->pathing.bLevel ], (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), NULL ) == TRAVELCOST_DOOR ) // closed door blocks! + { + // obstacle or wall there! + continue; + } - ubWhoIsThere = WhoIsThere2( sSpot2, pSoldier->pathing.bLevel ); - if ( ubWhoIsThere != NOBODY && ubWhoIsThere != pSoldier->ubID ) - { - // skip this direction b/c it's blocked by another merc! - continue; - } + ubWhoIsThere = WhoIsThere2( sSpot2, pSoldier->pathing.bLevel ); + if ( ubWhoIsThere != NOBODY && ubWhoIsThere != pSoldier->ubID ) + { + // skip this direction b/c it's blocked by another merc! + continue; + } - sSpot = sSpot2; + sSpot = sSpot2; - // If this spot is our soldier's gridno use that! - if ( sSpot == pSoldier->sGridNo ) - { - if (pubDirection) - { - (*pubDirection) = (UINT8)GetDirectionFromGridNo( sGridNo, pSoldier ); - } - //*pubDirection = pSoldier->ubDirection; - return( sSpot ); - } + // If this spot is our soldier's gridno use that! + if ( sSpot == pSoldier->sGridNo ) + { + if (pubDirection) + { + (*pubDirection) = (UINT8)GetDirectionFromGridNo( sGridNo, pSoldier ); + } + //*pubDirection = pSoldier->ubDirection; + return( sSpot ); + } - ubDir = (UINT8)GetDirectionToGridNoFromGridNo( sSpot, sGridNo ); + ubDir = (UINT8)GetDirectionToGridNoFromGridNo( sSpot, sGridNo ); - // don't store path, just measure it - if ( ( NewOKDestinationAndDirection( pSoldier, sSpot, ubDir, TRUE , pSoldier->pathing.bLevel ) > 0 ) && - ( ( sDistance = PlotPath( pSoldier, sSpot, NO_COPYROUTE, NO_PLOT, TEMPORARY, (INT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ) ) > 0 ) ) - { - if ( sDistance < sClosest ) - { - sClosest = sDistance; - sCloseGridNo = sSpot; - } - } - } - - if (!TileIsOutOfBounds(sClosest)) - { - // Take last direction and use opposite! - // This will be usefull for ours and AI mercs + // don't store path, just measure it + if ( ( NewOKDestinationAndDirection( pSoldier, sSpot, ubDir, TRUE , pSoldier->pathing.bLevel ) > 0 ) && + ( ( sDistance = PlotPath( pSoldier, sSpot, NO_COPYROUTE, NO_PLOT, TEMPORARY, (INT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ) ) > 0 ) ) + { + if ( sDistance < sClosest ) + { + sClosest = sDistance; + sCloseGridNo = sSpot; + } + } + } - // If our gridno is the same ( which can be if we are look at doors ) - if ( sGridNo == sCloseGridNo ) - { - if (pubDirection) - { - // ATE: Only if we have a valid door! - if ( pDoor ) - { - switch( pDoor->pDBStructureRef->pDBStructure->ubWallOrientation ) - { - case OUTSIDE_TOP_LEFT: - case INSIDE_TOP_LEFT: + if (!TileIsOutOfBounds(sClosest)) + { + // Take last direction and use opposite! + // This will be usefull for ours and AI mercs - *pubDirection = SOUTH; - break; + // If our gridno is the same ( which can be if we are look at doors ) + if ( sGridNo == sCloseGridNo ) + { + if (pubDirection) + { + // ATE: Only if we have a valid door! + if ( pDoor ) + { + switch( pDoor->pDBStructureRef->pDBStructure->ubWallOrientation ) + { + case OUTSIDE_TOP_LEFT: + case INSIDE_TOP_LEFT: - case OUTSIDE_TOP_RIGHT: - case INSIDE_TOP_RIGHT: + *pubDirection = SOUTH; + break; - *pubDirection = EAST; - break; - } - } - } - } - else - { - // Calculate direction if our gridno is different.... - ubDir = (UINT8)GetDirectionToGridNoFromGridNo( sCloseGridNo, sGridNo ); - if (pubDirection) - { - *pubDirection = ubDir; - } - } - - if (TileIsOutOfBounds(sCloseGridNo)) - { - return( -1 ); - } - return( sCloseGridNo ); - } - else - return( -1 ); + case OUTSIDE_TOP_RIGHT: + case INSIDE_TOP_RIGHT: + + *pubDirection = EAST; + break; + } + } + } + } + else + { + // Calculate direction if our gridno is different.... + ubDir = (UINT8)GetDirectionToGridNoFromGridNo( sCloseGridNo, sGridNo ); + if (pubDirection) + { + *pubDirection = ubDir; + } + } + + if (TileIsOutOfBounds(sCloseGridNo)) + { + return( -1 ); + } + return( sCloseGridNo ); + } + else + return( -1 ); - /* - if ( !TileIsOutOfBounds(sCloseGridNo)) - { - // Take last direction and use opposite! - // This will be usefull for ours and AI mercs + /* + if ( !TileIsOutOfBounds(sCloseGridNo)) + { + // Take last direction and use opposite! + // This will be usefull for ours and AI mercs - // If our gridno is the same ( which can be if we are look at doors ) - if ( sGridNo == sCloseGridNo ) - { - switch( pDoor->pDBStructureRef->pDBStructure->ubWallOrientation ) - { - case OUTSIDE_TOP_LEFT: - case INSIDE_TOP_LEFT: + // If our gridno is the same ( which can be if we are look at doors ) + if ( sGridNo == sCloseGridNo ) + { + switch( pDoor->pDBStructureRef->pDBStructure->ubWallOrientation ) + { + case OUTSIDE_TOP_LEFT: + case INSIDE_TOP_LEFT: - *pubDirection = SOUTH; - break; + *pubDirection = SOUTH; + break; - case OUTSIDE_TOP_RIGHT: - case INSIDE_TOP_RIGHT: + case OUTSIDE_TOP_RIGHT: + case INSIDE_TOP_RIGHT: - *pubDirection = EAST; - break; - } - } - else - { - // Calculate direction if our gridno is different.... - ubDir = (UINT8)GetDirectionToGridNoFromGridNo( sCloseGridNo, sGridNo ); - *pubDirection = ubDir; - } - return( sCloseGridNo ); - } - else - return( -1 ); - */ + *pubDirection = EAST; + break; + } + } + else + { + // Calculate direction if our gridno is different.... + ubDir = (UINT8)GetDirectionToGridNoFromGridNo( sCloseGridNo, sGridNo ); + *pubDirection = ubDir; + } + return( sCloseGridNo ); + } + else + return( -1 ); + */ } INT32 FindAdjacentPunchTarget( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTargetSoldier, INT32 * psAdjustedTargetGridNo, UINT8 * pubDirection ) { - INT32 sSpot; - UINT8 ubGuyThere; + INT32 sSpot; + UINT8 ubGuyThere; - for ( INT8 cnt = 0; cnt < NUM_WORLD_DIRECTIONS; cnt++ ) - { - sSpot = NewGridNo( pSoldier->sGridNo, DirectionInc( cnt ) ); + for ( INT8 cnt = 0; cnt < NUM_WORLD_DIRECTIONS; cnt++ ) + { + sSpot = NewGridNo( pSoldier->sGridNo, DirectionInc( cnt ) ); - if ( DoorTravelCost( pSoldier, sSpot, gubWorldMovementCosts[ sSpot ][ cnt ][ pSoldier->pathing.bLevel ], FALSE, NULL ) >= TRAVELCOST_BLOCKED ) - { - // blocked! - continue; - } + if ( DoorTravelCost( pSoldier, sSpot, gubWorldMovementCosts[ sSpot ][ cnt ][ pSoldier->pathing.bLevel ], FALSE, NULL ) >= TRAVELCOST_BLOCKED ) + { + // blocked! + continue; + } - // Check for who is there... - ubGuyThere = WhoIsThere2( sSpot, pSoldier->pathing.bLevel ); + // Check for who is there... + ubGuyThere = WhoIsThere2( sSpot, pSoldier->pathing.bLevel ); - if ( pTargetSoldier != NULL && ubGuyThere == pTargetSoldier->ubID ) - { - // We've got a guy here.... - // Who is the one we want...... - *psAdjustedTargetGridNo = pTargetSoldier->sGridNo; - *pubDirection = ( UINT8 )cnt; - return( sSpot ); - } - } + if ( pTargetSoldier != NULL && ubGuyThere == pTargetSoldier->ubID ) + { + // We've got a guy here.... + // Who is the one we want...... + *psAdjustedTargetGridNo = pTargetSoldier->sGridNo; + *pubDirection = ( UINT8 )cnt; + return( sSpot ); + } + } - return( NOWHERE ); + return( NOWHERE ); } BOOLEAN UIOKMoveDestination( SOLDIERTYPE *pSoldier, INT32 usMapPos ) { - BOOLEAN fVisible; + BOOLEAN fVisible; - // Check if a hidden tile exists but is not revealed - if ( DoesGridNoContainHiddenStruct( usMapPos, &fVisible ) ) - { - if ( !fVisible ) - { - // The player thinks this is OK! - return( TRUE ); - } - } + // Check if a hidden tile exists but is not revealed + if ( DoesGridNoContainHiddenStruct( usMapPos, &fVisible ) ) + { + if ( !fVisible ) + { + // The player thinks this is OK! + return( TRUE ); + } + } - if ( !NewOKDestination( pSoldier, usMapPos, FALSE, (INT8) gsInterfaceLevel ) ) - { - return( FALSE ); - } + if ( !NewOKDestination( pSoldier, usMapPos, FALSE, (INT8) gsInterfaceLevel ) ) + { + return( FALSE ); + } - // ATE: If we are a robot, see if we are being validly controlled... - if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT ) - { - if ( ! pSoldier->CanRobotBeControlled( ) ) - { - // Display message that robot cannot be controlled.... - return( 2 ); - } - } + // ATE: If we are a robot, see if we are being validly controlled... + if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT ) + { + if ( ! pSoldier->CanRobotBeControlled( ) ) + { + // Display message that robot cannot be controlled.... + return( 2 ); + } + } - // ATE: Experiment.. take out - //else if ( IsRoofVisible( sMapPos ) && gsInterfaceLevel == 0 ) - //{ - // return( FALSE ); - //} + // ATE: Experiment.. take out + //else if ( IsRoofVisible( sMapPos ) && gsInterfaceLevel == 0 ) + //{ + // return( FALSE ); + //} - return( TRUE); + return( TRUE); } void HandleTeamServices( UINT8 ubTeamNum ) { - INT32 cnt; - SOLDIERTYPE *pTeamSoldier, *pTargetSoldier; - UINT32 uiPointsUsed; - UINT16 usSoldierIndex, usInHand; - UINT16 usKitPts; - INT8 bSlot; - BOOLEAN fDone; + INT32 cnt; + SOLDIERTYPE *pTeamSoldier, *pTargetSoldier; + UINT32 uiPointsUsed; + UINT16 usSoldierIndex, usInHand; + UINT16 usKitPts; + INT8 bSlot; + BOOLEAN fDone; - // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED! - cnt = gTacticalStatus.Team[ ubTeamNum ].bFirstID; + // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED! + cnt = gTacticalStatus.Team[ ubTeamNum ].bFirstID; - // look for all mercs on the same team, - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ ubTeamNum ].bLastID; cnt++,pTeamSoldier++) - { - if ( pTeamSoldier->stats.bLife >= OKLIFE && pTeamSoldier->bActive && pTeamSoldier->bInSector ) - { - fDone = FALSE; - // Check for different events! - // FOR DOING AID - if ( pTeamSoldier->usAnimState == GIVING_AID || pTeamSoldier->usAnimState == GIVING_AID_PRN ) - { - // Get medkit info - usInHand = pTeamSoldier->inv[ HANDPOS ].usItem; + // look for all mercs on the same team, + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ ubTeamNum ].bLastID; cnt++,pTeamSoldier++) + { + if ( pTeamSoldier->stats.bLife >= OKLIFE && pTeamSoldier->bActive && pTeamSoldier->bInSector ) + { + fDone = FALSE; + // Check for different events! + // FOR DOING AID + if ( pTeamSoldier->usAnimState == GIVING_AID || pTeamSoldier->usAnimState == GIVING_AID_PRN ) + { + // Get medkit info + usInHand = pTeamSoldier->inv[ HANDPOS ].usItem; - // Get victim pointer - usSoldierIndex = WhoIsThere2( pTeamSoldier->sTargetGridNo, pTeamSoldier->pathing.bLevel ); - if ( usSoldierIndex != NOBODY ) - { - pTargetSoldier = MercPtrs[ usSoldierIndex ]; + // Get victim pointer + usSoldierIndex = WhoIsThere2( pTeamSoldier->sTargetGridNo, pTeamSoldier->pathing.bLevel ); + if ( usSoldierIndex != NOBODY ) + { + pTargetSoldier = MercPtrs[ usSoldierIndex ]; - if ( pTargetSoldier->ubServiceCount ) - { - BOOLEAN fThrowMessage = (pTargetSoldier->bBleeding ? TRUE : FALSE); // added by SANDRO + if ( pTargetSoldier->ubServiceCount ) + { + BOOLEAN fThrowMessage = (pTargetSoldier->bBleeding ? TRUE : FALSE); // added by SANDRO - usKitPts = TotalPoints( &(pTeamSoldier->inv[ HANDPOS ] ) ); + usKitPts = TotalPoints( &(pTeamSoldier->inv[ HANDPOS ] ) ); - uiPointsUsed = pTeamSoldier->SoldierDressWound( pTargetSoldier, usKitPts, usKitPts ); + uiPointsUsed = pTeamSoldier->SoldierDressWound( pTargetSoldier, usKitPts, usKitPts ); - // Determine if they are all banagded - if ( !pTargetSoldier->bBleeding && pTargetSoldier->stats.bLife >= OKLIFE && !(pTargetSoldier->iHealableInjury >= 100 && pTeamSoldier->fDoingSurgery)) // check for surgery added by SANDRO - { - if ( fThrowMessage ) // throw message "all bandaged" only if there was something to bandage - SANDRO - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ MERC_IS_ALL_BANDAGED_STR ], pTargetSoldier->GetName() ); + // Determine if they are all banagded + if ( !pTargetSoldier->bBleeding && pTargetSoldier->stats.bLife >= OKLIFE && !(pTargetSoldier->iHealableInjury >= 100 && pTeamSoldier->fDoingSurgery)) // check for surgery added by SANDRO + { + if ( fThrowMessage ) // throw message "all bandaged" only if there was something to bandage - SANDRO + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ MERC_IS_ALL_BANDAGED_STR ], pTargetSoldier->GetName() ); - // Cancel all services for this guy! - pTargetSoldier->ReceivingSoldierCancelServices( ); - fDone = TRUE; - } + // Cancel all services for this guy! + pTargetSoldier->ReceivingSoldierCancelServices( ); + fDone = TRUE; + } - UseKitPoints( &(pTeamSoldier->inv[ HANDPOS ] ), (UINT16)uiPointsUsed, pTeamSoldier ); + UseKitPoints( &(pTeamSoldier->inv[ HANDPOS ] ), (UINT16)uiPointsUsed, pTeamSoldier ); - // Get new total - usKitPts = TotalPoints( &(pTeamSoldier->inv[ HANDPOS ] ) ); + // Get new total + usKitPts = TotalPoints( &(pTeamSoldier->inv[ HANDPOS ] ) ); - // WHETHER OR NOT recipient is all bandaged, check if we've used them up! - if ( usKitPts <= 0) // no more bandages - { - if ( fDone ) - { - // don't swap if we're done - bSlot = NO_SLOT; - } - else - { - bSlot = FindFirstAidKit ( pTeamSoldier ); - if ( bSlot == NO_SLOT ) - { - bSlot = FindMedKit( pTeamSoldier ); - } - } - if ( bSlot != NO_SLOT ) - { - SwapObjs( pTeamSoldier, HANDPOS, bSlot, TRUE ); - } - else - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ MERC_IS_OUT_OF_BANDAGES_STR ], pTeamSoldier->GetName() ); - pTeamSoldier->GivingSoldierCancelServices( ); + // WHETHER OR NOT recipient is all bandaged, check if we've used them up! + if ( usKitPts <= 0) // no more bandages + { + if ( fDone ) + { + // don't swap if we're done + bSlot = NO_SLOT; + } + else + { + bSlot = FindFirstAidKit ( pTeamSoldier ); + if ( bSlot == NO_SLOT ) + { + bSlot = FindMedKit( pTeamSoldier ); + } + } + if ( bSlot != NO_SLOT ) + { + SwapObjs( pTeamSoldier, HANDPOS, bSlot, TRUE ); + } + else + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ MERC_IS_OUT_OF_BANDAGES_STR ], pTeamSoldier->GetName() ); + pTeamSoldier->GivingSoldierCancelServices( ); - if ( !gTacticalStatus.fAutoBandageMode ) - { - pTeamSoldier->DoMercBattleSound( (INT8)( BATTLE_SOUND_CURSE1 ) ); - } + if ( !gTacticalStatus.fAutoBandageMode ) + { + pTeamSoldier->DoMercBattleSound( (INT8)( BATTLE_SOUND_CURSE1 ) ); + } - } - } - } - } - } - } + } + } + } + } + } + } - } + } } void HandlePlayerServices( SOLDIERTYPE *pTeamSoldier ) { - SOLDIERTYPE *pTargetSoldier; - UINT32 uiPointsUsed; - UINT16 usSoldierIndex, usInHand; - UINT16 usKitPts; - INT8 bSlot; - BOOLEAN fDone = FALSE; + SOLDIERTYPE *pTargetSoldier; + UINT32 uiPointsUsed; + UINT16 usSoldierIndex, usInHand; + UINT16 usKitPts; + INT8 bSlot; + BOOLEAN fDone = FALSE; - if ( pTeamSoldier->stats.bLife >= OKLIFE && pTeamSoldier->bActive ) - { - // Check for different events! - // FOR DOING AID - if ( pTeamSoldier->usAnimState == GIVING_AID || pTeamSoldier->usAnimState == GIVING_AID_PRN ) - { - // Get medkit info - usInHand = pTeamSoldier->inv[ HANDPOS ].usItem; + if ( pTeamSoldier->stats.bLife >= OKLIFE && pTeamSoldier->bActive ) + { + // Check for different events! + // FOR DOING AID + if ( pTeamSoldier->usAnimState == GIVING_AID || pTeamSoldier->usAnimState == GIVING_AID_PRN ) + { + // Get medkit info + usInHand = pTeamSoldier->inv[ HANDPOS ].usItem; - // Get victim pointer - usSoldierIndex = WhoIsThere2( pTeamSoldier->sTargetGridNo, pTeamSoldier->pathing.bLevel ); + // Get victim pointer + usSoldierIndex = WhoIsThere2( pTeamSoldier->sTargetGridNo, pTeamSoldier->pathing.bLevel ); - if ( usSoldierIndex != NOBODY ) - { - pTargetSoldier = MercPtrs[ usSoldierIndex ]; + if ( usSoldierIndex != NOBODY ) + { + pTargetSoldier = MercPtrs[ usSoldierIndex ]; - if ( pTargetSoldier->ubServiceCount ) - { - BOOLEAN fThrowMessage = (pTargetSoldier->bBleeding ? TRUE : FALSE); // added by SANDRO + if ( pTargetSoldier->ubServiceCount ) + { + BOOLEAN fThrowMessage = (pTargetSoldier->bBleeding ? TRUE : FALSE); // added by SANDRO - usKitPts = TotalPoints( &(pTeamSoldier->inv[ HANDPOS ] ) ); + usKitPts = TotalPoints( &(pTeamSoldier->inv[ HANDPOS ] ) ); - uiPointsUsed = pTeamSoldier->SoldierDressWound( pTargetSoldier, usKitPts, usKitPts ); + uiPointsUsed = pTeamSoldier->SoldierDressWound( pTargetSoldier, usKitPts, usKitPts ); - // Determine if they are all banagded - if ( !pTargetSoldier->bBleeding && pTargetSoldier->stats.bLife >= OKLIFE && !(pTargetSoldier->iHealableInjury >= 100 && pTeamSoldier->fDoingSurgery)) // check for surgery added by SANDRO - { - if ( fThrowMessage ) // throw message "all bandaged" only if there was something to bandage - SANDRO - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ MERC_IS_ALL_BANDAGED_STR ], pTargetSoldier->GetName() ); + // Determine if they are all banagded + if ( !pTargetSoldier->bBleeding && pTargetSoldier->stats.bLife >= OKLIFE && !(pTargetSoldier->iHealableInjury >= 100 && pTeamSoldier->fDoingSurgery)) // check for surgery added by SANDRO + { + if ( fThrowMessage ) // throw message "all bandaged" only if there was something to bandage - SANDRO + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ MERC_IS_ALL_BANDAGED_STR ], pTargetSoldier->GetName() ); - // Cancel all services for this guy! - pTargetSoldier->ReceivingSoldierCancelServices( ); - fDone = TRUE; - } + // Cancel all services for this guy! + pTargetSoldier->ReceivingSoldierCancelServices( ); + fDone = TRUE; + } - UseKitPoints( &(pTeamSoldier->inv[ HANDPOS ] ), (UINT16)uiPointsUsed, pTeamSoldier ); + UseKitPoints( &(pTeamSoldier->inv[ HANDPOS ] ), (UINT16)uiPointsUsed, pTeamSoldier ); - // Get new total - usKitPts = TotalPoints( &(pTeamSoldier->inv[ HANDPOS ] ) ); + // Get new total + usKitPts = TotalPoints( &(pTeamSoldier->inv[ HANDPOS ] ) ); - // WHETHER OR NOT recipient is all bandaged, check if we've used them up! - if ( usKitPts <= 0) // no more bandages - { - if ( fDone ) - { - // don't swap if we're done - bSlot = NO_SLOT; - } - else - { - // SANDRO - on surgery, only search for medic bags - if (pTeamSoldier->fDoingSurgery) - { - bSlot = FindMedKit ( pTeamSoldier ); - } - else - { - bSlot = FindFirstAidKit ( pTeamSoldier); - if ( bSlot == NO_SLOT ) - { - bSlot = FindMedKit ( pTeamSoldier ); - } - } - } + // WHETHER OR NOT recipient is all bandaged, check if we've used them up! + if ( usKitPts <= 0) // no more bandages + { + if ( fDone ) + { + // don't swap if we're done + bSlot = NO_SLOT; + } + else + { + // SANDRO - on surgery, only search for medic bags + if (pTeamSoldier->fDoingSurgery) + { + bSlot = FindMedKit ( pTeamSoldier ); + } + else + { + bSlot = FindFirstAidKit ( pTeamSoldier); + if ( bSlot == NO_SLOT ) + { + bSlot = FindMedKit ( pTeamSoldier ); + } + } + } - if ( bSlot != NO_SLOT ) - { - SwapObjs( pTeamSoldier, HANDPOS, bSlot, FALSE ); // SANDRO - changed to FALSE, so we can continue in the service (???) - } - else - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ MERC_IS_OUT_OF_BANDAGES_STR ], pTeamSoldier->GetName() ); - pTeamSoldier->GivingSoldierCancelServices( ); + if ( bSlot != NO_SLOT ) + { + SwapObjs( pTeamSoldier, HANDPOS, bSlot, FALSE ); // SANDRO - changed to FALSE, so we can continue in the service (???) + } + else + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ MERC_IS_OUT_OF_BANDAGES_STR ], pTeamSoldier->GetName() ); + pTeamSoldier->GivingSoldierCancelServices( ); - if ( !gTacticalStatus.fAutoBandageMode ) - { - pTeamSoldier->DoMercBattleSound( (INT8)( BATTLE_SOUND_CURSE1 ) ); - } - } - } - } - } - } - } + if ( !gTacticalStatus.fAutoBandageMode ) + { + pTeamSoldier->DoMercBattleSound( (INT8)( BATTLE_SOUND_CURSE1 ) ); + } + } + } + } + } + } + } } void CommonEnterCombatModeCode( ) { - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CommonEnterCombatMode"); - UINT32 cnt; - SOLDIERTYPE *pSoldier; + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CommonEnterCombatMode"); + UINT32 cnt; + SOLDIERTYPE *pSoldier; - gTacticalStatus.uiFlags |= INCOMBAT; + gTacticalStatus.uiFlags |= INCOMBAT; - //gTacticalStatus.ubAttackBusyCount = 0; + //gTacticalStatus.ubAttackBusyCount = 0; - // Reset num enemies fought flag... - // SANDRO - removed from here - //memset( &(gTacticalStatus.bNumFoughtInBattle), 0, MAXTEAMS ); - gTacticalStatus.ubLastBattleSectorX = (UINT8) gWorldSectorX; - gTacticalStatus.ubLastBattleSectorY = (UINT8) gWorldSectorY; - gTacticalStatus.fLastBattleWon = FALSE; - gTacticalStatus.fItemsSeenOnAttack = FALSE; + // Reset num enemies fought flag... + // SANDRO - removed from here + //memset( &(gTacticalStatus.bNumFoughtInBattle), 0, MAXTEAMS ); + gTacticalStatus.ubLastBattleSectorX = (UINT8) gWorldSectorX; + gTacticalStatus.ubLastBattleSectorY = (UINT8) gWorldSectorY; + gTacticalStatus.fLastBattleWon = FALSE; + gTacticalStatus.fItemsSeenOnAttack = FALSE; - gTacticalStatus.ubInterruptPending = DISABLED_INTERRUPT; + gTacticalStatus.ubInterruptPending = DISABLED_INTERRUPT; - // ATE: If we have an item pointer end it! - CancelItemPointer( ); + // ATE: If we have an item pointer end it! + CancelItemPointer( ); - ResetInterfaceAndUI( ); - ResetMultiSelection( ); + ResetInterfaceAndUI( ); + ResetMultiSelection( ); - // OK, loop thorugh all guys and stop them! - // Loop through all mercs and make go - for ( pSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pSoldier++, cnt++ ) - { - if ( pSoldier->bActive ) - { - if ( pSoldier->bInSector && pSoldier->ubBodyType != CROW ) - { - // Set some flags for quotes - pSoldier->usQuoteSaidFlags &= (~SOLDIER_QUOTE_SAID_IN_SHIT ); - pSoldier->usQuoteSaidFlags &= (~SOLDIER_QUOTE_SAID_MULTIPLE_CREATURES); + // OK, loop thorugh all guys and stop them! + // Loop through all mercs and make go + for ( pSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pSoldier++, cnt++ ) + { + if ( pSoldier->bActive ) + { + if ( pSoldier->bInSector && pSoldier->ubBodyType != CROW ) + { + // Set some flags for quotes + pSoldier->usQuoteSaidFlags &= (~SOLDIER_QUOTE_SAID_IN_SHIT ); + pSoldier->usQuoteSaidFlags &= (~SOLDIER_QUOTE_SAID_MULTIPLE_CREATURES); - // Hault! - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + // Hault! + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - // END AI actions - CancelAIAction( pSoldier, TRUE ); + // END AI actions + CancelAIAction( pSoldier, TRUE ); - // turn off AI controlled flag - pSoldier->flags.uiStatusFlags &= ~SOLDIER_UNDERAICONTROL; + // turn off AI controlled flag + pSoldier->flags.uiStatusFlags &= ~SOLDIER_UNDERAICONTROL; - // Check if this guy is an enemy.... - // SANDRO - don't check this here, we've already checked that once - //CheckForPotentialAddToBattleIncrement( pSoldier ); + // Check if this guy is an enemy.... + // SANDRO - don't check this here, we've already checked that once + //CheckForPotentialAddToBattleIncrement( pSoldier ); - // If guy is sleeping, wake him up! - if ( pSoldier->flags.fMercAsleep == TRUE ) - { - pSoldier->ChangeSoldierState( WKAEUP_FROM_SLEEP, 1, TRUE ); - } + // If guy is sleeping, wake him up! + if ( pSoldier->flags.fMercAsleep == TRUE ) + { + pSoldier->ChangeSoldierState( WKAEUP_FROM_SLEEP, 1, TRUE ); + } - // ATE: Refresh APs - pSoldier->CalcNewActionPoints( ); - // Either I just noticed this, or it just hasn't been a problem before. But - // if the last battle left a soldier at 0 points, he will not gain full points with - // carryover for this battle. So we'll hit it again. - pSoldier->CalcNewActionPoints( ); + // ATE: Refresh APs + pSoldier->CalcNewActionPoints( ); + // Either I just noticed this, or it just hasn't been a problem before. But + // if the last battle left a soldier at 0 points, he will not gain full points with + // carryover for this battle. So we'll hit it again. + pSoldier->CalcNewActionPoints( ); - // SANDRO - Improved Interrupt System - reset interrupt counter - memset(pSoldier->aiData.ubInterruptCounter,0,sizeof(pSoldier->aiData.ubInterruptCounter)); + // SANDRO - Improved Interrupt System - reset interrupt counter + memset(pSoldier->aiData.ubInterruptCounter,0,sizeof(pSoldier->aiData.ubInterruptCounter)); - if ( pSoldier->ubProfile != NO_PROFILE ) - { - if ( pSoldier->bTeam == CIV_TEAM && pSoldier->aiData.bNeutral ) - { - // only set precombat gridno if unset - if ( gMercProfiles[ pSoldier->ubProfile ].sPreCombatGridNo == 0 || TileIsOutOfBounds(gMercProfiles[ pSoldier->ubProfile ].sPreCombatGridNo)) - { - gMercProfiles[ pSoldier->ubProfile ].sPreCombatGridNo = pSoldier->sGridNo; - } - } - else - { - gMercProfiles[ pSoldier->ubProfile ].sPreCombatGridNo = NOWHERE; - } - } + if ( pSoldier->ubProfile != NO_PROFILE ) + { + if ( pSoldier->bTeam == CIV_TEAM && pSoldier->aiData.bNeutral ) + { + // only set precombat gridno if unset + if ( gMercProfiles[ pSoldier->ubProfile ].sPreCombatGridNo == 0 || TileIsOutOfBounds(gMercProfiles[ pSoldier->ubProfile ].sPreCombatGridNo)) + { + gMercProfiles[ pSoldier->ubProfile ].sPreCombatGridNo = pSoldier->sGridNo; + } + } + else + { + gMercProfiles[ pSoldier->ubProfile ].sPreCombatGridNo = NOWHERE; + } + } - if ( !gTacticalStatus.fHasEnteredCombatModeSinceEntering ) - { - // ATE: reset player's movement mode at the very start of - // combat - //if ( pSoldier->bTeam == gbPlayerNum ) - //{ - //pSoldier->usUIMovementMode = RUNNING; - //} - } - } - } - } + if ( !gTacticalStatus.fHasEnteredCombatModeSinceEntering ) + { + // ATE: reset player's movement mode at the very start of + // combat + //if ( pSoldier->bTeam == gbPlayerNum ) + //{ + //pSoldier->usUIMovementMode = RUNNING; + //} + } + } + } + } - gTacticalStatus.fHasEnteredCombatModeSinceEntering = TRUE; + gTacticalStatus.fHasEnteredCombatModeSinceEntering = TRUE; - SyncStrategicTurnTimes( ); + SyncStrategicTurnTimes( ); - // Play tune.. - PlayJA2Sample( ENDTURN_1, RATE_11025, MIDVOLUME, 1, MIDDLEPAN ); + // Play tune.. + PlayJA2Sample( ENDTURN_1, RATE_11025, MIDVOLUME, 1, MIDDLEPAN ); - // Say quote..... + // Say quote..... - // Change music modes - SetMusicMode( MUSIC_TACTICAL_BATTLE ); + // Change music modes + SetMusicMode( MUSIC_TACTICAL_BATTLE ); - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CommonEnterCombatMode done"); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CommonEnterCombatMode done"); } void EnterCombatMode( UINT8 ubStartingTeam ) { - UINT32 cnt; - SOLDIERTYPE *pTeamSoldier; - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode"); + UINT32 cnt; + SOLDIERTYPE *pTeamSoldier; + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode"); - if ( gTacticalStatus.uiFlags & INCOMBAT ) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Can't enter combat when already in combat" ); - // we're already in combat! - return; - } + if ( gTacticalStatus.uiFlags & INCOMBAT ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Can't enter combat when already in combat" ); + // we're already in combat! + return; + } - // Alrighty, don't do this if no enemies in sector - if ( NumCapableEnemyInSector( ) == 0 ) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Can't enter combat when no capable enemies" ); - //ScreenMsg( MSG_FONT_RED, MSG_DEBUG, L"Trying to init combat when no enemies around!." ); - return; - } + // Alrighty, don't do this if no enemies in sector + if ( NumCapableEnemyInSector( ) == 0 ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Can't enter combat when no capable enemies" ); + //ScreenMsg( MSG_FONT_RED, MSG_DEBUG, L"Trying to init combat when no enemies around!." ); + return; + } - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Entering combat mode" ); + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Entering combat mode" ); - // ATE: Added here to guarentee we have fEnemyInSector - // Mostly this was not getting set if: - // 1 ) we see bloodcats ( which makes them hostile ) - // 2 ) we make civs hostile - // only do this once they are seen..... - if ( !gTacticalStatus.fEnemyInSector ) - { - SetEnemyPresence( ); - } + // ATE: Added here to guarentee we have fEnemyInSector + // Mostly this was not getting set if: + // 1 ) we see bloodcats ( which makes them hostile ) + // 2 ) we make civs hostile + // only do this once they are seen..... + if ( !gTacticalStatus.fEnemyInSector ) + { + SetEnemyPresence( ); + } - CommonEnterCombatModeCode( ); + CommonEnterCombatModeCode( ); - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode continuing..."); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode continuing..."); - if (ubStartingTeam == gbPlayerNum) - { - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("EnterCombatMode continuing... start player turn, selected soldier = %d",gusSelectedSoldier)); - // OK, make sure we have a selected guy - // Madd: this was causing a weird crash becuase gusSelectedSoldier was 156 (out of the array bounds) for some reason - //if ( MercPtrs[ gusSelectedSoldier ]->aiData.bOppCnt == 0 ) - if ( gusSelectedSoldier != NOBODY && MercPtrs[ gusSelectedSoldier ]->aiData.bOppCnt == 0 ) - { - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode continuing... nobody selected"); - // OK, look through and find one.... - for ( cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID, pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pTeamSoldier++ ) - { - if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) && pTeamSoldier->aiData.bOppCnt > 0 ) - { - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode continuing... select soldier"); - SelectSoldier( pTeamSoldier->ubID, FALSE, TRUE ); - } - } - } - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode continuing... calling startplayerteamturn"); + if (ubStartingTeam == gbPlayerNum) + { + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("EnterCombatMode continuing... start player turn, selected soldier = %d",gusSelectedSoldier)); + // OK, make sure we have a selected guy + // Madd: this was causing a weird crash becuase gusSelectedSoldier was 156 (out of the array bounds) for some reason + //if ( MercPtrs[ gusSelectedSoldier ]->aiData.bOppCnt == 0 ) + if ( gusSelectedSoldier != NOBODY && MercPtrs[ gusSelectedSoldier ]->aiData.bOppCnt == 0 ) + { + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode continuing... nobody selected"); + // OK, look through and find one.... + for ( cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID, pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pTeamSoldier++ ) + { + if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) && pTeamSoldier->aiData.bOppCnt > 0 ) + { + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode continuing... select soldier"); + SelectSoldier( pTeamSoldier->ubID, FALSE, TRUE ); + } + } + } + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode continuing... calling startplayerteamturn"); - if (!is_client || is_server) //hayden - { - StartPlayerTeamTurn( FALSE, TRUE ); - if(is_client)send_EndTurn( ubStartingTeam ); //hayden - } - else - { - //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"client skipped EnterCombatMode"); - if(is_client)startCombat(ubStartingTeam);//clients other than server meet and send request for combat for server - } - } - else - { - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode continuing... end turn"); - // have to call EndTurn so that we freeze the interface etc - EndTurn( ubStartingTeam ); - } + if (!is_client || is_server) //hayden + { + StartPlayerTeamTurn( FALSE, TRUE ); + if(is_client)send_EndTurn( ubStartingTeam ); //hayden + } + else + { + //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"client skipped EnterCombatMode"); + if(is_client)startCombat(ubStartingTeam);//clients other than server meet and send request for combat for server + } + } + else + { + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode continuing... end turn"); + // have to call EndTurn so that we freeze the interface etc + EndTurn( ubStartingTeam ); + } - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode done"); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode done"); } @@ -6171,162 +5972,162 @@ void EnterCombatMode( UINT8 ubStartingTeam ) void ExitCombatMode( ) { - UINT32 cnt; - SOLDIERTYPE *pSoldier; + UINT32 cnt; + SOLDIERTYPE *pSoldier; - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Exiting combat mode" ); + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Exiting combat mode" ); - // Leave combat mode - gTacticalStatus.uiFlags &= (~INCOMBAT); + // Leave combat mode + gTacticalStatus.uiFlags &= (~INCOMBAT); - EndTopMessage( ); + EndTopMessage( ); - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[ MSG_FTM_EXIT_COMBAT ] );// ary-05/05/2009 : add forced turn mode + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[ MSG_FTM_EXIT_COMBAT ] );// ary-05/05/2009 : add forced turn mode - // OK, we have exited combat mode..... - // Reset some flags for no aps to move, etc + // OK, we have exited combat mode..... + // Reset some flags for no aps to move, etc - // Set virgin sector to true.... - gTacticalStatus.fVirginSector = TRUE; + // Set virgin sector to true.... + gTacticalStatus.fVirginSector = TRUE; - // Loop through all mercs and make go - for ( pSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pSoldier++, cnt++ ) - { - if ( pSoldier->bActive ) - { - if ( pSoldier->bInSector ) - { - // Reset some flags - if ( pSoldier->flags.fNoAPToFinishMove && pSoldier->stats.bLife >= OKLIFE ) - { - pSoldier->AdjustNoAPToFinishMove( FALSE ); + // Loop through all mercs and make go + for ( pSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pSoldier++, cnt++ ) + { + if ( pSoldier->bActive ) + { + if ( pSoldier->bInSector ) + { + // Reset some flags + if ( pSoldier->flags.fNoAPToFinishMove && pSoldier->stats.bLife >= OKLIFE ) + { + pSoldier->AdjustNoAPToFinishMove( FALSE ); - // ary-05/05/2009 : fix lower ready weapons - //previously "ready weapon" state was being dropped in a couple of cases - //the fix involves bypassing the reset animation state for the various "ready weapon" types - //since this is a reset animation function, we should be VERY specific about when and what we dont reset + // ary-05/05/2009 : fix lower ready weapons + //previously "ready weapon" state was being dropped in a couple of cases + //the fix involves bypassing the reset animation state for the various "ready weapon" types + //since this is a reset animation function, we should be VERY specific about when and what we dont reset - UINT16 test; - test = pSoldier->usAnimState; - if (!( test == AIM_RIFLE_STAND || test == AIM_RIFLE_CROUCH || - test == AIM_RIFLE_PRONE || test == AIM_DUAL_STAND || - test == AIM_DUAL_CROUCH || test == AIM_DUAL_PRONE - )) - { - pSoldier->SoldierGotoStationaryStance( ); - } - } + UINT16 test; + test = pSoldier->usAnimState; + if (!( test == AIM_RIFLE_STAND || test == AIM_RIFLE_CROUCH || + test == AIM_RIFLE_PRONE || test == AIM_DUAL_STAND || + test == AIM_DUAL_CROUCH || test == AIM_DUAL_PRONE + )) + { + pSoldier->SoldierGotoStationaryStance( ); + } + } - //Cancel pending events - pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; - pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + //Cancel pending events + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - // Reset moved flag - pSoldier->aiData.bMoved = FALSE; + // Reset moved flag + pSoldier->aiData.bMoved = FALSE; - // Set final destination - pSoldier->pathing.sFinalDestination = pSoldier->sGridNo; + // Set final destination + pSoldier->pathing.sFinalDestination = pSoldier->sGridNo; - // remove AI controlled flag - pSoldier->flags.uiStatusFlags &= ~SOLDIER_UNDERAICONTROL; - } - } - } + // remove AI controlled flag + pSoldier->flags.uiStatusFlags &= ~SOLDIER_UNDERAICONTROL; + } + } + } - // Change music modes - // unused - //gfForceMusicToTense = TRUE; + // Change music modes + // unused + //gfForceMusicToTense = TRUE; #ifdef ENABLE_ZOMBIES - UseCreatureMusic(HostileZombiesPresent()); + UseCreatureMusic(HostileZombiesPresent()); #endif - SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT ); + SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT ); - BetweenTurnsVisibilityAdjustments(); + BetweenTurnsVisibilityAdjustments(); - // pause the AI for a bit - PauseAITemporarily(); + // pause the AI for a bit + PauseAITemporarily(); - // reset muzzle flashes - TurnOffEveryonesMuzzleFlashes(); + // reset muzzle flashes + TurnOffEveryonesMuzzleFlashes(); - // zap interrupt list - ClearIntList(); + // zap interrupt list + ClearIntList(); - // dirty interface - DirtyMercPanelInterface( MercPtrs[ 0 ], DIRTYLEVEL2 ); + // dirty interface + DirtyMercPanelInterface( MercPtrs[ 0 ], DIRTYLEVEL2 ); - // ATE: If we are IN_CONV - DONT'T DO THIS! - if ( !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) - { - HandleStrategicTurnImplicationsOfExitingCombatMode(); - } + // ATE: If we are IN_CONV - DONT'T DO THIS! + if ( !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) + { + HandleStrategicTurnImplicationsOfExitingCombatMode(); + } - // Make sure next opplist decay DOES happen right after we go to RT - // since this would be the same as what would happen at the end of the turn - gTacticalStatus.uiTimeSinceLastOpplistDecay = __max( 0, GetWorldTotalSeconds() - TIME_BETWEEN_RT_OPPLIST_DECAYS ); - NonCombatDecayPublicOpplist( GetWorldTotalSeconds() ); - -#ifdef JA2UB - //if we are in J13 and the fan is stopped, handle it - HandleFanStartingAtEndOfCombat(); + // Make sure next opplist decay DOES happen right after we go to RT + // since this would be the same as what would happen at the end of the turn + gTacticalStatus.uiTimeSinceLastOpplistDecay = __max( 0, GetWorldTotalSeconds() - TIME_BETWEEN_RT_OPPLIST_DECAYS ); + NonCombatDecayPublicOpplist( GetWorldTotalSeconds() ); + +#ifdef JA2UB + //if we are in J13 and the fan is stopped, handle it + HandleFanStartingAtEndOfCombat(); #endif } void SetEnemyPresence( ) { - // We have an ememy present.... - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SetEnemyPresence")); + // We have an ememy present.... + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SetEnemyPresence")); - // Check if we previously had no enemys present and we are in a virgin secotr ( no enemys spotted yet ) - if ( !gTacticalStatus.fEnemyInSector && gTacticalStatus.fVirginSector ) - { - // If we have a guy selected, say quote! - // For now, display ono status message - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ ENEMY_IN_SECTOR_STR ] ); + // Check if we previously had no enemys present and we are in a virgin secotr ( no enemys spotted yet ) + if ( !gTacticalStatus.fEnemyInSector && gTacticalStatus.fVirginSector ) + { + // If we have a guy selected, say quote! + // For now, display ono status message + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ ENEMY_IN_SECTOR_STR ] ); - // Change music modes.. + // Change music modes.. - // If we are just starting game, don't do this! - -#if (defined JA2UB) - //Ja25: no meanwhiles - if ( !DidGameJustStart() ) + // If we are just starting game, don't do this! + +#if (defined JA2UB) + //Ja25: no meanwhiles + if ( !DidGameJustStart() ) #else - if ( !DidGameJustStart() && !AreInMeanwhile( ) ) + if ( !DidGameJustStart() && !AreInMeanwhile( ) ) #endif - { + { #ifdef ENABLE_ZOMBIES - UseCreatureMusic(HostileZombiesPresent()); + UseCreatureMusic(HostileZombiesPresent()); #endif - SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT ); - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SetEnemyPresence: warnings = false")); - sniperwarning = FALSE; - biggunwarning = FALSE; - gogglewarning = FALSE; - // airstrikeavailable = TRUE; - } - else - { - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SetEnemyPresence: warnings = true")); - sniperwarning = TRUE; - biggunwarning = TRUE; - //gogglewarning = TRUE; - // airstrikeavailable = FALSE; - } + SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT ); + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SetEnemyPresence: warnings = false")); + sniperwarning = FALSE; + biggunwarning = FALSE; + gogglewarning = FALSE; + // airstrikeavailable = TRUE; + } + else + { + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SetEnemyPresence: warnings = true")); + sniperwarning = TRUE; + biggunwarning = TRUE; + //gogglewarning = TRUE; + // airstrikeavailable = FALSE; + } - // Say quote... - //SayQuoteFromAnyBodyInSector( QUOTE_ENEMY_PRESENCE ); + // Say quote... + //SayQuoteFromAnyBodyInSector( QUOTE_ENEMY_PRESENCE ); - gTacticalStatus.fEnemyInSector = TRUE; + gTacticalStatus.fEnemyInSector = TRUE; - } + } } @@ -6334,626 +6135,626 @@ extern BOOLEAN gfLastMercTalkedAboutKillingID; BOOLEAN SoldierHasSeenEnemiesLastFewTurns( SOLDIERTYPE *pTeamSoldier ) { - INT32 cnt2; - SOLDIERTYPE *pSoldier; - INT32 cnt; + INT32 cnt2; + SOLDIERTYPE *pSoldier; + INT32 cnt; - for ( cnt = 0; cnt < MAXTEAMS; cnt++ ) - { + for ( cnt = 0; cnt < MAXTEAMS; cnt++ ) + { - if ( gTacticalStatus.Team[ cnt ].bSide != pTeamSoldier->bSide ) - { + if ( gTacticalStatus.Team[ cnt ].bSide != pTeamSoldier->bSide ) + { - // check this team for possible enemies - cnt2 = gTacticalStatus.Team[ cnt ].bFirstID; - for ( pSoldier = MercPtrs[ cnt2 ]; cnt2 <= gTacticalStatus.Team[ cnt ].bLastID; cnt2++, pSoldier++ ) - { - if ( pSoldier->bActive && pSoldier->bInSector && ( pSoldier->bTeam == gbPlayerNum || pSoldier->stats.bLife >= OKLIFE ) ) - { - if ( !CONSIDERED_NEUTRAL( pTeamSoldier, pSoldier ) && ( pTeamSoldier->bSide != pSoldier->bSide ) ) - { - // Have we not seen this guy..... - if ( ( pTeamSoldier->aiData.bOppList[ cnt2 ] >= SEEN_CURRENTLY ) && - ( pTeamSoldier->aiData.bOppList[ cnt2 ] <= SEEN_THIS_TURN ) ) - { - gTacticalStatus.bConsNumTurnsNotSeen = 0; - return( TRUE ); - } - } - } - } - } - } + // check this team for possible enemies + cnt2 = gTacticalStatus.Team[ cnt ].bFirstID; + for ( pSoldier = MercPtrs[ cnt2 ]; cnt2 <= gTacticalStatus.Team[ cnt ].bLastID; cnt2++, pSoldier++ ) + { + if ( pSoldier->bActive && pSoldier->bInSector && ( pSoldier->bTeam == gbPlayerNum || pSoldier->stats.bLife >= OKLIFE ) ) + { + if ( !CONSIDERED_NEUTRAL( pTeamSoldier, pSoldier ) && ( pTeamSoldier->bSide != pSoldier->bSide ) ) + { + // Have we not seen this guy..... + if ( ( pTeamSoldier->aiData.bOppList[ cnt2 ] >= SEEN_CURRENTLY ) && + ( pTeamSoldier->aiData.bOppList[ cnt2 ] <= SEEN_THIS_TURN ) ) + { + gTacticalStatus.bConsNumTurnsNotSeen = 0; + return( TRUE ); + } + } + } + } + } + } - return( FALSE ); + return( FALSE ); } -BOOLEAN WeSeeNoOne( void ) +BOOLEAN WeSeeNoOne( ) { - UINT32 uiLoop; - SOLDIERTYPE * pSoldier; + UINT32 uiLoop; + SOLDIERTYPE * pSoldier; - for ( uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++ ) - { - pSoldier = MercSlots[ uiLoop ]; - if ( pSoldier != NULL ) - { - if ( pSoldier->bTeam == gbPlayerNum ) - { - if ( pSoldier->aiData.bOppCnt > 0 ) - { - return( FALSE ); - } - } - } - } + for ( uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++ ) + { + pSoldier = MercSlots[ uiLoop ]; + if ( pSoldier != NULL ) + { + if ( pSoldier->bTeam == gbPlayerNum ) + { + if ( pSoldier->aiData.bOppCnt > 0 ) + { + return( FALSE ); + } + } + } + } - return( TRUE ); + return( TRUE ); } -BOOLEAN NobodyAlerted( void ) +BOOLEAN NobodyAlerted( ) { - UINT32 uiLoop; - SOLDIERTYPE * pSoldier; + UINT32 uiLoop; + SOLDIERTYPE * pSoldier; - for ( uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++ ) - { - pSoldier = MercSlots[ uiLoop ]; - if ( pSoldier != NULL ) - { - if ( ( pSoldier->bTeam != gbPlayerNum ) && ( ! pSoldier->aiData.bNeutral ) && (pSoldier->stats.bLife >= OKLIFE) && (pSoldier->aiData.bAlertStatus >= STATUS_RED) ) - { - return( FALSE ); - } - } - } + for ( uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++ ) + { + pSoldier = MercSlots[ uiLoop ]; + if ( pSoldier != NULL ) + { + if ( ( pSoldier->bTeam != gbPlayerNum ) && ( ! pSoldier->aiData.bNeutral ) && (pSoldier->stats.bLife >= OKLIFE) && (pSoldier->aiData.bAlertStatus >= STATUS_RED) ) + { + return( FALSE ); + } + } + } - return( TRUE ); + return( TRUE ); } -BOOLEAN WeSawSomeoneThisTurn( void ) +BOOLEAN WeSawSomeoneThisTurn( ) { - UINT32 uiLoop, uiLoop2; - SOLDIERTYPE * pSoldier; + UINT32 uiLoop, uiLoop2; + SOLDIERTYPE * pSoldier; - for ( uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++ ) - { - pSoldier = MercSlots[ uiLoop ]; - if ( pSoldier != NULL ) - { - if ( pSoldier->bTeam == gbPlayerNum ) - { - for ( uiLoop2 = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; uiLoop2 < TOTAL_SOLDIERS; uiLoop2++ ) - { - if ( pSoldier->aiData.bOppList[ uiLoop2 ] == SEEN_THIS_TURN ) - { - return( TRUE ); - } - } - } - } - } - return( FALSE ); + for ( uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++ ) + { + pSoldier = MercSlots[ uiLoop ]; + if ( pSoldier != NULL ) + { + if ( pSoldier->bTeam == gbPlayerNum ) + { + for ( uiLoop2 = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; uiLoop2 < TOTAL_SOLDIERS; uiLoop2++ ) + { + if ( pSoldier->aiData.bOppList[ uiLoop2 ] == SEEN_THIS_TURN ) + { + return( TRUE ); + } + } + } + } + } + return( FALSE ); } void SayBattleSoundFromAnyBodyInSector( INT32 iBattleSnd ) { -// WDS - make number of mercenaries, etc. be configurable -// UINT8 ubMercsInSector[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ] = { 0 }; - std::vector ubMercsInSector (CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS, 0); - UINT8 ubNumMercs = 0; - UINT8 ubChosenMerc; - SOLDIERTYPE *pTeamSoldier; - INT32 cnt; + // WDS - make number of mercenaries, etc. be configurable + // UINT8 ubMercsInSector[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ] = { 0 }; + std::vector ubMercsInSector (CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS, 0); + UINT8 ubNumMercs = 0; + UINT8 ubChosenMerc; + SOLDIERTYPE *pTeamSoldier; + INT32 cnt; - // Loop through all our guys and randomly say one from someone in our sector + // Loop through all our guys and randomly say one from someone in our sector - // set up soldier ptr as first element in mercptrs list - cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; + // set up soldier ptr as first element in mercptrs list + cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; - // run through list - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ ) - { - // Add guy if he's a candidate... - if ( OK_INSECTOR_MERC( pTeamSoldier ) && !AM_AN_EPC( pTeamSoldier ) && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_GASSED ) && !(AM_A_ROBOT( pTeamSoldier )) && !pTeamSoldier->flags.fMercAsleep ) - { - ubMercsInSector[ ubNumMercs ] = (UINT8)cnt; - ubNumMercs++; - } - } + // run through list + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ ) + { + // Add guy if he's a candidate... + if ( OK_INSECTOR_MERC( pTeamSoldier ) && !AM_AN_EPC( pTeamSoldier ) && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_GASSED ) && !(AM_A_ROBOT( pTeamSoldier )) && !pTeamSoldier->flags.fMercAsleep ) + { + ubMercsInSector[ ubNumMercs ] = (UINT8)cnt; + ubNumMercs++; + } + } - // If we are > 0 - if ( ubNumMercs > 0 ) - { - ubChosenMerc = (UINT8)Random( ubNumMercs ); + // If we are > 0 + if ( ubNumMercs > 0 ) + { + ubChosenMerc = (UINT8)Random( ubNumMercs ); - MercPtrs[ ubChosenMerc ]->DoMercBattleSound( (UINT8)iBattleSnd ); - } + MercPtrs[ ubChosenMerc ]->DoMercBattleSound( (UINT8)iBattleSnd ); + } } BOOLEAN CheckForEndOfCombatMode( BOOLEAN fIncrementTurnsNotSeen ) { - SOLDIERTYPE *pTeamSoldier; - UINT32 cnt = 0; - BOOLEAN fWeSeeNoOne, fNobodyAlerted; - BOOLEAN fSayQuote = FALSE; - BOOLEAN fWeSawSomeoneRecently = FALSE, fSomeoneSawSomeoneRecently = FALSE; + SOLDIERTYPE *pTeamSoldier; + UINT32 cnt = 0; + BOOLEAN fWeSeeNoOne, fNobodyAlerted; + BOOLEAN fSayQuote = FALSE; + BOOLEAN fWeSawSomeoneRecently = FALSE, fSomeoneSawSomeoneRecently = FALSE; - //if(is_server && check_status()) - //{ - // return(FALSE); - //} + //if(is_server && check_status()) + //{ + // return(FALSE); + //} - // First check for end of battle.... - // If there are no enemies at all in the sector - // Battle end should take precedence! - if ( CheckForEndOfBattle( FALSE ) ) - { - return( TRUE ); - } + // First check for end of battle.... + // If there are no enemies at all in the sector + // Battle end should take precedence! + if ( CheckForEndOfBattle( FALSE ) ) + { + return( TRUE ); + } - // We can only check for end of combat if in combat mode - if ( ! ( gTacticalStatus.uiFlags & INCOMBAT ) ) - { - return( FALSE ); - } - //if (is_server || is_client) - //{ - // return(FALSE); // cheap band-aid to prevent return from turn based action in multiplayer, atleast until further dev... : hayden. - //} + // We can only check for end of combat if in combat mode + if ( ! ( gTacticalStatus.uiFlags & INCOMBAT ) ) + { + return( FALSE ); + } + //if (is_server || is_client) + //{ + // return(FALSE); // cheap band-aid to prevent return from turn based action in multiplayer, atleast until further dev... : hayden. + //} - // if we're boxing NEVER end combat mode - if ( gTacticalStatus.bBoxingState == BOXING ) - { - return( FALSE ); - } + // if we're boxing NEVER end combat mode + if ( gTacticalStatus.bBoxingState == BOXING ) + { + return( FALSE ); + } - fWeSeeNoOne = WeSeeNoOne(); - fNobodyAlerted = NobodyAlerted(); - if ( fWeSeeNoOne && fNobodyAlerted ) - { - // hack!!! - gTacticalStatus.bConsNumTurnsNotSeen = 5; - } - else - { + fWeSeeNoOne = WeSeeNoOne(); + fNobodyAlerted = NobodyAlerted(); + if ( fWeSeeNoOne && fNobodyAlerted ) + { + // hack!!! + gTacticalStatus.bConsNumTurnsNotSeen = 5; + } + else + { - // we have to loop through EVERYONE to see if anyone sees a hostile... if so, stay in turnbased... + // we have to loop through EVERYONE to see if anyone sees a hostile... if so, stay in turnbased... - for ( cnt = 0; cnt < guiNumMercSlots; cnt++ ) - { - pTeamSoldier = MercSlots[ cnt ]; - if ( pTeamSoldier && pTeamSoldier->stats.bLife >= OKLIFE && !pTeamSoldier->aiData.bNeutral ) - { - if ( SoldierHasSeenEnemiesLastFewTurns( pTeamSoldier ) ) - { - gTacticalStatus.bConsNumTurnsNotSeen = 0; - fSomeoneSawSomeoneRecently = TRUE; - if ( pTeamSoldier->bTeam == gbPlayerNum || (pTeamSoldier->bTeam == MILITIA_TEAM && pTeamSoldier->bSide == 0 ) ) // or friendly militia - { - fWeSawSomeoneRecently = TRUE; - break; - } - } - } - } + for ( cnt = 0; cnt < guiNumMercSlots; cnt++ ) + { + pTeamSoldier = MercSlots[ cnt ]; + if ( pTeamSoldier && pTeamSoldier->stats.bLife >= OKLIFE && !pTeamSoldier->aiData.bNeutral ) + { + if ( SoldierHasSeenEnemiesLastFewTurns( pTeamSoldier ) ) + { + gTacticalStatus.bConsNumTurnsNotSeen = 0; + fSomeoneSawSomeoneRecently = TRUE; + if ( pTeamSoldier->bTeam == gbPlayerNum || (pTeamSoldier->bTeam == MILITIA_TEAM && pTeamSoldier->bSide == 0 ) ) // or friendly militia + { + fWeSawSomeoneRecently = TRUE; + break; + } + } + } + } - if ( fSomeoneSawSomeoneRecently ) - { - if ( fWeSawSomeoneRecently ) - { - gTacticalStatus.bConsNumTurnsWeHaventSeenButEnemyDoes = 0; - } - else - { - // start tracking this - gTacticalStatus.bConsNumTurnsWeHaventSeenButEnemyDoes++; - } - return( FALSE ); - } + if ( fSomeoneSawSomeoneRecently ) + { + if ( fWeSawSomeoneRecently ) + { + gTacticalStatus.bConsNumTurnsWeHaventSeenButEnemyDoes = 0; + } + else + { + // start tracking this + gTacticalStatus.bConsNumTurnsWeHaventSeenButEnemyDoes++; + } + return( FALSE ); + } - // IF here, we don;t see anybody.... increment count for end check - if( fIncrementTurnsNotSeen ) - { - gTacticalStatus.bConsNumTurnsNotSeen++; - } - } + // IF here, we don;t see anybody.... increment count for end check + if( fIncrementTurnsNotSeen ) + { + gTacticalStatus.bConsNumTurnsNotSeen++; + } + } - gTacticalStatus.bConsNumTurnsWeHaventSeenButEnemyDoes = 0; + gTacticalStatus.bConsNumTurnsWeHaventSeenButEnemyDoes = 0; - // If we have reach a point where a cons. number of turns gone by.... - //if ( gTacticalStatus.bConsNumTurnsNotSeen > 1 ) - // ary-05/05/2009 : add forced turn mode : note : no forced turn mode option for Multi Player - if ( is_networked ) gGameSettings.fOptions[ TOPTION_TOGGLE_TURN_MODE ] = FALSE; - if ( gTacticalStatus.bConsNumTurnsNotSeen > 1 && !gGameSettings.fOptions[ TOPTION_TOGGLE_TURN_MODE ]) - { + // If we have reach a point where a cons. number of turns gone by.... + //if ( gTacticalStatus.bConsNumTurnsNotSeen > 1 ) + // ary-05/05/2009 : add forced turn mode : note : no forced turn mode option for Multi Player + if ( is_networked ) gGameSettings.fOptions[ TOPTION_TOGGLE_TURN_MODE ] = FALSE; + if ( gTacticalStatus.bConsNumTurnsNotSeen > 1 && !gGameSettings.fOptions[ TOPTION_TOGGLE_TURN_MODE ]) + { - if(is_networked && !getReal)//hayden - { - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[32] ); + if(is_networked && !getReal)//hayden + { + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[32] ); - sendRT(); + sendRT(); - return(FALSE); - } - gTacticalStatus.bConsNumTurnsNotSeen = 0; - - // Exit mode! - ExitCombatMode(); + return(FALSE); + } + gTacticalStatus.bConsNumTurnsNotSeen = 0; + + // Exit mode! + ExitCombatMode(); - if ( fNobodyAlerted ) - { - // if we don't see anyone currently BUT we did see someone this turn, THEN don't - // say quote - if ( fWeSeeNoOne && WeSawSomeoneThisTurn() ) - { - // don't say quote - } - else - { - fSayQuote = TRUE; - } - } - else - { - fSayQuote = TRUE; - } + if ( fNobodyAlerted ) + { + // if we don't see anyone currently BUT we did see someone this turn, THEN don't + // say quote + if ( fWeSeeNoOne && WeSawSomeoneThisTurn() ) + { + // don't say quote + } + else + { + fSayQuote = TRUE; + } + } + else + { + fSayQuote = TRUE; + } - // ATE: Are there creatures here? If so, say another quote... - if ( fSayQuote && ( gTacticalStatus.uiFlags & IN_CREATURE_LAIR ) ) - { - SayQuoteFromAnyBodyInSector( QUOTE_WORRIED_ABOUT_CREATURE_PRESENCE ); - } - // Are we fighting bloodcats? - else if ( NumBloodcatsInSectorNotDeadOrDying( ) > 0 ) - { + // ATE: Are there creatures here? If so, say another quote... + if ( fSayQuote && ( gTacticalStatus.uiFlags & IN_CREATURE_LAIR ) ) + { + SayQuoteFromAnyBodyInSector( QUOTE_WORRIED_ABOUT_CREATURE_PRESENCE ); + } + // Are we fighting bloodcats? + else if ( NumBloodcatsInSectorNotDeadOrDying( ) > 0 ) + { - } - else - { - if ( fSayQuote ) - { - // Double check by seeing if we have any active enemies in sector! - if ( NumEnemyInSectorNotDeadOrDying( ) > 0 ) - { - //comm by ddd SayQuoteFromAnyBodyInSector( QUOTE_WARNING_OUTSTANDING_ENEMY_AFTER_RT ); - if(Chance(gGameExternalOptions.iChanceSayAnnoyingPhrase) ) - SayQuoteFromAnyBodyInSector( QUOTE_WARNING_OUTSTANDING_ENEMY_AFTER_RT ); - } - } - } - /* - if ( (!fWeSeeNoOne || !fNobodyAlerted) && WeSawSomeoneThisTurn() ) - { - // Say quote to the effect that the battle has lulled - SayQuoteFromAnyBodyInSector( QUOTE_WARNING_OUTSTANDING_ENEMY_AFTER_RT ); - } - */ + } + else + { + if ( fSayQuote ) + { + // Double check by seeing if we have any active enemies in sector! + if ( NumEnemyInSectorNotDeadOrDying( ) > 0 ) + { + //comm by ddd SayQuoteFromAnyBodyInSector( QUOTE_WARNING_OUTSTANDING_ENEMY_AFTER_RT ); + if(Chance(gGameExternalOptions.iChanceSayAnnoyingPhrase) ) + SayQuoteFromAnyBodyInSector( QUOTE_WARNING_OUTSTANDING_ENEMY_AFTER_RT ); + } + } + } + /* + if ( (!fWeSeeNoOne || !fNobodyAlerted) && WeSawSomeoneThisTurn() ) + { + // Say quote to the effect that the battle has lulled + SayQuoteFromAnyBodyInSector( QUOTE_WARNING_OUTSTANDING_ENEMY_AFTER_RT ); + } + */ - // Begin tense music.... - // unused - //gfForceMusicToTense = TRUE; + // Begin tense music.... + // unused + //gfForceMusicToTense = TRUE; #ifdef ENABLE_ZOMBIES - UseCreatureMusic(HostileZombiesPresent()); + UseCreatureMusic(HostileZombiesPresent()); #endif - SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT ); + SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT ); - return( TRUE ); - } + return( TRUE ); + } - return( FALSE ); + return( FALSE ); } -void DeathNoMessageTimerCallback( void ) +void DeathNoMessageTimerCallback( ) { - //CheckAndHandleUnloadingOfCurrentWorld(); - if(!is_client) - CheckAndHandleUnloadingOfCurrentWorld(); - else - { - if (!isOwnTeamWipedOut) - { - ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[40] ); - if(!cDisableSpectatorMode) - { - gTacticalStatus.uiFlags |= SHOW_ALL_MERCS;//hayden - ScreenMsg( FONT_YELLOW, MSG_CHAT, MPClientMessage[41] ); - } - else - ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"spectator mode disabled"); - - teamwiped(); - } - } + //CheckAndHandleUnloadingOfCurrentWorld(); + if(!is_client) + CheckAndHandleUnloadingOfCurrentWorld(); + else + { + if (!isOwnTeamWipedOut) + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[40] ); + if(!cDisableSpectatorMode) + { + gTacticalStatus.uiFlags |= SHOW_ALL_MERCS;//hayden + ScreenMsg( FONT_YELLOW, MSG_CHAT, MPClientMessage[41] ); + } + else + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"spectator mode disabled"); + + teamwiped(); + } + } } // get a vector of all player-controlled sectors with prison facilities. It is assumed that a sector has max. one of these BOOLEAN GetPlayerControlledPrisonList( std::vector& arSectorIDVector ) { - arSectorIDVector.clear(); + arSectorIDVector.clear(); - for(INT16 sX = 1; sX < MAP_WORLD_X - 1; ++sX ) - { - for(INT16 sY = 1; sY < MAP_WORLD_X - 1; ++sY ) - { - // only sectors where there are no ongoing battles or even enemy garrisons are valid for our cause - if ( !SectorOursAndPeaceful( sX, sY, 0 ) ) - continue; + for(INT16 sX = 1; sX < MAP_WORLD_X - 1; ++sX ) + { + for(INT16 sY = 1; sY < MAP_WORLD_X - 1; ++sY ) + { + // only sectors where there are no ongoing battles or even enemy garrisons are valid for our cause + if ( !SectorOursAndPeaceful( sX, sY, 0 ) ) + continue; - // only allow sectors which we have controlled at least once - otherwise prisoners might get sent to San Mona prison, even though the player never was there - if ( !SectorInfo[ (UINT8)SECTOR( sX, sY ) ].fSurfaceWasEverPlayerControlled ) - continue; + // only allow sectors which we have controlled at least once - otherwise prisoners might get sent to San Mona prison, even though the player never was there + if ( !SectorInfo[ (UINT8)SECTOR( sX, sY ) ].fSurfaceWasEverPlayerControlled ) + continue; - // Is there a prison in this sector? - for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt) - { - // Is this facility here? - if (gFacilityLocations[SECTOR(sX, sY)][cnt].fFacilityHere) - { - // we determine wether this is a prison by checking for usPrisonBaseLimit - if ( gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit > 0 ) - { - arSectorIDVector.push_back( SECTOR(sX, sY) ); - break; - } - } - } - } - } + // Is there a prison in this sector? + for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt) + { + // Is this facility here? + if (gFacilityLocations[SECTOR(sX, sY)][cnt].fFacilityHere) + { + // we determine wether this is a prison by checking for usPrisonBaseLimit + if ( gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit > 0 ) + { + arSectorIDVector.push_back( SECTOR(sX, sY) ); + break; + } + } + } + } + } - return ( arSectorIDVector.size() > 0 ); + return ( arSectorIDVector.size() > 0 ); } extern INT32 giReinforcementPool; void PrisonerMessageBoxCallBack( UINT8 ubExitValue ) { - UINT32 usSectorID = 0; + UINT32 usSectorID = 0; - // Get a list of all available prisons, and create a fitting messagebox - std::vector prisonsectorvector; - if ( GetPlayerControlledPrisonList( prisonsectorvector ) ) - { - UINT8 cnt = 1; - std::vector::iterator itend = prisonsectorvector.end(); - for (std::vector::iterator it = prisonsectorvector.begin(); it != itend; ++it) - { - if ( ubExitValue == cnt ) - { - usSectorID = (*it); - break; - } + // Get a list of all available prisons, and create a fitting messagebox + std::vector prisonsectorvector; + if ( GetPlayerControlledPrisonList( prisonsectorvector ) ) + { + UINT8 cnt = 1; + std::vector::iterator itend = prisonsectorvector.end(); + for (std::vector::iterator it = prisonsectorvector.begin(); it != itend; ++it) + { + if ( ubExitValue == cnt ) + { + usSectorID = (*it); + break; + } - ++cnt; - } - } + ++cnt; + } + } - // if sector is still not set, then we did not select one - release prisoners - if ( usSectorID == 0 ) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_RELEASED] ); - } + // if sector is still not set, then we did not select one - release prisoners + if ( usSectorID == 0 ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_RELEASED] ); + } - UINT32 prisonerstobemoved = 0; - BOOLEAN success = FALSE; - if ( !gbWorldSectorZ ) - { - SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] ); + UINT32 prisonerstobemoved = 0; + BOOLEAN success = FALSE; + if ( !gbWorldSectorZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] ); - prisonerstobemoved = pSectorInfo->uiNumberOfPrisonersOfWar; + prisonerstobemoved = pSectorInfo->uiNumberOfPrisonersOfWar; - pSectorInfo->uiNumberOfPrisonersOfWar = 0; - - if ( usSectorID > 0) - { - SECTORINFO *pPrisonSectorInfo = &( SectorInfo[ usSectorID ] ); + pSectorInfo->uiNumberOfPrisonersOfWar = 0; - if ( pPrisonSectorInfo ) - { - success = TRUE; + if ( usSectorID > 0) + { + SECTORINFO *pPrisonSectorInfo = &( SectorInfo[ usSectorID ] ); - pPrisonSectorInfo->uiNumberOfPrisonersOfWar += prisonerstobemoved; + if ( pPrisonSectorInfo ) + { + success = TRUE; - CHAR16 wString[ 64 ]; - GetShortSectorString( SECTORX(usSectorID), SECTORY(usSectorID), wString ); - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_SENTTOSECTOR], prisonerstobemoved, wString ); - } - } - } - else - { - UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - - prisonerstobemoved = pSectorInfo->uiNumberOfPrisonersOfWar; + pPrisonSectorInfo->uiNumberOfPrisonersOfWar += prisonerstobemoved; - pSectorInfo->uiNumberOfPrisonersOfWar = 0; + CHAR16 wString[ 64 ]; + GetShortSectorString( SECTORX(usSectorID), SECTORY(usSectorID), wString ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_SENTTOSECTOR], prisonerstobemoved, wString ); + } + } + } + else + { + UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - if ( usSectorID > 0) - { - SECTORINFO *pPrisonSectorInfo = &( SectorInfo[ usSectorID ] ); + prisonerstobemoved = pSectorInfo->uiNumberOfPrisonersOfWar; - if ( pPrisonSectorInfo ) - { - success = TRUE; + pSectorInfo->uiNumberOfPrisonersOfWar = 0; - pPrisonSectorInfo->uiNumberOfPrisonersOfWar += prisonerstobemoved; + if ( usSectorID > 0) + { + SECTORINFO *pPrisonSectorInfo = &( SectorInfo[ usSectorID ] ); - CHAR16 wString[ 64 ]; - GetShortSectorString( SECTORX(usSectorID), SECTORY(usSectorID), wString ); - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_SENTTOSECTOR], prisonerstobemoved, wString ); - } - } - } + if ( pPrisonSectorInfo ) + { + success = TRUE; - if ( !success ) - // send some prisoners back to queen's pool - // there is a chance that escaped prisoners may return to the queen... - giReinforcementPool += (prisonerstobemoved * gGameExternalOptions.ubPrisonerReturntoQueenChance) / 100; + pPrisonSectorInfo->uiNumberOfPrisonersOfWar += prisonerstobemoved; + + CHAR16 wString[ 64 ]; + GetShortSectorString( SECTORX(usSectorID), SECTORY(usSectorID), wString ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_SENTTOSECTOR], prisonerstobemoved, wString ); + } + } + } + + if ( !success ) + // send some prisoners back to queen's pool + // there is a chance that escaped prisoners may return to the queen... + giReinforcementPool += (prisonerstobemoved * gGameExternalOptions.ubPrisonerReturntoQueenChance) / 100; } void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) { - SOLDIERTYPE *pTeamSoldier; - INT32 cnt = 0; - UINT8 ubNumPrisoners = 0; - UINT8 ubNumPrisonerAdmin = 0; - UINT8 ubNumPrisonerTroop = 0; - UINT8 ubNumPrisonerElite = 0; + SOLDIERTYPE *pTeamSoldier; + INT32 cnt = 0; + UINT8 ubNumPrisoners = 0; + UINT8 ubNumPrisonerAdmin = 0; + UINT8 ubNumPrisonerTroop = 0; + UINT8 ubNumPrisonerElite = 0; - // Check if the battle is won! - // Loop through all mercs and make go - for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; ++pTeamSoldier, ++cnt ) - { - // Kill those not already dead.,... - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == ENEMY_TEAM ) - { - // Only pows that are not dead yet - if ( ( pTeamSoldier->bSoldierFlagMask & SOLDIER_POW ) && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) - { - // if we arrive here and the guy has lifepoints < OKLIFE, something is very odd... better take him prisoner and remove him anyway - //if ( pTeamSoldier->stats.bLife > OKLIFE && pTeamSoldier->stats.bLife != 0 ) - { - switch ( pTeamSoldier->ubSoldierClass ) - { - case SOLDIER_CLASS_ADMINISTRATOR: ubNumPrisonerAdmin++; break; - case SOLDIER_CLASS_ARMY: ubNumPrisonerTroop++; break; - case SOLDIER_CLASS_ELITE: ubNumPrisonerElite++; break; - default: - // if none of the above classes, ignore this one - continue; - break; - } + // Check if the battle is won! + // Loop through all mercs and make go + for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; ++pTeamSoldier, ++cnt ) + { + // Kill those not already dead.,... + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == ENEMY_TEAM ) + { + // Only pows that are not dead yet + if ( ( pTeamSoldier->bSoldierFlagMask & SOLDIER_POW ) && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) + { + // if we arrive here and the guy has lifepoints < OKLIFE, something is very odd... better take him prisoner and remove him anyway + //if ( pTeamSoldier->stats.bLife > OKLIFE && pTeamSoldier->stats.bLife != 0 ) + { + switch ( pTeamSoldier->ubSoldierClass ) + { + case SOLDIER_CLASS_ADMINISTRATOR: ubNumPrisonerAdmin++; break; + case SOLDIER_CLASS_ARMY: ubNumPrisonerTroop++; break; + case SOLDIER_CLASS_ELITE: ubNumPrisonerElite++; break; + default: + // if none of the above classes, ignore this one + continue; + break; + } - ++ubNumPrisoners; + ++ubNumPrisoners; - // place items on the floor - INT8 bVisible = 0; - UINT16 usItemFlags = 0; - UINT8 size = pTeamSoldier->inv.size(); - for ( UINT8 cnt = 0; cnt < size; ++cnt ) - { - OBJECTTYPE* pObj = &( pTeamSoldier->inv[ cnt ] ); + // place items on the floor + INT8 bVisible = 0; + UINT16 usItemFlags = 0; + UINT8 size = pTeamSoldier->inv.size(); + for ( UINT8 cnt = 0; cnt < size; ++cnt ) + { + OBJECTTYPE* pObj = &( pTeamSoldier->inv[ cnt ] ); - if ( pObj->exists() == true ) - { - // Check if it's supposed to be dropped - if ( !( (*pObj).fFlags & OBJECT_UNDROPPABLE ) || pTeamSoldier->bTeam == gbPlayerNum ) - { - if ( !(Item[ pObj->usItem ].defaultundroppable ) ) - { - //ReduceAmmoDroppedByNonPlayerSoldiers( pTeamSoldier, cnt ); + if ( pObj->exists() == true ) + { + // Check if it's supposed to be dropped + if ( !( (*pObj).fFlags & OBJECT_UNDROPPABLE ) || pTeamSoldier->bTeam == gbPlayerNum ) + { + if ( !(Item[ pObj->usItem ].defaultundroppable ) ) + { + //ReduceAmmoDroppedByNonPlayerSoldiers( pTeamSoldier, cnt ); - //if this soldier was an enemy - // Kaiden: Added from UB's reveal all items after combat feature! - // HEADROCK HAM B2.8: Now also reveals equipment dropped by militia, if requirement is met. - if( pTeamSoldier->bTeam == ENEMY_TEAM || - ( gGameExternalOptions.ubMilitiaDropEquipment == 2 && pTeamSoldier->bTeam == MILITIA_TEAM ) || - ( gGameExternalOptions.ubMilitiaDropEquipment == 1 && pTeamSoldier->bTeam == MILITIA_TEAM && Menptr[ pTeamSoldier->ubAttackerID ].bTeam != OUR_TEAM )) - { - //add a flag to the item so when all enemies are killed, we can run through and reveal all the enemies items - usItemFlags |= WORLD_ITEM_DROPPED_FROM_ENEMY; + //if this soldier was an enemy + // Kaiden: Added from UB's reveal all items after combat feature! + // HEADROCK HAM B2.8: Now also reveals equipment dropped by militia, if requirement is met. + if( pTeamSoldier->bTeam == ENEMY_TEAM || + ( gGameExternalOptions.ubMilitiaDropEquipment == 2 && pTeamSoldier->bTeam == MILITIA_TEAM ) || + ( gGameExternalOptions.ubMilitiaDropEquipment == 1 && pTeamSoldier->bTeam == MILITIA_TEAM && Menptr[ pTeamSoldier->ubAttackerID ].bTeam != OUR_TEAM )) + { + //add a flag to the item so when all enemies are killed, we can run through and reveal all the enemies items + usItemFlags |= WORLD_ITEM_DROPPED_FROM_ENEMY; - if ( Item[pObj->usItem].damageable && Item[pObj->usItem].usItemClass != IC_THROWING_KNIFE ) // Madd: drop crappier items from enemies on higher difficulty levels - note the quick fix for throwing knives - { - (*pObj)[0]->data.objectStatus -= (gGameOptions.ubDifficultyLevel - 1) * Random(20); - (*pObj)[0]->data.objectStatus = min(max((*pObj)[0]->data.objectStatus,1),100); // never below 1% or above 100% + if ( Item[pObj->usItem].damageable && Item[pObj->usItem].usItemClass != IC_THROWING_KNIFE ) // Madd: drop crappier items from enemies on higher difficulty levels - note the quick fix for throwing knives + { + (*pObj)[0]->data.objectStatus -= (gGameOptions.ubDifficultyLevel - 1) * Random(20); + (*pObj)[0]->data.objectStatus = min(max((*pObj)[0]->data.objectStatus,1),100); // never below 1% or above 100% - (*pObj)[0]->data.sRepairThreshold = max(1, min(100, ((*pObj)[0]->data.objectStatus + 200)/3 )); - } - } + (*pObj)[0]->data.sRepairThreshold = max(1, min(100, ((*pObj)[0]->data.objectStatus + 200)/3 )); + } + } - //if(UsingNewAttachmentSystem()==true) - //ReduceAttachmentsOnGunForNonPlayerChars(pTeamSoldier, pObj); + //if(UsingNewAttachmentSystem()==true) + //ReduceAttachmentsOnGunForNonPlayerChars(pTeamSoldier, pObj); - // HEADROCK HAM B2.8: Militia will drop items only if allowed. - if (!(gGameExternalOptions.ubMilitiaDropEquipment == 0 && pTeamSoldier->bTeam == MILITIA_TEAM ) && - !(gGameExternalOptions.ubMilitiaDropEquipment == 1 && pTeamSoldier->bTeam == MILITIA_TEAM && Menptr[ pTeamSoldier->ubAttackerID ].bTeam == OUR_TEAM )) - { - AddItemToPool( pTeamSoldier->sGridNo, pObj, bVisible , pTeamSoldier->pathing.bLevel, usItemFlags, -1 ); - } - } - } - } - } + // HEADROCK HAM B2.8: Militia will drop items only if allowed. + if (!(gGameExternalOptions.ubMilitiaDropEquipment == 0 && pTeamSoldier->bTeam == MILITIA_TEAM ) && + !(gGameExternalOptions.ubMilitiaDropEquipment == 1 && pTeamSoldier->bTeam == MILITIA_TEAM && Menptr[ pTeamSoldier->ubAttackerID ].bTeam == OUR_TEAM )) + { + AddItemToPool( pTeamSoldier->sGridNo, pObj, bVisible , pTeamSoldier->pathing.bLevel, usItemFlags, -1 ); + } + } + } + } + } - DropKeysInKeyRing( pTeamSoldier, pTeamSoldier->sGridNo, pTeamSoldier->pathing.bLevel, bVisible, FALSE, 0, FALSE ); + DropKeysInKeyRing( pTeamSoldier, pTeamSoldier->sGridNo, pTeamSoldier->pathing.bLevel, bVisible, FALSE, 0, FALSE ); - // Make team look for items - AllSoldiersLookforItems( TRUE ); + // Make team look for items + AllSoldiersLookforItems( TRUE ); - if ( pTeamSoldier->bTeam != gbPlayerNum ) - // Remove merc! - // ATE: Remove merc slot first - will disappear if no corpse data found! - TacticalRemoveSoldier( pTeamSoldier->ubID ); - else - pTeamSoldier->RemoveSoldierFromGridNo( ); + if ( pTeamSoldier->bTeam != gbPlayerNum ) + // Remove merc! + // ATE: Remove merc slot first - will disappear if no corpse data found! + TacticalRemoveSoldier( pTeamSoldier->ubID ); + else + pTeamSoldier->RemoveSoldierFromGridNo( ); - // this function updates number of enemies, and also updates groups - ProcessQueenCmdImplicationsOfDeath( pTeamSoldier ); + // this function updates number of enemies, and also updates groups + ProcessQueenCmdImplicationsOfDeath( pTeamSoldier ); + + // Remove as target + RemoveManAsTarget( pTeamSoldier ); + } + } + } + } - // Remove as target - RemoveManAsTarget( pTeamSoldier ); - } - } - } - } - if (!bMapZ) // Battle ended Above-ground { SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); - pSectorInfo->uiNumberOfPrisonersOfWar += ubNumPrisoners; + pSectorInfo->uiNumberOfPrisonersOfWar += ubNumPrisoners; } else { UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ ); - pSectorInfo->uiNumberOfPrisonersOfWar += ubNumPrisoners; + pSectorInfo->uiNumberOfPrisonersOfWar += ubNumPrisoners; } - if ( ubNumPrisoners ) - { - // Get a list of all available prisons, and create a fitting messagebox - std::vector prisonsectorvector; - if ( GetPlayerControlledPrisonList( prisonsectorvector ) ) - { - UINT8 cnt = 0; - std::vector::iterator itend = prisonsectorvector.end(); - for (std::vector::iterator it = prisonsectorvector.begin(); it != itend; ++it) - { - UINT32 usSectorID = (*it); - CHAR16 zShortTownIDString[ 50 ]; + if ( ubNumPrisoners ) + { + // Get a list of all available prisons, and create a fitting messagebox + std::vector prisonsectorvector; + if ( GetPlayerControlledPrisonList( prisonsectorvector ) ) + { + UINT8 cnt = 0; + std::vector::iterator itend = prisonsectorvector.end(); + for (std::vector::iterator it = prisonsectorvector.begin(); it != itend; ++it) + { + UINT32 usSectorID = (*it); + CHAR16 zShortTownIDString[ 50 ]; - GetShortSectorString( SECTORX(usSectorID), SECTORY(usSectorID), zShortTownIDString ); + GetShortSectorString( SECTORX(usSectorID), SECTORY(usSectorID), zShortTownIDString ); - // Set string for generic button - swprintf( gzUserDefinedButton[ cnt++ ], L"%s", zShortTownIDString ); + // Set string for generic button + swprintf( gzUserDefinedButton[ cnt++ ], L"%s", zShortTownIDString ); - if ( cnt >= 7 ) - break; - } + if ( cnt >= 7 ) + break; + } - for ( ; cnt < 8; ++cnt) - { - wcscpy( gzUserDefinedButton[ cnt ], TacticalStr[ PRISONER_LETGO_STR ] ); - } + for ( ; cnt < 8; ++cnt) + { + wcscpy( gzUserDefinedButton[ cnt ], TacticalStr[ PRISONER_LETGO_STR ] ); + } - DoMessageBox( MSG_BOX_BASIC_MEDIUM_BUTTONS, TacticalStr[ PRISONER_DECIDE_STR ], GAME_SCREEN, MSG_BOX_FLAG_GENERIC_EIGHT_BUTTONS, PrisonerMessageBoxCallBack, NULL ); - } - else - DoMessageBox( MSG_BOX_BASIC_STYLE, TacticalStr[ PRISONER_NO_PRISONS_STR ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, NULL, NULL ); - } + DoMessageBox( MSG_BOX_BASIC_MEDIUM_BUTTONS, TacticalStr[ PRISONER_DECIDE_STR ], GAME_SCREEN, MSG_BOX_FLAG_GENERIC_EIGHT_BUTTONS, PrisonerMessageBoxCallBack, NULL ); + } + else + DoMessageBox( MSG_BOX_BASIC_STYLE, TacticalStr[ PRISONER_NO_PRISONS_STR ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, NULL, NULL ); + } } void RemoveStaticEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) @@ -6968,7 +6769,7 @@ void RemoveStaticEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) else { UNDERGROUND_SECTORINFO *pSectorInfo; - + pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ ); pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = 0; pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = 0; @@ -6981,2623 +6782,2637 @@ void RemoveStaticEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) //Whenever returning TRUE, make sure you clear gfBlitBattleSectorLocator; BOOLEAN CheckForEndOfBattle( BOOLEAN fAnEnemyRetreated ) { - SOLDIERTYPE *pTeamSoldier; - BOOLEAN fBattleWon = TRUE; - BOOLEAN fBattleLost = FALSE; - INT32 cnt = 0; - UINT16 usAnimState; + SOLDIERTYPE *pTeamSoldier; + BOOLEAN fBattleWon = TRUE; + BOOLEAN fBattleLost = FALSE; + INT32 cnt = 0; + UINT16 usAnimState; - if ( gTacticalStatus.bBoxingState == BOXING ) - { - // no way are we going to exit boxing prematurely, thank you! :-) - return( FALSE ); - } + if ( gTacticalStatus.bBoxingState == BOXING ) + { + // no way are we going to exit boxing prematurely, thank you! :-) + return( FALSE ); + } - // OJW - 090212 - Fix end conditions for multiplayer - TeamDM - if(is_server) - { - // check the server's conditions for continueing the game, if the server wants to continue the game it returns true - // hence we return false that the battle has ended. If not, when this function returns below we will force the game to end. - if ( check_status() ) - return(FALSE); - // the block of code below would always cause this function to exit before checking the servers desires - // in cases of team deathmatch where there were no more enemies - } - else - { - // We can only check for end of battle if in combat mode or there are enemies - // present (they might bleed to death or run off the map!) - if ( ! ( gTacticalStatus.uiFlags & INCOMBAT ) ) - { - if ( ! (gTacticalStatus.fEnemyInSector) ) - { - return( FALSE ); - } - } - } + // OJW - 090212 - Fix end conditions for multiplayer - TeamDM + if(is_server) + { + // check the server's conditions for continueing the game, if the server wants to continue the game it returns true + // hence we return false that the battle has ended. If not, when this function returns below we will force the game to end. + if ( check_status() ) + return(FALSE); + // the block of code below would always cause this function to exit before checking the servers desires + // in cases of team deathmatch where there were no more enemies + } + else + { + // We can only check for end of battle if in combat mode or there are enemies + // present (they might bleed to death or run off the map!) + if ( ! ( gTacticalStatus.uiFlags & INCOMBAT ) ) + { + if ( ! (gTacticalStatus.fEnemyInSector) ) + { + return( FALSE ); + } + } + } - // ATE: If attack busy count.. get out... - if ( (gTacticalStatus.ubAttackBusyCount > 0 ) ) - { - return( FALSE ); - } + // ATE: If attack busy count.. get out... + if ( (gTacticalStatus.ubAttackBusyCount > 0 ) ) + { + return( FALSE ); + } #ifdef ENABLE_ZOMBIES - if ( HostileZombiesPresent() ) //Madd: got tired of the victory music playing right after the zombies arose - return FALSE; + if ( HostileZombiesPresent() ) //Madd: got tired of the victory music playing right after the zombies arose + return FALSE; #endif - - // OK, this is to releave infinate looping...becasue we can kill guys in this function - if ( gfKillingGuysForLosingBattle ) - { - return( FALSE ); - } - // Check if the battle is won! - if ( NumCapableEnemyInSector( ) > 0 ) - { - fBattleWon = FALSE; - } + // OK, this is to releave infinate looping...becasue we can kill guys in this function + if ( gfKillingGuysForLosingBattle ) + { + return( FALSE ); + } - if ( CheckForLosingEndOfBattle( ) == TRUE ) - { - fBattleLost = TRUE; - } + // Check if the battle is won! + if ( NumCapableEnemyInSector( ) > 0 ) + { + fBattleWon = FALSE; + } - //NEW (Nov 24, 98) by Kris - if( !gbWorldSectorZ && fBattleWon ) - { //Check to see if more enemy soldiers exist in the strategic layer - //It is possible to have more than 20 enemies in a sector. By failing here, - //it gives the engine a chance to add these soldiers as reinforcements. This - //is naturally handled. - AddPossiblePendingEnemiesToBattle(); - if( gfPendingEnemies ) - { - fBattleWon = FALSE; - } - } + if ( CheckForLosingEndOfBattle( ) == TRUE ) + { + fBattleLost = TRUE; + } - if( ( fBattleLost ) || ( fBattleWon ) ) - { - if( !gbWorldSectorZ ) - { - SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY) ].bLastKnownEnemies = NumEnemiesInSector( gWorldSectorX, gWorldSectorY ); - } - } + //NEW (Nov 24, 98) by Kris + if( !gbWorldSectorZ && fBattleWon ) + { //Check to see if more enemy soldiers exist in the strategic layer + //It is possible to have more than 20 enemies in a sector. By failing here, + //it gives the engine a chance to add these soldiers as reinforcements. This + //is naturally handled. + AddPossiblePendingEnemiesToBattle(); + if( gfPendingEnemies ) + { + fBattleWon = FALSE; + } + } - // We should NEVER have a battle lost and won at the same time... + if( ( fBattleLost ) || ( fBattleWon ) ) + { + if( !gbWorldSectorZ ) + { + SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY) ].bLastKnownEnemies = NumEnemiesInSector( gWorldSectorX, gWorldSectorY ); + } + } - if ( fBattleLost ) - { - // CJC: End AI's turn here.... first... so that UnSetUIBusy will succeed if militia win - // battle for us - EndAllAITurns( ); + // We should NEVER have a battle lost and won at the same time... - // Set enemy presence to false - // This is safe 'cause we're about to unload the friggen sector anyway.... - gTacticalStatus.fEnemyInSector = FALSE; - // SANDRO - reset number of enemies here - memset( &(gTacticalStatus.bNumFoughtInBattle), 0, MAXTEAMS ); + if ( fBattleLost ) + { + // CJC: End AI's turn here.... first... so that UnSetUIBusy will succeed if militia win + // battle for us + EndAllAITurns( ); - // If here, the battle has been lost! - UnSetUIBusy( (UINT8)gusSelectedSoldier ); + // Set enemy presence to false + // This is safe 'cause we're about to unload the friggen sector anyway.... + gTacticalStatus.fEnemyInSector = FALSE; + // SANDRO - reset number of enemies here + memset( &(gTacticalStatus.bNumFoughtInBattle), 0, MAXTEAMS ); - if ( gTacticalStatus.uiFlags & INCOMBAT ) - { - // Exit mode! - ExitCombatMode(); - } + // If here, the battle has been lost! + UnSetUIBusy( (UINT8)gusSelectedSoldier ); - HandleMoraleEvent( NULL, MORALE_HEARD_BATTLE_LOST, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_BATTLE_LOST, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + if ( gTacticalStatus.uiFlags & INCOMBAT ) + { + // Exit mode! + ExitCombatMode(); + } - // SANDRO - end quest if cleared the sector after interrogation (sector N7 by Meduna) - if ( gWorldSectorX == 7 && gWorldSectorY == 14 && gbWorldSectorZ == 0 && gubQuest[ QUEST_INTERROGATION ] == QUESTINPROGRESS ) - { - // Quest failed - InternalEndQuest( QUEST_INTERROGATION, gWorldSectorX, gWorldSectorY, FALSE ); - } + HandleMoraleEvent( NULL, MORALE_HEARD_BATTLE_LOST, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_BATTLE_LOST, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - // Play death music - SetMusicMode( MUSIC_TACTICAL_DEATH ); + // SANDRO - end quest if cleared the sector after interrogation (sector N7 by Meduna) + if ( gWorldSectorX == 7 && gWorldSectorY == 14 && gbWorldSectorZ == 0 && gubQuest[ QUEST_INTERROGATION ] == QUESTINPROGRESS ) + { + // Quest failed + InternalEndQuest( QUEST_INTERROGATION, gWorldSectorX, gWorldSectorY, FALSE ); + } - SetCustomizableTimerCallbackAndDelay( 10000, DeathNoMessageTimerCallback, FALSE ); - - if (is_networked) - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[42] ); + // Play death music + SetMusicMode( MUSIC_TACTICAL_DEATH ); - if ( CheckFact( FACT_FIRST_BATTLE_BEING_FOUGHT, 0 ) ) - { - // this is our first battle... and we lost it! - SetFactTrue( FACT_FIRST_BATTLE_FOUGHT ); - SetFactFalse( FACT_FIRST_BATTLE_BEING_FOUGHT ); - SetTheFirstBattleSector( (INT16) (gWorldSectorX + gWorldSectorY * MAP_WORLD_X) ); + SetCustomizableTimerCallbackAndDelay( 10000, DeathNoMessageTimerCallback, FALSE ); + + if (is_networked) + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[42] ); + + if ( CheckFact( FACT_FIRST_BATTLE_BEING_FOUGHT, 0 ) ) + { + // this is our first battle... and we lost it! + SetFactTrue( FACT_FIRST_BATTLE_FOUGHT ); + SetFactFalse( FACT_FIRST_BATTLE_BEING_FOUGHT ); + SetTheFirstBattleSector( (INT16) (gWorldSectorX + gWorldSectorY * MAP_WORLD_X) ); #if (defined JA2UB) -//Ja25 no meanwhile + //Ja25 no meanwhile #else - HandleFirstBattleEndingWhileInTown( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, FALSE ); + HandleFirstBattleEndingWhileInTown( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, FALSE ); #endif - } + } - if( NumEnemyInSectorExceptCreatures() ) - { - SetThisSectorAsEnemyControlled( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, TRUE ); - } + if( NumEnemyInSectorExceptCreatures() ) + { + SetThisSectorAsEnemyControlled( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, TRUE ); + } - // ATE: Important! THis is delayed until music ends so we can have proper effect! - // CheckAndHandleUnloadingOfCurrentWorld(); + // ATE: Important! THis is delayed until music ends so we can have proper effect! + // CheckAndHandleUnloadingOfCurrentWorld(); - //Whenever returning TRUE, make sure you clear gfBlitBattleSectorLocator; - LogBattleResults( LOG_DEFEAT ); - gfBlitBattleSectorLocator = FALSE; - // If we are the server, we escape this function at the top if we think the game should still be running - // hence if we get here the game is over for all clients and we should report it - if (is_networked && is_server) - game_over(); - return( TRUE ); - } + //Whenever returning TRUE, make sure you clear gfBlitBattleSectorLocator; + LogBattleResults( LOG_DEFEAT ); + gfBlitBattleSectorLocator = FALSE; + // If we are the server, we escape this function at the top if we think the game should still be running + // hence if we get here the game is over for all clients and we should report it + if (is_networked && is_server) + game_over(); + return( TRUE ); + } - // If battle won, do stuff right away! - if ( fBattleWon ) - { + // If battle won, do stuff right away! + if ( fBattleWon ) + { - if ( gTacticalStatus.bBoxingState == NOT_BOXING ) // if boxing don't do any of this stuff - { - gTacticalStatus.fLastBattleWon = TRUE; + if ( gTacticalStatus.bBoxingState == NOT_BOXING ) // if boxing don't do any of this stuff + { + gTacticalStatus.fLastBattleWon = TRUE; - // OK, KILL any enemies that are incompacitated - if ( KillIncompacitatedEnemyInSector( ) ) - { - return( FALSE ); - } - } + // OK, KILL any enemies that are incompacitated + if ( KillIncompacitatedEnemyInSector( ) ) + { + return( FALSE ); + } + } - // Flugente: remove those enemies that are captured and add them to the prisoner pool - RemoveCapturedEnemiesFromSectorInfo( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + // Flugente: remove those enemies that are captured and add them to the prisoner pool + RemoveCapturedEnemiesFromSectorInfo( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - // Kill all enemies. Sometime even after killing all the enemies, there appeares "in battle" enemies in sector info - RemoveStaticEnemiesFromSectorInfo( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + // Kill all enemies. Sometime even after killing all the enemies, there appeares "in battle" enemies in sector info + RemoveStaticEnemiesFromSectorInfo( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - // If here, the battle has been won! - // hurray! a glorious victory! + // If here, the battle has been won! + // hurray! a glorious victory! - // Set enemy presence to false - gTacticalStatus.fEnemyInSector = FALSE; + // Set enemy presence to false + gTacticalStatus.fEnemyInSector = FALSE; - // CJC: End AI's turn here.... first... so that UnSetUIBusy will succeed if militia win - // battle for us - EndAllAITurns( ); + // CJC: End AI's turn here.... first... so that UnSetUIBusy will succeed if militia win + // battle for us + EndAllAITurns( ); - UnSetUIBusy( (UINT8)gusSelectedSoldier ); + UnSetUIBusy( (UINT8)gusSelectedSoldier ); - // ATE: - // If we ended battle in any team other than the player's - // we need to end the UI lock using this method.... - guiPendingOverrideEvent = LU_ENDUILOCK; - HandleTacticalUI( ); + // ATE: + // If we ended battle in any team other than the player's + // we need to end the UI lock using this method.... + guiPendingOverrideEvent = LU_ENDUILOCK; + HandleTacticalUI( ); - if ( gTacticalStatus.uiFlags & INCOMBAT ) - { - // Exit mode! - ExitCombatMode(); - } + if ( gTacticalStatus.uiFlags & INCOMBAT ) + { + // Exit mode! + ExitCombatMode(); + } - if ( gTacticalStatus.bBoxingState == NOT_BOXING ) // if boxing don't do any of this stuff - { + if ( gTacticalStatus.bBoxingState == NOT_BOXING ) // if boxing don't do any of this stuff + { - // Only do some stuff if we actually faught a battle - if ( gTacticalStatus.bNumFoughtInBattle[ ENEMY_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CREATURE_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CIV_TEAM ] > 0 ) - //if ( gTacticalStatus.bNumEnemiesFoughtInBattle > 0 ) - { - // Loop through all mercs and make go - for ( pTeamSoldier = MercPtrs[ gTacticalStatus.Team[ gbPlayerNum ].bFirstID ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++) - { - if ( pTeamSoldier->bActive ) - { - if ( pTeamSoldier->bInSector ) - { - if( pTeamSoldier->bTeam == gbPlayerNum ) - { - // SANDRO - records - num tactical battles - gMercProfiles[pTeamSoldier->ubProfile].records.usBattlesTactical++; - // largest battle experienced - if (gMercProfiles[pTeamSoldier->ubProfile].records.usLargestBattleFought < ( gTacticalStatus.bNumFoughtInBattle[ ENEMY_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CREATURE_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CIV_TEAM ] )) - { - gMercProfiles[pTeamSoldier->ubProfile].records.usLargestBattleFought = ( gTacticalStatus.bNumFoughtInBattle[ ENEMY_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CREATURE_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CIV_TEAM ] ); - } + // Only do some stuff if we actually faught a battle + if ( gTacticalStatus.bNumFoughtInBattle[ ENEMY_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CREATURE_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CIV_TEAM ] > 0 ) + //if ( gTacticalStatus.bNumEnemiesFoughtInBattle > 0 ) + { + // Loop through all mercs and make go + for ( pTeamSoldier = MercPtrs[ gTacticalStatus.Team[ gbPlayerNum ].bFirstID ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++) + { + if ( pTeamSoldier->bActive ) + { + if ( pTeamSoldier->bInSector ) + { + if( pTeamSoldier->bTeam == gbPlayerNum ) + { + // SANDRO - records - num tactical battles + gMercProfiles[pTeamSoldier->ubProfile].records.usBattlesTactical++; + // largest battle experienced + if (gMercProfiles[pTeamSoldier->ubProfile].records.usLargestBattleFought < ( gTacticalStatus.bNumFoughtInBattle[ ENEMY_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CREATURE_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CIV_TEAM ] )) + { + gMercProfiles[pTeamSoldier->ubProfile].records.usLargestBattleFought = ( gTacticalStatus.bNumFoughtInBattle[ ENEMY_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CREATURE_TEAM ] + gTacticalStatus.bNumFoughtInBattle[ CIV_TEAM ] ); + } - // If this guy is OKLIFE & not standing, make stand.... - if ( pTeamSoldier->stats.bLife >= OKLIFE && !pTeamSoldier->bCollapsed ) - { - if ( pTeamSoldier->bAssignment < ON_DUTY ) - { - // Reset some quote flags.... - pTeamSoldier->usQuoteSaidExtFlags &= (~SOLDIER_QUOTE_SAID_BUDDY_1_WITNESSED); - pTeamSoldier->usQuoteSaidExtFlags &= (~SOLDIER_QUOTE_SAID_BUDDY_2_WITNESSED); - pTeamSoldier->usQuoteSaidExtFlags &= (~SOLDIER_QUOTE_SAID_BUDDY_3_WITNESSED); + // If this guy is OKLIFE & not standing, make stand.... + if ( pTeamSoldier->stats.bLife >= OKLIFE && !pTeamSoldier->bCollapsed ) + { + if ( pTeamSoldier->bAssignment < ON_DUTY ) + { + // Reset some quote flags.... + pTeamSoldier->usQuoteSaidExtFlags &= (~SOLDIER_QUOTE_SAID_BUDDY_1_WITNESSED); + pTeamSoldier->usQuoteSaidExtFlags &= (~SOLDIER_QUOTE_SAID_BUDDY_2_WITNESSED); + pTeamSoldier->usQuoteSaidExtFlags &= (~SOLDIER_QUOTE_SAID_BUDDY_3_WITNESSED); - // toggle stealth mode.... - gfUIStanceDifferent = TRUE; - pTeamSoldier->bStealthMode = FALSE; - fInterfacePanelDirty = DIRTYLEVEL2; - //DBrot: Stance change - if (gGameExternalOptions.fStandUpAfterBattle){ - if ( gAnimControl[ pTeamSoldier->usAnimState ].ubHeight != ANIM_STAND ) - { - pTeamSoldier->ChangeSoldierStance( ANIM_STAND ); - } - else - { - // If they are aiming, end aim! - usAnimState = PickSoldierReadyAnimation( pTeamSoldier, TRUE, FALSE ); + // toggle stealth mode.... + gfUIStanceDifferent = TRUE; + pTeamSoldier->bStealthMode = FALSE; + fInterfacePanelDirty = DIRTYLEVEL2; + //DBrot: Stance change + if (gGameExternalOptions.fStandUpAfterBattle){ + if ( gAnimControl[ pTeamSoldier->usAnimState ].ubHeight != ANIM_STAND ) + { + pTeamSoldier->ChangeSoldierStance( ANIM_STAND ); + } + else + { + // If they are aiming, end aim! + usAnimState = PickSoldierReadyAnimation( pTeamSoldier, TRUE, FALSE ); - if ( usAnimState != INVALID_ANIMATION ) - { - pTeamSoldier->EVENT_InitNewSoldierAnim( usAnimState, 0, FALSE ); - } - } - } - } - } - } - } - } - } + if ( usAnimState != INVALID_ANIMATION ) + { + pTeamSoldier->EVENT_InitNewSoldierAnim( usAnimState, 0, FALSE ); + } + } + } + } + } + } + } + } + } - HandleMoraleEvent( NULL, MORALE_BATTLE_WON, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_BATTLE_WON, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + HandleMoraleEvent( NULL, MORALE_BATTLE_WON, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_BATTLE_WON, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - // Change music modes - if ( gfLastMercTalkedAboutKillingID == NOBODY || ( gfLastMercTalkedAboutKillingID != NOBODY && !( MercPtrs[ gfLastMercTalkedAboutKillingID ]->flags.uiStatusFlags & SOLDIER_MONSTER ) ) ) - { - SetMusicMode( MUSIC_TACTICAL_VICTORY ); + // Change music modes + if ( gfLastMercTalkedAboutKillingID == NOBODY || ( gfLastMercTalkedAboutKillingID != NOBODY && !( MercPtrs[ gfLastMercTalkedAboutKillingID ]->flags.uiStatusFlags & SOLDIER_MONSTER ) ) ) + { + SetMusicMode( MUSIC_TACTICAL_VICTORY ); - // OJW - 20081222 - dont auto-bandage if networked - if (!is_networked) - ShouldBeginAutoBandage( ); - } - else if ( gfLastMercTalkedAboutKillingID != NOBODY && ( MercPtrs[ gfLastMercTalkedAboutKillingID ]->flags.uiStatusFlags & SOLDIER_MONSTER ) ) - { - // OJW - 20081222 - dont auto-bandage if networked - if (!is_networked) - ShouldBeginAutoBandage( ); - } - // SANDRO - end quest if cleared the sector after interrogation (sector N7 by Meduna) - if ( gWorldSectorX == 7 && gWorldSectorY == 14 && gbWorldSectorZ == 0 && gubQuest[ QUEST_INTERROGATION ] == QUESTINPROGRESS ) - { - // Complete quest - EndQuest( QUEST_INTERROGATION, gWorldSectorX, gWorldSectorY ); - } + // OJW - 20081222 - dont auto-bandage if networked + if (!is_networked) + ShouldBeginAutoBandage( ); + } + else if ( gfLastMercTalkedAboutKillingID != NOBODY && ( MercPtrs[ gfLastMercTalkedAboutKillingID ]->flags.uiStatusFlags & SOLDIER_MONSTER ) ) + { + // OJW - 20081222 - dont auto-bandage if networked + if (!is_networked) + ShouldBeginAutoBandage( ); + } + // SANDRO - end quest if cleared the sector after interrogation (sector N7 by Meduna) + if ( gWorldSectorX == 7 && gWorldSectorY == 14 && gbWorldSectorZ == 0 && gubQuest[ QUEST_INTERROGATION ] == QUESTINPROGRESS ) + { + // Complete quest + EndQuest( QUEST_INTERROGATION, gWorldSectorX, gWorldSectorY ); + } - // Say battle end quote.... + // Say battle end quote.... - if (fAnEnemyRetreated) - { - SayQuoteFromAnyBodyInSector( QUOTE_ENEMY_RETREATED ); - } - else - { - // OK, If we have just finished a battle with creatures........ play killed creature quote... - // - if ( gfLastMercTalkedAboutKillingID != NOBODY && ( MercPtrs[ gfLastMercTalkedAboutKillingID ]->flags.uiStatusFlags & SOLDIER_MONSTER ) ) - { + if (fAnEnemyRetreated) + { + SayQuoteFromAnyBodyInSector( QUOTE_ENEMY_RETREATED ); + } + else + { + // OK, If we have just finished a battle with creatures........ play killed creature quote... + // + if ( gfLastMercTalkedAboutKillingID != NOBODY && ( MercPtrs[ gfLastMercTalkedAboutKillingID ]->flags.uiStatusFlags & SOLDIER_MONSTER ) ) + { - } - else if ( gfLastMercTalkedAboutKillingID != NOBODY && ( MercPtrs[ gfLastMercTalkedAboutKillingID ]->ubBodyType == BLOODCAT ) ) - { - SayBattleSoundFromAnyBodyInSector( BATTLE_SOUND_COOL1 ); - } - else - { - SayQuoteFromAnyBodyInSector( QUOTE_SECTOR_SAFE ); - } - } + } + else if ( gfLastMercTalkedAboutKillingID != NOBODY && ( MercPtrs[ gfLastMercTalkedAboutKillingID ]->ubBodyType == BLOODCAT ) ) + { + SayBattleSoundFromAnyBodyInSector( BATTLE_SOUND_COOL1 ); + } + else + { + SayQuoteFromAnyBodyInSector( QUOTE_SECTOR_SAFE ); + } + } - // SANDRO - reset number of enemies here - memset( &(gTacticalStatus.bNumFoughtInBattle), 0, MAXTEAMS ); - } - else - { - // Change to nothing music... - SetMusicMode( MUSIC_TACTICAL_NOTHING ); - // OJW - 20081222 - dont auto bandage if networked - if (!is_networked) - ShouldBeginAutoBandage(); - } + // SANDRO - reset number of enemies here + memset( &(gTacticalStatus.bNumFoughtInBattle), 0, MAXTEAMS ); + } + else + { + // Change to nothing music... + SetMusicMode( MUSIC_TACTICAL_NOTHING ); + // OJW - 20081222 - dont auto bandage if networked + if (!is_networked) + ShouldBeginAutoBandage(); + } - HandleMilitiaStatusInCurrentMapBeforeLoadingNewMap(); - //gfStrategicMilitiaChangesMade = TRUE; + HandleMilitiaStatusInCurrentMapBeforeLoadingNewMap(); + //gfStrategicMilitiaChangesMade = TRUE; - // Loop through all militia and restore them to peaceful status - cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++,pTeamSoldier++) - { - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) - { - pTeamSoldier->aiData.bAlertStatus = STATUS_GREEN; - CheckForChangingOrders( pTeamSoldier ); - pTeamSoldier->aiData.sNoiseGridno = NOWHERE; - pTeamSoldier->aiData.ubNoiseVolume = 0; - pTeamSoldier->aiData.bNewSituation = FALSE; - pTeamSoldier->aiData.bOrders = STATIONARY; - if ( pTeamSoldier->stats.bLife < OKLIFE ) - { - // SANDRO - the insta-healable value for doctor trait check - pTeamSoldier->iHealableInjury -= ((OKLIFE - pTeamSoldier->stats.bLife) * 100); - if (pTeamSoldier->iHealableInjury < 0) - pTeamSoldier->iHealableInjury = 0; + // Loop through all militia and restore them to peaceful status + cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++,pTeamSoldier++) + { + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) + { + pTeamSoldier->aiData.bAlertStatus = STATUS_GREEN; + CheckForChangingOrders( pTeamSoldier ); + pTeamSoldier->aiData.sNoiseGridno = NOWHERE; + pTeamSoldier->aiData.ubNoiseVolume = 0; + pTeamSoldier->aiData.bNewSituation = FALSE; + pTeamSoldier->aiData.bOrders = STATIONARY; + if ( pTeamSoldier->stats.bLife < OKLIFE ) + { + // SANDRO - the insta-healable value for doctor trait check + pTeamSoldier->iHealableInjury -= ((OKLIFE - pTeamSoldier->stats.bLife) * 100); + if (pTeamSoldier->iHealableInjury < 0) + pTeamSoldier->iHealableInjury = 0; - pTeamSoldier->bPoisonLife = min(pTeamSoldier->bPoisonSum, pTeamSoldier->bPoisonLife + OKLIFE - pTeamSoldier->stats.bLife); - pTeamSoldier->stats.bLife = OKLIFE; - } + pTeamSoldier->bPoisonLife = min(pTeamSoldier->bPoisonSum, pTeamSoldier->bPoisonLife + OKLIFE - pTeamSoldier->stats.bLife); + pTeamSoldier->stats.bLife = OKLIFE; + } - pTeamSoldier->bBleeding = 0; // let's think, the autobandage was done for the militia too - pTeamSoldier->bPoisonBleeding = 0; - } - } - gTacticalStatus.Team[ MILITIA_TEAM ].bAwareOfOpposition = FALSE; + pTeamSoldier->bBleeding = 0; // let's think, the autobandage was done for the militia too + pTeamSoldier->bPoisonBleeding = 0; + } + } + gTacticalStatus.Team[ MILITIA_TEAM ].bAwareOfOpposition = FALSE; - // Loop through all civs and restore them to peaceful status - cnt = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; cnt++,pTeamSoldier++) - { - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) - { - pTeamSoldier->aiData.bAlertStatus = STATUS_GREEN; - pTeamSoldier->aiData.sNoiseGridno = NOWHERE; - pTeamSoldier->aiData.ubNoiseVolume = 0; - pTeamSoldier->aiData.bNewSituation = FALSE; - CheckForChangingOrders( pTeamSoldier ); - } - } - gTacticalStatus.Team[ CIV_TEAM ].bAwareOfOpposition = FALSE; + // Loop through all civs and restore them to peaceful status + cnt = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; cnt++,pTeamSoldier++) + { + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) + { + pTeamSoldier->aiData.bAlertStatus = STATUS_GREEN; + pTeamSoldier->aiData.sNoiseGridno = NOWHERE; + pTeamSoldier->aiData.ubNoiseVolume = 0; + pTeamSoldier->aiData.bNewSituation = FALSE; + CheckForChangingOrders( pTeamSoldier ); + } + } + gTacticalStatus.Team[ CIV_TEAM ].bAwareOfOpposition = FALSE; - } + } - fInterfacePanelDirty = DIRTYLEVEL2; + fInterfacePanelDirty = DIRTYLEVEL2; - if ( gTacticalStatus.bBoxingState == NOT_BOXING ) // if boxing don't do any of this stuff - { - LogBattleResults( LOG_VICTORY ); + if ( gTacticalStatus.bBoxingState == NOT_BOXING ) // if boxing don't do any of this stuff + { + LogBattleResults( LOG_VICTORY ); - SetThisSectorAsPlayerControlled( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, TRUE ); - HandleVictoryInNPCSector( gWorldSectorX, gWorldSectorY,( INT16 ) gbWorldSectorZ ); - if ( CheckFact( FACT_FIRST_BATTLE_BEING_FOUGHT, 0 ) ) - { - // ATE: Need to trigger record for this event .... for NPC scripting - TriggerNPCRecord( PACOS, 18 ); + SetThisSectorAsPlayerControlled( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, TRUE ); + HandleVictoryInNPCSector( gWorldSectorX, gWorldSectorY,( INT16 ) gbWorldSectorZ ); + if ( CheckFact( FACT_FIRST_BATTLE_BEING_FOUGHT, 0 ) ) + { + // ATE: Need to trigger record for this event .... for NPC scripting + TriggerNPCRecord( PACOS, 18 ); - // this is our first battle... and we won! - SetFactTrue( FACT_FIRST_BATTLE_FOUGHT ); - SetFactTrue( FACT_FIRST_BATTLE_WON ); - SetFactFalse( FACT_FIRST_BATTLE_BEING_FOUGHT ); - SetTheFirstBattleSector( (INT16) (gWorldSectorX + gWorldSectorY * MAP_WORLD_X) ); + // this is our first battle... and we won! + SetFactTrue( FACT_FIRST_BATTLE_FOUGHT ); + SetFactTrue( FACT_FIRST_BATTLE_WON ); + SetFactFalse( FACT_FIRST_BATTLE_BEING_FOUGHT ); + SetTheFirstBattleSector( (INT16) (gWorldSectorX + gWorldSectorY * MAP_WORLD_X) ); #if (defined JA2UB) -//Ja25 no meanwhile + //Ja25 no meanwhile #else - HandleFirstBattleEndingWhileInTown( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, FALSE ); + HandleFirstBattleEndingWhileInTown( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, FALSE ); #endif - } - } + } + } - //Whenever returning TRUE, make sure you clear gfBlitBattleSectorLocator; - gfBlitBattleSectorLocator = FALSE; + //Whenever returning TRUE, make sure you clear gfBlitBattleSectorLocator; + gfBlitBattleSectorLocator = FALSE; - // Kaiden: More UB Reveal All Items after combat code. - //When all the enemy gets killed, reveal the items they dropped - //But only if the option is turned ON. - if(gGameExternalOptions.gfRevealItems) - RevealAllDroppedEnemyItems(); + // Kaiden: More UB Reveal All Items after combat code. + //When all the enemy gets killed, reveal the items they dropped + //But only if the option is turned ON. + if(gGameExternalOptions.gfRevealItems) + RevealAllDroppedEnemyItems(); - // If we are the server, we escape this function at the top if we think the game should still be running - // hence if we get here the game is over for all clients and we should report it - if (is_networked && is_server) - game_over(); - return( TRUE ); - } - // If we are the server, we escape this function at the top if we think the game should still be running - // hence if we get here the game is over for all clients and we should report it - if (is_networked && is_server) - game_over(); + // If we are the server, we escape this function at the top if we think the game should still be running + // hence if we get here the game is over for all clients and we should report it + if (is_networked && is_server) + game_over(); + return( TRUE ); + } + // If we are the server, we escape this function at the top if we think the game should still be running + // hence if we get here the game is over for all clients and we should report it + if (is_networked && is_server) + game_over(); - return( FALSE ); + return( FALSE ); } void CycleThroughKnownEnemies( ) { - // static to indicate last position we were at: - SOLDIERTYPE *pSoldier; - static BOOLEAN fFirstTime = TRUE; - static UINT16 usStartToLook; - UINT32 cnt; - BOOLEAN fEnemyBehindStartLook = FALSE; - BOOLEAN fEnemiesFound = FALSE; + // static to indicate last position we were at: + SOLDIERTYPE *pSoldier; + static BOOLEAN fFirstTime = TRUE; + static UINT16 usStartToLook; + UINT32 cnt; + BOOLEAN fEnemyBehindStartLook = FALSE; + BOOLEAN fEnemiesFound = FALSE; - if ( fFirstTime ) - { - fFirstTime = FALSE; + if ( fFirstTime ) + { + fFirstTime = FALSE; - usStartToLook = gTacticalStatus.Team[ gbPlayerNum ].bLastID; - } + usStartToLook = gTacticalStatus.Team[ gbPlayerNum ].bLastID; + } - for ( cnt = gTacticalStatus.Team[ gbPlayerNum ].bLastID, pSoldier = MercPtrs[ cnt ]; cnt < TOTAL_SOLDIERS; cnt++, pSoldier++ ) - { - // try to find first active, OK enemy - if ( pSoldier->bActive && pSoldier->bInSector && !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum) && (pSoldier->stats.bLife > 0) ) - { - if ( pSoldier->bVisible != -1 ) - { - fEnemiesFound = TRUE; + for ( cnt = gTacticalStatus.Team[ gbPlayerNum ].bLastID, pSoldier = MercPtrs[ cnt ]; cnt < TOTAL_SOLDIERS; cnt++, pSoldier++ ) + { + // try to find first active, OK enemy + if ( pSoldier->bActive && pSoldier->bInSector && !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum) && (pSoldier->stats.bLife > 0) ) + { + if ( pSoldier->bVisible != -1 ) + { + fEnemiesFound = TRUE; - // If we are > ok start, this is the one! - if ( cnt > usStartToLook ) - { - usStartToLook = (UINT16)cnt; + // If we are > ok start, this is the one! + if ( cnt > usStartToLook ) + { + usStartToLook = (UINT16)cnt; - // Locate to! - //LocateSoldier( pSoldier->ubID, 1 ); + // Locate to! + //LocateSoldier( pSoldier->ubID, 1 ); - //ATE: Change to Slide To... - SlideTo( 0, pSoldier->ubID, 0, SETANDREMOVEPREVIOUSLOCATOR ); - return; - } - else - { - fEnemyBehindStartLook = TRUE; - } - } - } - } + //ATE: Change to Slide To... + SlideTo( 0, pSoldier->ubID, 0, SETANDREMOVEPREVIOUSLOCATOR ); + return; + } + else + { + fEnemyBehindStartLook = TRUE; + } + } + } + } - if ( !fEnemiesFound ) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NO_ENEMIES_IN_SIGHT_STR ] ); - } + if ( !fEnemiesFound ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NO_ENEMIES_IN_SIGHT_STR ] ); + } - // If here, we found nobody, but there may be someone behind - // If to, recurse! - if ( fEnemyBehindStartLook ) - { - usStartToLook = gTacticalStatus.Team[ gbPlayerNum ].bLastID; + // If here, we found nobody, but there may be someone behind + // If to, recurse! + if ( fEnemyBehindStartLook ) + { + usStartToLook = gTacticalStatus.Team[ gbPlayerNum ].bLastID; - CycleThroughKnownEnemies( ); - } + CycleThroughKnownEnemies( ); + } } void CycleVisibleEnemies( SOLDIERTYPE *pSrcSoldier ) { - // static to indicate last position we were at: - SOLDIERTYPE *pSoldier; - UINT16 usStartToLook; - UINT32 cnt; + // static to indicate last position we were at: + SOLDIERTYPE *pSoldier; + UINT16 usStartToLook; + UINT32 cnt; - usStartToLook = gTacticalStatus.Team[ gbPlayerNum ].bLastID; + usStartToLook = gTacticalStatus.Team[ gbPlayerNum ].bLastID; - for ( cnt = gTacticalStatus.Team[ gbPlayerNum ].bLastID, pSoldier = MercPtrs[ cnt ]; cnt < TOTAL_SOLDIERS; cnt++, pSoldier++ ) - { - // try to find first active, OK enemy - if ( pSoldier->bActive && pSoldier->bInSector && !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum) && (pSoldier->stats.bLife > 0) ) - { - if ( pSrcSoldier->aiData.bOppList[ pSoldier->ubID ] == SEEN_CURRENTLY ) - { - // If we are > ok start, this is the one! - if ( cnt > pSrcSoldier->ubLastEnemyCycledID ) - { - pSrcSoldier->ubLastEnemyCycledID = (UINT8)cnt; + for ( cnt = gTacticalStatus.Team[ gbPlayerNum ].bLastID, pSoldier = MercPtrs[ cnt ]; cnt < TOTAL_SOLDIERS; cnt++, pSoldier++ ) + { + // try to find first active, OK enemy + if ( pSoldier->bActive && pSoldier->bInSector && !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum) && (pSoldier->stats.bLife > 0) ) + { + if ( pSrcSoldier->aiData.bOppList[ pSoldier->ubID ] == SEEN_CURRENTLY ) + { + // If we are > ok start, this is the one! + if ( cnt > pSrcSoldier->ubLastEnemyCycledID ) + { + pSrcSoldier->ubLastEnemyCycledID = (UINT8)cnt; - //ATE: Change to Slide To... - SlideTo( 0, pSoldier->ubID, 0, SETANDREMOVEPREVIOUSLOCATOR ); + //ATE: Change to Slide To... + SlideTo( 0, pSoldier->ubID, 0, SETANDREMOVEPREVIOUSLOCATOR ); - ChangeInterfaceLevel( pSoldier->pathing.bLevel ); - return; - } - } - } - } + ChangeInterfaceLevel( pSoldier->pathing.bLevel ); + return; + } + } + } + } - // If here.. reset to zero... - pSrcSoldier->ubLastEnemyCycledID = 0; + // If here.. reset to zero... + pSrcSoldier->ubLastEnemyCycledID = 0; - usStartToLook = gTacticalStatus.Team[ gbPlayerNum ].bLastID; - for ( cnt = gTacticalStatus.Team[ gbPlayerNum ].bLastID, pSoldier = MercPtrs[ cnt ]; cnt < TOTAL_SOLDIERS; cnt++, pSoldier++ ) - { - // try to find first active, OK enemy - if ( pSoldier->bActive && pSoldier->bInSector && !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum) && (pSoldier->stats.bLife > 0) ) - { - if ( pSrcSoldier->aiData.bOppList[ pSoldier->ubID ] == SEEN_CURRENTLY ) - { + usStartToLook = gTacticalStatus.Team[ gbPlayerNum ].bLastID; + for ( cnt = gTacticalStatus.Team[ gbPlayerNum ].bLastID, pSoldier = MercPtrs[ cnt ]; cnt < TOTAL_SOLDIERS; cnt++, pSoldier++ ) + { + // try to find first active, OK enemy + if ( pSoldier->bActive && pSoldier->bInSector && !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum) && (pSoldier->stats.bLife > 0) ) + { + if ( pSrcSoldier->aiData.bOppList[ pSoldier->ubID ] == SEEN_CURRENTLY ) + { - // If we are > ok start, this is the one! - if ( cnt > pSrcSoldier->ubLastEnemyCycledID ) - { - pSrcSoldier->ubLastEnemyCycledID = (UINT8)cnt; + // If we are > ok start, this is the one! + if ( cnt > pSrcSoldier->ubLastEnemyCycledID ) + { + pSrcSoldier->ubLastEnemyCycledID = (UINT8)cnt; - //ATE: Change to Slide To... - SlideTo( 0, pSoldier->ubID, 0, SETANDREMOVEPREVIOUSLOCATOR ); + //ATE: Change to Slide To... + SlideTo( 0, pSoldier->ubID, 0, SETANDREMOVEPREVIOUSLOCATOR ); - ChangeInterfaceLevel( pSoldier->pathing.bLevel ); - return; - } - } - } - } + ChangeInterfaceLevel( pSoldier->pathing.bLevel ); + return; + } + } + } + } } -UINT32 CountNonVehiclesOnPlayerTeam( void ) +UINT32 CountNonVehiclesOnPlayerTeam( ) { - UINT32 cnt; - SOLDIERTYPE *pSoldier; - UINT32 bNumber = 0; + UINT32 cnt; + SOLDIERTYPE *pSoldier; + UINT32 bNumber = 0; - for ( cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID, pSoldier = MercPtrs[ cnt ]; cnt <= (UINT32)( gTacticalStatus.Team[ gbPlayerNum ].bLastID ); cnt++, pSoldier++ ) - { - if ( pSoldier->bActive && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) - { - bNumber++; - } - } + for ( cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID, pSoldier = MercPtrs[ cnt ]; cnt <= (UINT32)( gTacticalStatus.Team[ gbPlayerNum ].bLastID ); cnt++, pSoldier++ ) + { + if ( pSoldier->bActive && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) + { + bNumber++; + } + } - return( bNumber ); + return( bNumber ); } BOOLEAN PlayerTeamFull( ) { - // last ID for the player team is 19, so long as we have at most 17 non-vehicles... - if ( CountNonVehiclesOnPlayerTeam() < gGameExternalOptions.ubGameMaximumNumberOfPlayerMercs /*gTacticalStatus.Team[ gbPlayerNum ].bLastID - 2*/ ) - { - return( FALSE ); - } + // last ID for the player team is 19, so long as we have at most 17 non-vehicles... + if ( CountNonVehiclesOnPlayerTeam() < gGameExternalOptions.ubGameMaximumNumberOfPlayerMercs /*gTacticalStatus.Team[ gbPlayerNum ].bLastID - 2*/ ) + { + return( FALSE ); + } - return( TRUE ); + return( TRUE ); } -UINT8 NumPCsInSector( void ) +UINT8 NumPCsInSector( ) { - SOLDIERTYPE *pTeamSoldier; - UINT32 cnt = 0; - UINT8 ubNumPlayers = 0; + SOLDIERTYPE *pTeamSoldier; + UINT32 cnt = 0; + UINT8 ubNumPlayers = 0; - // Check if the battle is won! - // Loop through all mercs and make go - for ( cnt = 0; cnt < guiNumMercSlots; cnt++ ) - { - if ( MercSlots[ cnt ] ) - { - pTeamSoldier = MercSlots[ cnt ]; - if ( pTeamSoldier->bTeam == gbPlayerNum && pTeamSoldier->stats.bLife > 0 ) - { - ubNumPlayers++; - } - } - } + // Check if the battle is won! + // Loop through all mercs and make go + for ( cnt = 0; cnt < guiNumMercSlots; cnt++ ) + { + if ( MercSlots[ cnt ] ) + { + pTeamSoldier = MercSlots[ cnt ]; + if ( pTeamSoldier->bTeam == gbPlayerNum && pTeamSoldier->stats.bLife > 0 ) + { + ubNumPlayers++; + } + } + } - return( ubNumPlayers ); + return( ubNumPlayers ); } UINT8 NumEnemyInSector( ) { - SOLDIERTYPE *pTeamSoldier; - INT32 cnt = 0; - UINT8 ubNumEnemies = 0; + SOLDIERTYPE *pTeamSoldier; + INT32 cnt = 0; + UINT8 ubNumEnemies = 0; - // Check if the battle is won! - // Loop through all mercs and make go - for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) - { - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 ) - { - // Checkf for any more bacguys - if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) ) - { - ubNumEnemies++; - } - } - } + // Check if the battle is won! + // Loop through all mercs and make go + for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) + { + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 ) + { + // Checkf for any more bacguys + if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) ) + { + ubNumEnemies++; + } + } + } - return( ubNumEnemies ); + return( ubNumEnemies ); } #ifdef ENABLE_ZOMBIES - UINT8 NumZombiesInSector( ) - { - SOLDIERTYPE *pTeamSoldier; - INT32 cnt = 0; - UINT8 ubNumZombies = 0; +UINT8 NumZombiesInSector( ) +{ + SOLDIERTYPE *pTeamSoldier; + INT32 cnt = 0; + UINT8 ubNumZombies = 0; - for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; ++pTeamSoldier, ++cnt ) - { - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 ) - { - if ( pTeamSoldier->IsZombie() ) - { - ++ubNumZombies; - } - } - } + for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; ++pTeamSoldier, ++cnt ) + { + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 ) + { + if ( pTeamSoldier->IsZombie() ) + { + ++ubNumZombies; + } + } + } - return( ubNumZombies ); - } + return( ubNumZombies ); +} #endif UINT8 NumEnemyInSectorExceptCreatures() { - SOLDIERTYPE *pTeamSoldier; - INT32 cnt = 0; - UINT8 ubNumEnemies = 0; + SOLDIERTYPE *pTeamSoldier; + INT32 cnt = 0; + UINT8 ubNumEnemies = 0; - // Check if the battle is won! - // Loop through all mercs and make go - for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) - { - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 && pTeamSoldier->bTeam != CREATURE_TEAM ) - { - // Checkf for any more bacguys - if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) ) - { - ubNumEnemies++; - } - } - } + // Check if the battle is won! + // Loop through all mercs and make go + for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) + { + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 && pTeamSoldier->bTeam != CREATURE_TEAM ) + { + // Checkf for any more bacguys + if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) ) + { + ubNumEnemies++; + } + } + } - return( ubNumEnemies ); + return( ubNumEnemies ); } UINT8 NumEnemyInSectorNotDeadOrDying( ) { - SOLDIERTYPE *pTeamSoldier; - INT32 cnt = 0; - UINT8 ubNumEnemies = 0; + SOLDIERTYPE *pTeamSoldier; + INT32 cnt = 0; + UINT8 ubNumEnemies = 0; - // Check if the battle is won! - // Loop through all mercs and make go - for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) - { - // Kill those not already dead.,... - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) - { - // For sure for flag thet they are dead is not set - if ( !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) - { - // Also, we want to pick up unconcious guys as NOT being capable, - // but we want to make sure we don't get those ones that are in the - // process of dying - if ( pTeamSoldier->stats.bLife >= OKLIFE ) - { - // Check for any more badguys - if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) ) - { - ubNumEnemies++; - } - } - } - } - } + // Check if the battle is won! + // Loop through all mercs and make go + for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) + { + // Kill those not already dead.,... + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) + { + // For sure for flag thet they are dead is not set + if ( !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) + { + // Also, we want to pick up unconcious guys as NOT being capable, + // but we want to make sure we don't get those ones that are in the + // process of dying + if ( pTeamSoldier->stats.bLife >= OKLIFE ) + { + // Check for any more badguys + if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) ) + { + ubNumEnemies++; + } + } + } + } + } - return( ubNumEnemies ); + return( ubNumEnemies ); } UINT8 NumBloodcatsInSectorNotDeadOrDying( ) { - SOLDIERTYPE *pTeamSoldier; - INT32 cnt = 0; - UINT8 ubNumEnemies = 0; + SOLDIERTYPE *pTeamSoldier; + INT32 cnt = 0; + UINT8 ubNumEnemies = 0; - // Check if the battle is won! - // Loop through all mercs and make go - for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) - { - // Kill those not already dead.,... - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) - { - if ( pTeamSoldier->ubBodyType == BLOODCAT ) - { - // For sure for flag thet they are dead is not set - if ( !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) - { - // Also, we want to pick up unconcious guys as NOT being capable, - // but we want to make sure we don't get those ones that are in the - // process of dying - if ( pTeamSoldier->stats.bLife >= OKLIFE ) - { - // Check for any more badguys - if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) ) - { - ubNumEnemies++; - } - } - } - } - } - } + // Check if the battle is won! + // Loop through all mercs and make go + for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) + { + // Kill those not already dead.,... + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) + { + if ( pTeamSoldier->ubBodyType == BLOODCAT ) + { + // For sure for flag thet they are dead is not set + if ( !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) + { + // Also, we want to pick up unconcious guys as NOT being capable, + // but we want to make sure we don't get those ones that are in the + // process of dying + if ( pTeamSoldier->stats.bLife >= OKLIFE ) + { + // Check for any more badguys + if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) ) + { + ubNumEnemies++; + } + } + } + } + } + } - return( ubNumEnemies ); + return( ubNumEnemies ); } UINT8 NumCapableEnemyInSector( ) { - SOLDIERTYPE *pTeamSoldier; - INT32 cnt = 0; - UINT8 ubNumEnemies = 0; + SOLDIERTYPE *pTeamSoldier; + INT32 cnt = 0; + UINT8 ubNumEnemies = 0; - // Check if the battle is won! - // Loop through all mercs and make go - for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) - { - // Kill those not already dead.,... - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) - { - // For sure for flag thet they are dead is not set - if ( !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) - { - // Also, we want to pick up unconcious guys as NOT being capable, - // but we want to make sure we don't get those ones that are in the - // process of dying - if ( pTeamSoldier->stats.bLife < OKLIFE && pTeamSoldier->stats.bLife != 0 ) - { + // Check if the battle is won! + // Loop through all mercs and make go + for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) + { + // Kill those not already dead.,... + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) + { + // For sure for flag thet they are dead is not set + if ( !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) + { + // Also, we want to pick up unconcious guys as NOT being capable, + // but we want to make sure we don't get those ones that are in the + // process of dying + if ( pTeamSoldier->stats.bLife < OKLIFE && pTeamSoldier->stats.bLife != 0 ) + { - } - else - { - // Flugente: captured soldiers also do not count - if ( pTeamSoldier->bSoldierFlagMask & SOLDIER_POW ) - continue; + } + else + { + // Flugente: captured soldiers also do not count + if ( pTeamSoldier->bSoldierFlagMask & SOLDIER_POW ) + continue; - // Check for any more badguys - if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) ) - { - ubNumEnemies++; - } - } - } - } - } + // Check for any more badguys + if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) ) + { + ubNumEnemies++; + } + } + } + } + } - return( ubNumEnemies ); + return( ubNumEnemies ); } BOOLEAN CheckForLosingEndOfBattle( ) { - SOLDIERTYPE *pTeamSoldier; - INT32 cnt = 0; - INT8 bNumDead = 0, bNumNotOK = 0, bNumInBattle = 0, bNumNotOKRealMercs = 0; - BOOLEAN fMadeCorpse; - BOOLEAN fDoCapture = FALSE; - BOOLEAN fOnlyEPCsLeft = TRUE; - BOOLEAN fMilitiaInSector = FALSE; + SOLDIERTYPE *pTeamSoldier; + INT32 cnt = 0; + INT8 bNumDead = 0, bNumNotOK = 0, bNumInBattle = 0, bNumNotOKRealMercs = 0; + BOOLEAN fMadeCorpse; + BOOLEAN fDoCapture = FALSE; + BOOLEAN fOnlyEPCsLeft = TRUE; + BOOLEAN fMilitiaInSector = FALSE; - // ATE: Check for MILITIA - we won't lose if we have some..... - cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++,pTeamSoldier++) - { - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bSide == gbPlayerNum ) - { - if ( pTeamSoldier->stats.bLife >= OKLIFE ) - { - // We have at least one poor guy who will still fight.... - // we have not lost ( yet )! - fMilitiaInSector = TRUE; - } - } - } + // ATE: Check for MILITIA - we won't lose if we have some..... + cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++,pTeamSoldier++) + { + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bSide == gbPlayerNum ) + { + if ( pTeamSoldier->stats.bLife >= OKLIFE ) + { + // We have at least one poor guy who will still fight.... + // we have not lost ( yet )! + fMilitiaInSector = TRUE; + } + } + } - // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED! - cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; + // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED! + cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; - // look for all mercs on the same team, - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++) - { - // Are we active and in sector..... - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) - { - bNumInBattle++; + // look for all mercs on the same team, + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++) + { + // Are we active and in sector..... + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) + { + bNumInBattle++; - if ( pTeamSoldier->stats.bLife == 0 ) - { - bNumDead++; - } - else if ( pTeamSoldier->stats.bLife < OKLIFE ) - { - bNumNotOK++; + if ( pTeamSoldier->stats.bLife == 0 ) + { + bNumDead++; + } + else if ( pTeamSoldier->stats.bLife < OKLIFE ) + { + bNumNotOK++; - if ( !AM_AN_EPC( pTeamSoldier ) && !AM_A_ROBOT( pTeamSoldier ) ) - { - bNumNotOKRealMercs++; - } - } - else - { - if ( !AM_A_ROBOT( pTeamSoldier ) || !AM_AN_EPC( pTeamSoldier ) ) - { - fOnlyEPCsLeft = FALSE; - } - } - } - } + if ( !AM_AN_EPC( pTeamSoldier ) && !AM_A_ROBOT( pTeamSoldier ) ) + { + bNumNotOKRealMercs++; + } + } + else + { + if ( !AM_A_ROBOT( pTeamSoldier ) || !AM_AN_EPC( pTeamSoldier ) ) + { + fOnlyEPCsLeft = FALSE; + } + } + } + } - // OK< check ALL in battle, if that matches SUM of dead, incompacitated, we're done! - if ( ( bNumDead + bNumNotOK ) == bNumInBattle || fOnlyEPCsLeft ) - { - // Are there militia in sector? - if ( fMilitiaInSector ) - { - if( guiCurrentScreen != AUTORESOLVE_SCREEN ) - { - // if here, check if we should autoresolve. - // if we have at least one guy unconscious, call below function... - if ( HandlePotentialBringUpAutoresolveToFinishBattle( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) ) - { - // return false here as we are autoresolving... - return( FALSE ); - } - } - else - { - return( FALSE ); - } - } + // OK< check ALL in battle, if that matches SUM of dead, incompacitated, we're done! + if ( ( bNumDead + bNumNotOK ) == bNumInBattle || fOnlyEPCsLeft ) + { + // Are there militia in sector? + if ( fMilitiaInSector ) + { + if( guiCurrentScreen != AUTORESOLVE_SCREEN ) + { + // if here, check if we should autoresolve. + // if we have at least one guy unconscious, call below function... + if ( HandlePotentialBringUpAutoresolveToFinishBattle( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) ) + { + // return false here as we are autoresolving... + return( FALSE ); + } + } + else + { + return( FALSE ); + } + } - // Bring up box if we have ANY guy incompaciteded..... - if ( bNumDead != bNumInBattle ) - { - // If we get captured... - // Your unconscious mercs are captured! + // Bring up box if we have ANY guy incompaciteded..... + if ( bNumDead != bNumInBattle ) + { + // If we get captured... + // Your unconscious mercs are captured! - // Check if we should get captured.... - if ( bNumNotOKRealMercs < 4 && bNumNotOKRealMercs > 1 ) - { - // Check if any enemies exist.... - if ( gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector > 0 ) - { - //if( GetWorldDay() > STARTDAY_ALLOW_PLAYER_CAPTURE_FOR_RESCUE && !( gStrategicStatus.uiFlags & STRATEGIC_PLAYER_CAPTURED_FOR_RESCUE )) - { - if ( gubQuest[ QUEST_HELD_IN_ALMA ] == QUESTNOTSTARTED || ( gubQuest[ QUEST_HELD_IN_ALMA ] == QUESTDONE && gubQuest[ QUEST_INTERROGATION ] == QUESTNOTSTARTED ) ) - { - fDoCapture = TRUE; - // CJC Dec 1 2002: fix capture sequences - BeginCaptureSquence(); - } - } - } - } + // Check if we should get captured.... + if ( bNumNotOKRealMercs < 4 && bNumNotOKRealMercs > 1 ) + { + // Check if any enemies exist.... + if ( gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector > 0 ) + { + //if( GetWorldDay() > STARTDAY_ALLOW_PLAYER_CAPTURE_FOR_RESCUE && !( gStrategicStatus.uiFlags & STRATEGIC_PLAYER_CAPTURED_FOR_RESCUE )) + { + if ( gubQuest[ QUEST_HELD_IN_ALMA ] == QUESTNOTSTARTED || ( gubQuest[ QUEST_HELD_IN_ALMA ] == QUESTDONE && gubQuest[ QUEST_INTERROGATION ] == QUESTNOTSTARTED ) ) + { + fDoCapture = TRUE; + // CJC Dec 1 2002: fix capture sequences + BeginCaptureSquence(); + } + } + } + } - gfKillingGuysForLosingBattle = TRUE; + gfKillingGuysForLosingBattle = TRUE; - // KIll them now... - // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED! - cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; + // KIll them now... + // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED! + cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++) - { - // Are we active and in sector..... - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) - { - if ( pTeamSoldier->stats.bLife != 0 && pTeamSoldier->stats.bLife < OKLIFE || AM_AN_EPC( pTeamSoldier ) || AM_A_ROBOT( pTeamSoldier ) ) - { - // Captured EPCs or ROBOTS will be kiiled in capture routine.... - if ( !fDoCapture ) - { - // Kill! - pTeamSoldier->stats.bLife = 0; + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++) + { + // Are we active and in sector..... + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) + { + if ( pTeamSoldier->stats.bLife != 0 && pTeamSoldier->stats.bLife < OKLIFE || AM_AN_EPC( pTeamSoldier ) || AM_A_ROBOT( pTeamSoldier ) ) + { + // Captured EPCs or ROBOTS will be kiiled in capture routine.... + if ( !fDoCapture ) + { + // Kill! + pTeamSoldier->stats.bLife = 0; - HandleSoldierDeath( pTeamSoldier, &fMadeCorpse ); + HandleSoldierDeath( pTeamSoldier, &fMadeCorpse ); - //HandlePlayerTeamMemberDeath( pTeamSoldier ); - // Make corpse.. - //TurnSoldierIntoCorpse( pTeamSoldier, TRUE, TRUE ); - } - } + //HandlePlayerTeamMemberDeath( pTeamSoldier ); + // Make corpse.. + //TurnSoldierIntoCorpse( pTeamSoldier, TRUE, TRUE ); + } + } - // ATE: if we are told to do capture.... - if ( pTeamSoldier->stats.bLife != 0 && fDoCapture ) - { - EnemyCapturesPlayerSoldier( pTeamSoldier ); + // ATE: if we are told to do capture.... + if ( pTeamSoldier->stats.bLife != 0 && fDoCapture ) + { + EnemyCapturesPlayerSoldier( pTeamSoldier ); - RemoveSoldierFromTacticalSector( pTeamSoldier, TRUE ); - } + RemoveSoldierFromTacticalSector( pTeamSoldier, TRUE ); + } - } - } + } + } - gfKillingGuysForLosingBattle = FALSE; + gfKillingGuysForLosingBattle = FALSE; - // WANNE - MP: Only do special scenes (capture, ...) in a single player game - if (!is_networked) - { - if ( fDoCapture ) - { - EndCaptureSequence( ); - SetCustomizableTimerCallbackAndDelay( 3000, CaptureTimerCallback, FALSE ); - } - else - { - SetCustomizableTimerCallbackAndDelay( 10000, DeathTimerCallback, FALSE ); - } - } - } - return( TRUE ); - } + // WANNE - MP: Only do special scenes (capture, ...) in a single player game + if (!is_networked) + { + if ( fDoCapture ) + { + EndCaptureSequence( ); + SetCustomizableTimerCallbackAndDelay( 3000, CaptureTimerCallback, FALSE ); + } + else + { + SetCustomizableTimerCallbackAndDelay( 10000, DeathTimerCallback, FALSE ); + } + } + } + return( TRUE ); + } - return( FALSE ); + return( FALSE ); } BOOLEAN KillIncompacitatedEnemyInSector( ) { - SOLDIERTYPE *pTeamSoldier; - INT32 cnt = 0; - BOOLEAN fReturnVal = FALSE; + SOLDIERTYPE *pTeamSoldier; + INT32 cnt = 0; + BOOLEAN fReturnVal = FALSE; - // Check if the battle is won! - // Loop through all mercs and make go - for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) - { - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife < OKLIFE && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) - { - // Checkf for any more bacguys - if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != gbPlayerNum ) ) - { - // KIll...... - // SANDRO - if the soldier is bleeding out, consider this damage as done by the last attacker - if ( pTeamSoldier->ubAttackerID != NOBODY ) - pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubAttackerID, NOWHERE, 0, TRUE ); - else if ( pTeamSoldier->ubPreviousAttackerID != NOBODY ) - pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubPreviousAttackerID, NOWHERE, 0, TRUE ); - else if ( pTeamSoldier->ubNextToPreviousAttackerID != NOBODY ) - pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubNextToPreviousAttackerID, NOWHERE, 0, TRUE ); - else - pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE ); + // Check if the battle is won! + // Loop through all mercs and make go + for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) + { + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife < OKLIFE && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) + { + // Checkf for any more bacguys + if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != gbPlayerNum ) ) + { + // KIll...... + // SANDRO - if the soldier is bleeding out, consider this damage as done by the last attacker + if ( pTeamSoldier->ubAttackerID != NOBODY ) + pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubAttackerID, NOWHERE, 0, TRUE ); + else if ( pTeamSoldier->ubPreviousAttackerID != NOBODY ) + pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubPreviousAttackerID, NOWHERE, 0, TRUE ); + else if ( pTeamSoldier->ubNextToPreviousAttackerID != NOBODY ) + pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubNextToPreviousAttackerID, NOWHERE, 0, TRUE ); + else + pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE ); - fReturnVal = TRUE; - } - } - } - return( fReturnVal ); + fReturnVal = TRUE; + } + } + } + return( fReturnVal ); } BOOLEAN AttackOnGroupWitnessed( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget ) { - UINT32 uiSlot; - SOLDIERTYPE * pGroupMember; + UINT32 uiSlot; + SOLDIERTYPE * pGroupMember; - // look for all group members... rebels could be on the civ team or ours! - for ( uiSlot = 0; uiSlot < guiNumMercSlots; uiSlot++ ) - { - pGroupMember = MercSlots[ uiSlot ]; - if (pGroupMember && (pGroupMember->ubCivilianGroup == pTarget->ubCivilianGroup) && pGroupMember != pTarget) - { - if (pGroupMember->aiData.bOppList[pSoldier->ubID] == SEEN_CURRENTLY || pGroupMember->aiData.bOppList[pTarget->ubID] == SEEN_CURRENTLY) - { - return( TRUE ); - } - if ( SpacesAway( pGroupMember->sGridNo, pSoldier->sGridNo ) < 12 || SpacesAway( pGroupMember->sGridNo, pTarget->sGridNo ) < 12 ) - { - return( TRUE ); - } - } - } + // look for all group members... rebels could be on the civ team or ours! + for ( uiSlot = 0; uiSlot < guiNumMercSlots; uiSlot++ ) + { + pGroupMember = MercSlots[ uiSlot ]; + if (pGroupMember && (pGroupMember->ubCivilianGroup == pTarget->ubCivilianGroup) && pGroupMember != pTarget) + { + if (pGroupMember->aiData.bOppList[pSoldier->ubID] == SEEN_CURRENTLY || pGroupMember->aiData.bOppList[pTarget->ubID] == SEEN_CURRENTLY) + { + return( TRUE ); + } + if ( SpacesAway( pGroupMember->sGridNo, pSoldier->sGridNo ) < 12 || SpacesAway( pGroupMember->sGridNo, pTarget->sGridNo ) < 12 ) + { + return( TRUE ); + } + } + } - return( FALSE ); + return( FALSE ); } INT8 CalcSuppressionTolerance( SOLDIERTYPE * pSoldier ) { - INT8 bTolerance; + INT8 bTolerance; - // Calculate basic tolerance value - bTolerance = pSoldier->stats.bExpLevel * 2; - if (pSoldier->flags.uiStatusFlags & SOLDIER_PC) - { - // give +1 for every 10% morale from 50, for a maximum bonus/penalty of 5. - bTolerance += ( pSoldier->aiData.bMorale - 50 ) / 10; - } - else - { - // give +2 for every morale category from normal, for a max change of 4 - bTolerance += ( pSoldier->aiData.bAIMorale - MORALE_NORMAL ) * 2; - } + // Calculate basic tolerance value + bTolerance = pSoldier->stats.bExpLevel * 2; + if (pSoldier->flags.uiStatusFlags & SOLDIER_PC) + { + // give +1 for every 10% morale from 50, for a maximum bonus/penalty of 5. + bTolerance += ( pSoldier->aiData.bMorale - 50 ) / 10; + } + else + { + // give +2 for every morale category from normal, for a max change of 4 + bTolerance += ( pSoldier->aiData.bAIMorale - MORALE_NORMAL ) * 2; + } - if ( pSoldier->ubProfile != NO_PROFILE ) - { - // SANDRO - check for character traits - if ( gGameOptions.fNewTraitSystem ) - { - if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_INTELLECTUAL ) - bTolerance += -2; - else if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_DAUNTLESS ) - bTolerance += 2; - } - else - { - // change tolerance based on attitude - switch ( gMercProfiles[ pSoldier->ubProfile ].bAttitude ) - { - case ATT_AGGRESSIVE: - bTolerance += 2; - break; - case ATT_COWARD: - bTolerance += -2; - break; - default: - break; - } - } - } - else - { - // generic NPC/civvie; change tolerance based on attitude - switch ( pSoldier->aiData.bAttitude ) - { - case BRAVESOLO: - case BRAVEAID: - bTolerance += 2; - break; - case AGGRESSIVE: - bTolerance += 1; - break; - case DEFENSIVE: - bTolerance += -1; - break; - default: - break; - } - } + if ( pSoldier->ubProfile != NO_PROFILE ) + { + // SANDRO - check for character traits + if ( gGameOptions.fNewTraitSystem ) + { + if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_INTELLECTUAL ) + bTolerance += -2; + else if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_DAUNTLESS ) + bTolerance += 2; + } + else + { + // change tolerance based on attitude + switch ( gMercProfiles[ pSoldier->ubProfile ].bAttitude ) + { + case ATT_AGGRESSIVE: + bTolerance += 2; + break; + case ATT_COWARD: + bTolerance += -2; + break; + default: + break; + } + } + } + else + { + // generic NPC/civvie; change tolerance based on attitude + switch ( pSoldier->aiData.bAttitude ) + { + case BRAVESOLO: + case BRAVEAID: + bTolerance += 2; + break; + case AGGRESSIVE: + bTolerance += 1; + break; + case DEFENSIVE: + bTolerance += -1; + break; + default: + break; + } + } - // HEADROCK HAM 3.2: This is actually a feature from HAM 2.9. It adds bonuses/penalties for nearby friends. - if (gGameExternalOptions.fFriendliesAffectTolerance) - { - bTolerance += CheckStatusNearbyFriendlies( pSoldier ); - } + // HEADROCK HAM 3.2: This is actually a feature from HAM 2.9. It adds bonuses/penalties for nearby friends. + if (gGameExternalOptions.fFriendliesAffectTolerance) + { + bTolerance += CheckStatusNearbyFriendlies( pSoldier ); + } - // HEADROCK HAM 3.3: Moving rapidly makes one less prone to suppression. - if (gGameExternalOptions.ubTilesMovedPerBonusTolerancePoint > 0) - { - bTolerance += pSoldier->bTilesMoved / gGameExternalOptions.ubTilesMovedPerBonusTolerancePoint; - } - // HEADROCK HAM 3.6: This value has moved here. It reduces tolerance if the character is massively shocked. - if (gGameExternalOptions.ubCowerEffectOnSuppression != 0) - { - if (pSoldier->aiData.bShock > bTolerance) - { - bTolerance -= gGameExternalOptions.ubCowerEffectOnSuppression; - } - } - - // SANDRO - STOMP traits - squadleader's bonus to suppression tolerance - if ( gGameOptions.fNewTraitSystem && IS_MERC_BODY_TYPE(pSoldier) && - (pSoldier->bTeam == ENEMY_TEAM || pSoldier->bTeam == MILITIA_TEAM || pSoldier->bTeam == gbPlayerNum) ) - { - UINT8 ubNumberOfSL = GetSquadleadersCountInVicinity( pSoldier, FALSE, FALSE ); - // Also take ourselves into account - if ((ubNumberOfSL < gSkillTraitValues.ubSLMaxBonuses) && HAS_SKILL_TRAIT( pSoldier, SQUADLEADER_NT )) - { - // Flugente: This seems wrong. gSkillTraitValues.ubSLMaxBonuses should be the upper, not lower bound of squadleasders... - //ubNumberOfSL = max( gSkillTraitValues.ubSLMaxBonuses, (ubNumberOfSL + NUM_SKILL_TRAITS( pSoldier, SQUADLEADER_NT )) ); - ubNumberOfSL = min( gSkillTraitValues.ubSLMaxBonuses, (ubNumberOfSL + NUM_SKILL_TRAITS( pSoldier, SQUADLEADER_NT )) ); - } - bTolerance += (bTolerance * gSkillTraitValues.ubSLOverallSuppresionBonusPercent * ubNumberOfSL / 100); - } - - bTolerance = __max(bTolerance, gGameExternalOptions.ubSuppressionToleranceMin); - bTolerance = __min(bTolerance, gGameExternalOptions.ubSuppressionToleranceMax); + // HEADROCK HAM 3.3: Moving rapidly makes one less prone to suppression. + if (gGameExternalOptions.ubTilesMovedPerBonusTolerancePoint > 0) + { + bTolerance += pSoldier->bTilesMoved / gGameExternalOptions.ubTilesMovedPerBonusTolerancePoint; + } + // HEADROCK HAM 3.6: This value has moved here. It reduces tolerance if the character is massively shocked. + if (gGameExternalOptions.ubCowerEffectOnSuppression != 0) + { + if (pSoldier->aiData.bShock > bTolerance) + { + bTolerance -= gGameExternalOptions.ubCowerEffectOnSuppression; + } + } - return( bTolerance ); + // SANDRO - STOMP traits - squadleader's bonus to suppression tolerance + if ( gGameOptions.fNewTraitSystem && IS_MERC_BODY_TYPE(pSoldier) && + (pSoldier->bTeam == ENEMY_TEAM || pSoldier->bTeam == MILITIA_TEAM || pSoldier->bTeam == gbPlayerNum) ) + { + UINT8 ubNumberOfSL = GetSquadleadersCountInVicinity( pSoldier, FALSE, FALSE ); + // Also take ourselves into account + if ((ubNumberOfSL < gSkillTraitValues.ubSLMaxBonuses) && HAS_SKILL_TRAIT( pSoldier, SQUADLEADER_NT )) + { + // Flugente: This seems wrong. gSkillTraitValues.ubSLMaxBonuses should be the upper, not lower bound of squadleasders... + //ubNumberOfSL = max( gSkillTraitValues.ubSLMaxBonuses, (ubNumberOfSL + NUM_SKILL_TRAITS( pSoldier, SQUADLEADER_NT )) ); + ubNumberOfSL = min( gSkillTraitValues.ubSLMaxBonuses, (ubNumberOfSL + NUM_SKILL_TRAITS( pSoldier, SQUADLEADER_NT )) ); + } + bTolerance += (bTolerance * gSkillTraitValues.ubSLOverallSuppresionBonusPercent * ubNumberOfSL / 100); + } + + bTolerance = __max(bTolerance, gGameExternalOptions.ubSuppressionToleranceMin); + bTolerance = __min(bTolerance, gGameExternalOptions.ubSuppressionToleranceMax); + + return( bTolerance ); } void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker ) { - /////////////////////////////////////////////////////////////////////////////// - // - // HEADROCK HAM B2: This entire function has been completely revamped. - // HEADROCK HAM 3.5: Revamped again. - // - /////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + // + // HEADROCK HAM B2: This entire function has been completely revamped. + // HEADROCK HAM 3.5: Revamped again. + // + /////////////////////////////////////////////////////////////////////////////// - // This function runs after very attack is completed. It calculates the number - // of "Suppression Points" any character has received during the attack, and - // inflicts various penalties accordingly. - // The most important result of this function is AP loss. + // This function runs after very attack is completed. It calculates the number + // of "Suppression Points" any character has received during the attack, and + // inflicts various penalties accordingly. + // The most important result of this function is AP loss. - //INT8 SUPPRESSION_AP_LIMIT = gGameExternalOptions.iMinAPLimitFromSuppression; + //INT8 SUPPRESSION_AP_LIMIT = gGameExternalOptions.iMinAPLimitFromSuppression; - INT8 bTolerance; - INT32 sClosestOpponent, sClosestOppLoc; - UINT8 ubPointsLost, ubNewStance; - UINT32 uiLoop; - UINT8 ubLoop2; - // Flag to determine if the target is cowering (if allowed) - BOOLEAN fCower; - SOLDIERTYPE * pSoldier; - // External options - - // JA2_OPTIONS.INI - INT8 MAXIMUM_SUPPRESSION_SHOCK = gGameExternalOptions.ubMaxSuppressionShock; - - // APBPConstants.INI - UINT16 usLimitSuppressionAPsLostPerAttack = APBPConstants[AP_MAX_SUPPRESSED]; - UINT16 usLimitSuppressionAPsLostPerTurn = APBPConstants[AP_MAX_TURN_SUPPRESSED]; - //HEADROCK HAM 3.5: Ratio between AP Loss and Suppression Shock - UINT16 uiShockPerAPLossDivisor = APBPConstants[AP_SUPPRESSION_SHOCK_DIVISOR]; + INT8 bTolerance; + INT32 sClosestOpponent, sClosestOppLoc; + UINT8 ubPointsLost, ubNewStance; + UINT32 uiLoop; + UINT8 ubLoop2; + // Flag to determine if the target is cowering (if allowed) + BOOLEAN fCower; + SOLDIERTYPE * pSoldier; + // External options - //////////////////////////////////////////////////////////////////////////////////////////////////// - // SANDRO - modify suppression effectiveness based on weapon caliber (i.e. damage) - INT16 sFinalSuppressionEffectiveness = gGameExternalOptions.sSuppressionEffectiveness; - pSoldier = MercPtrs[ubCausedAttacker]; - if ( Item[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].usItemClass == IC_GUN ) - { - // +1% per point above 20 impact - if ( Weapon[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].ubImpact > 20 ) - { - sFinalSuppressionEffectiveness += (Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubImpact - 20); + // JA2_OPTIONS.INI + INT8 MAXIMUM_SUPPRESSION_SHOCK = gGameExternalOptions.ubMaxSuppressionShock; - // +2% per point above 30 impact - if ( Weapon[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].ubImpact > 30 ) - { - sFinalSuppressionEffectiveness += (Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubImpact - 30); + // APBPConstants.INI + UINT16 usLimitSuppressionAPsLostPerAttack = APBPConstants[AP_MAX_SUPPRESSED]; + UINT16 usLimitSuppressionAPsLostPerTurn = APBPConstants[AP_MAX_TURN_SUPPRESSED]; + //HEADROCK HAM 3.5: Ratio between AP Loss and Suppression Shock + UINT16 uiShockPerAPLossDivisor = APBPConstants[AP_SUPPRESSION_SHOCK_DIVISOR]; - // +3% per point above 40 impact - if ( Weapon[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].ubImpact > 40 ) - { - sFinalSuppressionEffectiveness += (Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubImpact - 40); + //////////////////////////////////////////////////////////////////////////////////////////////////// + // SANDRO - modify suppression effectiveness based on weapon caliber (i.e. damage) + INT16 sFinalSuppressionEffectiveness = gGameExternalOptions.sSuppressionEffectiveness; + pSoldier = MercPtrs[ubCausedAttacker]; + if ( Item[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].usItemClass == IC_GUN ) + { + // +1% per point above 20 impact + if ( Weapon[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].ubImpact > 20 ) + { + sFinalSuppressionEffectiveness += (Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubImpact - 20); - // +4% per point above 50 impact, some crazy gun here - if ( Weapon[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].ubImpact > 50 ) - { - sFinalSuppressionEffectiveness += (Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubImpact - 50); - } - } - } - } + // +2% per point above 30 impact + if ( Weapon[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].ubImpact > 30 ) + { + sFinalSuppressionEffectiveness += (Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubImpact - 30); - // add a small bonus to effectiveness based on weapon loudness - UINT8 ubGunVolume = Weapon[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].ubAttackVolume; - ubGunVolume = __max( 1, ( ubGunVolume * GetPercentNoiseVolume( pSoldier->GetUsedWeapon( &pSoldier->inv[pSoldier->ubAttackingHand] ) ) ) / 100 ); - if ( ubGunVolume >= 50 ) - { - if ( ubGunVolume < 70 ) // up to 5% - sFinalSuppressionEffectiveness += ((ubGunVolume - 50)/4); - else if ( ubGunVolume < 85 ) // 5% to 10% - sFinalSuppressionEffectiveness += (5 + (ubGunVolume - 70)/3); - else // 10% to 25% (extremely noisy weaponry) - sFinalSuppressionEffectiveness += (10 + (ubGunVolume - 85)); - } - } - //////////////////////////////////////////////////////////////////////////////////////////////////// + // +3% per point above 40 impact + if ( Weapon[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].ubImpact > 40 ) + { + sFinalSuppressionEffectiveness += (Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubImpact - 40); - // Loop through every character. - for (uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++) - { - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: loop = %d, numslots = %d ",uiLoop, guiNumMercSlots)); - pSoldier = MercSlots[uiLoop]; + // +4% per point above 50 impact, some crazy gun here + if ( Weapon[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].ubImpact > 50 ) + { + sFinalSuppressionEffectiveness += (Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubImpact - 50); + } + } + } + } + + // add a small bonus to effectiveness based on weapon loudness + UINT8 ubGunVolume = Weapon[ pSoldier->inv[pSoldier->ubAttackingHand].usItem ].ubAttackVolume; + ubGunVolume = __max( 1, ( ubGunVolume * GetPercentNoiseVolume( pSoldier->GetUsedWeapon( &pSoldier->inv[pSoldier->ubAttackingHand] ) ) ) / 100 ); + if ( ubGunVolume >= 50 ) + { + if ( ubGunVolume < 70 ) // up to 5% + sFinalSuppressionEffectiveness += ((ubGunVolume - 50)/4); + else if ( ubGunVolume < 85 ) // 5% to 10% + sFinalSuppressionEffectiveness += (5 + (ubGunVolume - 70)/3); + else // 10% to 25% (extremely noisy weaponry) + sFinalSuppressionEffectiveness += (10 + (ubGunVolume - 85)); + } + } + //////////////////////////////////////////////////////////////////////////////////////////////////// + + // Loop through every character. + for (uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++) + { + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: loop = %d, numslots = %d ",uiLoop, guiNumMercSlots)); + pSoldier = MercSlots[uiLoop]; #ifdef ENABLE_ZOMBIES - // Flugente: zombies do not receive any suppression at all! - if ( pSoldier != NULL && pSoldier->IsZombie() ) - continue; + // Flugente: zombies do not receive any suppression at all! + if ( pSoldier != NULL && pSoldier->IsZombie() ) + continue; #endif - // Has this character received any Suppression Points since the last attack? - // HEADROCK: Suppression Points accumulate by bullets flying near the character. It includes - // friendly fire at a certain distance. As of HAM 3.2, it also happens with nearby explosions. - // The number of points accumulated resets to 0 at the end of this function. - - if (pSoldier && IS_MERC_BODY_TYPE( pSoldier) && pSoldier->stats.bLife >= OKLIFE && pSoldier->ubSuppressionPoints > 0) - { - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: soldier id = %d, life = %d, suppression points = %d",pSoldier->ubID,pSoldier->stats.bLife, pSoldier->ubSuppressionPoints)); - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: calc suppression tolerance")); + // Has this character received any Suppression Points since the last attack? + // HEADROCK: Suppression Points accumulate by bullets flying near the character. It includes + // friendly fire at a certain distance. As of HAM 3.2, it also happens with nearby explosions. + // The number of points accumulated resets to 0 at the end of this function. - // Calculate the character's tolerance to suppression. Helps reduce the severity of the penalties inflicted - // during this function. - bTolerance = CalcSuppressionTolerance( pSoldier ); + if (pSoldier && IS_MERC_BODY_TYPE( pSoldier) && pSoldier->stats.bLife >= OKLIFE && pSoldier->ubSuppressionPoints > 0) + { + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: soldier id = %d, life = %d, suppression points = %d",pSoldier->ubID,pSoldier->stats.bLife, pSoldier->ubSuppressionPoints)); + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: calc suppression tolerance")); - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: figure out aps lost")); + // Calculate the character's tolerance to suppression. Helps reduce the severity of the penalties inflicted + // during this function. + bTolerance = CalcSuppressionTolerance( pSoldier ); - // This formula gives a linear increase in AP loss relative to Suppression Points. The most Suppression - // Points we have, the most APs we're going to lose. Tolerance mitigates this by making the graph angle - // more shallow. - // The relation between AP Loss and Suppression Points is LINEAR. - ubPointsLost = ( ( (pSoldier->ubSuppressionPoints * APBPConstants[AP_SUPPRESSION_MOD]) / (bTolerance + 6) ) * 2 + 1 ) / 2; + // This formula gives a linear increase in AP loss relative to Suppression Points. The most Suppression + // Points we have, the most APs we're going to lose. Tolerance mitigates this by making the graph angle + // more shallow. + // The relation between AP Loss and Suppression Points is LINEAR. + ubPointsLost = ( ( (pSoldier->ubSuppressionPoints * APBPConstants[AP_SUPPRESSION_MOD]) / (bTolerance + 6) ) * 2 + 1 ) / 2; - // Flugente: added ini options for suppression effectiveness for player team and everybody else - if ( pSoldier->bTeam == gbPlayerNum ) - sFinalSuppressionEffectiveness = sFinalSuppressionEffectiveness * gGameExternalOptions.usSuppressionEffectivenessPlayer / 100; - else - sFinalSuppressionEffectiveness = sFinalSuppressionEffectiveness * gGameExternalOptions.usSuppressionEffectivenessAI / 100; - - // INI-Controlled intensity. SuppressionEffectiveness acts as a percentage applied to the number of lost APs. - // To turn off the entire Suppression system, simply set the INI value to 0. (0% AP Loss) - // The default is obviously 100%. You can increase or decrease it, at will. - // PLEASE NOTE that AP loss governs ALL OTHER SUPPRESSION EFFECTS. - ubPointsLost = ( ubPointsLost * sFinalSuppressionEffectiveness ) / 100; + // Flugente: added ini options for suppression effectiveness for player team and everybody else + if ( pSoldier->bTeam == gbPlayerNum ) + sFinalSuppressionEffectiveness = sFinalSuppressionEffectiveness * gGameExternalOptions.usSuppressionEffectivenessPlayer / 100; + else + sFinalSuppressionEffectiveness = sFinalSuppressionEffectiveness * gGameExternalOptions.usSuppressionEffectivenessAI / 100; - // This is an upper cap for the number of APs we can lose per attack. - if (usLimitSuppressionAPsLostPerAttack > 0) - { - if (ubPointsLost > usLimitSuppressionAPsLostPerAttack) - { - // Flugente: eh.. wouldn't this _always_ be 255? I suspect this should be __min - //ubPointsLost = __max(255,(UINT8)usLimitSuppressionAPsLostPerAttack); - ubPointsLost = __min(255,(UINT8)usLimitSuppressionAPsLostPerAttack); - } - } + // INI-Controlled intensity. SuppressionEffectiveness acts as a percentage applied to the number of lost APs. + // To turn off the entire Suppression system, simply set the INI value to 0. (0% AP Loss) + // The default is obviously 100%. You can increase or decrease it, at will. + // PLEASE NOTE that AP loss governs ALL OTHER SUPPRESSION EFFECTS. + ubPointsLost = ( ubPointsLost * sFinalSuppressionEffectiveness ) / 100; + // This is an upper cap for the number of APs we can lose per attack. + if (usLimitSuppressionAPsLostPerAttack > 0) + { + if (ubPointsLost > usLimitSuppressionAPsLostPerAttack) + { + // Flugente: eh.. wouldn't this _always_ be 255? I suspect this should be __min + //ubPointsLost = __max(255,(UINT8)usLimitSuppressionAPsLostPerAttack); + ubPointsLost = __min(255,(UINT8)usLimitSuppressionAPsLostPerAttack); + } + } - // This makes sure that we never lose more APs than we're allowed per turn. - if (usLimitSuppressionAPsLostPerTurn > 0) - { - // Flugente: apply a bit of safety here (beware of underflow) - if (pSoldier->ubAPsLostToSuppression + ubPointsLost > usLimitSuppressionAPsLostPerTurn) - { - ubPointsLost = __max(0, usLimitSuppressionAPsLostPerTurn - pSoldier->ubAPsLostToSuppression); - } - } + // INI-Controlled intensity. SuppressionEffectiveness acts as a percentage applied to the number of lost APs. + // To turn off the entire Suppression system, simply set the INI value to 0. (0% AP Loss) + // The default is obviously 100%. You can increase or decrease it, at will. + // PLEASE NOTE that AP loss governs ALL OTHER SUPPRESSION EFFECTS. + ubPointsLost = ( ubPointsLost * sFinalSuppressionEffectiveness ) / 100; - // This nifty little bit gives suppression an "extra kick". Soldiers affected by suppression (I.E. lost APs) - // will also suffer from SHOCK. As shock accumulates, the soldier becomes less accurate and may find it - // difficult to perform certain manual tasks. Additionally, he also becomes harder to hit, because the fear - // causes him to hide as best as he can from incoming fire. - // Shock is sliced in half at the start of every turn. Also note that shock may cause "cowering" (see below). - if (gGameExternalOptions.usSuppressionShockEffect > 0) - { - // Can't get shock if we haven't lost APs. - if (ubPointsLost > 0) - { - INT8 bShockValue, bShockLimit; - // Limit defined by INI. - bShockLimit = MAXIMUM_SUPPRESSION_SHOCK; - // The amount of shock received depends on how many APs we've lost - Every AP lost will cause one - // point of shock. This is then divided by 4 if using the 100AP system. - if (uiShockPerAPLossDivisor == 0) // SANDRO - check if we are not going to divide by zero - uiShockPerAPLossDivisor = 4; // set to default value in this case - bShockValue = ubPointsLost / uiShockPerAPLossDivisor; + // This is an upper cap for the number of APs we can lose per attack. + if (usLimitSuppressionAPsLostPerAttack > 0) + { + if (ubPointsLost > usLimitSuppressionAPsLostPerAttack) + { + // Flugente: eh.. woudln't this _always_ be 255? I suspect this should be __min + //ubPointsLost = __max(255,(UINT8)usLimitSuppressionAPsLostPerAttack); + ubPointsLost = __min(255,(UINT8)usLimitSuppressionAPsLostPerAttack); + } + } - bShockValue = __max(0,bShockValue); - bShockLimit = __max(0,bShockLimit); + // This makes sure that we never lose more APs than we're allowed per turn. + if (usLimitSuppressionAPsLostPerTurn > 0) + { + // Flugente: apply a bit of safety here (beware of underflow) + if (pSoldier->ubAPsLostToSuppression + ubPointsLost > usLimitSuppressionAPsLostPerTurn) + { + ubPointsLost = __max(0, usLimitSuppressionAPsLostPerTurn - pSoldier->ubAPsLostToSuppression); + } + } - // use external value to determine how effective SHOCK really is. - bShockValue = (bShockValue * gGameExternalOptions.usSuppressionShockEffect) / 100; + // This nifty little bit gives suppression an "extra kick". Soldiers affected by suppression (I.E. lost APs) + // will also suffer from SHOCK. As shock accumulates, the soldier becomes less accurate and may find it + // difficult to perform certain manual tasks. Additionally, he also becomes harder to hit, because the fear + // causes him to hide as best as he can from incoming fire. + // Shock is sliced in half at the start of every turn. Also note that shock may cause "cowering" (see below). + if (gGameExternalOptions.usSuppressionShockEffect > 0) + { + // Can't get shock if we haven't lost APs. + if (ubPointsLost > 0) + { + INT8 bShockValue, bShockLimit; + // Limit defined by INI. + bShockLimit = MAXIMUM_SUPPRESSION_SHOCK; + // The amount of shock received depends on how many APs we've lost - Every AP lost will cause one + // point of shock. This is then divided by 4 if using the 100AP system. + if (uiShockPerAPLossDivisor == 0) // SANDRO - check if we are not going to divide by zero + uiShockPerAPLossDivisor = 4; // set to default value in this case + bShockValue = ubPointsLost / uiShockPerAPLossDivisor; - // Make sure total shock doesn't go TOO high. Maximum is around 30, including previous shock - // from suppression and/or wounds. It is possible to breach the maximum after a good suppressive - // attack. + bShockValue = __max(0,bShockValue); + bShockLimit = __max(0,bShockLimit); - if ( pSoldier->aiData.bShock + bShockValue <= bShockLimit ) - { - // Shock limit not yet breached. Add shock to character. - pSoldier->aiData.bShock = __min(127, pSoldier->aiData.bShock + bShockValue); - } - else if ( pSoldier->aiData.bShock < bShockLimit ) // Shock limit will be breached. - { - // Original shock was lower than the limit, so add extra shock and breach the limit. - pSoldier->aiData.bShock = __min(127, pSoldier->aiData.bShock + bShockValue); - } - // Else, original shock was already over the limit. No more shock is added. - } - // HEADROCK: Cowering is the panic that grips a character due to suffering too much suppression shock. If - // enough shock has been accumulated, the soldier goes into this panic. Generally, cowering will cause - // the character to drop a stance if he can, overriding other conditions for a stance-change (see below). - // Cowering characters may become considerably easier to suppress with additional firepower. In other - // words, if you're cowering, you've effectively turned from a bad-ass to a wimp. + // use external value to determine how effective SHOCK really is. + bShockValue = (bShockValue * gGameExternalOptions.usSuppressionShockEffect) / 100; - fCower = false; - // SANDRO - STOMP traits - INT8 bShockForCower = pSoldier->aiData.bShock; - if ( gGameOptions.fNewTraitSystem ) - { - // Squadleader's resistance to cowering - if ( HAS_SKILL_TRAIT( pSoldier, SQUADLEADER_NT )) - { - bShockForCower = (INT8)((bShockForCower * (100 - gSkillTraitValues.ubSLFearResistance * NUM_SKILL_TRAITS( pSoldier, SQUADLEADER_NT )) /100) + 0.5); - } - // Check for character traits - if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_INTELLECTUAL ) - { - bShockForCower = (INT8)((bShockForCower * 23 / 20 ) + 0.5); // +15% as shock - } - else if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_DAUNTLESS ) - { - bShockForCower = (INT8)((bShockForCower * 17 / 20 ) + 0.5); // -15% as shock - } - } - if (bShockForCower >= bTolerance) - { - fCower = true; + // Make sure total shock doesn't go TOO high. Maximum is around 30, including previous shock + // from suppression and/or wounds. It is possible to breach the maximum after a good suppressive + // attack. - // If soldier is visible on-screen, report to player that they are cowering. - if ( pSoldier->bVisible != -1 ) - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113HAMMessage[0], pSoldier->GetName() ); - } - } + if ( pSoldier->aiData.bShock + bShockValue <= bShockLimit ) + { + // Shock limit not yet breached. Add shock to character. + pSoldier->aiData.bShock = __min(127, pSoldier->aiData.bShock + bShockValue); + } + else if ( pSoldier->aiData.bShock < bShockLimit ) // Shock limit will be breached. + { + // Original shock was lower than the limit, so add extra shock and breach the limit. + pSoldier->aiData.bShock = __min(127, pSoldier->aiData.bShock + bShockValue); + } + // Else, original shock was already over the limit. No more shock is added. + } + // HEADROCK: Cowering is the panic that grips a character due to suffering too much suppression shock. If + // enough shock has been accumulated, the soldier goes into this panic. Generally, cowering will cause + // the character to drop a stance if he can, overriding other conditions for a stance-change (see below). + // Cowering characters may become considerably easier to suppress with additional firepower. In other + // words, if you're cowering, you've effectively turned from a bad-ass to a wimp. - // Suppression reduces morale. For every X APs lost, morale goes down by a point. X is defined by INI. - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for morale effects")); - if (APBPConstants[AP_LOST_PER_MORALE_DROP] > 0 && ubPointsLost > 0) - { - for ( ubLoop2 = 0; ubLoop2 < (ubPointsLost / APBPConstants[AP_LOST_PER_MORALE_DROP]); ubLoop2++ ) - { - HandleMoraleEvent( pSoldier, MORALE_SUPPRESSED, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); - } - } - + fCower = false; + // SANDRO - STOMP traits + INT8 bShockForCower = pSoldier->aiData.bShock; + if ( gGameOptions.fNewTraitSystem ) + { + // Squadleader's resistance to cowering + if ( HAS_SKILL_TRAIT( pSoldier, SQUADLEADER_NT )) + { + bShockForCower = (INT8)((bShockForCower * (100 - gSkillTraitValues.ubSLFearResistance * NUM_SKILL_TRAITS( pSoldier, SQUADLEADER_NT )) /100) + 0.5); + } + // Check for character traits + if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_INTELLECTUAL ) + { + bShockForCower = (INT8)((bShockForCower * 23 / 20 ) + 0.5); // +15% as shock + } + else if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_DAUNTLESS ) + { + bShockForCower = (INT8)((bShockForCower * 17 / 20 ) + 0.5); // -15% as shock + } + } + if (bShockForCower >= bTolerance) + { + fCower = true; - ubNewStance = 0; + // If soldier is visible on-screen, report to player that they are cowering. + if ( pSoldier->bVisible != -1 ) + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113HAMMessage[0], pSoldier->GetName() ); + } + } - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for reaction")); - - // HEADROCK HAM 3.5: Characters who have enough APs to drop WILL DROP. This is strictly for survival reasons, - // because upright characters can easily get themselves killed. Soldiers drop stance for "free", using up - // the APs that they've just lost to do so. - - switch (gAnimControl[ pSoldier->usAnimState ].ubEndHeight) - { - case ANIM_PRONE: - // can't change stance below prone! - // SANDRO - added cower animation when prone (made by Pashancock) - if ( fCower ) - { - if ( pSoldier->usAnimState == COWERING_PRONE ) // if cowering alread, do nothing - { - ubNewStance = 0; - } - else - { - pSoldier->EVENT_InitNewSoldierAnim( START_COWER_PRONE, 0 , FALSE ); - ubNewStance = 0; - } - } - break; - case ANIM_CROUCH: - if (ubPointsLost >= GetAPsProne(pSoldier, TRUE) && IsValidStance( pSoldier, ANIM_PRONE ) ) - { - sClosestOpponent = ClosestKnownOpponent( pSoldier, &sClosestOppLoc, NULL ); - // HEADROCK: Added cowering. - if (TileIsOutOfBounds(sClosestOpponent) || SpacesAway( pSoldier->sGridNo, sClosestOppLoc ) > 8 || fCower) - { - if ( fCower ) - { - // SANDRO - added cowering animation - //if ( Random(4) == 0 ) - //{ - // pSoldier->usPendingAnimation = START_COWER_PRONE; - // pSoldier->ubDesiredHeight = ANIM_PRONE; - // pSoldier->EVENT_InitNewSoldierAnim( PRONE_DOWN, 0 , FALSE ); - // ubNewStance = 0; - //} - //else - if ( pSoldier->usAnimState == COWERING ) // if cowering alread, do nothing - { - ubNewStance = 0; - } - else - { - pSoldier->EVENT_InitNewSoldierAnim( START_COWER_CROUCHED, 0 , FALSE ); - ubNewStance = 0; - } - } - else - { - ubPointsLost -= GetAPsProne(pSoldier, TRUE); - ubNewStance = ANIM_PRONE; - } - } - } - break; - default: // standing! - if ( pSoldier->MercInWater()) - { - // can't change stance here! - break; - } - else if (ubPointsLost >= (GetAPsCrouch(pSoldier, TRUE) + GetAPsProne(pSoldier, TRUE)) && IsValidStance( pSoldier, ANIM_PRONE ) ) - { - sClosestOpponent = ClosestKnownOpponent( pSoldier, &sClosestOppLoc, NULL ); - // HEADROCK: Added cowering. - if (TileIsOutOfBounds(sClosestOpponent) || SpacesAway( pSoldier->sGridNo, sClosestOppLoc ) > 8 || fCower ) - { - if ( fCower ) - { - // SANDRO - added cowering animation - DeductPoints( pSoldier, GetAPsCrouch(pSoldier, TRUE), APBPConstants[BP_CROUCH], DISABLED_INTERRUPT ); - pSoldier->EVENT_InitNewSoldierAnim( START_COWER, 0 , FALSE ); - ubNewStance = 0; - } - else - { - // can only crouch for now - ubPointsLost -= GetAPsCrouch(pSoldier, TRUE); - ubNewStance = ANIM_CROUCH; - } - } - else if ( IsValidStance( pSoldier, ANIM_CROUCH ) ) - { - // crouch! - ubPointsLost -= GetAPsCrouch(pSoldier, TRUE); - ubNewStance = ANIM_CROUCH; - } - } - else if ( ubPointsLost >= GetAPsCrouch(pSoldier, TRUE) && ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_CROUCH ) && IsValidStance( pSoldier, ANIM_CROUCH ) ) - { - if ( fCower ) - { - DeductPoints( pSoldier, GetAPsCrouch(pSoldier, TRUE), APBPConstants[BP_CROUCH], DISABLED_INTERRUPT ); - pSoldier->EVENT_InitNewSoldierAnim( START_COWER, 0 , FALSE ); - ubNewStance = 0; - } - else - { - // crouch! - ubPointsLost -= GetAPsCrouch(pSoldier, TRUE); - ubNewStance = ANIM_CROUCH; - } - } - break; - } + // Suppression reduces morale. For every X APs lost, morale goes down by a point. X is defined by INI. + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for morale effects")); + if (APBPConstants[AP_LOST_PER_MORALE_DROP] > 0 && ubPointsLost > 0) + { + for ( ubLoop2 = 0; ubLoop2 < (ubPointsLost / APBPConstants[AP_LOST_PER_MORALE_DROP]); ubLoop2++ ) + { + HandleMoraleEvent( pSoldier, MORALE_SUPPRESSED, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); + } + } - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: reduce action points")); + ubNewStance = 0; - // HEADROCK HAM 3.1: If this setting is enabled, it will show an on-screen message that tells us the - // character has lost his entire next turn. This only fires once per turn, the moment a character drops - // to the minimum AP limit. + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for reaction")); - if (gGameExternalOptions.fShowSuppressionShutdown) - { - // If we're about the hit the lower limit - if (pSoldier->bActionPoints > APBPConstants[AP_MIN_LIMIT] && pSoldier->bActionPoints - ubPointsLost <= APBPConstants[AP_MIN_LIMIT]) - { - // And soldier is visible - if ( pSoldier->bVisible != -1 ) - { - // "Soldier is pinned down!" - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113HAMMessage[1], pSoldier->GetName() ); - // HEADROCK HAM 3.2: Added a radio locator! - ShowRadioLocator( (UINT8)pSoldier->ubID, SHOW_LOCATOR_NORMAL ); - } - } - } + // HEADROCK HAM 3.5: Characters who have enough APs to drop WILL DROP. This is strictly for survival reasons, + // because upright characters can easily get themselves killed. Soldiers drop stance for "free", using up + // the APs that they've just lost to do so. - // Reduce action points! - // HEADROCK HAM Beta 2.2: Enforce a minimum limit via INI. - if (pSoldier->bActionPoints - ubPointsLost <= APBPConstants[AP_MIN_LIMIT] ) - { - pSoldier->bActionPoints = APBPConstants[AP_MIN_LIMIT]; - } - else - { - pSoldier->bActionPoints -= ubPointsLost; - } - // Remember how many APs were lost. This prevents us from losing more and more APs without receiving - // extra suppression. Note that a specific HAM setting will reset this value after every attack, - // but also resets ubSuppressionPoints. - pSoldier->ubAPsLostToSuppression = __min(255, pSoldier->ubAPsLostToSuppression + ubPointsLost); + switch (gAnimControl[ pSoldier->usAnimState ].ubEndHeight) + { + case ANIM_PRONE: + // can't change stance below prone! + // SANDRO - added cower animation when prone (made by Pashancock) + if ( fCower ) + { + if ( pSoldier->usAnimState == COWERING_PRONE ) // if cowering alread, do nothing + { + ubNewStance = 0; + } + else + { + pSoldier->EVENT_InitNewSoldierAnim( START_COWER_PRONE, 0 , FALSE ); + ubNewStance = 0; + } + } + break; + case ANIM_CROUCH: + if (ubPointsLost >= GetAPsProne(pSoldier, TRUE) && IsValidStance( pSoldier, ANIM_PRONE ) ) + { + sClosestOpponent = ClosestKnownOpponent( pSoldier, &sClosestOppLoc, NULL ); + // HEADROCK: Added cowering. + if (TileIsOutOfBounds(sClosestOpponent) || SpacesAway( pSoldier->sGridNo, sClosestOppLoc ) > 8 || fCower) + { + if ( fCower ) + { + // SANDRO - added cowering animation + //if ( Random(4) == 0 ) + //{ + // pSoldier->usPendingAnimation = START_COWER_PRONE; + // pSoldier->ubDesiredHeight = ANIM_PRONE; + // pSoldier->EVENT_InitNewSoldierAnim( PRONE_DOWN, 0 , FALSE ); + // ubNewStance = 0; + //} + //else + if ( pSoldier->usAnimState == COWERING ) // if cowering alread, do nothing + { + ubNewStance = 0; + } + else + { + pSoldier->EVENT_InitNewSoldierAnim( START_COWER_CROUCHED, 0 , FALSE ); + ubNewStance = 0; + } + } + else + { + ubPointsLost -= GetAPsProne(pSoldier, TRUE); + ubNewStance = ANIM_PRONE; + } + } + } + break; + default: // standing! + if ( pSoldier->MercInWater()) + { + // can't change stance here! + break; + } + else if (ubPointsLost >= (GetAPsCrouch(pSoldier, TRUE) + GetAPsProne(pSoldier, TRUE)) && IsValidStance( pSoldier, ANIM_PRONE ) ) + { + sClosestOpponent = ClosestKnownOpponent( pSoldier, &sClosestOppLoc, NULL ); + // HEADROCK: Added cowering. + if (TileIsOutOfBounds(sClosestOpponent) || SpacesAway( pSoldier->sGridNo, sClosestOppLoc ) > 8 || fCower ) + { + if ( fCower ) + { + // SANDRO - added cowering animation + DeductPoints( pSoldier, GetAPsCrouch(pSoldier, TRUE), APBPConstants[BP_CROUCH], DISABLED_INTERRUPT ); + pSoldier->EVENT_InitNewSoldierAnim( START_COWER, 0 , FALSE ); + ubNewStance = 0; + } + else + { + // can only crouch for now + ubPointsLost -= GetAPsCrouch(pSoldier, TRUE); + ubNewStance = ANIM_CROUCH; + } + } + else if ( IsValidStance( pSoldier, ANIM_CROUCH ) ) + { + // crouch! + ubPointsLost -= GetAPsCrouch(pSoldier, TRUE); + ubNewStance = ANIM_CROUCH; + } + } + else if ( ubPointsLost >= GetAPsCrouch(pSoldier, TRUE) && ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_CROUCH ) && IsValidStance( pSoldier, ANIM_CROUCH ) ) + { + if ( fCower ) + { + DeductPoints( pSoldier, GetAPsCrouch(pSoldier, TRUE), APBPConstants[BP_CROUCH], DISABLED_INTERRUPT ); + pSoldier->EVENT_InitNewSoldierAnim( START_COWER, 0 , FALSE ); + ubNewStance = 0; + } + else + { + // crouch! + ubPointsLost -= GetAPsCrouch(pSoldier, TRUE); + ubNewStance = ANIM_CROUCH; + } + } + break; + } - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for quote")); - if ( (pSoldier->flags.uiStatusFlags & SOLDIER_PC) && (pSoldier->ubSuppressionPoints > 8) && (pSoldier->ubID == ubTargetedMerc) ) - { - if ( !(pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_BEING_PUMMELED ) ) - { - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: say quote")); - pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_BEING_PUMMELED; - // say we're under heavy fire! - // ATE: For some reason, we forgot #53! - if ( pSoldier->ubProfile != 53 ) - { - TacticalCharacterDialogue( pSoldier, QUOTE_UNDER_HEAVY_FIRE ); - } - } - } + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: reduce action points")); - if ( ubNewStance != 0 ) - { - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: setup change stance")); - // This person is going to change stance + // HEADROCK HAM 3.1: If this setting is enabled, it will show an on-screen message that tells us the + // character has lost his entire next turn. This only fires once per turn, the moment a character drops + // to the minimum AP limit. - // This person will be busy while they crouch or go prone - if ((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Starting suppression, on %d", pSoldier->ubID ) ); - DebugAttackBusy( String("!!!!!!! Starting suppression, on %d\n", pSoldier->ubID ) ); - //gTacticalStatus.ubAttackBusyCount++; + if (gGameExternalOptions.fShowSuppressionShutdown) + { + // If we're about the hit the lower limit + if (pSoldier->bActionPoints > APBPConstants[AP_MIN_LIMIT] && pSoldier->bActionPoints - ubPointsLost <= APBPConstants[AP_MIN_LIMIT]) + { + // And soldier is visible + if ( pSoldier->bVisible != -1 ) + { + // "Soldier is pinned down!" + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113HAMMessage[1], pSoldier->GetName() ); + // HEADROCK HAM 3.2: Added a radio locator! + ShowRadioLocator( (UINT8)pSoldier->ubID, SHOW_LOCATOR_NORMAL ); + } + } + } - // make sure supressor ID is the same! - pSoldier->ubSuppressorID = ubCausedAttacker; - } + // Reduce action points! + // HEADROCK HAM Beta 2.2: Enforce a minimum limit via INI. + if (pSoldier->bActionPoints - ubPointsLost <= APBPConstants[AP_MIN_LIMIT] ) + { + pSoldier->bActionPoints = APBPConstants[AP_MIN_LIMIT]; + } + else + { + pSoldier->bActionPoints -= ubPointsLost; + } + // Remember how many APs were lost. This prevents us from losing more and more APs without receiving + // extra suppression. Note that a specific HAM setting will reset this value after every attack, + // but also resets ubSuppressionPoints. + pSoldier->ubAPsLostToSuppression = __min(255, pSoldier->ubAPsLostToSuppression + ubPointsLost); - // AI people will have to have their actions cancelled - if (!(pSoldier->flags.uiStatusFlags & SOLDIER_PC)) - { - CancelAIAction( pSoldier, TRUE ); + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for quote")); + if ( (pSoldier->flags.uiStatusFlags & SOLDIER_PC) && (pSoldier->ubSuppressionPoints > 8) && (pSoldier->ubID == ubTargetedMerc) ) + { + if ( !(pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_BEING_PUMMELED ) ) + { + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: say quote")); + pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_BEING_PUMMELED; + // say we're under heavy fire! + + // ATE: For some reason, we forgot #53! + if ( pSoldier->ubProfile != 53 ) + { + TacticalCharacterDialogue( pSoldier, QUOTE_UNDER_HEAVY_FIRE ); + } + } + } + + if ( ubNewStance != 0 ) + { + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: setup change stance")); + // This person is going to change stance + + // This person will be busy while they crouch or go prone + if ((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Starting suppression, on %d", pSoldier->ubID ) ); + DebugAttackBusy( String("!!!!!!! Starting suppression, on %d\n", pSoldier->ubID ) ); + //gTacticalStatus.ubAttackBusyCount++; + + // make sure supressor ID is the same! + pSoldier->ubSuppressorID = ubCausedAttacker; + } + + // AI people will have to have their actions cancelled + if (!(pSoldier->flags.uiStatusFlags & SOLDIER_PC)) + { + CancelAIAction( pSoldier, TRUE ); #if 0 - pSoldier->aiData.bAction = AI_ACTION_CHANGE_STANCE; - pSoldier->aiData.usActionData = ubNewStance; - pSoldier->aiData.bActionInProgress = TRUE; + pSoldier->aiData.bAction = AI_ACTION_CHANGE_STANCE; + pSoldier->aiData.usActionData = ubNewStance; + pSoldier->aiData.bActionInProgress = TRUE; #endif - } + } - // go for it! - // ATE: Cancel any PENDING ANIMATIONS... - pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; - // ATE: Turn off non-interrupt flag ( this NEEDS to be done! ) - pSoldier->flags.fInNonintAnim = FALSE; - pSoldier->flags.fRTInNonintAnim = FALSE; - gTacticalStatus.ubAttackBusyCount++; - DebugAttackBusy( String( "Attack busy %d due to suppression fire on %d\n", gTacticalStatus.ubAttackBusyCount, pSoldier->ubID )); + // go for it! + // ATE: Cancel any PENDING ANIMATIONS... + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + // ATE: Turn off non-interrupt flag ( this NEEDS to be done! ) + pSoldier->flags.fInNonintAnim = FALSE; + pSoldier->flags.fRTInNonintAnim = FALSE; + gTacticalStatus.ubAttackBusyCount++; + DebugAttackBusy( String( "Attack busy %d due to suppression fire on %d\n", gTacticalStatus.ubAttackBusyCount, pSoldier->ubID )); - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: change stance")); - pSoldier->ChangeSoldierStance( ubNewStance ); + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: change stance")); + pSoldier->ChangeSoldierStance( ubNewStance ); - pSoldier->flags.fChangingStanceDueToSuppression = TRUE; - pSoldier->flags.fDontChargeAPsForStanceChange = TRUE; - } + pSoldier->flags.fChangingStanceDueToSuppression = TRUE; + pSoldier->flags.fDontChargeAPsForStanceChange = TRUE; + } - // HEADROCK HAM 3.5: After sufficient testing, suppression clearing now works immediately at the end of - // the attack. ubAPsLostToSuppression is only cleared at the end of the turn, but no longer plays a role - // in affecting the number of APs lost, so it is largely irrelevant now. + // HEADROCK HAM 3.5: After sufficient testing, suppression clearing now works immediately at the end of + // the attack. ubAPsLostToSuppression is only cleared at the end of the turn, but no longer plays a role + // in affecting the number of APs lost, so it is largely irrelevant now. - pSoldier->ubSuppressionPoints = 0; + pSoldier->ubSuppressionPoints = 0; - } // end of examining one soldier - } // end of loop + } // end of examining one soldier + } // end of loop - DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire done")); + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire done")); } BOOLEAN ProcessImplicationsOfPCAttack( SOLDIERTYPE * pSoldier, SOLDIERTYPE ** ppTarget, INT8 bReason ) { - INT16 sTargetXPos, sTargetYPos; - BOOLEAN fEnterCombat = TRUE; - SOLDIERTYPE * pTarget = *ppTarget; + INT16 sTargetXPos, sTargetYPos; + BOOLEAN fEnterCombat = TRUE; + SOLDIERTYPE * pTarget = *ppTarget; - if ( pTarget->aiData.fAIFlags & AI_ASLEEP ) - { - // waaaaaaaaaaaaake up! - pTarget->aiData.fAIFlags &= (~AI_ASLEEP); - } + if ( pTarget->aiData.fAIFlags & AI_ASLEEP ) + { + // waaaaaaaaaaaaake up! + pTarget->aiData.fAIFlags &= (~AI_ASLEEP); + } - if (pTarget->ubProfile == PABLO && CheckFact( FACT_PLAYER_FOUND_ITEMS_MISSING, 0 ) ) - { - SetFactTrue( FACT_PABLO_PUNISHED_BY_PLAYER ); - } + if (pTarget->ubProfile == PABLO && CheckFact( FACT_PLAYER_FOUND_ITEMS_MISSING, 0 ) ) + { + SetFactTrue( FACT_PABLO_PUNISHED_BY_PLAYER ); + } - if ( gTacticalStatus.bBoxingState == BOXING ) - { - // should have a check for "in boxing ring", no? - if ( ( pSoldier->usAttackingWeapon != NOTHING && !Item[pSoldier->usAttackingWeapon].brassknuckles ) || !( pSoldier->flags.uiStatusFlags & SOLDIER_BOXER ) ) - { - // someone's cheating! - if ( (Item[ pSoldier->usAttackingWeapon ].usItemClass == IC_BLADE || Item[ pSoldier->usAttackingWeapon ].usItemClass == IC_PUNCH) && (pTarget->flags.uiStatusFlags & SOLDIER_BOXER) ) - { - // knife or brass knuckles disqualify the player! - BoxingPlayerDisqualified( pSoldier, BAD_ATTACK ); - } - else - { - // anything else is open war! - //gTacticalStatus.bBoxingState = NOT_BOXING; - SetBoxingState( NOT_BOXING ); - // if we are attacking a boxer we should set them to neutral (temporarily) so that the rest of the civgroup code works... - if ( (pTarget->bTeam == CIV_TEAM) && (pTarget->flags.uiStatusFlags & SOLDIER_BOXER) ) - { - SetSoldierNeutral( pTarget ); - } - } + if ( gTacticalStatus.bBoxingState == BOXING ) + { + // should have a check for "in boxing ring", no? + if ( ( pSoldier->usAttackingWeapon != NOTHING && !Item[pSoldier->usAttackingWeapon].brassknuckles ) || !( pSoldier->flags.uiStatusFlags & SOLDIER_BOXER ) ) + { + // someone's cheating! + if ( (Item[ pSoldier->usAttackingWeapon ].usItemClass == IC_BLADE || Item[ pSoldier->usAttackingWeapon ].usItemClass == IC_PUNCH) && (pTarget->flags.uiStatusFlags & SOLDIER_BOXER) ) + { + // knife or brass knuckles disqualify the player! + BoxingPlayerDisqualified( pSoldier, BAD_ATTACK ); + } + else + { + // anything else is open war! + //gTacticalStatus.bBoxingState = NOT_BOXING; + SetBoxingState( NOT_BOXING ); + // if we are attacking a boxer we should set them to neutral (temporarily) so that the rest of the civgroup code works... + if ( (pTarget->bTeam == CIV_TEAM) && (pTarget->flags.uiStatusFlags & SOLDIER_BOXER) ) + { + SetSoldierNeutral( pTarget ); + } + } - } - } + } + } - // silversurfer: if militia was attacked and not already hostile make them hostile towards the player - // but only IF the player was the attacker! - if ( (pTarget->bTeam == MILITIA_TEAM) && (pSoldier->bTeam == OUR_TEAM) ) - { - // HEADROCK HAM 3.6: INI setting controls their response - { - if (pTarget->flags.fIntendedTarget // Must be intentional - && gGameExternalOptions.ubCanMilitiaBecomeHostile == 2 // INI setting - && pTarget->bSide == gbPlayerNum // Must not be hostile by now - ) - { - // rebel militia attacked by the player! - MilitiaChangesSides(); - } - } - } - // JA2 Gold: fix Slay - else if ( (pTarget->bTeam == CIV_TEAM && pTarget->aiData.bNeutral) && pTarget->ubProfile == SLAY && pTarget->stats.bLife >= OKLIFE && CheckFact( 155, 0 ) == FALSE ) - { - TriggerNPCRecord( SLAY, 1 ); - } - else if ( (pTarget->bTeam == CIV_TEAM) && (pTarget->ubCivilianGroup == 0) && (pTarget->aiData.bNeutral) && !( pTarget->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) - { - if ( pTarget->ubBodyType == COW && gWorldSectorX == 10 && gWorldSectorY == MAP_ROW_F ) - { - // hicks could get mad!!! - HickCowAttacked( pSoldier, pTarget ); - } - else if (pTarget->ubProfile == PABLO && pTarget->stats.bLife >= OKLIFE && CheckFact( FACT_PABLO_PUNISHED_BY_PLAYER, 0 ) && !CheckFact( 38, 0 ) ) - { - TriggerNPCRecord( PABLO, 3 ); - // Nailed Pablo. So reset the fact that he stole from the last shipment since he's supposed to be returning - // the goods now. - SetFactFalse( FACT_PABLOS_STOLE_FROM_LATEST_SHIPMENT); - SetFactFalse( FACT_PLAYER_FOUND_ITEMS_MISSING); - } - else - { - // regular civ attacked, turn non-neutral - AddToShouldBecomeHostileOrSayQuoteList( pTarget->ubID ); + // silversurfer: if militia was attacked and not already hostile make them hostile towards the player + // but only IF the player was the attacker! + if ( (pTarget->bTeam == MILITIA_TEAM) && (pSoldier->bTeam == OUR_TEAM) ) + { + // HEADROCK HAM 3.6: INI setting controls their response + { + if (pTarget->flags.fIntendedTarget // Must be intentional + && gGameExternalOptions.ubCanMilitiaBecomeHostile == 2 // INI setting + && pTarget->bSide == gbPlayerNum // Must not be hostile by now + ) + { + // rebel militia attacked by the player! + MilitiaChangesSides(); + } + } + } + // JA2 Gold: fix Slay + else if ( (pTarget->bTeam == CIV_TEAM && pTarget->aiData.bNeutral) && pTarget->ubProfile == SLAY && pTarget->stats.bLife >= OKLIFE && CheckFact( 155, 0 ) == FALSE ) + { + TriggerNPCRecord( SLAY, 1 ); + } + else if ( (pTarget->bTeam == CIV_TEAM) && (pTarget->ubCivilianGroup == 0) && (pTarget->aiData.bNeutral) && !( pTarget->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) + { + if ( pTarget->ubBodyType == COW && gWorldSectorX == 10 && gWorldSectorY == MAP_ROW_F ) + { + // hicks could get mad!!! + HickCowAttacked( pSoldier, pTarget ); + } + else if (pTarget->ubProfile == PABLO && pTarget->stats.bLife >= OKLIFE && CheckFact( FACT_PABLO_PUNISHED_BY_PLAYER, 0 ) && !CheckFact( 38, 0 ) ) + { + TriggerNPCRecord( PABLO, 3 ); + // Nailed Pablo. So reset the fact that he stole from the last shipment since he's supposed to be returning + // the goods now. + SetFactFalse( FACT_PABLOS_STOLE_FROM_LATEST_SHIPMENT); + SetFactFalse( FACT_PLAYER_FOUND_ITEMS_MISSING); + } + else + { + // regular civ attacked, turn non-neutral + AddToShouldBecomeHostileOrSayQuoteList( pTarget->ubID ); + + if ( pTarget->ubProfile == NO_PROFILE || !(gMercProfiles[ pTarget->ubProfile ].ubMiscFlags3 & PROFILE_MISC_FLAG3_TOWN_DOESNT_CARE_ABOUT_DEATH) ) + { + //Kaiden: Added to keep Militia from going Hostile if you attack a Crow or Cow with an explosive. + if ( (pTarget->ubBodyType != CROW) && (pTarget->ubBodyType != COW) ) + // militia, if any, turn hostile + MilitiaChangesSides(); + } + } + } + // Flugente: if we attack prisoners, the local support might wane, as we turned out to be cruel oppressors, not liberators + else if ( (pTarget->bTeam == CIV_TEAM) && (pTarget->ubCivilianGroup == POW_PRISON_CIV_GROUP) ) + { + HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_PRISONERS_TORTURED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + } + else if (pTarget->bTeam == CREATURE_TEAM && pTarget->ubBodyType == BLOODCAT && pTarget->aiData.bNeutral) + { + // Attacked a bloodcat. + MakeBloodcatsHostile(); + // Are bloodcats in this sector affiliated with a faction? + if ( gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][0].PlacementType == BLOODCAT_PLACEMENT_STATIC && + gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation > NON_CIV_GROUP ) + { + // Temporarily change bloodcat's civilian group + UINT8 ubFaction = pTarget->ubCivilianGroup; + pTarget->ubCivilianGroup = gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation; + // Make entire faction hostile + CivilianGroupMembersChangeSidesWithinProximity( pTarget ); + // Change back + pTarget->ubCivilianGroup = ubFaction; + } + } + else + { - if ( pTarget->ubProfile == NO_PROFILE || !(gMercProfiles[ pTarget->ubProfile ].ubMiscFlags3 & PROFILE_MISC_FLAG3_TOWN_DOESNT_CARE_ABOUT_DEATH) ) - { - //Kaiden: Added to keep Militia from going Hostile if you attack a Crow or Cow with an explosive. - if ( (pTarget->ubBodyType != CROW) && (pTarget->ubBodyType != COW) ) - // militia, if any, turn hostile - MilitiaChangesSides(); - } - } - } - // Flugente: if we attack prisoners, the local support might wane, as we turned out to be cruel oppressors, not liberators - else if ( (pTarget->bTeam == CIV_TEAM) && (pTarget->ubCivilianGroup == POW_PRISON_CIV_GROUP) ) - { - HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_PRISONERS_TORTURED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); - } - else if (pTarget->bTeam == CREATURE_TEAM && pTarget->ubBodyType == BLOODCAT && pTarget->aiData.bNeutral) - { - // Attacked a bloodcat. - MakeBloodcatsHostile(); - // Are bloodcats in this sector affiliated with a faction? - if ( gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][0].PlacementType == BLOODCAT_PLACEMENT_STATIC && - gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation > NON_CIV_GROUP ) - { - // Temporarily change bloodcat's civilian group - UINT8 ubFaction = pTarget->ubCivilianGroup; - pTarget->ubCivilianGroup = gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation; - // Make entire faction hostile - CivilianGroupMembersChangeSidesWithinProximity( pTarget ); - // Change back - pTarget->ubCivilianGroup = ubFaction; - } - } - else - { - #ifdef JA2UB -//Ja25: No carmen + //Ja25: No carmen #else - if (pTarget->ubProfile == CARMEN)// Carmen - { - // Special stuff for Carmen the bounty hunter - if (pSoldier->ubProfile != SLAY) // attacked by someone other than Slay - { - // change attitude - pTarget->aiData.bAttitude = AGGRESSIVE; - } - } + if (pTarget->ubProfile == CARMEN)// Carmen + { + // Special stuff for Carmen the bounty hunter + if (pSoldier->ubProfile != SLAY) // attacked by someone other than Slay + { + // change attitude + pTarget->aiData.bAttitude = AGGRESSIVE; + } + } #endif - if ( pTarget->ubCivilianGroup && ( (pTarget->bTeam == gbPlayerNum) || pTarget->aiData.bNeutral ) ) - { + if ( pTarget->ubCivilianGroup && ( (pTarget->bTeam == gbPlayerNum) || pTarget->aiData.bNeutral ) ) + { #ifdef JA2TESTVERSION - if (pTarget->flags.uiStatusFlags & SOLDIER_PC) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"%s is changing teams", pTarget->GetName() ); - } + if (pTarget->flags.uiStatusFlags & SOLDIER_PC) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"%s is changing teams", pTarget->GetName() ); + } #endif - // member of a civ group, either recruited or neutral, so should - // change sides individually or all together + // member of a civ group, either recruited or neutral, so should + // change sides individually or all together - CivilianGroupMemberChangesSides( pTarget ); + CivilianGroupMemberChangesSides( pTarget ); - if (pTarget->ubProfile != NO_PROFILE && pTarget->stats.bLife >= OKLIFE && pTarget->bVisible == TRUE) - { - // trigger quote! - PauseAITemporarily(); - AddToShouldBecomeHostileOrSayQuoteList( pTarget->ubID ); - //TriggerNPCWithIHateYouQuote( pTarget->ubProfile ); - } - } - else if ( pTarget->ubCivilianGroup != NON_CIV_GROUP && !( pTarget->flags.uiStatusFlags & SOLDIER_BOXER ) ) - { - // Firing at a civ in a civ group who isn't hostile... if anyone in that civ group can see this - // going on they should become hostile. - CivilianGroupMembersChangeSidesWithinProximity( pTarget ); + if (pTarget->ubProfile != NO_PROFILE && pTarget->stats.bLife >= OKLIFE && pTarget->bVisible == TRUE) + { + // trigger quote! + PauseAITemporarily(); + AddToShouldBecomeHostileOrSayQuoteList( pTarget->ubID ); + //TriggerNPCWithIHateYouQuote( pTarget->ubProfile ); + } + } + else if ( pTarget->ubCivilianGroup != NON_CIV_GROUP && !( pTarget->flags.uiStatusFlags & SOLDIER_BOXER ) ) + { + // Firing at a civ in a civ group who isn't hostile... if anyone in that civ group can see this + // going on they should become hostile. + CivilianGroupMembersChangeSidesWithinProximity( pTarget ); - // HEADROCK HAM 3.6: If there are bloodcats affiliated with his group... - if ( gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][0].PlacementType == BLOODCAT_PLACEMENT_STATIC && - gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation == pTarget->ubCivilianGroup ) - { - // Make them hostile. - MakeBloodcatsHostile(); - } - } - else if ( pTarget->bTeam == gbPlayerNum && !(gTacticalStatus.uiFlags & INCOMBAT) ) - { - // firing at one of our own guys who is not a rebel etc - if ( pTarget->stats.bLife >= OKLIFE && !(pTarget->bCollapsed) && !AM_A_ROBOT( pTarget ) && (bReason == REASON_NORMAL_ATTACK ) ) - { - // OK, sturn towards the prick - // Change to fire ready animation - ConvertGridNoToXY( pSoldier->sGridNo, &sTargetXPos, &sTargetYPos ); + // HEADROCK HAM 3.6: If there are bloodcats affiliated with his group... + if ( gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][0].PlacementType == BLOODCAT_PLACEMENT_STATIC && + gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation == pTarget->ubCivilianGroup ) + { + // Make them hostile. + MakeBloodcatsHostile(); + } + } + else if ( pTarget->bTeam == gbPlayerNum && !(gTacticalStatus.uiFlags & INCOMBAT) ) + { + // firing at one of our own guys who is not a rebel etc + if ( pTarget->stats.bLife >= OKLIFE && !(pTarget->bCollapsed) && !AM_A_ROBOT( pTarget ) && (bReason == REASON_NORMAL_ATTACK ) ) + { + // OK, sturn towards the prick + // Change to fire ready animation + ConvertGridNoToXY( pSoldier->sGridNo, &sTargetXPos, &sTargetYPos ); - pTarget->flags.fDontChargeReadyAPs = TRUE; - // Ready weapon - pTarget->SoldierReadyWeapon( sTargetXPos, sTargetYPos, FALSE, AIDecideHipOrShoulderStance( pTarget, pSoldier->sGridNo ) ); + pTarget->flags.fDontChargeReadyAPs = TRUE; + // Ready weapon + pTarget->SoldierReadyWeapon( sTargetXPos, sTargetYPos, FALSE, AIDecideHipOrShoulderStance( pTarget, pSoldier->sGridNo ) ); - // ATE: Depending on personality, fire back..... + // ATE: Depending on personality, fire back..... - // Do we have a gun in a\hand? - if ( Item[ pTarget->inv[ HANDPOS ].usItem ].usItemClass == IC_GUN ) - { - // Toggle burst capable... - if ( !pTarget->bDoBurst ) - { - // Changed by ADB, 1513 - //if ( IsGunBurstCapable( pTarget, HANDPOS , FALSE ) ) - if ( IsGunBurstCapable( &pTarget->inv[HANDPOS], FALSE, pTarget ) ) - { - ChangeWeaponMode( pTarget ); - } - } + // Do we have a gun in a\hand? + if ( Item[ pTarget->inv[ HANDPOS ].usItem ].usItemClass == IC_GUN ) + { + // Toggle burst capable... + if ( !pTarget->bDoBurst ) + { + // Changed by ADB, 1513 + //if ( IsGunBurstCapable( pTarget, HANDPOS , FALSE ) ) + if ( IsGunBurstCapable( &pTarget->inv[HANDPOS], FALSE, pTarget ) ) + { + ChangeWeaponMode( pTarget ); + } + } - // Fire back! - HandleItem( pTarget, pSoldier->sGridNo, pSoldier->pathing.bLevel, pTarget->inv[ HANDPOS ].usItem, FALSE ); + // Fire back! + HandleItem( pTarget, pSoldier->sGridNo, pSoldier->pathing.bLevel, pTarget->inv[ HANDPOS ].usItem, FALSE ); - } + } - } + } - // don't enter combat on attack on one of our own mercs - fEnterCombat = FALSE; - } + // don't enter combat on attack on one of our own mercs + fEnterCombat = FALSE; + } - // if we've attacked a miner - if ( IsProfileAHeadMiner( pTarget->ubProfile ) ) - { - PlayerAttackedHeadMiner( pTarget->ubProfile ); - } - } + // if we've attacked a miner + if ( IsProfileAHeadMiner( pTarget->ubProfile ) ) + { + PlayerAttackedHeadMiner( pTarget->ubProfile ); + } + } - *ppTarget = pTarget; - return( fEnterCombat ); + *ppTarget = pTarget; + return( fEnterCombat ); } SOLDIERTYPE *InternalReduceAttackBusyCount( ) { - // Strange as this may seem, this function returns a pointer to - // the *target* in case the target has changed sides as a result - // of being attacked - SOLDIERTYPE * pSoldier; - SOLDIERTYPE * pTarget; - BOOLEAN fEnterCombat = FALSE; - UINT32 cnt; - UINT8 ubID; + // Strange as this may seem, this function returns a pointer to + // the *target* in case the target has changed sides as a result + // of being attacked + SOLDIERTYPE * pSoldier; + SOLDIERTYPE * pTarget; + BOOLEAN fEnterCombat = FALSE; + UINT32 cnt; + UINT8 ubID; #if 0 -// 0verhaul: None of this is necessary anymore with the new attack busy system - if (ubID == NOBODY) - { - pSoldier = NULL; - pTarget = NULL; - } - else - { - pSoldier = MercPtrs[ ubID ]; - if ( ubTargetID != NOBODY) - { - pTarget = MercPtrs[ ubTargetID ]; - } - else - { - pTarget = NULL; - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String(">>Target ptr is null!" ) ); - } - } + // 0verhaul: None of this is necessary anymore with the new attack busy system + if (ubID == NOBODY) + { + pSoldier = NULL; + pTarget = NULL; + } + else + { + pSoldier = MercPtrs[ ubID ]; + if ( ubTargetID != NOBODY) + { + pTarget = MercPtrs[ ubTargetID ]; + } + else + { + pTarget = NULL; + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String(">>Target ptr is null!" ) ); + } + } - if (fCalledByAttacker) - { - if (pSoldier && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_GUN) - { - if (pSoldier->bBulletsLeft > 0) - { - return( pTarget ); - } - } - } + if (fCalledByAttacker) + { + if (pSoldier && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_GUN) + { + if (pSoldier->bBulletsLeft > 0) + { + return( pTarget ); + } + } + } #endif -// if ((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) -// { + // if ((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) + // { - if ( gTacticalStatus.ubAttackBusyCount == 0 ) - { - // ATE: We have a problem here... if testversion, report error...... - // But for all means.... DON'T wrap! - if ( (gTacticalStatus.uiFlags & INCOMBAT) ) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! &&&&&&& Problem with attacker busy count decrementing past 0.... preventing wrap-around." ) ); + if ( gTacticalStatus.ubAttackBusyCount == 0 ) + { + // ATE: We have a problem here... if testversion, report error...... + // But for all means.... DON'T wrap! + if ( (gTacticalStatus.uiFlags & INCOMBAT) ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! &&&&&&& Problem with attacker busy count decrementing past 0.... preventing wrap-around." ) ); #ifdef JA2BETAVERSION - if(!is_networked)ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Attack busy problem. Save, exit and send debug.txt + save file to Sir-Tech." ); - DebugAttackBusy( "Attack Busy Problem\n"); - //cheap hack to suppress message in MP - hayden. + if(!is_networked)ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Attack busy problem. Save, exit and send debug.txt + save file to Sir-Tech." ); + DebugAttackBusy( "Attack Busy Problem\n"); + //cheap hack to suppress message in MP - hayden. #endif - } - } - else - { - gTacticalStatus.ubAttackBusyCount--; - } + } + } + else + { + gTacticalStatus.ubAttackBusyCount--; + } - DebugAttackBusy( String( "New attack busy %d\n", gTacticalStatus.ubAttackBusyCount)); + DebugAttackBusy( String( "New attack busy %d\n", gTacticalStatus.ubAttackBusyCount)); - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Ending attack, attack count now %d", gTacticalStatus.ubAttackBusyCount) ); - // } + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Ending attack, attack count now %d", gTacticalStatus.ubAttackBusyCount) ); + // } - if (gTacticalStatus.ubAttackBusyCount > 0) - { - return( NULL ); - } + if (gTacticalStatus.ubAttackBusyCount > 0) + { + return( NULL ); + } - // I'm going to go out on limb here and decide that from this point on we really care about the current soldier who - // started this chain of events. So we'll grab that one instead of relying on the correct one passed in. - // This should help with collapses and other 'attacks' with - // no attackers that happened due to actions from other soldiers or turns, shots against dead bodies, etc. + // I'm going to go out on limb here and decide that from this point on we really care about the current soldier who + // started this chain of events. So we'll grab that one instead of relying on the correct one passed in. + // This should help with collapses and other 'attacks' with + // no attackers that happened due to actions from other soldiers or turns, shots against dead bodies, etc. - pSoldier = NULL; + pSoldier = NULL; - if (gTacticalStatus.ubCurrentTeam == gbPlayerNum) - { - pSoldier = MercPtrs[ gusSelectedSoldier ]; - } - else - { - for (cnt = gTacticalStatus.Team[ gTacticalStatus.ubCurrentTeam ].bFirstID; - cnt <= gTacticalStatus.Team[ gTacticalStatus.ubCurrentTeam ].bLastID; - cnt++) - { - if (MercPtrs[ cnt ] && - MercPtrs[ cnt ]->flags.uiStatusFlags & SOLDIER_UNDERAICONTROL) - { - pSoldier = MercPtrs[ cnt ]; - break; - } - } - } - // If we still haven't figured out who last acted, it could be that the team number changed during the attack. Unfortunately this - // can happen during a switch from real-time. For now we will assume the last actor was a PC, but a real "Who started this?" pointer - // would work quite well. If only I could close all the holes that the UI opens so that one routine could handle everything. - if (!pSoldier) - { - if (is_networked) - { - if(gusSelectedSoldier==156) - return( NULL ); - } + if (gTacticalStatus.ubCurrentTeam == gbPlayerNum) + { + pSoldier = MercPtrs[ gusSelectedSoldier ]; + } + else + { + for (cnt = gTacticalStatus.Team[ gTacticalStatus.ubCurrentTeam ].bFirstID; + cnt <= gTacticalStatus.Team[ gTacticalStatus.ubCurrentTeam ].bLastID; + cnt++) + { + if (MercPtrs[ cnt ] && + MercPtrs[ cnt ]->flags.uiStatusFlags & SOLDIER_UNDERAICONTROL) + { + pSoldier = MercPtrs[ cnt ]; + break; + } + } + } + // If we still haven't figured out who last acted, it could be that the team number changed during the attack. Unfortunately this + // can happen during a switch from real-time. For now we will assume the last actor was a PC, but a real "Who started this?" pointer + // would work quite well. If only I could close all the holes that the UI opens so that one routine could handle everything. + if (!pSoldier) + { + if (is_networked) + { + if(gusSelectedSoldier==156) + return( NULL ); + } - pSoldier = MercPtrs[ gusSelectedSoldier ]; - } + pSoldier = MercPtrs[ gusSelectedSoldier ]; + } - if (!pSoldier) - return (NULL); + if (!pSoldier) + return (NULL); - //if(!pSoldier && AreInMeanwhile())//dnl fix for preventing game crash in meanwhile after Queen slap Elliot - // return(NULL); + //if(!pSoldier && AreInMeanwhile())//dnl fix for preventing game crash in meanwhile after Queen slap Elliot + // return(NULL); - //if (!pSoldier) + //if (!pSoldier) - ubID = pSoldier->ubID; + ubID = pSoldier->ubID; - DebugAttackBusy( String( "Ending action for %d\n", ubID ) ); - // Get the intended target info - pTarget = NULL; - if (pSoldier->ubTargetID != NOBODY) - { - pTarget = MercPtrs[ pSoldier->ubTargetID ]; - } + DebugAttackBusy( String( "Ending action for %d\n", ubID ) ); + // Get the intended target info + pTarget = NULL; + if (pSoldier->ubTargetID != NOBODY) + { + pTarget = MercPtrs[ pSoldier->ubTargetID ]; + } - if ((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) - { + if ((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) + { - // Check to see if anyone was suppressed - if (pTarget) - { - HandleSuppressionFire( pTarget->ubID, ubID ); - } - else - { - HandleSuppressionFire( NOBODY, ubID ); - } + // Check to see if anyone was suppressed + if (pTarget) + { + HandleSuppressionFire( pTarget->ubID, ubID ); + } + else + { + HandleSuppressionFire( NOBODY, ubID ); + } - //HandleAfterShootingGuy( pSoldier, pTarget ); + //HandleAfterShootingGuy( pSoldier, pTarget ); - // suppression fire might cause the count to be increased, so check it again - if (gTacticalStatus.ubAttackBusyCount > 0) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Starting suppression, attack count now %d", gTacticalStatus.ubAttackBusyCount) ); - return( NULL ); - } - } + // suppression fire might cause the count to be increased, so check it again + if (gTacticalStatus.ubAttackBusyCount > 0) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Starting suppression, attack count now %d", gTacticalStatus.ubAttackBusyCount) ); + return( NULL ); + } + } #ifdef JA2UB -//Ja25 no queen + //Ja25 no queen #else - // ATE: IN MEANWHILES, we have 'combat' in realtime.... - // this is so we DON'T call freeupattacker() which will cancel - // the AI guy's meanwhile NPC stuff. - // OK< let's NOT do this if it was the queen attacking.... - if ( AreInMeanwhile( ) && pSoldier != NULL && pSoldier->ubProfile != QUEEN ) - { - return( NULL ); - } + // ATE: IN MEANWHILES, we have 'combat' in realtime.... + // this is so we DON'T call freeupattacker() which will cancel + // the AI guy's meanwhile NPC stuff. + // OK< let's NOT do this if it was the queen attacking.... + if ( AreInMeanwhile( ) && pSoldier != NULL && pSoldier->ubProfile != QUEEN ) + { + return( NULL ); + } #endif #if 0 -// 0verhaul: This is moved to the end loop where everybody's state is reset for the next action - if (pTarget) - { - // reset # of shotgun pellets hit by - pTarget->bNumPelletsHitBy = 0; - // reset flag for making "ow" sound on being shot - } + // 0verhaul: This is moved to the end loop where everybody's state is reset for the next action + if (pTarget) + { + // reset # of shotgun pellets hit by + pTarget->bNumPelletsHitBy = 0; + // reset flag for making "ow" sound on being shot + } #endif - if (pSoldier) - { - // reset attacking hand - pSoldier->ubAttackingHand = HANDPOS; + if (pSoldier) + { + // reset attacking hand + pSoldier->ubAttackingHand = HANDPOS; - // if there is a valid target, and our attack was noticed - if ( pTarget && (pSoldier->flags.uiStatusFlags & SOLDIER_ATTACK_NOTICED) ) - { - // stuff that only applies to when we attack - if ( pTarget->ubBodyType != CROW ) - { - if ( pSoldier->bTeam == gbPlayerNum ) - { - fEnterCombat = ProcessImplicationsOfPCAttack( pSoldier, &pTarget, REASON_NORMAL_ATTACK ); - if ( !fEnterCombat ) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, ">>Not entering combat as a result of PC attack" ); - } - } - } + // if there is a valid target, and our attack was noticed + if ( pTarget && (pSoldier->flags.uiStatusFlags & SOLDIER_ATTACK_NOTICED) ) + { + // stuff that only applies to when we attack + if ( pTarget->ubBodyType != CROW ) + { + if ( pSoldier->bTeam == gbPlayerNum ) + { + fEnterCombat = ProcessImplicationsOfPCAttack( pSoldier, &pTarget, REASON_NORMAL_ATTACK ); + if ( !fEnterCombat ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, ">>Not entering combat as a result of PC attack" ); + } + } + } - // global + // global - // ATE: If we are an animal, etc, don't change to hostile... - // ( and don't go into combat ) - if ( pTarget->ubBodyType == CROW ) - { - // Loop through our team, make guys who can see this fly away.... - { - UINT32 cnt; - SOLDIERTYPE *pTeamSoldier; - UINT8 ubTeam; + // ATE: If we are an animal, etc, don't change to hostile... + // ( and don't go into combat ) + if ( pTarget->ubBodyType == CROW ) + { + // Loop through our team, make guys who can see this fly away.... + { + UINT32 cnt; + SOLDIERTYPE *pTeamSoldier; + UINT8 ubTeam; - ubTeam = pTarget->bTeam; + ubTeam = pTarget->bTeam; - for ( cnt = gTacticalStatus.Team[ ubTeam ].bFirstID, pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ ubTeam ].bLastID; cnt++, pTeamSoldier++ ) - { - if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) - { - if ( pTeamSoldier->ubBodyType == CROW ) - { - if ( pTeamSoldier->aiData.bOppList[ pSoldier->ubID ] == SEEN_CURRENTLY ) - { - //ZEROTIMECOUNTER( pTeamSoldier->timeCounters.AICounter ); + for ( cnt = gTacticalStatus.Team[ ubTeam ].bFirstID, pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ ubTeam ].bLastID; cnt++, pTeamSoldier++ ) + { + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector ) + { + if ( pTeamSoldier->ubBodyType == CROW ) + { + if ( pTeamSoldier->aiData.bOppList[ pSoldier->ubID ] == SEEN_CURRENTLY ) + { + //ZEROTIMECOUNTER( pTeamSoldier->timeCounters.AICounter ); - //MakeCivHostile( pTeamSoldier, 2 ); + //MakeCivHostile( pTeamSoldier, 2 ); - HandleCrowFlyAway( pTeamSoldier ); + HandleCrowFlyAway( pTeamSoldier ); - } - } - } - } - } + } + } + } + } + } - // Don't enter combat... - fEnterCombat = FALSE; - } + // Don't enter combat... + fEnterCombat = FALSE; + } - if ( gTacticalStatus.bBoxingState == BOXING ) - { - if ( pTarget && pTarget->stats.bLife <= 0 ) - { - // someone has won! - EndBoxingMatch( pTarget ); - } - } + if ( gTacticalStatus.bBoxingState == BOXING ) + { + if ( pTarget && pTarget->stats.bLife <= 0 ) + { + // someone has won! + EndBoxingMatch( pTarget ); + } + } - // if soldier and target were not both players and target was not under fire before... - if ( ( pSoldier->bTeam != gbPlayerNum || pTarget->bTeam != gbPlayerNum ) ) - { - if (pTarget->aiData.bOppList[ pSoldier->ubID ] != SEEN_CURRENTLY ) - { - NoticeUnseenAttacker( pSoldier, pTarget, 0 ); - } - // "under fire" lasts for 2 turns - pTarget->aiData.bUnderFire = 2; - } + // if soldier and target were not both players and target was not under fire before... + if ( ( pSoldier->bTeam != gbPlayerNum || pTarget->bTeam != gbPlayerNum ) ) + { + if (pTarget->aiData.bOppList[ pSoldier->ubID ] != SEEN_CURRENTLY ) + { + NoticeUnseenAttacker( pSoldier, pTarget, 0 ); + } + // "under fire" lasts for 2 turns + pTarget->aiData.bUnderFire = 2; + } - } - else if ( pTarget ) - { - // something is wrong here! - if ( !pTarget->bActive || !pTarget->bInSector ) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, ">>Invalid target attacked!" ); - } - else if ( ! (pSoldier->flags.uiStatusFlags & SOLDIER_ATTACK_NOTICED) ) - { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, ">>Attack not noticed" ); - } - } - else - { - // no target, don't enter combat - fEnterCombat = FALSE; - } + } + else if ( pTarget ) + { + // something is wrong here! + if ( !pTarget->bActive || !pTarget->bInSector ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, ">>Invalid target attacked!" ); + } + else if ( ! (pSoldier->flags.uiStatusFlags & SOLDIER_ATTACK_NOTICED) ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, ">>Attack not noticed" ); + } + } + else + { + // no target, don't enter combat + fEnterCombat = FALSE; + } - if ( pSoldier->flags.fSayAmmoQuotePending ) - { - pSoldier->flags.fSayAmmoQuotePending = FALSE; - TacticalCharacterDialogue( pSoldier, QUOTE_OUT_OF_AMMO ); - } + if ( pSoldier->flags.fSayAmmoQuotePending ) + { + pSoldier->flags.fSayAmmoQuotePending = FALSE; + TacticalCharacterDialogue( pSoldier, QUOTE_OUT_OF_AMMO ); + } - if (pSoldier->flags.uiStatusFlags & SOLDIER_PC) - { - UnSetUIBusy( ubID ); - } - else - { - FreeUpNPCFromAttacking( ubID ); - } + if (pSoldier->flags.uiStatusFlags & SOLDIER_PC) + { + UnSetUIBusy( ubID ); + } + else + { + FreeUpNPCFromAttacking( ubID ); + } - if ( !fEnterCombat ) - { - // It's still possible that something happened - if (!(gTacticalStatus.uiFlags & INCOMBAT) ) - { - HandleBestSightingPositionInRealtime(); - } - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, ">>Not to enter combat from this attack" ); - } + if ( !fEnterCombat ) + { + // It's still possible that something happened + if (!(gTacticalStatus.uiFlags & INCOMBAT) ) + { + HandleBestSightingPositionInRealtime(); + } + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, ">>Not to enter combat from this attack" ); + } - if ( fEnterCombat && !( gTacticalStatus.uiFlags & INCOMBAT ) ) - { - // Go into combat! + if ( fEnterCombat && !( gTacticalStatus.uiFlags & INCOMBAT ) ) + { + // Go into combat! - // If we are in a meanwhile... don't enter combat here... + // If we are in a meanwhile... don't enter combat here... #if (defined JA2UB) -//Ja25 no meanwhiles + //Ja25 no meanwhiles #else - if ( !AreInMeanwhile( ) ) + if ( !AreInMeanwhile( ) ) #endif - { - EnterCombatMode( pSoldier->bTeam ); - } - } + { + EnterCombatMode( pSoldier->bTeam ); + } + } - pSoldier->flags.uiStatusFlags &= (~SOLDIER_ATTACK_NOTICED); - } + pSoldier->flags.uiStatusFlags &= (~SOLDIER_ATTACK_NOTICED); + } - if ( gTacticalStatus.fKilledEnemyOnAttack ) - { - // Check for death quote... - HandleKilledQuote( MercPtrs[ gTacticalStatus.ubEnemyKilledOnAttack ], MercPtrs[ gTacticalStatus.ubEnemyKilledOnAttackKiller ], gTacticalStatus.ubEnemyKilledOnAttackLocation, gTacticalStatus.bEnemyKilledOnAttackLevel ); - gTacticalStatus.fKilledEnemyOnAttack = FALSE; - } + if ( gTacticalStatus.fKilledEnemyOnAttack ) + { + // Check for death quote... + HandleKilledQuote( MercPtrs[ gTacticalStatus.ubEnemyKilledOnAttack ], MercPtrs[ gTacticalStatus.ubEnemyKilledOnAttackKiller ], gTacticalStatus.ubEnemyKilledOnAttackLocation, gTacticalStatus.bEnemyKilledOnAttackLevel ); + gTacticalStatus.fKilledEnemyOnAttack = FALSE; + } - // ATE: Check for stat changes.... - HandleAnyStatChangesAfterAttack( ); + // ATE: Check for stat changes.... + HandleAnyStatChangesAfterAttack( ); - if ( gTacticalStatus.fItemsSeenOnAttack && gTacticalStatus.ubCurrentTeam == gbPlayerNum ) - { - gTacticalStatus.fItemsSeenOnAttack = FALSE; + if ( gTacticalStatus.fItemsSeenOnAttack && gTacticalStatus.ubCurrentTeam == gbPlayerNum ) + { + gTacticalStatus.fItemsSeenOnAttack = FALSE; - // Display quote! - if ( !AM_AN_EPC( MercPtrs[ gTacticalStatus.ubItemsSeenOnAttackSoldier ] ) ) - { - //ddd TacticalCharacterDialogueWithSpecialEvent( MercPtrs[ gTacticalStatus.ubItemsSeenOnAttackSoldier ], (UINT16)( QUOTE_SPOTTED_SOMETHING_ONE + Random( 2 ) ), DIALOGUE_SPECIAL_EVENT_SIGNAL_ITEM_LOCATOR_START, gTacticalStatus.sItemsSeenOnAttackGridNo, 0 ); - if(Chance(gGameExternalOptions.iChanceSayAnnoyingPhrase) ) - TacticalCharacterDialogueWithSpecialEvent( MercPtrs[ gTacticalStatus.ubItemsSeenOnAttackSoldier ], (UINT16)( QUOTE_SPOTTED_SOMETHING_ONE + Random( 2 ) ), DIALOGUE_SPECIAL_EVENT_SIGNAL_ITEM_LOCATOR_START, gTacticalStatus.usItemsSeenOnAttackGridNo, 0 ); - } - else - { - // Turn off item lock for locators... - gTacticalStatus.fLockItemLocators = FALSE; - // Slide to location! - SlideToLocation( 0, gTacticalStatus.usItemsSeenOnAttackGridNo ); - } - } + // Display quote! + if ( !AM_AN_EPC( MercPtrs[ gTacticalStatus.ubItemsSeenOnAttackSoldier ] ) ) + { + //ddd TacticalCharacterDialogueWithSpecialEvent( MercPtrs[ gTacticalStatus.ubItemsSeenOnAttackSoldier ], (UINT16)( QUOTE_SPOTTED_SOMETHING_ONE + Random( 2 ) ), DIALOGUE_SPECIAL_EVENT_SIGNAL_ITEM_LOCATOR_START, gTacticalStatus.sItemsSeenOnAttackGridNo, 0 ); + if(Chance(gGameExternalOptions.iChanceSayAnnoyingPhrase) ) + TacticalCharacterDialogueWithSpecialEvent( MercPtrs[ gTacticalStatus.ubItemsSeenOnAttackSoldier ], (UINT16)( QUOTE_SPOTTED_SOMETHING_ONE + Random( 2 ) ), DIALOGUE_SPECIAL_EVENT_SIGNAL_ITEM_LOCATOR_START, gTacticalStatus.usItemsSeenOnAttackGridNo, 0 ); + } + else + { + // Turn off item lock for locators... + gTacticalStatus.fLockItemLocators = FALSE; + // Slide to location! + SlideToLocation( 0, gTacticalStatus.usItemsSeenOnAttackGridNo ); + } + } - if ( gTacticalStatus.uiFlags & CHECK_SIGHT_AT_END_OF_ATTACK ) - { - UINT8 ubLoop; - SOLDIERTYPE * pSightSoldier; + if ( gTacticalStatus.uiFlags & CHECK_SIGHT_AT_END_OF_ATTACK ) + { + UINT8 ubLoop; + SOLDIERTYPE * pSightSoldier; - AllTeamsLookForAll( FALSE ); + AllTeamsLookForAll( FALSE ); - // call fov code - ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; - for ( pSightSoldier = MercPtrs[ ubLoop ]; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++, pSightSoldier++ ) - { - if ( pSightSoldier->bActive && pSightSoldier->bInSector ) - { - RevealRoofsAndItems( pSightSoldier, TRUE, FALSE, pSightSoldier->pathing.bLevel, FALSE ); - } - } - gTacticalStatus.uiFlags &= ~CHECK_SIGHT_AT_END_OF_ATTACK; - } + // call fov code + ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; + for ( pSightSoldier = MercPtrs[ ubLoop ]; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++, pSightSoldier++ ) + { + if ( pSightSoldier->bActive && pSightSoldier->bInSector ) + { + RevealRoofsAndItems( pSightSoldier, TRUE, FALSE, pSightSoldier->pathing.bLevel, FALSE ); + } + } + gTacticalStatus.uiFlags &= ~CHECK_SIGHT_AT_END_OF_ATTACK; + } - DequeueAllDemandGameEvents( TRUE ); + DequeueAllDemandGameEvents( TRUE ); - // if we're in realtime, turn off the attacker's muzzle flash at this point - if ( !(gTacticalStatus.uiFlags & INCOMBAT) && pSoldier ) - { - EndMuzzleFlash( pSoldier ); - } + // if we're in realtime, turn off the attacker's muzzle flash at this point + if ( !(gTacticalStatus.uiFlags & INCOMBAT) && pSoldier ) + { + EndMuzzleFlash( pSoldier ); + } - if ( pSoldier && (pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )) - { - if ( !Weapon[pSoldier->inv[HANDPOS].usItem].NoSemiAuto ) - { - // change back to single shot - pSoldier->bWeaponMode = WM_NORMAL; - pSoldier->bDoAutofire = 0; - pSoldier->bDoBurst = 0; - } - else - { - // change back to autofire - pSoldier->bWeaponMode = WM_AUTOFIRE; - pSoldier->bDoAutofire = 1; - pSoldier->bDoBurst = TRUE; - } - if ( Item[pSoldier->inv[ HANDPOS ].usItem].twohanded && Weapon[pSoldier->inv[ HANDPOS ].usItem].HeavyGun && gGameExternalOptions.ubAllowAlternativeWeaponHolding == 3 ) - pSoldier->bScopeMode = USE_ALT_WEAPON_HOLD; - else - pSoldier->bScopeMode = USE_BEST_SCOPE; - - DirtyMercPanelInterface(pSoldier, DIRTYLEVEL2 ); - } + if ( pSoldier && (pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )) + { + if ( !Weapon[pSoldier->inv[HANDPOS].usItem].NoSemiAuto ) + { + // change back to single shot + pSoldier->bWeaponMode = WM_NORMAL; + pSoldier->bDoAutofire = 0; + pSoldier->bDoBurst = 0; + } + else + { + // change back to autofire + pSoldier->bWeaponMode = WM_AUTOFIRE; + pSoldier->bDoAutofire = 1; + pSoldier->bDoBurst = TRUE; + } + if ( Item[pSoldier->inv[ HANDPOS ].usItem].twohanded && Weapon[pSoldier->inv[ HANDPOS ].usItem].HeavyGun && gGameExternalOptions.ubAllowAlternativeWeaponHolding == 3 ) + pSoldier->bScopeMode = USE_ALT_WEAPON_HOLD; + else + pSoldier->bScopeMode = USE_BEST_SCOPE; - // record last target - // Check for valid target! - if ( pSoldier ) - { - pSoldier->sLastTarget = pSoldier->sTargetGridNo; - } + DirtyMercPanelInterface(pSoldier, DIRTYLEVEL2 ); + } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // SANDRO - if pending interrupt flag was set for after-shot type of interupt, try to resolve it now - if ( gGameOptions.fImprovedInterruptSystem ) - { - if ( ResolvePendingInterrupt( pSoldier, AFTERSHOT_INTERRUPT ) ) - { - pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; - pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; - // "artificially" set lock ui flag - if (pSoldier->bTeam == gbPlayerNum) - { - //AddTopMessage( COMPUTER_INTERRUPT_MESSAGE, Message[STR_INTERRUPT] ); - guiPendingOverrideEvent = LU_BEGINUILOCK; - HandleTacticalUI( ); - } - } - } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // record last target + // Check for valid target! + if ( pSoldier ) + { + pSoldier->sLastTarget = pSoldier->sTargetGridNo; + } - // Reset various flags and values that should be 0 once the action is overwith - for (cnt = 0; cnt < guiNumMercSlots; cnt++) - { - pSoldier = MercSlots[ cnt ]; - if ( pSoldier ) - { - pSoldier->bNumPelletsHitBy = 0; - if ( !( pSoldier->flags.uiStatusFlags & SOLDIER_TURNINGFROMHIT ) ) - { - // 0verhaul: This is an ugly hack. I don't like it, but until I figure out a better solution - // for turning from a hit, it's the only way to not stop a soldier in mid-turn. - pSoldier->flags.fGettingHit = FALSE; - } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // SANDRO - if pending interrupt flag was set for after-shot type of interupt, try to resolve it now + if ( gGameOptions.fImprovedInterruptSystem ) + { + if ( ResolvePendingInterrupt( pSoldier, AFTERSHOT_INTERRUPT ) ) + { + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + pSoldier->ubPendingDirection = NO_PENDING_DIRECTION; + // "artificially" set lock ui flag + if (pSoldier->bTeam == gbPlayerNum) + { + //AddTopMessage( COMPUTER_INTERRUPT_MESSAGE, Message[STR_INTERRUPT] ); + guiPendingOverrideEvent = LU_BEGINUILOCK; + HandleTacticalUI( ); + } + } + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (pSoldier->ubAttackerID != NOBODY ) - { - if (pSoldier->ubPreviousAttackerID != pSoldier->ubAttackerID) - { - pSoldier->ubNextToPreviousAttackerID = pSoldier->ubPreviousAttackerID; - } + // Reset various flags and values that should be 0 once the action is overwith + for (cnt = 0; cnt < guiNumMercSlots; cnt++) + { + pSoldier = MercSlots[ cnt ]; + if ( pSoldier ) + { + pSoldier->bNumPelletsHitBy = 0; + if ( !( pSoldier->flags.uiStatusFlags & SOLDIER_TURNINGFROMHIT ) ) + { + // 0verhaul: This is an ugly hack. I don't like it, but until I figure out a better solution + // for turning from a hit, it's the only way to not stop a soldier in mid-turn. + pSoldier->flags.fGettingHit = FALSE; + } - pSoldier->ubPreviousAttackerID = pSoldier->ubAttackerID; + if (pSoldier->ubAttackerID != NOBODY ) + { + if (pSoldier->ubPreviousAttackerID != pSoldier->ubAttackerID) + { + pSoldier->ubNextToPreviousAttackerID = pSoldier->ubPreviousAttackerID; + } - // Why not keep the attacker ID for a dead queen monster? - if ( pSoldier->stats.bLife != 0 && pSoldier->ubBodyType != QUEENMONSTER ) - { - pSoldier->ubAttackerID = NOBODY; - } - } - } - } + pSoldier->ubPreviousAttackerID = pSoldier->ubAttackerID; - CheckForEndOfBattle( FALSE ); + // Why not keep the attacker ID for a dead queen monster? + if ( pSoldier->stats.bLife != 0 && pSoldier->ubBodyType != QUEENMONSTER ) + { + pSoldier->ubAttackerID = NOBODY; + } + } + } + } - return( pTarget ); + CheckForEndOfBattle( FALSE ); + + return( pTarget ); } SOLDIERTYPE * ReduceAttackBusyCount( ) { #if 0 - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("ReduceAttackBusyCount") ); - if ( ubID == NOBODY ) - { - return( InternalReduceAttackBusyCount( ubID, fCalledByAttacker, NOBODY ) ); - } - else - { - return( InternalReduceAttackBusyCount( ubID, fCalledByAttacker, MercPtrs[ ubID ]->ubTargetID ) ); - } + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("ReduceAttackBusyCount") ); + if ( ubID == NOBODY ) + { + return( InternalReduceAttackBusyCount( ubID, fCalledByAttacker, NOBODY ) ); + } + else + { + return( InternalReduceAttackBusyCount( ubID, fCalledByAttacker, MercPtrs[ ubID ]->ubTargetID ) ); + } #endif -// 0verhaul: This is now a simple subroutine. - return InternalReduceAttackBusyCount( ); + // 0verhaul: This is now a simple subroutine. + return InternalReduceAttackBusyCount( ); } SOLDIERTYPE * FreeUpAttacker( ) { - // Okay, so the objective here is not to simply decrease the ABC, but to twiddle it and see what - // falls out. So there's an increase followed immediately by a decrease. - // If the ABC is 0 at this point, such as an aborted action might give, this will finalize the - // action and allow the soldier to try something else. - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("FreeUpAttacker") ); - DebugAttackBusy( "Freeing up attacker\n"); - gTacticalStatus.ubAttackBusyCount++; - return( ReduceAttackBusyCount( ) ); + // Okay, so the objective here is not to simply decrease the ABC, but to twiddle it and see what + // falls out. So there's an increase followed immediately by a decrease. + // If the ABC is 0 at this point, such as an aborted action might give, this will finalize the + // action and allow the soldier to try something else. + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("FreeUpAttacker") ); + DebugAttackBusy( "Freeing up attacker\n"); + gTacticalStatus.ubAttackBusyCount++; + return( ReduceAttackBusyCount( ) ); } #if 0 -// 0verhaul: These routines are declared obsolete. Call ReduceAttackBusyCount instead. +// 0verhaul: These routines are declared obsolete. Call ReduceAttackBusyCount instead. SOLDIERTYPE * FreeUpAttackerGivenTarget( UINT8 ubID, UINT8 ubTargetID ) { - // Strange as this may seem, this function returns a pointer to - // the *target* in case the target has changed sides as a result - // of being attacked - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("FreeUpAttackerGivenTarget") ); - return( InternalReduceAttackBusyCount( ubID, TRUE, ubTargetID ) ); + // Strange as this may seem, this function returns a pointer to + // the *target* in case the target has changed sides as a result + // of being attacked + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("FreeUpAttackerGivenTarget") ); + return( InternalReduceAttackBusyCount( ubID, TRUE, ubTargetID ) ); } SOLDIERTYPE * ReduceAttackBusyGivenTarget( UINT8 ubID, UINT8 ubTargetID ) { - // Strange as this may seem, this function returns a pointer to - // the *target* in case the target has changed sides as a result - // of being attacked - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("ReduceAttackBusyGivenTarget") ); - return( InternalReduceAttackBusyCount( ubID, FALSE, ubTargetID ) ); + // Strange as this may seem, this function returns a pointer to + // the *target* in case the target has changed sides as a result + // of being attacked + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("ReduceAttackBusyGivenTarget") ); + return( InternalReduceAttackBusyCount( ubID, FALSE, ubTargetID ) ); } #endif void StopMercAnimation( BOOLEAN fStop ) { - static INT8 bOldRealtimeSpeed; + static INT8 bOldRealtimeSpeed; - if ( fStop ) - { - if ( !(gTacticalStatus.uiFlags & SLOW_ANIMATION ) ) - { - bOldRealtimeSpeed = gTacticalStatus.bRealtimeSpeed; - gTacticalStatus.bRealtimeSpeed = -1; + if ( fStop ) + { + if ( !(gTacticalStatus.uiFlags & SLOW_ANIMATION ) ) + { + bOldRealtimeSpeed = gTacticalStatus.bRealtimeSpeed; + gTacticalStatus.bRealtimeSpeed = -1; - gTacticalStatus.uiFlags |=(SLOW_ANIMATION ); + gTacticalStatus.uiFlags |=(SLOW_ANIMATION ); - ResetAllMercSpeeds( ); + ResetAllMercSpeeds( ); - } - } - else - { - if ( gTacticalStatus.uiFlags & SLOW_ANIMATION ) - { - gTacticalStatus.bRealtimeSpeed = bOldRealtimeSpeed; + } + } + else + { + if ( gTacticalStatus.uiFlags & SLOW_ANIMATION ) + { + gTacticalStatus.bRealtimeSpeed = bOldRealtimeSpeed; - gTacticalStatus.uiFlags &=(~SLOW_ANIMATION ); + gTacticalStatus.uiFlags &=(~SLOW_ANIMATION ); - ResetAllMercSpeeds( ); - } + ResetAllMercSpeeds( ); + } - } + } } void ResetAllMercSpeeds( ) { - SOLDIERTYPE *pSoldier; - UINT32 cnt; + SOLDIERTYPE *pSoldier; + UINT32 cnt; - for ( cnt = 0; cnt < TOTAL_SOLDIERS; cnt++ ) - { - pSoldier = MercPtrs[ cnt ]; + for ( cnt = 0; cnt < TOTAL_SOLDIERS; cnt++ ) + { + pSoldier = MercPtrs[ cnt ]; - if ( pSoldier->bActive && pSoldier->bInSector ) - { - SetSoldierAniSpeed( pSoldier ); - } + if ( pSoldier->bActive && pSoldier->bInSector ) + { + SetSoldierAniSpeed( pSoldier ); + } - } + } } -void SetActionToDoOnceMercsGetToLocation( UINT8 ubActionCode, INT8 bNumMercsWaiting, UINT32 uiData1, UINT32 uiData2, UINT32 uiData3 ) +void SetActionToDoOnceMercsGetToLocation( UINT8 ubActionCode, INT8 bNumMercsWaiting, UINT32 uiData1, UINT32 uiData2, UINT32 uiData3 ) { - gubWaitingForAllMercsToExitCode = ubActionCode; - gbNumMercsUntilWaitingOver = bNumMercsWaiting; - guiWaitingForAllMercsToExitData[ 0 ] = uiData1; - guiWaitingForAllMercsToExitData[ 1 ] = uiData2; - guiWaitingForAllMercsToExitData[ 2 ] = uiData3; + gubWaitingForAllMercsToExitCode = ubActionCode; + gbNumMercsUntilWaitingOver = bNumMercsWaiting; + guiWaitingForAllMercsToExitData[ 0 ] = uiData1; + guiWaitingForAllMercsToExitData[ 1 ] = uiData2; + guiWaitingForAllMercsToExitData[ 2 ] = uiData3; - // Setup timer counter and report back if too long.... - guiWaitingForAllMercsToExitTimer = GetJA2Clock( ); + // Setup timer counter and report back if too long.... + guiWaitingForAllMercsToExitTimer = GetJA2Clock( ); - // ATE: Set flag to ignore sight... - gTacticalStatus.uiFlags |= ( DISALLOW_SIGHT ); + // ATE: Set flag to ignore sight... + gTacticalStatus.uiFlags |= ( DISALLOW_SIGHT ); } void HandleBloodForNewGridNo( SOLDIERTYPE *pSoldier ) { - // Handle bleeding... - if ( ( pSoldier->bBleeding > MIN_BLEEDING_THRESHOLD ) ) - { - INT8 bBlood; + // Handle bleeding... + if ( ( pSoldier->bBleeding > MIN_BLEEDING_THRESHOLD ) ) + { + INT8 bBlood; - bBlood = ( ( pSoldier->bBleeding-MIN_BLEEDING_THRESHOLD ) / BLOODDIVISOR); + bBlood = ( ( pSoldier->bBleeding-MIN_BLEEDING_THRESHOLD ) / BLOODDIVISOR); - if ( bBlood > MAXBLOODQUANTITY ) - { - bBlood = MAXBLOODQUANTITY; - } + if ( bBlood > MAXBLOODQUANTITY ) + { + bBlood = MAXBLOODQUANTITY; + } - // now, he shouldn't ALWAYS bleed the same amount; LOWER it perhaps. If it - // goes less than zero, then no blood! - bBlood -= (INT8)Random(7); + // now, he shouldn't ALWAYS bleed the same amount; LOWER it perhaps. If it + // goes less than zero, then no blood! + bBlood -= (INT8)Random(7); - if ( bBlood >= 0 ) - { - // this handles all soldiers' dropping blood during movement - DropBlood( pSoldier, bBlood, pSoldier->bVisible ); - } - } + if ( bBlood >= 0 ) + { + // this handles all soldiers' dropping blood during movement + DropBlood( pSoldier, bBlood, pSoldier->bVisible ); + } + } } -void CencelAllActionsForTimeCompression( void ) +void CencelAllActionsForTimeCompression( ) { - SOLDIERTYPE *pSoldier; - INT32 cnt; + SOLDIERTYPE *pSoldier; + INT32 cnt; - for ( pSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pSoldier++, cnt++ ) - { - if ( pSoldier->bActive ) - { - if ( pSoldier->bInSector ) - { - // Hault! - pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); + for ( pSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pSoldier++, cnt++ ) + { + if ( pSoldier->bActive ) + { + if ( pSoldier->bInSector ) + { + // Hault! + pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); - // END AI actions - CancelAIAction( pSoldier, TRUE ); - } - } - } + // END AI actions + CancelAIAction( pSoldier, TRUE ); + } + } + } } void AddManToTeam( INT8 bTeam ) { - // ATE: If not loading game! - if( !( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) ) - { - // Increment men in sector number! - if (gTacticalStatus.Team[ bTeam ].bMenInSector == 0) - { - gTacticalStatus.Team[ bTeam ].bTeamActive = TRUE; - } - gTacticalStatus.Team[ bTeam ].bMenInSector++; - if ( bTeam == ENEMY_TEAM ) - { - gTacticalStatus.bOriginalSizeOfEnemyForce++; - } - } + // ATE: If not loading game! + if( !( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) ) + { + // Increment men in sector number! + if (gTacticalStatus.Team[ bTeam ].bMenInSector == 0) + { + gTacticalStatus.Team[ bTeam ].bTeamActive = TRUE; + } + gTacticalStatus.Team[ bTeam ].bMenInSector++; + if ( bTeam == ENEMY_TEAM ) + { + gTacticalStatus.bOriginalSizeOfEnemyForce++; + } + } } void RemoveManFromTeam( INT8 bTeam ) { - // ATE; if not loading game! - if( !( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) ) - { - // Decrement men in sector number! - gTacticalStatus.Team[ bTeam ].bMenInSector--; - if (gTacticalStatus.Team[ bTeam ].bMenInSector == 0) - { - gTacticalStatus.Team[ bTeam ].bTeamActive = FALSE; - } - else if (gTacticalStatus.Team[ bTeam ].bMenInSector < 0) - { + // ATE; if not loading game! + if( !( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) ) + { + // Decrement men in sector number! + gTacticalStatus.Team[ bTeam ].bMenInSector--; + if (gTacticalStatus.Team[ bTeam ].bMenInSector == 0) + { + gTacticalStatus.Team[ bTeam ].bTeamActive = FALSE; + } + else if (gTacticalStatus.Team[ bTeam ].bMenInSector < 0) + { #ifdef JA2BETAVERSION - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Number of people on team %d dropped to %d", bTeam, gTacticalStatus.Team[ bTeam ].bMenInSector ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Number of people on team %d dropped to %d", bTeam, gTacticalStatus.Team[ bTeam ].bMenInSector ); #endif - // reset! - gTacticalStatus.Team[ bTeam ].bMenInSector = 0; - } - } + // reset! + gTacticalStatus.Team[ bTeam ].bMenInSector = 0; + } + } } void RemoveSoldierFromTacticalSector( SOLDIERTYPE *pSoldier, BOOLEAN fAdjustSelected ) { - UINT8 ubID; - SOLDIERTYPE *pNewSoldier; + UINT8 ubID; + SOLDIERTYPE *pNewSoldier; - // reset merc's opplist - InitSoldierOppList( pSoldier ); + // reset merc's opplist + InitSoldierOppList( pSoldier ); - // Remove! - pSoldier->RemoveSoldierFromGridNo( ); + // Remove! + pSoldier->RemoveSoldierFromGridNo( ); - RemoveMercSlot( pSoldier ); + RemoveMercSlot( pSoldier ); - pSoldier->bInSector = FALSE; + pSoldier->bInSector = FALSE; - // Select next avialiable guy.... - if ( fAdjustSelected ) - { - if ( guiCurrentScreen == GAME_SCREEN ) - { - if ( gusSelectedSoldier == pSoldier->ubID ) - { - ubID = FindNextActiveAndAliveMerc( pSoldier, FALSE, FALSE ); + // Select next avialiable guy.... + if ( fAdjustSelected ) + { + if ( guiCurrentScreen == GAME_SCREEN ) + { + if ( gusSelectedSoldier == pSoldier->ubID ) + { + ubID = FindNextActiveAndAliveMerc( pSoldier, FALSE, FALSE ); - if ( ubID != NOBODY && ubID != gusSelectedSoldier ) - { - SelectSoldier( ubID, FALSE, FALSE ); - } - else - { - // OK - let's look for another squad... - pNewSoldier = FindNextActiveSquad( pSoldier ); + if ( ubID != NOBODY && ubID != gusSelectedSoldier ) + { + SelectSoldier( ubID, FALSE, FALSE ); + } + else + { + // OK - let's look for another squad... + pNewSoldier = FindNextActiveSquad( pSoldier ); - if ( pNewSoldier != pSoldier ) - { - // Good squad found! - SelectSoldier( pNewSoldier->ubID, FALSE, FALSE ); - } - else - { - // if here, make nobody - gusSelectedSoldier = NOBODY; - } - } - } - UpdateTeamPanelAssignments( ); - } - else - { - gusSelectedSoldier = NOBODY; + if ( pNewSoldier != pSoldier ) + { + // Good squad found! + SelectSoldier( pNewSoldier->ubID, FALSE, FALSE ); + } + else + { + // if here, make nobody + gusSelectedSoldier = NOBODY; + } + } + } + UpdateTeamPanelAssignments( ); + } + else + { + gusSelectedSoldier = NOBODY; - if ( guiCurrentScreen == GAME_SCREEN ) - { - // otherwise, make sure interface is team panel... - UpdateTeamPanelAssignments( ); - SetCurrentInterfacePanel( (UINT8)TEAM_PANEL ); - } - } - } + if ( guiCurrentScreen == GAME_SCREEN ) + { + // otherwise, make sure interface is team panel... + UpdateTeamPanelAssignments( ); + SetCurrentInterfacePanel( (UINT8)TEAM_PANEL ); + } + } + } } -void DoneFadeOutDueToDeath( void ) +void DoneFadeOutDueToDeath( ) { - // Quit game.... - InternalLeaveTacticalScreen( MAINMENU_SCREEN ); - //SetPendingNewScreen( MAINMENU_SCREEN ); + // Quit game.... + InternalLeaveTacticalScreen( MAINMENU_SCREEN ); + //SetPendingNewScreen( MAINMENU_SCREEN ); } void EndBattleWithUnconsciousGuysCallback( UINT8 bExitValue ) { - // Enter mapscreen..... - if(!is_client)CheckAndHandleUnloadingOfCurrentWorld(); - else - { - ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[40] ); - if(!cDisableSpectatorMode) - { - gTacticalStatus.uiFlags |= SHOW_ALL_MERCS;//hayden - ScreenMsg( FONT_YELLOW, MSG_CHAT, MPClientMessage[41] ); - } - else - ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"spectator mode disabled"); - - teamwiped(); - } + // Enter mapscreen..... + if(!is_client)CheckAndHandleUnloadingOfCurrentWorld(); + else + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[40] ); + if(!cDisableSpectatorMode) + { + gTacticalStatus.uiFlags |= SHOW_ALL_MERCS;//hayden + ScreenMsg( FONT_YELLOW, MSG_CHAT, MPClientMessage[41] ); + } + else + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"spectator mode disabled"); + + teamwiped(); + } } -void InitializeTacticalStatusAtBattleStart( void ) +void InitializeTacticalStatusAtBattleStart( ) { - INT8 bLoop; - INT32 cnt; - SOLDIERTYPE * pSoldier; + INT8 bLoop; + INT32 cnt; + SOLDIERTYPE * pSoldier; - gTacticalStatus.ubArmyGuysKilled = 0; - gTacticalStatus.bOriginalSizeOfEnemyForce = 0; + gTacticalStatus.ubArmyGuysKilled = 0; + gTacticalStatus.bOriginalSizeOfEnemyForce = 0; - gTacticalStatus.fPanicFlags = 0; - gTacticalStatus.fEnemyFlags = 0; - for ( bLoop = 0; bLoop < NUM_PANIC_TRIGGERS; bLoop++ ) - { - gTacticalStatus.sPanicTriggerGridNo[ bLoop ] = NOWHERE; - gTacticalStatus.bPanicTriggerIsAlarm[ bLoop ] = FALSE; - gTacticalStatus.ubPanicTolerance[ bLoop ] = 0; - } + gTacticalStatus.fPanicFlags = 0; + gTacticalStatus.fEnemyFlags = 0; + for ( bLoop = 0; bLoop < NUM_PANIC_TRIGGERS; bLoop++ ) + { + gTacticalStatus.sPanicTriggerGridNo[ bLoop ] = NOWHERE; + gTacticalStatus.bPanicTriggerIsAlarm[ bLoop ] = FALSE; + gTacticalStatus.ubPanicTolerance[ bLoop ] = 0; + } - for( cnt = 0; cnt < MAXTEAMS; cnt++ ) - { - gTacticalStatus.Team[ cnt ].ubLastMercToRadio = NOBODY; - gTacticalStatus.Team[ cnt ].bAwareOfOpposition = FALSE; - } + for( cnt = 0; cnt < MAXTEAMS; cnt++ ) + { + gTacticalStatus.Team[ cnt ].ubLastMercToRadio = NOBODY; + gTacticalStatus.Team[ cnt ].bAwareOfOpposition = FALSE; + } - gTacticalStatus.ubTheChosenOne = NOBODY; + gTacticalStatus.ubTheChosenOne = NOBODY; - ClearIntList(); + ClearIntList(); - // make sure none of our guys have leftover shock values etc - for ( cnt = gTacticalStatus.Team[ 0 ].bFirstID; cnt <= gTacticalStatus.Team[ 0 ].bLastID; cnt++ ) - { - pSoldier = MercPtrs[ cnt ]; - pSoldier->aiData.bShock = 0; - pSoldier->bTilesMoved = 0; - } + // make sure none of our guys have leftover shock values etc + for ( cnt = gTacticalStatus.Team[ 0 ].bFirstID; cnt <= gTacticalStatus.Team[ 0 ].bLastID; cnt++ ) + { + pSoldier = MercPtrs[ cnt ]; + pSoldier->aiData.bShock = 0; + pSoldier->bTilesMoved = 0; + } - // loop through everyone; clear misc flags - for ( cnt = 0; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; cnt++ ) - { - MercPtrs[ cnt ]->ubMiscSoldierFlags = 0; - } + // loop through everyone; clear misc flags + for ( cnt = 0; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; cnt++ ) + { + MercPtrs[ cnt ]->ubMiscSoldierFlags = 0; + } } -void DoneFadeOutDemoCreatureLevel( void ) +void DoneFadeOutDemoCreatureLevel( ) { - // OK, insertion data found, enter sector! - SetCurrentWorldSector( 1, 16, 0 ); + // OK, insertion data found, enter sector! + SetCurrentWorldSector( 1, 16, 0 ); - FadeInGameScreen( ); + FadeInGameScreen( ); } @@ -9610,310 +9425,310 @@ void HandleEndDemoInCreatureLevel( ) } -void DeathTimerCallback( void ) +void DeathTimerCallback( ) { - if (gTacticalStatus.Team[ CREATURE_TEAM ].bMenInSector > gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector ) - { - DoMessageBox( MSG_BOX_BASIC_STYLE, LargeTacticalStr[ LARGESTR_NOONE_LEFT_CAPABLE_OF_BATTLE_AGAINST_CREATURES_STR ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, EndBattleWithUnconsciousGuysCallback, NULL ); - } - else - { - DoMessageBox( MSG_BOX_BASIC_STYLE, LargeTacticalStr[ LARGESTR_NOONE_LEFT_CAPABLE_OF_BATTLE_STR ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, EndBattleWithUnconsciousGuysCallback, NULL ); - } + if (gTacticalStatus.Team[ CREATURE_TEAM ].bMenInSector > gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector ) + { + DoMessageBox( MSG_BOX_BASIC_STYLE, LargeTacticalStr[ LARGESTR_NOONE_LEFT_CAPABLE_OF_BATTLE_AGAINST_CREATURES_STR ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, EndBattleWithUnconsciousGuysCallback, NULL ); + } + else + { + DoMessageBox( MSG_BOX_BASIC_STYLE, LargeTacticalStr[ LARGESTR_NOONE_LEFT_CAPABLE_OF_BATTLE_STR ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, EndBattleWithUnconsciousGuysCallback, NULL ); + } } -void CaptureTimerCallback( void ) +void CaptureTimerCallback( ) { - if( gfSurrendered ) - { - DoMessageBox( MSG_BOX_BASIC_STYLE, LargeTacticalStr[ 3 ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, EndBattleWithUnconsciousGuysCallback, NULL ); - } - else - { - DoMessageBox( MSG_BOX_BASIC_STYLE, LargeTacticalStr[ LARGESTR_HAVE_BEEN_CAPTURED ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, EndBattleWithUnconsciousGuysCallback, NULL ); - } - gfSurrendered = FALSE; + if( gfSurrendered ) + { + DoMessageBox( MSG_BOX_BASIC_STYLE, LargeTacticalStr[ 3 ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, EndBattleWithUnconsciousGuysCallback, NULL ); + } + else + { + DoMessageBox( MSG_BOX_BASIC_STYLE, LargeTacticalStr[ LARGESTR_HAVE_BEEN_CAPTURED ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, EndBattleWithUnconsciousGuysCallback, NULL ); + } + gfSurrendered = FALSE; } -void DoPOWPathChecks( void ) +void DoPOWPathChecks( ) { - INT32 iLoop; - SOLDIERTYPE * pSoldier; + INT32 iLoop; + SOLDIERTYPE * pSoldier; - // loop through all mercs on our team and if they are POWs in sector, do POW path check and - // put on a squad if available - for ( iLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; iLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; iLoop++ ) - { - pSoldier = MercPtrs[ iLoop ]; + // loop through all mercs on our team and if they are POWs in sector, do POW path check and + // put on a squad if available + for ( iLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; iLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; iLoop++ ) + { + pSoldier = MercPtrs[ iLoop ]; - if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->bAssignment == ASSIGNMENT_POW ) - { - // check to see if POW has been freed! - // this will be true if a path can be made from the POW to either of 3 gridnos - // 10492 (hallway) or 10482 (outside), or 9381 (outside) - if ( FindBestPath( pSoldier, 10492, 0, WALKING, NO_COPYROUTE, PATH_THROUGH_PEOPLE ) )//dnl!!! - { - // drop out of if - } - else if ( FindBestPath( pSoldier, 10482, 0, WALKING, NO_COPYROUTE, PATH_THROUGH_PEOPLE ) )//dnl!!! - { - // drop out of if - } - else if ( FindBestPath( pSoldier, 9381, 0, WALKING, NO_COPYROUTE, PATH_THROUGH_PEOPLE ) )//dnl!!! - { - // drop out of if - } - else - { - continue; - } - // free! free! - // put them on any available squad - pSoldier->aiData.bNeutral = FALSE; - AddCharacterToAnySquad( pSoldier ); - pSoldier->DoMercBattleSound( BATTLE_SOUND_COOL1 ); - } - } + if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->bAssignment == ASSIGNMENT_POW ) + { + // check to see if POW has been freed! + // this will be true if a path can be made from the POW to either of 3 gridnos + // 10492 (hallway) or 10482 (outside), or 9381 (outside) + if ( FindBestPath( pSoldier, 10492, 0, WALKING, NO_COPYROUTE, PATH_THROUGH_PEOPLE ) )//dnl!!! + { + // drop out of if + } + else if ( FindBestPath( pSoldier, 10482, 0, WALKING, NO_COPYROUTE, PATH_THROUGH_PEOPLE ) )//dnl!!! + { + // drop out of if + } + else if ( FindBestPath( pSoldier, 9381, 0, WALKING, NO_COPYROUTE, PATH_THROUGH_PEOPLE ) )//dnl!!! + { + // drop out of if + } + else + { + continue; + } + // free! free! + // put them on any available squad + pSoldier->aiData.bNeutral = FALSE; + AddCharacterToAnySquad( pSoldier ); + pSoldier->DoMercBattleSound( BATTLE_SOUND_COOL1 ); + } + } } -BOOLEAN HostileCiviliansPresent( void ) +BOOLEAN HostileCiviliansPresent( ) { - INT32 iLoop; - SOLDIERTYPE * pSoldier; + INT32 iLoop; + SOLDIERTYPE * pSoldier; - if ( gTacticalStatus.Team[ CIV_TEAM ].bTeamActive == FALSE ) - { - return( FALSE ); - } + if ( gTacticalStatus.Team[ CIV_TEAM ].bTeamActive == FALSE ) + { + return( FALSE ); + } - for ( iLoop = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; iLoop <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; iLoop++ ) - { - pSoldier = MercPtrs[ iLoop ]; + for ( iLoop = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; iLoop <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; iLoop++ ) + { + pSoldier = MercPtrs[ iLoop ]; - if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 && !pSoldier->aiData.bNeutral ) - { - return( TRUE ); - } - } + if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 && !pSoldier->aiData.bNeutral ) + { + return( TRUE ); + } + } - return( FALSE ); + return( FALSE ); } -BOOLEAN HostileCiviliansWithGunsPresent( void ) +BOOLEAN HostileCiviliansWithGunsPresent( ) { - INT32 iLoop; - SOLDIERTYPE * pSoldier; + INT32 iLoop; + SOLDIERTYPE * pSoldier; - if ( gTacticalStatus.Team[ CIV_TEAM ].bTeamActive == FALSE ) - { - return( FALSE ); - } + if ( gTacticalStatus.Team[ CIV_TEAM ].bTeamActive == FALSE ) + { + return( FALSE ); + } - for ( iLoop = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; iLoop <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; iLoop++ ) - { - pSoldier = MercPtrs[ iLoop ]; + for ( iLoop = gTacticalStatus.Team[ CIV_TEAM ].bFirstID; iLoop <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; iLoop++ ) + { + pSoldier = MercPtrs[ iLoop ]; - if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 && !pSoldier->aiData.bNeutral ) - { - if ( FindAIUsableObjClass( pSoldier, IC_WEAPON ) == -1 ) - { - return( TRUE ); - } + if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 && !pSoldier->aiData.bNeutral ) + { + if ( FindAIUsableObjClass( pSoldier, IC_WEAPON ) == -1 ) + { + return( TRUE ); + } - } - } + } + } - return( FALSE ); + return( FALSE ); } -BOOLEAN HostileBloodcatsPresent( void ) +BOOLEAN HostileBloodcatsPresent( ) { - INT32 iLoop; - SOLDIERTYPE * pSoldier; + INT32 iLoop; + SOLDIERTYPE * pSoldier; - if ( gTacticalStatus.Team[ CREATURE_TEAM ].bTeamActive == FALSE ) - { - return( FALSE ); - } + if ( gTacticalStatus.Team[ CREATURE_TEAM ].bTeamActive == FALSE ) + { + return( FALSE ); + } - for ( iLoop = gTacticalStatus.Team[ CREATURE_TEAM ].bFirstID; iLoop <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; iLoop++ ) - { - pSoldier = MercPtrs[ iLoop ]; + for ( iLoop = gTacticalStatus.Team[ CREATURE_TEAM ].bFirstID; iLoop <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; iLoop++ ) + { + pSoldier = MercPtrs[ iLoop ]; - //KM : Aug 11, 1999 -- Patch fix: Removed the check for bNeutral. Bloodcats automatically become hostile - // on site. Because the check used to be there, it was possible to get into a 2nd battle elsewhere - // which is BAD BAD BAD! - if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 && pSoldier->ubBodyType == BLOODCAT ) - { - return( TRUE ); - } - } + //KM : Aug 11, 1999 -- Patch fix: Removed the check for bNeutral. Bloodcats automatically become hostile + // on site. Because the check used to be there, it was possible to get into a 2nd battle elsewhere + // which is BAD BAD BAD! + if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 && pSoldier->ubBodyType == BLOODCAT ) + { + return( TRUE ); + } + } - return( FALSE ); + return( FALSE ); } #ifdef ENABLE_ZOMBIES - BOOLEAN HostileZombiesPresent( void ) - { - INT32 iLoop; - SOLDIERTYPE * pSoldier; - - if ( gTacticalStatus.Team[ CREATURE_TEAM ].bTeamActive == FALSE ) - { - return( FALSE ); - } +BOOLEAN HostileZombiesPresent( ) +{ + INT32 iLoop; + SOLDIERTYPE * pSoldier; - for ( iLoop = gTacticalStatus.Team[ CREATURE_TEAM ].bFirstID; iLoop <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; iLoop++ ) - { - pSoldier = MercPtrs[ iLoop ]; + if ( gTacticalStatus.Team[ CREATURE_TEAM ].bTeamActive == FALSE ) + { + return( FALSE ); + } - if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 && pSoldier->IsZombie() ) - { - return( TRUE ); - } - } + for ( iLoop = gTacticalStatus.Team[ CREATURE_TEAM ].bFirstID; iLoop <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; iLoop++ ) + { + pSoldier = MercPtrs[ iLoop ]; - return( FALSE ); - } + if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 && pSoldier->IsZombie() ) + { + return( TRUE ); + } + } + + return( FALSE ); +} #endif void HandleCreatureTenseQuote( ) { -// WDS - make number of mercenaries, etc. be configurable -// UINT8 ubMercsInSector[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ] = { 0 }; - std::vector ubMercsInSector (CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS, 0); - UINT8 ubNumMercs = 0; - UINT8 ubChosenMerc; - SOLDIERTYPE *pTeamSoldier; - INT32 cnt; - INT32 uiTime; + // WDS - make number of mercenaries, etc. be configurable + // UINT8 ubMercsInSector[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ] = { 0 }; + std::vector ubMercsInSector (CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS, 0); + UINT8 ubNumMercs = 0; + UINT8 ubChosenMerc; + SOLDIERTYPE *pTeamSoldier; + INT32 cnt; + INT32 uiTime; - // Check for quote seeing creature attacks.... - if ( gubQuest[ QUEST_CREATURES ] != QUESTDONE ) - { - if ( gTacticalStatus.uiFlags & IN_CREATURE_LAIR ) - { - if( !(gTacticalStatus.uiFlags & INCOMBAT ) ) - { - uiTime = GetJA2Clock( ); + // Check for quote seeing creature attacks.... + if ( gubQuest[ QUEST_CREATURES ] != QUESTDONE ) + { + if ( gTacticalStatus.uiFlags & IN_CREATURE_LAIR ) + { + if( !(gTacticalStatus.uiFlags & INCOMBAT ) ) + { + uiTime = GetJA2Clock( ); - if ( ( uiTime - gTacticalStatus.uiCreatureTenseQuoteLastUpdate ) > (UINT32)( gTacticalStatus.sCreatureTenseQuoteDelay * 1000 ) ) - { - gTacticalStatus.uiCreatureTenseQuoteLastUpdate = uiTime; + if ( ( uiTime - gTacticalStatus.uiCreatureTenseQuoteLastUpdate ) > (UINT32)( gTacticalStatus.sCreatureTenseQuoteDelay * 1000 ) ) + { + gTacticalStatus.uiCreatureTenseQuoteLastUpdate = uiTime; - // set up soldier ptr as first element in mercptrs list - cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; + // set up soldier ptr as first element in mercptrs list + cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; - // run through list - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ ) - { - // Add guy if he's a candidate... - if ( OK_INSECTOR_MERC( pTeamSoldier ) && !AM_AN_EPC( pTeamSoldier ) && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_GASSED ) && !(AM_A_ROBOT( pTeamSoldier )) && !pTeamSoldier->flags.fMercAsleep ) - { - ubMercsInSector[ ubNumMercs ] = (UINT8)cnt; - ubNumMercs++; - } - } + // run through list + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ ) + { + // Add guy if he's a candidate... + if ( OK_INSECTOR_MERC( pTeamSoldier ) && !AM_AN_EPC( pTeamSoldier ) && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_GASSED ) && !(AM_A_ROBOT( pTeamSoldier )) && !pTeamSoldier->flags.fMercAsleep ) + { + ubMercsInSector[ ubNumMercs ] = (UINT8)cnt; + ubNumMercs++; + } + } - // If we are > 0 - if ( ubNumMercs > 0 ) - { - ubChosenMerc = (UINT8)Random( ubNumMercs ); + // If we are > 0 + if ( ubNumMercs > 0 ) + { + ubChosenMerc = (UINT8)Random( ubNumMercs ); - DoCreatureTensionQuote ( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ] ); - } + DoCreatureTensionQuote ( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ] ); + } - // Adjust delay.... - gTacticalStatus.sCreatureTenseQuoteDelay = (INT16)( 60 + Random( 60 ) ); + // Adjust delay.... + gTacticalStatus.sCreatureTenseQuoteDelay = (INT16)( 60 + Random( 60 ) ); - } - } - } - } + } + } + } + } } void DoCreatureTensionQuote( SOLDIERTYPE *pSoldier ) { - INT32 iRandomQuote; - BOOLEAN fCanDoQuote = TRUE; - INT32 iQuoteToUse; + INT32 iRandomQuote; + BOOLEAN fCanDoQuote = TRUE; + INT32 iQuoteToUse; - // Check for playing smell quote.... - iRandomQuote = Random( 3 ); + // Check for playing smell quote.... + iRandomQuote = Random( 3 ); - switch( iRandomQuote ) - { - case 0: + switch( iRandomQuote ) + { + case 0: - iQuoteToUse = QUOTE_SMELLED_CREATURE; - if ( !( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_SMELLED_CREATURE ) ) - { - // set flag - pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_SMELLED_CREATURE; - } - else - { - fCanDoQuote = FALSE; - } - break; + iQuoteToUse = QUOTE_SMELLED_CREATURE; + if ( !( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_SMELLED_CREATURE ) ) + { + // set flag + pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_SMELLED_CREATURE; + } + else + { + fCanDoQuote = FALSE; + } + break; - case 1: + case 1: - iQuoteToUse = QUOTE_TRACES_OF_CREATURE_ATTACK; - if ( !( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_SPOTTING_CREATURE_ATTACK ) ) - { - // set flag - pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_SPOTTING_CREATURE_ATTACK; - } - else - { - fCanDoQuote = FALSE; - } - break; + iQuoteToUse = QUOTE_TRACES_OF_CREATURE_ATTACK; + if ( !( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_SPOTTING_CREATURE_ATTACK ) ) + { + // set flag + pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_SPOTTING_CREATURE_ATTACK; + } + else + { + fCanDoQuote = FALSE; + } + break; - case 2: + case 2: - iQuoteToUse = QUOTE_WORRIED_ABOUT_CREATURE_PRESENCE; - if ( !( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_WORRIED_ABOUT_CREATURES ) ) - { - // set flag - pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_WORRIED_ABOUT_CREATURES; - } - else - { - fCanDoQuote = FALSE; - } - break; - default: - AssertMsg(0, "Invalid quote"); - return; - } + iQuoteToUse = QUOTE_WORRIED_ABOUT_CREATURE_PRESENCE; + if ( !( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_WORRIED_ABOUT_CREATURES ) ) + { + // set flag + pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_WORRIED_ABOUT_CREATURES; + } + else + { + fCanDoQuote = FALSE; + } + break; + default: + AssertMsg(0, "Invalid quote"); + return; + } - if ( fCanDoQuote ) - { - TacticalCharacterDialogue( pSoldier, (INT16)iQuoteToUse ); - } + if ( fCanDoQuote ) + { + TacticalCharacterDialogue( pSoldier, (INT16)iQuoteToUse ); + } } // Kaiden: Taken from UB to reveal all items after combat. void RevealAllDroppedEnemyItems() { - UINT32 uiCnt=0; + UINT32 uiCnt=0; - //loop through all the items - for(uiCnt=0; uiCntbTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; iCounter ++ ) - { - pLeader = MercPtrs[ iCounter ]; - // Make sure that character is alive, not too shocked, and conscious, and of higher experience level - // than the character being suppressed. - if (pLeader != pSoldier && pLeader->bActive && pLeader->aiData.bShock < pLeader->stats.bLeadership/5 && - pLeader->stats.bLife >= OKLIFE ) - { - ubLevelDifference = (pLeader->stats.bExpLevel - pSoldier->stats.bExpLevel ); - // Calculate character's leadership and range/3 - usEffectiveLeadership = ((EffectiveLeadership( pLeader ) - 25) / 15); - usEffectiveRangeToLeader = PythSpacesAway( pSoldier->sGridNo, pLeader->sGridNo ) / 3; + // Run through each friendly. + for ( UINT8 iCounter = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; iCounter ++ ) + { + pLeader = MercPtrs[ iCounter ]; + // Make sure that character is alive, not too shocked, and conscious, and of higher experience level + // than the character being suppressed. + if (pLeader != pSoldier && pLeader->bActive && pLeader->aiData.bShock < pLeader->stats.bLeadership/5 && + pLeader->stats.bLife >= OKLIFE ) + { + ubLevelDifference = (pLeader->stats.bExpLevel - pSoldier->stats.bExpLevel ); + // Calculate character's leadership and range/3 + usEffectiveLeadership = ((EffectiveLeadership( pLeader ) - 25) / 15); + usEffectiveRangeToLeader = PythSpacesAway( pSoldier->sGridNo, pLeader->sGridNo ) / 3; - // SANDRO - add effective leadership and level to determine if we can help our friend to feel better :) - if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pLeader, SQUADLEADER_NT ) ) - { - ubLevelDifference += (gSkillTraitValues.ubSLEffectiveLevelAsStandby * NUM_SKILL_TRAITS( pLeader, SQUADLEADER_NT )); - usEffectiveLeadership += (gSkillTraitValues.ubSLEffectiveLevelAsStandby * NUM_SKILL_TRAITS( pLeader, SQUADLEADER_NT )); - } + // SANDRO - add effective leadership and level to determine if we can help our friend to feel better :) + if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pLeader, SQUADLEADER_NT ) ) + { + ubLevelDifference += (gSkillTraitValues.ubSLEffectiveLevelAsStandby * NUM_SKILL_TRAITS( pLeader, SQUADLEADER_NT )); + usEffectiveLeadership += (gSkillTraitValues.ubSLEffectiveLevelAsStandby * NUM_SKILL_TRAITS( pLeader, SQUADLEADER_NT )); + } - if ( ubLevelDifference >= 0 ) - { - // If leader is within range of his leadership stat - if (usEffectiveRangeToLeader <= usEffectiveLeadership+1) - { - // The difference in experience level is important! - usEffectiveLeadership += ubLevelDifference; - // Reduce effective leadership with every 3 tiles of distance - usEffectiveLeadership -= usEffectiveRangeToLeader-1; + if ( ubLevelDifference >= 0 ) + { + // If leader is within range of his leadership stat + if (usEffectiveRangeToLeader <= usEffectiveLeadership+1) + { + // The difference in experience level is important! + usEffectiveLeadership += ubLevelDifference; + // Reduce effective leadership with every 3 tiles of distance + usEffectiveLeadership -= usEffectiveRangeToLeader-1; - // If this is the best leader we've seen so far, - if (usEffectiveLeadership > usBestLeader) - { - // Set this as the best leader - usBestLeader = usEffectiveLeadership; - } - // Friends within range always give at least one tolerance bonus point. - usFriendBonus += 1; - } - } - } - // Incapacitated or heavily suppressed friends will not be good for our tolerance! - else if (pLeader != pSoldier && pLeader->bActive && (pLeader->aiData.bShock > pSoldier->aiData.bShock || pLeader->stats.bLife <= OKLIFE) ) - { - usEffectiveRangeToLeader = PythSpacesAway( pSoldier->sGridNo, pLeader->sGridNo ); - // If they are no more than 5 tiles away, - if (usEffectiveRangeToLeader <= 5) - { - // Penalty is based on the difference between experience levels, and the range between them, - // and is never less than 1 point. - usEffectiveLeadership = (pLeader->stats.bExpLevel - pSoldier->stats.bExpLevel) / __max(1,(usEffectiveRangeToLeader/2)); - usFriendBonus -= __max(1, usEffectiveLeadership); - } - // SANDRO - however, dead squadleader is very bad for our psychics - if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pLeader, SQUADLEADER_NT ) && - ( pLeader->flags.uiStatusFlags & SOLDIER_DEAD ) && usEffectiveRangeToLeader <= 10 ) - { - usFriendBonus -= ( gSkillTraitValues.ubSLDeathMoralelossMultiplier * NUM_SKILL_TRAITS( pLeader, SQUADLEADER_NT )); - } - } - } + // If this is the best leader we've seen so far, + if (usEffectiveLeadership > usBestLeader) + { + // Set this as the best leader + usBestLeader = usEffectiveLeadership; + } + // Friends within range always give at least one tolerance bonus point. + usFriendBonus += 1; + } + } + } + // Incapacitated or heavily suppressed friends will not be good for our tolerance! + else if (pLeader != pSoldier && pLeader->bActive && (pLeader->aiData.bShock > pSoldier->aiData.bShock || pLeader->stats.bLife <= OKLIFE) ) + { + usEffectiveRangeToLeader = PythSpacesAway( pSoldier->sGridNo, pLeader->sGridNo ); + // If they are no more than 5 tiles away, + if (usEffectiveRangeToLeader <= 5) + { + // Penalty is based on the difference between experience levels, and the range between them, + // and is never less than 1 point. + usEffectiveLeadership = (pLeader->stats.bExpLevel - pSoldier->stats.bExpLevel) / __max(1,(usEffectiveRangeToLeader/2)); + usFriendBonus -= __max(1, usEffectiveLeadership); + } + // SANDRO - however, dead squadleader is very bad for our psychics + if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pLeader, SQUADLEADER_NT ) && + ( pLeader->flags.uiStatusFlags & SOLDIER_DEAD ) && usEffectiveRangeToLeader <= 10 ) + { + usFriendBonus -= ( gSkillTraitValues.ubSLDeathMoralelossMultiplier * NUM_SKILL_TRAITS( pLeader, SQUADLEADER_NT )); + } + } + } - // If we did find someone who's a good enough leader to help us out, - if (usBestLeader > 0) - { - // Add his leadership bonus, minus the point we got for him before. He'll give at least one - // point, like anybody else. - usFriendBonus += __max(usBestLeader-1, 1); - } + // If we did find someone who's a good enough leader to help us out, + if (usBestLeader > 0) + { + // Add his leadership bonus, minus the point we got for him before. He'll give at least one + // point, like anybody else. + usFriendBonus += __max(usBestLeader-1, 1); + } - // Add no more than five points for nearby friends. - usFriendBonus = __min(usFriendBonus, 5); - usFriendBonus = __max(usFriendBonus, -5); - sModifier += usFriendBonus; + // Add no more than five points for nearby friends. + usFriendBonus = __min(usFriendBonus, 5); + usFriendBonus = __max(usFriendBonus, -5); + sModifier += usFriendBonus; - return(sModifier); + return(sModifier); } @@ -10016,101 +9831,101 @@ INT8 CheckStatusNearbyFriendlies( SOLDIERTYPE *pSoldier ) #ifdef JA2UB void SetMsgBoxForPlayerBeNotifiedOfSomeoneElseInSector() { - //if the player in the same sector as MANUEL - if( !CanMsgBoxForPlayerToBeNotifiedOfSomeoneElseInSector() ) - { - return; - } + //if the player in the same sector as MANUEL + if( !CanMsgBoxForPlayerToBeNotifiedOfSomeoneElseInSector() ) + { + return; + } - gJa25SaveStruct.fShouldMsgBoxComeUpSayingSomeoneImportantIsInSector = TRUE; + gJa25SaveStruct.fShouldMsgBoxComeUpSayingSomeoneImportantIsInSector = TRUE; } void HandleThePlayerBeNotifiedOfSomeoneElseInSector() { - //if we shouldnt be here, get out - if( !gJa25SaveStruct.fShouldMsgBoxComeUpSayingSomeoneImportantIsInSector ) - { - return; - } + //if we shouldnt be here, get out + if( !gJa25SaveStruct.fShouldMsgBoxComeUpSayingSomeoneImportantIsInSector ) + { + return; + } - //if somehting else is going on, leave - if( gTacticalStatus.fAutoBandageMode || - DialogueActive( ) || - gTacticalStatus.fAutoBandagePending || - guiPendingScreen == MSG_BOX_SCREEN || - guiCurrentScreen == MSG_BOX_SCREEN || - AreWeInAUIMenu( ) - ) - { - return; - } + //if somehting else is going on, leave + if( gTacticalStatus.fAutoBandageMode || + DialogueActive( ) || + gTacticalStatus.fAutoBandagePending || + guiPendingScreen == MSG_BOX_SCREEN || + guiCurrentScreen == MSG_BOX_SCREEN || + AreWeInAUIMenu( ) + ) + { + return; + } - gJa25SaveStruct.fShouldMsgBoxComeUpSayingSomeoneImportantIsInSector = FALSE; + gJa25SaveStruct.fShouldMsgBoxComeUpSayingSomeoneImportantIsInSector = FALSE; - //if the player in the same sector as MANUEL - if( !CanMsgBoxForPlayerToBeNotifiedOfSomeoneElseInSector() ) - { - return; - } + //if the player in the same sector as MANUEL + if( !CanMsgBoxForPlayerToBeNotifiedOfSomeoneElseInSector() ) + { + return; + } - DoMessageBox( MSG_BOX_BASIC_STYLE, zNewTacticalMessages[ TACT_MSG__SOMEONE_ELSE_IN_SECTOR ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, NULL, NULL ); + DoMessageBox( MSG_BOX_BASIC_STYLE, zNewTacticalMessages[ TACT_MSG__SOMEONE_ELSE_IN_SECTOR ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, NULL, NULL ); } BOOLEAN CanMsgBoxForPlayerToBeNotifiedOfSomeoneElseInSector() { - // ATE: if this is a custom map, return -/* if ( gbWorldSectorZ == 0 ) - { - if ( SectorInfo[ SECTOR( gWorldSectorY, gWorldSectorX ) ].fCustomSector ) - { - return( FALSE ); - } - } -*/ - if( ( gWorldSectorX == gMercProfiles[ 60 ].sSectorX && gWorldSectorY == gMercProfiles[ 60 ].sSectorY && gbWorldSectorZ == gMercProfiles[ 60 ].bSectorZ ) ) - { - //IF MANUEL is already hired - if( gMercProfiles[ 60 ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED ) - { - //then we shouldnt display the message - return( FALSE ); - } + // ATE: if this is a custom map, return + /* if ( gbWorldSectorZ == 0 ) + { + if ( SectorInfo[ SECTOR( gWorldSectorY, gWorldSectorX ) ].fCustomSector ) + { + return( FALSE ); + } + } + */ + if( ( gWorldSectorX == gMercProfiles[ 60 ].sSectorX && gWorldSectorY == gMercProfiles[ 60 ].sSectorY && gbWorldSectorZ == gMercProfiles[ 60 ].bSectorZ ) ) + { + //IF MANUEL is already hired + if( gMercProfiles[ 60 ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED ) + { + //then we shouldnt display the message + return( FALSE ); + } - return( TRUE ); - } + return( TRUE ); + } - return( FALSE ); + return( FALSE ); } INT8 NumMercsOnPlayerTeam( ) { - INT32 cnt; - SOLDIERTYPE *pSoldier; - UINT8 ubCount = 0; + INT32 cnt; + SOLDIERTYPE *pSoldier; + UINT8 ubCount = 0; - cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; + cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; - // look for all mercs on the same team, - for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++,pSoldier++) - { - if( pSoldier->bActive && pSoldier->stats.bLife > 0 ) - { - ubCount++; - } - } + // look for all mercs on the same team, + for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++,pSoldier++) + { + if( pSoldier->bActive && pSoldier->stats.bLife > 0 ) + { + ubCount++; + } + } - return( ubCount ); + return( ubCount ); } -void HandleDisplayingOfPlayerLostDialogue( void ) +void HandleDisplayingOfPlayerLostDialogue( ) { - //if the laptop transmitter is broken, and the player doesnt have any other team members - if( gubQuest[ QUEST_FIX_LAPTOP ] != QUESTDONE && NumMercsOnPlayerTeam( ) == 0 && gGameUBOptions.LaptopQuestEnabled == TRUE ) - { - gJa25SaveStruct.ubDisplayPlayerLostMsgBox = 1; - } + //if the laptop transmitter is broken, and the player doesnt have any other team members + if( gubQuest[ QUEST_FIX_LAPTOP ] != QUESTDONE && NumMercsOnPlayerTeam( ) == 0 && gGameUBOptions.LaptopQuestEnabled == TRUE ) + { + gJa25SaveStruct.ubDisplayPlayerLostMsgBox = 1; + } } #endif @@ -10118,211 +9933,212 @@ static UINT8 prisonerdialoguetargetID = 0; void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue ) { - SOLDIERTYPE *pSoldier = NULL; - UINT32 uiCnt=0; - BOOLEAN success = FALSE; + SOLDIERTYPE *pSoldier = NULL; + UINT32 uiCnt=0; + BOOLEAN success = FALSE; - if ( ubExitValue == 1 ) - { - if ( !gGameExternalOptions.fEnemyCanSurrender ) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[ SRT_PRISONER_INI_SETTING_OFF ] ); - return; - } + if ( ubExitValue == 1 ) + { + if ( !gGameExternalOptions.fEnemyCanSurrender ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[ SRT_PRISONER_INI_SETTING_OFF ] ); + return; + } - // we have to remove the region, as we are calling a message from within a messagebox - MSYS_RemoveRegion(&(gMsgBox.BackRegion) ); + // we have to remove the region, as we are calling a message from within a messagebox + MSYS_RemoveRegion(&(gMsgBox.BackRegion) ); - // we determine the chance that enemy will surrender. This depends on the strength of our and their side - UINT32 playersidestrength = 0; - UINT32 enemysidestrength = 0; - - // player team - UINT32 firstid = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; - UINT32 lastid = gTacticalStatus.Team[ gbPlayerNum ].bLastID; - for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) - { - if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) ) - { - // if we are disguised as a civilian, the enemy does not take us into the equation - he does not consider us - if ( pSoldier->bSoldierFlagMask & SOLDIER_COVERT_CIV ) - ; - // if we are disguised as a soldier, the enemy counts us on HIS team - else if ( pSoldier->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER ) - enemysidestrength += pSoldier->GetSurrenderStrength(); - else - // player side counts double, to put more emphasize on overwhelming the enemy with mercs and not just spamming militia - playersidestrength += 2 * pSoldier->GetSurrenderStrength(); - } - } + // we determine the chance that enemy will surrender. This depends on the strength of our and their side + UINT32 playersidestrength = 0; + UINT32 enemysidestrength = 0; - // militia team - firstid = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; - lastid = gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; - for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) - { - if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) ) - { - playersidestrength += pSoldier->GetSurrenderStrength(); - } - } + // player team + UINT32 firstid = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; + UINT32 lastid = gTacticalStatus.Team[ gbPlayerNum ].bLastID; + for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) + { + if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) ) + { + // if we are disguised as a civilian, the enemy does not take us into the equation - he does not consider us + if ( pSoldier->bSoldierFlagMask & SOLDIER_COVERT_CIV ) + ; + // if we are disguised as a soldier, the enemy counts us on HIS team + else if ( pSoldier->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER ) + enemysidestrength += pSoldier->GetSurrenderStrength(); + else + // player side counts double, to put more emphasize on overwhelming the enemy with mercs and not just spamming militia + playersidestrength += 2 * pSoldier->GetSurrenderStrength(); + } + } - // enemy team - firstid = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; - lastid = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; - for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) - { - if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) ) - { - enemysidestrength += pSoldier->GetSurrenderStrength(); - } - } + // militia team + firstid = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; + lastid = gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; + for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) + { + if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) ) + { + playersidestrength += pSoldier->GetSurrenderStrength(); + } + } - // print out values - if ( gGameExternalOptions.fDisplaySurrenderSValues ) - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"PlayerStrength : %d Enemystrength: %6.0f", playersidestrength, gGameExternalOptions.fSurrenderMultiplier * enemysidestrength ); + // enemy team + firstid = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; + lastid = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; + for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) + { + if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) ) + { + enemysidestrength += pSoldier->GetSurrenderStrength(); + } + } - // perhaps this can be fleshed out more, for now, let's see if this is acceptable behaviour - if ( playersidestrength >= gGameExternalOptions.fSurrenderMultiplier * enemysidestrength ) - { - // it is enough to simply set all soldiers to captured - firstid = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; - lastid = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; - for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) - { - if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) ) - { - // only if not dying, and if not a NPC (Mike...) - if( pSoldier->stats.bLife >= OKLIFE && pSoldier->ubProfile == NO_PROFILE ) - { - pSoldier->bSoldierFlagMask |= SOLDIER_POW; + // print out values + if ( gGameExternalOptions.fDisplaySurrenderSValues ) + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"PlayerStrength : %d Enemystrength: %6.0f", playersidestrength, gGameExternalOptions.fSurrenderMultiplier * enemysidestrength ); - // Remove as target - RemoveManAsTarget( pSoldier ); - } - } - } - } - else - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_REFUSE_SURRENDER] ); + // perhaps this can be fleshed out more, for now, let's see if this is acceptable behaviour + if ( playersidestrength >= gGameExternalOptions.fSurrenderMultiplier * enemysidestrength ) + { + // it is enough to simply set all soldiers to captured + firstid = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; + lastid = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; + for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) + { + if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) ) + { + // only if not dying, and if not a NPC (Mike...) + if( pSoldier->stats.bLife >= OKLIFE && pSoldier->ubProfile == NO_PROFILE ) + { + pSoldier->bSoldierFlagMask |= SOLDIER_POW; - // if asking for surrender while undercover and the enemy refuses, he learns who you are, so he uncovers you - if ( gusSelectedSoldier != NOBODY && MercPtrs[ gusSelectedSoldier ]->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) ) - { - MercPtrs[ gusSelectedSoldier ]->LooseDisguise(); + // Remove as target + RemoveManAsTarget( pSoldier ); + } + } + } + } + else + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_REFUSE_SURRENDER] ); - MercPtrs[ gusSelectedSoldier ]->Strip(); + // if asking for surrender while undercover and the enemy refuses, he learns who you are, so he uncovers you + if ( gusSelectedSoldier != NOBODY && MercPtrs[ gusSelectedSoldier ]->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) ) + { + MercPtrs[ gusSelectedSoldier ]->LooseDisguise(); - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_SURRENDER_FAILED] ); - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_UNCOVER_SINGLE], MercPtrs[ gusSelectedSoldier ]->GetName() ); - } - } - } - // we offered to surrender OURSELVES TO the enemy - else if ( ubExitValue == 2 ) - { - if ( !gGameExternalOptions.fPlayerCanAsktoSurrender ) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[ SRT_PRISONER_INI_SETTING_OFF ] ); - return; - } + MercPtrs[ gusSelectedSoldier ]->Strip(); - // in order for this to work, there must be no militia present, the enemy must not already have offered asked you to surrender, and certain quests may not be active - if ( !( gTacticalStatus.fEnemyFlags & ENEMY_OFFERED_SURRENDER ) && gTacticalStatus.Team[ MILITIA_TEAM ].bMenInSector == 0 ) - { - if ( gubQuest[ QUEST_HELD_IN_ALMA ] == QUESTNOTSTARTED || ( gubQuest[ QUEST_HELD_IN_ALMA ] == QUESTDONE && gubQuest[ QUEST_INTERROGATION ] == QUESTNOTSTARTED ) ) - { - gTacticalStatus.fEnemyFlags |= ENEMY_OFFERED_SURRENDER; + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_SURRENDER_FAILED] ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_UNCOVER_SINGLE], MercPtrs[ gusSelectedSoldier ]->GetName() ); + } + } + } + // we offered to surrender OURSELVES TO the enemy + else if ( ubExitValue == 2 ) + { + if ( !gGameExternalOptions.fPlayerCanAsktoSurrender ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[ SRT_PRISONER_INI_SETTING_OFF ] ); + return; + } - // CJC Dec 1 2002: fix multiple captures - BeginCaptureSquence(); + // in order for this to work, there must be no militia present, the enemy must not already have offered asked you to surrender, and certain quests may not be active + if ( !( gTacticalStatus.fEnemyFlags & ENEMY_OFFERED_SURRENDER ) && gTacticalStatus.Team[ MILITIA_TEAM ].bMenInSector == 0 ) + { + if ( gubQuest[ QUEST_HELD_IN_ALMA ] == QUESTNOTSTARTED || ( gubQuest[ QUEST_HELD_IN_ALMA ] == QUESTDONE && gubQuest[ QUEST_INTERROGATION ] == QUESTNOTSTARTED ) ) + { + gTacticalStatus.fEnemyFlags |= ENEMY_OFFERED_SURRENDER; - // Do capture.... - uiCnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; - for ( pSoldier = MercPtrs[ uiCnt ]; uiCnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++uiCnt, ++pSoldier) - { - // Are we active and in sector..... - if ( pSoldier->bActive && pSoldier->bInSector ) - { - if ( pSoldier->stats.bLife != 0 ) - { - EnemyCapturesPlayerSoldier( pSoldier ); + // CJC Dec 1 2002: fix multiple captures + BeginCaptureSquence(); - RemoveSoldierFromTacticalSector( pSoldier, TRUE ); - } - } - } + // Do capture.... + uiCnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; + for ( pSoldier = MercPtrs[ uiCnt ]; uiCnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++uiCnt, ++pSoldier) + { + // Are we active and in sector..... + if ( pSoldier->bActive && pSoldier->bInSector ) + { + if ( pSoldier->stats.bLife != 0 ) + { + EnemyCapturesPlayerSoldier( pSoldier ); - EndCaptureSequence( ); + RemoveSoldierFromTacticalSector( pSoldier, TRUE ); + } + } + } - gfSurrendered = TRUE; - SetCustomizableTimerCallbackAndDelay( 3000, CaptureTimerCallback, FALSE ); + EndCaptureSequence( ); - success = TRUE; - } - } + gfSurrendered = TRUE; + SetCustomizableTimerCallbackAndDelay( 3000, CaptureTimerCallback, FALSE ); - if ( !success ) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[ STR_PRISONER_REFUSE_TAKE_PRISONERS ] ); - } - } - else - { - // normal dialog - StartCivQuote( MercPtrs[ prisonerdialoguetargetID ] ); - } + success = TRUE; + } + } - ReduceAttackBusyCount( ); + if ( !success ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[ STR_PRISONER_REFUSE_TAKE_PRISONERS ] ); + } + } + else + { + // normal dialog + StartCivQuote( MercPtrs[ prisonerdialoguetargetID ] ); + } + + ReduceAttackBusyCount( ); } // Flugente: offer the enemy the chance to surrender void HandleSurrenderOffer( SOLDIERTYPE* pSoldier ) { - // only against enemies... - if ( !pSoldier || pSoldier->bTeam != ENEMY_TEAM ) - return; + // only against enemies... + if ( !pSoldier || pSoldier->bTeam != ENEMY_TEAM ) + return; - // remember the target's ID - prisonerdialoguetargetID = pSoldier->ubID; + // remember the target's ID + prisonerdialoguetargetID = pSoldier->ubID; - // open a dialogue box and see wether we really want to offer this, or just talk - wcscpy( gzUserDefinedButton[0], TacticalStr[ PRISONER_DEMAND_SURRENDER_STR ] ); - wcscpy( gzUserDefinedButton[1], TacticalStr[ PRISONER_OFFER_SURRENDER_STR ] ); - wcscpy( gzUserDefinedButton[2], TacticalStr[ PRISONER_TALK_STR ] ); - wcscpy( gzUserDefinedButton[3], TacticalStr[ PRISONER_TALK_STR ] ); - DoMessageBox( MSG_BOX_BASIC_MEDIUM_BUTTONS, TacticalStr[ PRISONER_OFFER_SURRENDER ], guiCurrentScreen, MSG_BOX_FLAG_GENERIC_FOUR_BUTTONS, PrisonerSurrenderMessageBoxCallBack, NULL ); + // open a dialogue box and see wether we really want to offer this, or just talk + wcscpy( gzUserDefinedButton[0], TacticalStr[ PRISONER_DEMAND_SURRENDER_STR ] ); + wcscpy( gzUserDefinedButton[1], TacticalStr[ PRISONER_OFFER_SURRENDER_STR ] ); + wcscpy( gzUserDefinedButton[2], TacticalStr[ PRISONER_TALK_STR ] ); + wcscpy( gzUserDefinedButton[3], TacticalStr[ PRISONER_TALK_STR ] ); + DoMessageBox( MSG_BOX_BASIC_MEDIUM_BUTTONS, TacticalStr[ PRISONER_OFFER_SURRENDER ], guiCurrentScreen, MSG_BOX_FLAG_GENERIC_FOUR_BUTTONS, PrisonerSurrenderMessageBoxCallBack, NULL ); } void TeamDropAll(UINT8 bTeam, BOOLEAN fForce) { - if ( bTeam > PLAYER_PLAN ) - return; + if ( bTeam > PLAYER_PLAN ) + return; - // not if there is a battle going on - if ( (gTacticalStatus.uiFlags & INCOMBAT ) && !fForce ) - return; + // not if there is a battle going on + if ( (gTacticalStatus.uiFlags & INCOMBAT ) && !fForce ) + return; - // not if this team is hostile to us - if ( gTacticalStatus.Team[ gbPlayerNum ].bSide != gTacticalStatus.Team[ bTeam ].bSide ) - return; + // not if this team is hostile to us + if ( gTacticalStatus.Team[ gbPlayerNum ].bSide != gTacticalStatus.Team[ bTeam ].bSide ) + return; - SOLDIERTYPE *pSoldier; + SOLDIERTYPE *pSoldier; #ifdef JA2BETAVERSION - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Team %d drops all items for inspection!", bTeam ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Team %d drops all items for inspection!", bTeam ); #endif - UINT32 uiCnt = 0; - UINT32 firstid = gTacticalStatus.Team[ bTeam ].bFirstID; - UINT32 lastid = gTacticalStatus.Team[ bTeam ].bLastID; - for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) - { - // if soldier is in the current sector, drop all equipment (that has the TAKEN_BY_MILITIA-flag set) - if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) ) - { - pSoldier->DropSectorEquipment(); - } - } + UINT32 uiCnt = 0; + UINT32 firstid = gTacticalStatus.Team[ bTeam ].bFirstID; + UINT32 lastid = gTacticalStatus.Team[ bTeam ].bLastID; + for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) + { + // if soldier is in the current sector, drop all equipment (that has the TAKEN_BY_MILITIA-flag set) + if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) ) + { + pSoldier->DropSectorEquipment(); + } + } } + diff --git a/Tactical/Overhead.h b/Tactical/Overhead.h index a303cdd5..7b9ce81d 100644 --- a/Tactical/Overhead.h +++ b/Tactical/Overhead.h @@ -6,215 +6,193 @@ #include "Soldier Control.h" #include "overhead types.h" #include "soldier find.h" -#define ADD_SOLDIER_NO_PROFILE_ID 200 +#define ADD_SOLDIER_NO_PROFILE_ID 200 -#define MAX_REALTIME_SPEED_VAL 10 - -/* -enum -{ - TOPTION_SUBTITLES, - TOPTION_SPEECH, - TOPTION_KEY_ADVANCE_SPEECH, - TOPTION_RTCONFIRM, - TOPTION_HIDE_BULLETS, - TOPTION_TRACKING_MODE, - TOPTION_CONFIRM_MOVE, - TOPTION_MUTE_CONFIRMATIONS, - TOPTION_SHADOWS, - TOPTION_BLOOD_N_GORE, - - NUM_TOPTIONS -}; -*/ +#define MAX_REALTIME_SPEED_VAL 10 // Enums for waiting for mercs to finish codes enum -{ - NO_WAIT_EVENT = 0, - WAIT_FOR_MERCS_TO_WALKOFF_SCREEN, - WAIT_FOR_MERCS_TO_WALKON_SCREEN, - WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO +{ + NO_WAIT_EVENT = 0, + WAIT_FOR_MERCS_TO_WALKOFF_SCREEN, + WAIT_FOR_MERCS_TO_WALKON_SCREEN, + WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO }; - - // TACTICAL ENGINE STATUS FLAGS typedef struct { - UINT8 bFirstID; - UINT8 bLastID; - COLORVAL RadarColor; - INT8 bSide; - INT8 bMenInSector; - UINT8 ubLastMercToRadio; - INT8 bTeamActive; - INT8 bAwareOfOpposition; - INT8 bHuman; + UINT8 bFirstID; + UINT8 bLastID; + COLORVAL RadarColor; + INT8 bSide; + INT8 bMenInSector; + UINT8 ubLastMercToRadio; + INT8 bTeamActive; + INT8 bAwareOfOpposition; + INT8 bHuman; } TacticalTeamType; //for use with TacticalStatusType.ubEnemyIntention enum { - INTENTION_SCOUTING, - INTENTION_PATROLLING, - INTENTION_ATTACKING, - INTENTION_DEFENDING, - INTENTION_RETREATING + INTENTION_SCOUTING, + INTENTION_PATROLLING, + INTENTION_ATTACKING, + INTENTION_DEFENDING, + INTENTION_RETREATING }; //for use with TacticalStatusType.ubEnemyIntendedRetreatDirection enum { - RETREAT_NORTH, - RETREAT_EAST, - RETREAT_SOUTH, - RETREAT_WEST + RETREAT_NORTH, + RETREAT_EAST, + RETREAT_SOUTH, + RETREAT_WEST }; -#define PANIC_BOMBS_HERE 0x01 -#define PANIC_TRIGGERS_HERE 0x02 - -#define NUM_PANIC_TRIGGERS 3 - +#define PANIC_BOMBS_HERE 0x01 +#define PANIC_TRIGGERS_HERE 0x02 +#define NUM_PANIC_TRIGGERS 3 #define ENEMY_OFFERED_SURRENDER 0x01 typedef struct { - UINT32 uiFlags; - TacticalTeamType Team[ MAXTEAMS ]; - UINT8 ubCurrentTeam; - INT32 sSlideTarget; - INT16 sSlideReason; - UINT32 uiTimeSinceMercAIStart; - INT8 fPanicFlags; - INT32 sPanicTriggerGridNoUnused; - INT16 sHandGrid; - UINT8 ubSpottersCalledForBy; - UINT8 ubTheChosenOne; - UINT32 uiTimeOfLastInput; - UINT32 uiTimeSinceDemoOn; - UINT32 uiCountdownToRestart; - BOOLEAN fGoingToEnterDemo; - BOOLEAN fNOTDOLASTDEMO; - BOOLEAN fMultiplayer; - BOOLEAN fCivGroupHostile[ NUM_CIV_GROUPS ]; - UINT8 ubLastBattleSectorX; - UINT8 ubLastBattleSectorY; - BOOLEAN fLastBattleWon; - INT8 bOriginalSizeOfEnemyForce; - INT8 bPanicTriggerIsAlarmUnused; - BOOLEAN fVirginSector; - BOOLEAN fEnemyInSector; - BOOLEAN fInterruptOccurred; - INT8 bRealtimeSpeed; - UINT8 ubEnemyIntention; - UINT8 ubEnemyIntendedRetreatDirection; - UINT8 ubEnemySightingOnTheirTurnEnemyID; - UINT8 ubEnemySightingOnTheirTurnPlayerID; - BOOLEAN fEnemySightingOnTheirTurn; - BOOLEAN fAutoBandageMode; - UINT8 ubAttackBusyCount; - INT8 bNumEnemiesFoughtInBattleUnused; - UINT8 ubEngagedInConvFromActionMercID; - UINT16 usTactialTurnLimitCounter; - BOOLEAN fInTopMessage; - UINT8 ubTopMessageType; - CHAR16 zTopMessageString[20]; - UINT16 usTactialTurnLimitMax; - UINT32 uiTactialTurnLimitClock; - BOOLEAN fTactialTurnLimitStartedBeep; - INT8 bBoxingState; - INT8 bConsNumTurnsNotSeen; - UINT8 ubArmyGuysKilled; + UINT32 uiFlags; + TacticalTeamType Team[ MAXTEAMS ]; + UINT8 ubCurrentTeam; + INT32 sSlideTarget; + INT16 sSlideReason; + UINT32 uiTimeSinceMercAIStart; + INT8 fPanicFlags; + INT32 sPanicTriggerGridNoUnused; + INT16 sHandGrid; + UINT8 ubSpottersCalledForBy; + UINT8 ubTheChosenOne; + UINT32 uiTimeOfLastInput; + UINT32 uiTimeSinceDemoOn; + UINT32 uiCountdownToRestart; + BOOLEAN fGoingToEnterDemo; + BOOLEAN fNOTDOLASTDEMO; + BOOLEAN fMultiplayer; + BOOLEAN fCivGroupHostile[ NUM_CIV_GROUPS ]; + UINT8 ubLastBattleSectorX; + UINT8 ubLastBattleSectorY; + BOOLEAN fLastBattleWon; + INT8 bOriginalSizeOfEnemyForce; + INT8 bPanicTriggerIsAlarmUnused; + BOOLEAN fVirginSector; + BOOLEAN fEnemyInSector; + BOOLEAN fInterruptOccurred; + INT8 bRealtimeSpeed; + UINT8 ubEnemyIntention; + UINT8 ubEnemyIntendedRetreatDirection; + UINT8 ubEnemySightingOnTheirTurnEnemyID; + UINT8 ubEnemySightingOnTheirTurnPlayerID; + BOOLEAN fEnemySightingOnTheirTurn; + BOOLEAN fAutoBandageMode; + UINT8 ubAttackBusyCount; + INT8 bNumEnemiesFoughtInBattleUnused; + UINT8 ubEngagedInConvFromActionMercID; + UINT16 usTactialTurnLimitCounter; + BOOLEAN fInTopMessage; + UINT8 ubTopMessageType; + CHAR16 zTopMessageString[20]; + UINT16 usTactialTurnLimitMax; + UINT32 uiTactialTurnLimitClock; + BOOLEAN fTactialTurnLimitStartedBeep; + INT8 bBoxingState; + INT8 bConsNumTurnsNotSeen; + UINT8 ubArmyGuysKilled; - INT32 sPanicTriggerGridNo[ NUM_PANIC_TRIGGERS ]; - INT8 bPanicTriggerIsAlarm[ NUM_PANIC_TRIGGERS ]; - UINT8 ubPanicTolerance[ NUM_PANIC_TRIGGERS ]; - BOOLEAN fAtLeastOneGuyOnMultiSelect; - BOOLEAN fSaidCreatureFlavourQuote; - BOOLEAN fHaveSeenCreature; - BOOLEAN fKilledEnemyOnAttack; - UINT8 ubEnemyKilledOnAttack; - INT8 bEnemyKilledOnAttackLevel; - UINT16 ubEnemyKilledOnAttackLocation; - BOOLEAN fItemsSeenOnAttack; - BOOLEAN ubItemsSeenOnAttackSoldier; - BOOLEAN fBeenInCombatOnce; - BOOLEAN fSaidCreatureSmellQuote; - UINT32 usItemsSeenOnAttackGridNo; - BOOLEAN fLockItemLocators; - UINT8 ubLastQuoteSaid; - UINT8 ubLastQuoteProfileNUm; - BOOLEAN fCantGetThrough; - INT32 sCantGetThroughGridNo; - INT32 sCantGetThroughSoldierGridNo; - UINT8 ubCantGetThroughID; - BOOLEAN fDidGameJustStart; - BOOLEAN fStatChangeCheatOn; - UINT8 ubLastRequesterTargetID; - BOOLEAN fGoodToAllowCrows; - UINT8 ubNumCrowsPossible; - UINT32 uiTimeCounterForGiveItemSrc; - BOOLEAN fUnLockUIAfterHiddenInterrupt; - INT8 bNumFoughtInBattle[ MAXTEAMS ]; - UINT32 uiDecayBloodLastUpdate; - UINT32 uiTimeSinceLastInTactical; - BOOLEAN fHasAGameBeenStarted; - INT8 bConsNumTurnsWeHaventSeenButEnemyDoes; - BOOLEAN fSomeoneHit; - UINT8 ubPaddingSmall; - UINT32 uiTimeSinceLastOpplistDecay; - INT8 bMercArrivingQuoteBeingUsed; - UINT8 ubEnemyKilledOnAttackKiller; - BOOLEAN fCountingDownForGuideDescription; - INT8 bGuideDescriptionCountDown; - UINT8 ubGuideDescriptionToUse; - INT8 bGuideDescriptionSectorX; - INT8 bGuideDescriptionSectorY; - INT8 fEnemyFlags; - BOOLEAN fAutoBandagePending; - BOOLEAN fHasEnteredCombatModeSinceEntering; - BOOLEAN fDontAddNewCrows; - UINT8 ubMorePadding; - UINT16 sCreatureTenseQuoteDelay; - UINT32 uiCreatureTenseQuoteLastUpdate; - // SANDRO - added these - UINT8 ubLastRequesterSurgeryTargetID; - UINT8 ubInterruptPending; + INT32 sPanicTriggerGridNo[ NUM_PANIC_TRIGGERS ]; + INT8 bPanicTriggerIsAlarm[ NUM_PANIC_TRIGGERS ]; + UINT8 ubPanicTolerance[ NUM_PANIC_TRIGGERS ]; + BOOLEAN fAtLeastOneGuyOnMultiSelect; + BOOLEAN fSaidCreatureFlavourQuote; + BOOLEAN fHaveSeenCreature; + BOOLEAN fKilledEnemyOnAttack; + UINT8 ubEnemyKilledOnAttack; + INT8 bEnemyKilledOnAttackLevel; + UINT16 ubEnemyKilledOnAttackLocation; + BOOLEAN fItemsSeenOnAttack; + BOOLEAN ubItemsSeenOnAttackSoldier; + BOOLEAN fBeenInCombatOnce; + BOOLEAN fSaidCreatureSmellQuote; + UINT32 usItemsSeenOnAttackGridNo; + BOOLEAN fLockItemLocators; + UINT8 ubLastQuoteSaid; + UINT8 ubLastQuoteProfileNUm; + BOOLEAN fCantGetThrough; + INT32 sCantGetThroughGridNo; + INT32 sCantGetThroughSoldierGridNo; + UINT8 ubCantGetThroughID; + BOOLEAN fDidGameJustStart; + BOOLEAN fStatChangeCheatOn; + UINT8 ubLastRequesterTargetID; + BOOLEAN fGoodToAllowCrows; + UINT8 ubNumCrowsPossible; + UINT32 uiTimeCounterForGiveItemSrc; + BOOLEAN fUnLockUIAfterHiddenInterrupt; + INT8 bNumFoughtInBattle[ MAXTEAMS ]; + UINT32 uiDecayBloodLastUpdate; + UINT32 uiTimeSinceLastInTactical; + BOOLEAN fHasAGameBeenStarted; + INT8 bConsNumTurnsWeHaventSeenButEnemyDoes; + BOOLEAN fSomeoneHit; + UINT8 ubPaddingSmall; + UINT32 uiTimeSinceLastOpplistDecay; + INT8 bMercArrivingQuoteBeingUsed; + UINT8 ubEnemyKilledOnAttackKiller; + BOOLEAN fCountingDownForGuideDescription; + INT8 bGuideDescriptionCountDown; + UINT8 ubGuideDescriptionToUse; + INT8 bGuideDescriptionSectorX; + INT8 bGuideDescriptionSectorY; + INT8 fEnemyFlags; + BOOLEAN fAutoBandagePending; + BOOLEAN fHasEnteredCombatModeSinceEntering; + BOOLEAN fDontAddNewCrows; + UINT8 ubMorePadding; + UINT16 sCreatureTenseQuoteDelay; + UINT32 uiCreatureTenseQuoteLastUpdate; + // SANDRO - added these + UINT8 ubLastRequesterSurgeryTargetID; + UINT8 ubInterruptPending; - // PADDING GONE!!!!! + // PADDING GONE!!!!! } TacticalStatusType; -extern UINT8 gbPlayerNum; -extern INT8 gbShowEnemies; +extern UINT8 gbPlayerNum; +extern INT8 gbShowEnemies; -extern UINT16 gusSelectedSoldier; -extern UINT16 gusOldSelectedSoldier; +extern UINT16 gusSelectedSoldier; +extern UINT16 gusOldSelectedSoldier; -extern CHAR8 gzAlertStr[][ 30 ]; -extern CHAR8 gzActionStr[][ 30 ]; -extern CHAR8 gzDirectionStr[][ 30 ]; +extern CHAR8 gzAlertStr[][ 30 ]; +extern CHAR8 gzActionStr[][ 30 ]; +extern CHAR8 gzDirectionStr[][ 30 ]; // TEMP FOR E3 -extern UINT8 gubCurrentScene; -extern CHAR8 *GetSceneFilename( ); -extern INT8 ubLevelMoveLink[ 10 ]; +extern UINT8 gubCurrentScene; +extern CHAR8 *GetSceneFilename( ); +extern INT8 ubLevelMoveLink[ 10 ]; // Soldier List used for all soldier overhead interaction -extern SOLDIERTYPE Menptr[ TOTAL_SOLDIERS ]; -extern SOLDIERTYPE *MercPtrs[ TOTAL_SOLDIERS ]; +extern SOLDIERTYPE Menptr[ TOTAL_SOLDIERS ]; +extern SOLDIERTYPE *MercPtrs[ TOTAL_SOLDIERS ]; // MERC SLOTS - A LIST OF ALL ACTIVE MERCS -extern SOLDIERTYPE *MercSlots[ TOTAL_SOLDIERS ]; -extern UINT32 guiNumMercSlots; +extern SOLDIERTYPE *MercSlots[ TOTAL_SOLDIERS ]; +extern UINT32 guiNumMercSlots; -extern BOOLEAN gfMovingAnimation; +extern BOOLEAN gfMovingAnimation; -extern TacticalStatusType gTacticalStatus; +extern TacticalStatusType gTacticalStatus; @@ -226,7 +204,7 @@ BOOLEAN InitOverhead( ); BOOLEAN ShutdownOverhead( ); BOOLEAN GetSoldier( SOLDIERTYPE **ppSoldier, UINT16 usSoldierIndex ); -UINT32 CountNonVehiclesOnPlayerTeam( void ); +UINT32 CountNonVehiclesOnPlayerTeam( ); INT16 NewOKDestination( SOLDIERTYPE * pCurrSoldier, INT32 sGridNo, BOOLEAN fPeopleToo, INT8 bLevel ); @@ -237,7 +215,7 @@ extern BOOLEAN FlatRoofAboveGridNo( INT32 iMapIndex ); BOOLEAN ExecuteOverhead( ); -BOOLEAN ResetAllAnimationCache( ); +BOOLEAN ResetAllAnimationCache( ); void EndTurn( ); void EndTurn( UINT8 ubNextTeam ); @@ -245,7 +223,7 @@ void EndTurn( UINT8 ubNextTeam ); void StartPlayerTeamTurn( BOOLEAN fDoBattleSnd, BOOLEAN fEnteringCombatMode ); void EndTacticalDemo( ); -void SelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fForceReselect ); +void SelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fForceReselect ); //Kaiden: Function declaration from UB to reveal all items after combat. void RevealAllDroppedEnemyItems(); @@ -282,93 +260,66 @@ void SelectNextAvailSoldier( SOLDIERTYPE *pSoldier ); BOOLEAN TeamMemberNear(INT8 bTeam, INT32 sGridNo, INT32 iRange); BOOLEAN IsValidTargetMerc( UINT8 ubSoldierID ); - - - // FUNCTIONS FOR MANIPULATING MERC SLOTS - A LIST OF ALL ACTIVE MERCS -INT32 GetFreeMercSlot(void); -void RecountMercSlots(void); -INT32 AddMercSlot( SOLDIERTYPE *pSoldier ); -BOOLEAN RemoveMercSlot( SOLDIERTYPE *pSoldier ); +INT32 GetFreeMercSlot( ); +INT32 AddMercSlot( SOLDIERTYPE *pSoldier ); +BOOLEAN RemoveMercSlot( SOLDIERTYPE *pSoldier ); -INT32 AddAwaySlot( SOLDIERTYPE *pSoldier ); +INT32 AddAwaySlot( SOLDIERTYPE *pSoldier ); BOOLEAN RemoveAwaySlot( SOLDIERTYPE *pSoldier ); -INT32 MoveSoldierFromMercToAwaySlot( SOLDIERTYPE * pSoldier ); -INT32 MoveSoldierFromAwayToMercSlot( SOLDIERTYPE * pSoldier ); +INT32 MoveSoldierFromMercToAwaySlot( SOLDIERTYPE * pSoldier ); +INT32 MoveSoldierFromAwayToMercSlot( SOLDIERTYPE * pSoldier ); void EnterCombatMode( UINT8 ubStartingTeam ); void ExitCombatMode( ); - void HandleTeamServices( UINT8 ubTeamNum ); void HandlePlayerServices( SOLDIERTYPE *pTeamSoldier ); - void SetEnemyPresence( ); - void CycleThroughKnownEnemies( ); - BOOLEAN CheckForEndOfCombatMode( BOOLEAN fIncrementTurnsNotSeen ); - SOLDIERTYPE * FreeUpAttacker( ); - BOOLEAN PlayerTeamFull( ); - -void SetActionToDoOnceMercsGetToLocation( UINT8 ubActionCode, INT8 bNumMercsWaiting, UINT32 uiData1, UINT32 uiData2, UINT32 uiData3 ); - +void SetActionToDoOnceMercsGetToLocation( UINT8 ubActionCode, INT8 bNumMercsWaiting, UINT32 uiData1, UINT32 uiData2, UINT32 uiData3 ); void ResetAllMercSpeeds( ); - BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLEAN fInitialMove, UINT16 usAnimState ); - SOLDIERTYPE * ReduceAttackBusyCount( ); + // HEADROCK HAM B2.6: Made this public so it can be used elsewhere. INT8 CalcSuppressionTolerance( SOLDIERTYPE * pSoldier ); // HEADROCK HAM 3.2: A new function for checking the condition of nearby friendlies and returning a modifier. INT8 CheckStatusNearbyFriendlies( SOLDIERTYPE *pSoldier ); void CommonEnterCombatModeCode( ); - void CheckForPotentialAddToBattleIncrement( SOLDIERTYPE *pSoldier ); - -void CencelAllActionsForTimeCompression( void ); - +void CencelAllActionsForTimeCompression( ); BOOLEAN CheckForEndOfBattle( BOOLEAN fAnEnemyRetreated ); - void AddManToTeam( INT8 bTeam ); - void RemoveManFromTeam( INT8 bTeam ); - void RemoveSoldierFromTacticalSector( SOLDIERTYPE *pSoldier, BOOLEAN fAdjustSelected ); - void MakeCivHostile( SOLDIERTYPE *pSoldier, INT8 bNewSide ); -#define REASON_NORMAL_ATTACK 1 -#define REASON_EXPLOSION 2 +#define REASON_NORMAL_ATTACK 1 +#define REASON_EXPLOSION 2 BOOLEAN ProcessImplicationsOfPCAttack( SOLDIERTYPE * pSoldier, SOLDIERTYPE ** ppTarget, INT8 bReason ); - INT32 FindAdjacentPunchTarget( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTargetSoldier, INT32 * psAdjustedTargetGridNo, UINT8 * pubDirection ); - SOLDIERTYPE * CivilianGroupMemberChangesSides( SOLDIERTYPE * pAttacked ); void CivilianGroupChangesSides( UINT8 ubCivilianGroup ); - void CycleVisibleEnemies( SOLDIERTYPE *pSrcSoldier ); UINT8 CivilianGroupMembersChangeSidesWithinProximity( SOLDIERTYPE * pAttacked ); - -void PauseAITemporarily( void ); -void PauseAIUntilManuallyUnpaused( void ); -void UnPauseAI( void ); - -void DoPOWPathChecks( void ); - -BOOLEAN HostileCiviliansWithGunsPresent( void ); -BOOLEAN HostileCiviliansPresent( void ); -BOOLEAN HostileBloodcatsPresent( void ); +void PauseAITemporarily( ); +void PauseAIUntilManuallyUnpaused( ); +void UnPauseAI( ); +void DoPOWPathChecks( ); +BOOLEAN HostileCiviliansWithGunsPresent( ); +BOOLEAN HostileCiviliansPresent( ); +BOOLEAN HostileBloodcatsPresent( ); #ifdef ENABLE_ZOMBIES - BOOLEAN HostileZombiesPresent( void ); +BOOLEAN HostileZombiesPresent( ); #endif -UINT8 NumPCsInSector( void ); - +UINT8 NumPCsInSector( ); void SetSoldierNonNeutral( SOLDIERTYPE * pSoldier ); void SetSoldierNeutral( SOLDIERTYPE * pSoldier ); @@ -376,13 +327,13 @@ void SetSoldierNeutral( SOLDIERTYPE * pSoldier ); void HandleThePlayerBeNotifiedOfSomeoneElseInSector(); void SetMsgBoxForPlayerBeNotifiedOfSomeoneElseInSector(); -void HandleDisplayingOfPlayerLostDialogue( void ); +void HandleDisplayingOfPlayerLostDialogue( ); // UTILITY FUNCTIONS -INT8 NumActiveAndConsciousTeamMembers( UINT8 ubTeam ); +INT8 NumActiveAndConsciousTeamMembers( UINT8 ubTeam ); UINT8 NumEnemyInSector( ); UINT8 NumCapableEnemyInSector( ); -INT8 NumMercsOnPlayerTeam( ); +INT8 NumMercsOnPlayerTeam( ); #endif extern BOOLEAN sniperwarning; @@ -395,18 +346,17 @@ extern BOOLEAN gogglewarning; // will a sam site under the players control shoot down an airraid? BOOLEAN WillAirRaidBeStopped( INT16 sSectorX, INT16 sSectorY ); - // HEADROCK HAM 3.5: Externalized for First Arrival enemy check extern UINT8 NumEnemyInSector(); #ifdef ENABLE_ZOMBIES - // Flugente - extern UINT8 NumZombiesInSector(); +// Flugente +extern UINT8 NumZombiesInSector(); #endif -void HandleSurrenderOffer( SOLDIERTYPE* pSoldier ); // Flugente: offer the enemy the chance to surrender - +void HandleSurrenderOffer( SOLDIERTYPE* pSoldier ); // Flugente: offer the enemy the chance to surrender // setting fForce to TRUE allows dropping of gear in combat (used in auto-resolve instances) void TeamDropAll(UINT8 bTeam, BOOLEAN fForce = FALSE); -#endif \ No newline at end of file +#endif + diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index afc97538..ce4a6f1d 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -100,6 +100,7 @@ #endif #include "ub_config.h" +#include "../ModularizedTacticalAI/include/Plan.h" // for plan destructor call #ifdef JA2UB #include "Ja25_Tactical.h" @@ -1023,11 +1024,16 @@ SOLDIERTYPE& SOLDIERTYPE::operator=(const OLDSOLDIERTYPE_101& src) this->bDrinkLevel = 0; this->usStarveDamageHealth = 0; this->usStarveDamageStrength = 0; + this->bAIIndex = 0; } return *this; } -SOLDIERTYPE::~SOLDIERTYPE() {} +SOLDIERTYPE::~SOLDIERTYPE() +{ + if(ai_masterplan_) + delete ai_masterplan_; +} SOLDIERTYPE::SOLDIERTYPE() { initialize(); @@ -1061,38 +1067,6 @@ UINT32 SOLDIERTYPE::GetChecksum( ) return( uiChecksum ); } - -// Copy Constructor -SOLDIERTYPE::SOLDIERTYPE(const SOLDIERTYPE& src) -{ - memcpy(this, &src, SIZEOF_SOLDIERTYPE_POD); - inv = src.inv; - aiData = src.aiData; - flags = src.flags; - timeChanges = src.timeChanges; - timeCounters = src.timeCounters; - drugs = src.drugs; - stats = src.stats; - pathing = src.pathing; -} - -// Assignment operator -SOLDIERTYPE& SOLDIERTYPE::operator=(const SOLDIERTYPE& src) -{ - if (this != &src) { - memcpy(this, &src, SIZEOF_SOLDIERTYPE_POD); - aiData = src.aiData; - flags = src.flags; - timeChanges = src.timeChanges; - timeCounters = src.timeCounters; - drugs = src.drugs; - stats = src.stats; - pathing = src.pathing; - inv = src.inv; - } - return *this; -} - // Initialize the soldier. // Use this instead of the old method of calling memset! // Note that the constructor does this automatically. @@ -1100,6 +1074,7 @@ void SOLDIERTYPE::initialize() { memset( this, 0, SIZEOF_SOLDIERTYPE_POD); inv.clear(); + ai_masterplan_ = 0; memset( &aiData, 0, sizeof(STRUCT_AIData) ); memset( &flags, 0, sizeof(STRUCT_Flags) ); @@ -19270,4 +19245,5 @@ BOOLEAN DecideAltAnimForBigMerc( SOLDIERTYPE * pSoldier ) BOOLEAN TwoStagedTrait( UINT8 uiSkillTraitNumber ) { return( uiSkillTraitNumber > 0 && (uiSkillTraitNumber <= NUM_ORIGINAL_MAJOR_TRAITS || uiSkillTraitNumber == COVERT_NT) ); -} \ No newline at end of file +} + diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 473b9898..ed1b14dc 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -723,6 +723,15 @@ public: TIMECOUNTER NextTileCounter; }; +// forward declaration for modularized tactical ai +namespace AI +{ + namespace tactical + { + class Plan; + } +} + class STRUCT_Statistics//last edited at version 102 { public: @@ -775,10 +784,6 @@ public: // Constructor SOLDIERTYPE(); - // Copy Constructor - SOLDIERTYPE(const SOLDIERTYPE&); - // Assignment operator - SOLDIERTYPE& operator=(const SOLDIERTYPE&); // Destructor ~SOLDIERTYPE(); @@ -1265,8 +1270,9 @@ public: INT32 sMTActionGridNo; // gridno on which we perfrom our multi-turn action UINT8 usMultiTurnAction; // specifies which multi-turn action we are currently performing, 0: none + INT16 bAIIndex; // PlanFactory from the modularized tactical AI that shall be used // Flugente: Decrease this filler by 1 for each new UINT8 / BOOLEAN variable, so we can maintain savegame compatibility!! - UINT8 ubFiller[13]; + UINT8 ubFiller[11]; #ifdef JA2UB //ja25 @@ -1285,6 +1291,7 @@ public: // properly until it is all fixed and the files updated. Inventory inv; + AI::tactical::Plan* ai_masterplan_; // Interface object for ModularizedTacticalAI //data from version 101 wrapped into structs STRUCT_AIData aiData; diff --git a/Tactical/XML_Sounds.cpp b/Tactical/XML_Sounds.cpp index ecde7d82..26150aa4 100644 --- a/Tactical/XML_Sounds.cpp +++ b/Tactical/XML_Sounds.cpp @@ -1,272 +1,202 @@ #ifdef PRECOMPILEDHEADERS - #include "Tactical All.h" +#include "Tactical All.h" #else - #include "sgp.h" - #include "overhead types.h" - #include "Sound Control.h" - #include "overhead.h" - #include "Event Pump.h" - #include "weapons.h" - #include "Animation Control.h" - #include "sys globals.h" - #include "Handle UI.h" - #include "Isometric Utils.h" - #include "worldman.h" - #include "math.h" - #include "points.h" - #include "ai.h" - #include "los.h" - #include "renderworld.h" - #include "opplist.h" - #include "interface.h" - #include "message.h" - #include "campaign.h" - #include "items.h" - #include "text.h" - #include "Soldier Profile.h" - #include "tile animation.h" - #include "Dialogue Control.h" - #include "SkillCheck.h" - #include "explosion control.h" - #include "Quests.h" - #include "Physics.h" - #include "Random.h" - #include "Vehicles.h" - #include "bullets.h" - #include "morale.h" - #include "meanwhile.h" - #include "SkillCheck.h" - #include "gamesettings.h" - #include "SaveLoadMap.h" - #include "Debug Control.h" - #include "expat.h" - #include "XML.h" +#include +#include "sgp.h" +#include "Sound Control.h" +#include "Debug Control.h" +#include "expat.h" +#include "XML.h" #endif extern char szSoundEffects[MAX_SAMPLES][255]; struct { - PARSE_STAGE curElement; - - CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1]; - - UINT32 maxArraySize; - UINT32 curIndex; - UINT32 currentDepth; - UINT32 maxReadDepth; + PARSE_STAGE curElement; + CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1]; + UINT32 maxArraySize; + UINT32 curIndex; + UINT32 currentDepth; + UINT32 maxReadDepth; } typedef soundParseData; static void XMLCALL soundStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts) { - soundParseData * pData = (soundParseData *)userData; + soundParseData * pData = (soundParseData *)userData; - if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element? - { - if(strcmp(name, "SOUNDLIST") == 0 && pData->curElement == ELEMENT_NONE) - { - pData->curElement = ELEMENT_LIST; + if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element? + { + if(strcmp(name, "SOUNDLIST") == 0 && pData->curElement == ELEMENT_NONE) + { + pData->curElement = ELEMENT_LIST; - pData->maxReadDepth++; //we are not skipping this element - } - else if(strcmp(name, "SOUND") == 0 && pData->curElement == ELEMENT_LIST) - { - pData->curElement = ELEMENT; + pData->maxReadDepth++; //we are not skipping this element + } + else if(strcmp(name, "SOUND") == 0 && pData->curElement == ELEMENT_LIST) + { + pData->curElement = ELEMENT; - pData->maxReadDepth++; //we are not skipping this element - pData->curIndex++; - } + pData->maxReadDepth++; //we are not skipping this element + pData->curIndex++; + } - pData->szCharData[0] = '\0'; - } + pData->szCharData[0] = '\0'; + } - pData->currentDepth++; + pData->currentDepth++; } static void XMLCALL soundCharacterDataHandle(void *userData, const XML_Char *str, int len) { - soundParseData * pData = (soundParseData *)userData; + soundParseData * pData = (soundParseData *)userData; - if( (pData->currentDepth <= pData->maxReadDepth) && - (strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH) - ){ - strncat(pData->szCharData,str,__min((unsigned int)len,MAX_CHAR_DATA_LENGTH-strlen(pData->szCharData))); - } + if((pData->currentDepth <= pData->maxReadDepth) && (strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH)) + { + strncat(pData->szCharData,str,__min((unsigned int)len,MAX_CHAR_DATA_LENGTH-strlen(pData->szCharData))); + } } static void XMLCALL soundEndElementHandle(void *userData, const XML_Char *name) { - soundParseData * pData = (soundParseData *)userData; + soundParseData * pData = (soundParseData *)userData; - if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading - { - if(strcmp(name, "SOUNDLIST") == 0) - { - pData->curElement = ELEMENT_NONE; - } - else if(strcmp(name, "SOUND") == 0) - { - pData->curElement = ELEMENT_LIST; + if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading + { + if(strcmp(name, "SOUNDLIST") == 0) + { + pData->curElement = ELEMENT_NONE; + } + else if(strcmp(name, "SOUND") == 0) + { + pData->curElement = ELEMENT_LIST; - if(pData->curIndex < pData->maxArraySize) - { - char temp; - for(int i=0;iszCharData),255);i++) - { - temp = pData->szCharData[i]; - szSoundEffects[pData->curIndex][i] = temp; - } - } - } - - pData->maxReadDepth--; - } - - pData->currentDepth--; + if(pData->curIndex < pData->maxArraySize) + { + char temp; + for(int i=0;iszCharData),255);i++) + { + temp = pData->szCharData[i]; + szSoundEffects[pData->curIndex][i] = temp; + } + } + } + pData->maxReadDepth--; + } + pData->currentDepth--; } - - - BOOLEAN ReadInSoundArray(STR fileName) { - HWFILE hFile; - UINT32 uiBytesRead; - UINT32 uiFSize; - CHAR8 * lpcBuffer; - XML_Parser parser = XML_ParserCreate(NULL); + HWFILE hFile; + UINT32 uiBytesRead; + UINT32 uiFSize; + CHAR8 * lpcBuffer; + XML_Parser parser = XML_ParserCreate(NULL); + soundParseData pData; + DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("Loading %s",SOUNDSFILENAME ) ); - soundParseData pData; + // Open sounds file + hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE ); + if ( !hFile ) + return( FALSE ); - DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("Loading %s",SOUNDSFILENAME ) ); + uiFSize = FileGetSize(hFile); + lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1); + //Read in block + if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) ) + { + MemFree(lpcBuffer); + return( FALSE ); + } + lpcBuffer[uiFSize] = 0; //add a null terminator + FileClose( hFile ); - // Open sounds file - hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE ); - if ( !hFile ) - return( FALSE ); - - uiFSize = FileGetSize(hFile); - lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1); - - //Read in block - if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) ) - { - MemFree(lpcBuffer); - return( FALSE ); - } - - lpcBuffer[uiFSize] = 0; //add a null terminator - - FileClose( hFile ); - - - XML_SetElementHandler(parser, soundStartElementHandle, soundEndElementHandle); - XML_SetCharacterDataHandler(parser, soundCharacterDataHandle); - - - memset(&pData,0,sizeof(pData)); - pData.maxArraySize = MAX_SAMPLES; - pData.curIndex = -1; - - XML_SetUserData(parser, &pData); - - - if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE)) - { - CHAR8 errorBuf[511]; - - sprintf(errorBuf, "XML Parser Error in %s.xml: %s at line %d", SOUNDSFILENAME, XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); - LiveMessage(errorBuf); - - MemFree(lpcBuffer); - return FALSE; - } - - MemFree(lpcBuffer); - - - XML_ParserFree(parser); - - return( TRUE ); + XML_SetElementHandler(parser, soundStartElementHandle, soundEndElementHandle); + XML_SetCharacterDataHandler(parser, soundCharacterDataHandle); + memset(&pData,0,sizeof(pData)); + pData.maxArraySize = MAX_SAMPLES; + pData.curIndex = -1; + XML_SetUserData(parser, &pData); + if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE)) + { + CHAR8 errorBuf[511]; + sprintf(errorBuf, "XML Parser Error in %s.xml: %s at line %d", SOUNDSFILENAME, XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); + LiveMessage(errorBuf); + MemFree(lpcBuffer); + return FALSE; + } + MemFree(lpcBuffer); + XML_ParserFree(parser); + return( TRUE ); } + BOOLEAN WriteSoundArray() { - HWFILE hFile; - DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("WriteSoundArray")); - //Debug code; make sure that what we got from the file is the same as what's there - // Open a new file - hFile = FileOpen( "TABLEDATA\\Sounds out.xml", FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE ); - if ( !hFile ) - return( FALSE ); + HWFILE hFile; + DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("WriteSoundArray")); + //Debug code; make sure that what we got from the file is the same as what's there + // Open a new file + hFile = FileOpen( "TABLEDATA\\Sounds out.xml", FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE ); + if ( !hFile ) + return( FALSE ); + UINT32 cnt; - { - UINT32 cnt; + FilePrintf(hFile,"\r\n"); + for(cnt = 0;cnt < NUM_SAMPLES;cnt++) + { + FilePrintf(hFile,"\t"); + STR8 szRemainder = szSoundEffects[cnt]; //the remaining string to be output (for making valid XML) + while(szRemainder[0] != '\0') + { + UINT32 uiCharLoc = strcspn(szRemainder,"&<>\'\"\0"); + char invChar = szRemainder[uiCharLoc]; - FilePrintf(hFile,"\r\n"); - for(cnt = 0;cnt < NUM_SAMPLES;cnt++) - { - FilePrintf(hFile,"\t"); + if(uiCharLoc) + { + szRemainder[uiCharLoc] = '\0'; + FilePrintf(hFile,"%s",szRemainder); + szRemainder[uiCharLoc] = invChar; + } + szRemainder += uiCharLoc; + switch(invChar) + { + case '&': + FilePrintf(hFile,"&"); + szRemainder++; + break; - STR8 szRemainder = szSoundEffects[cnt]; //the remaining string to be output (for making valid XML) + case '<': + FilePrintf(hFile,"<"); + szRemainder++; + break; - while(szRemainder[0] != '\0') - { - UINT32 uiCharLoc = strcspn(szRemainder,"&<>\'\"\0"); - char invChar = szRemainder[uiCharLoc]; + case '>': + FilePrintf(hFile,">"); + szRemainder++; + break; - if(uiCharLoc) - { - szRemainder[uiCharLoc] = '\0'; - FilePrintf(hFile,"%s",szRemainder); - szRemainder[uiCharLoc] = invChar; - } + case '\'': + FilePrintf(hFile,"'"); + szRemainder++; + break; - szRemainder += uiCharLoc; - - switch(invChar) - { - case '&': - FilePrintf(hFile,"&"); - szRemainder++; - break; - - case '<': - FilePrintf(hFile,"<"); - szRemainder++; - break; - - case '>': - FilePrintf(hFile,">"); - szRemainder++; - break; - - case '\'': - FilePrintf(hFile,"'"); - szRemainder++; - break; - - case '\"': - FilePrintf(hFile,"""); - szRemainder++; - break; - } - } - -// FilePrintf(hFile,"\t\t%s\r\n", szSoundEffects[cnt]); - - FilePrintf(hFile,"\r\n"); - } - FilePrintf(hFile,"\r\n"); - } - FileClose( hFile ); - - return( TRUE ); + case '\"': + FilePrintf(hFile,"""); + szRemainder++; + break; + } + } + FilePrintf(hFile,"\r\n"); + } + FilePrintf(hFile,"\r\n"); + FileClose( hFile ); + return( TRUE ); } - diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index 17cdbd2c..db886009 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -59,6 +59,12 @@ #endif #include "connect.h" +// needed to use the modularized tactical AI: +#include "ModularizedTacticalAI/include/Plan.h" +#include "ModularizedTacticalAI/include/PlanFactoryLibrary.h" +#include "ModularizedTacticalAI/include/AbstractPlanFactory.h" +#include +#include #ifdef JA2UB #include "Ja25_Tactical.h" @@ -165,17 +171,13 @@ BOOLEAN InitAI( void ) return( TRUE ); } - - BOOLEAN AimingGun(SOLDIERTYPE *pSoldier) { return(FALSE); } -void HandleSoldierAI( SOLDIERTYPE *pSoldier ) +void HandleSoldierAI( SOLDIERTYPE *pSoldier ) // FIXME - this function is named inappropriately { - UINT32 uiCurrTime = GetJA2Clock(); - // ATE // Bail if we are engaged in a NPC conversation/ and/or sequence ... or we have a pause because // we just saw someone... or if there are bombs on the bomb queue @@ -204,30 +206,9 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) } } - /* - else - { - // AI is run on all PCs except the one who is selected - if (pSoldier->flags.uiStatusFlags & SOLDIER_PC ) - { - // if this soldier is "selected" then only let user give orders! - if ((pSoldier->ubID == gusSelectedSoldier) && !(gTacticalStatus.uiFlags & DEMOMODE)) - { - return; - } - } - } - */ - // determine what sort of AI to use - if ( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) ) - { - gfTurnBasedAI = TRUE; - } - else - { - gfTurnBasedAI = FALSE; - } + //gfTurnBasedAI = (bool)( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) ); + gfTurnBasedAI = ( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) ); // If TURN BASED and NOT NPC's turn, or realtime and not our chance to think, bail... if (gfTurnBasedAI) @@ -279,7 +260,6 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) { //Reset counter! RESETTIMECOUNTER( pSoldier->timeCounters.AICounter, pSoldier->uiAIDelay ); - //DebugMsg( TOPIC_JA2, DBG_LEVEL_0, String( "%s waiting %d from %d", pSoldier->name, pSoldier->timeCounters.AICounter, uiCurrTime ) ); } //#endif } @@ -423,29 +403,6 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) if ( gTacticalStatus.ubAttackBusyCount > 0 ) { fProcessNewSituation = FALSE; -#if 0 - // HACK!! - if ( pSoldier->aiData.bAction == AI_ACTION_FIRE_GUN ) - { - if ( guiNumBullets == 0 ) - { - // abort attack! - //DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String(">>>>>> Attack busy count lobotomized due to new situation for %d", pSoldier->ubID ) ); - //gTacticalStatus.ubAttackBusyCount = 0; - fProcessNewSituation = TRUE; - } - } - else if ( pSoldier->aiData.bAction == AI_ACTION_TOSS_PROJECTILE ) - { - if ( guiNumObjectSlots == 0 ) - { - // abort attack! - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String(">>>>>> Attack busy count lobotomized due to new situation for %d", pSoldier->ubID ) ); - //gTacticalStatus.ubAttackBusyCount = 0; - fProcessNewSituation = TRUE; - } - } -#endif } else { @@ -454,7 +411,8 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) if ( fProcessNewSituation ) { - if ( (pSoldier->flags.uiStatusFlags & SOLDIER_UNDERAICONTROL) && pSoldier->ubQuoteActionID >= QUOTE_ACTION_ID_TRAVERSE_EAST && pSoldier->ubQuoteActionID <= QUOTE_ACTION_ID_TRAVERSE_NORTH && !GridNoOnVisibleWorldTile( pSoldier->sGridNo ) ) + if ( (pSoldier->flags.uiStatusFlags & SOLDIER_UNDERAICONTROL) && pSoldier->ubQuoteActionID >= QUOTE_ACTION_ID_TRAVERSE_EAST && + pSoldier->ubQuoteActionID <= QUOTE_ACTION_ID_TRAVERSE_NORTH && !GridNoOnVisibleWorldTile( pSoldier->sGridNo ) ) { // traversing offmap, ignore new situations } @@ -541,21 +499,20 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) } gubAICounter++; - // figure out what to do! - if (gfTurnBasedAI) - { - if (pSoldier->flags.fNoAPToFinishMove) - { - // well that move must have been cancelled because we're thinking now! - //pSoldier->flags.fNoAPToFinishMove = FALSE; - } - TurnBasedHandleNPCAI( pSoldier ); - } - else - { - RTHandleAI( pSoldier ); - } + if(!pSoldier->ai_masterplan_) // if the Soldier has no plan, create one + { + if(pSoldier->bAIIndex == 0) // not yet initialized, use bTeam+1 as default + pSoldier->bAIIndex = pSoldier->bTeam + 1; + AI::tactical::AIInputData ai_input; + ai_input.npc_to_plan_for_ = pSoldier; + AI::tactical::PlanFactoryLibrary* plan_lib(AI::tactical::PlanFactoryLibrary::instance()); + pSoldier->ai_masterplan_ = plan_lib->create_plan(pSoldier->bAIIndex, ai_input); + } + + AI::tactical::PlanInputData plan_input; + plan_input.controlled_npc_ = pSoldier; + pSoldier->ai_masterplan_->execute(gfTurnBasedAI, plan_input); } else { @@ -669,11 +626,9 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) } } - /********* End of new overall AI system ********/ - } #define NOSCORE 99 @@ -1061,62 +1016,6 @@ void FreeUpNPCFromAttacking(UINT8 ubID) pSoldier = MercPtrs[ubID]; ActionDone(pSoldier); pSoldier->pathing.bNeedToLook = TRUE; - - /* - if (pSoldier->aiData.bActionInProgress) - { - #ifdef TESTAI - DebugMsg( TOPIC_JA2AI, DBG_LEVEL_0, String( "FreeUpNPCFromAttacking for %d", pSoldier->ubID ) ); - #endif - if (pSoldier->aiData.bAction == AI_ACTION_FIRE_GUN) - { - if (pSoldier->bDoBurst) - { - if (pSoldier->bBulletsLeft == 0) - { - // now find the target and have them say "close call" quote if - // applicable - pTarget = SimpleFindSoldier( pSoldier->sTargetGridNo, pSoldier->bTargetLevel ); - if (pTarget && pTarget->bTeam == OUR_TEAM && pTarget->flags.fCloseCall && pTarget->bShock == 0) - { - // say close call quote! - TacticalCharacterDialogue( pTarget, QUOTE_CLOSE_CALL ); - pTarget->flags.fCloseCall = FALSE; - } - ActionDone(pSoldier); - pSoldier->bDoBurst = FALSE; - } - } - else - { - pTarget = SimpleFindSoldier( pSoldier->sTargetGridNo, pSoldier->bTargetLevel ); - if (pTarget && pTarget->bTeam == OUR_TEAM && pTarget->flags.fCloseCall && pTarget->bShock == 0) - { - // say close call quote! - TacticalCharacterDialogue( pTarget, QUOTE_CLOSE_CALL ); - pTarget->flags.fCloseCall = FALSE; - } - ActionDone(pSoldier); - } - } - else if ((pSoldier->aiData.bAction == AI_ACTION_TOSS_PROJECTILE) || (pSoldier->aiData.bAction == AI_ACTION_KNIFE_STAB)) - { - ActionDone(pSoldier); - } - } - - // DO WE NEED THIS??? - //pSoldier->sTarget = NOWHERE; - - // make him look in case he turns to face a new direction - pSoldier->pathing.bNeedToLook = TRUE; - - // This is here to speed up resolution of interrupts that have already been - // delayed while AttackingPerson was still set (causing ChangeControl to - // bail). Without it, an interrupt would have to wait until next ani frame! - //if (SwitchTo > -1) - // ChangeControl(); - */ } void FreeUpNPCFromLoweringGun( SOLDIERTYPE *pSoldier ) @@ -1324,16 +1223,13 @@ void NPCDoesNothing(SOLDIERTYPE *pSoldier) { // NPC, for whatever reason, did/could not start an action, so end his turn //pSoldier->moved = TRUE; - #ifdef TESTAICONTROL if (gfTurnBasedAI) { DebugAI( String("Ending turn for %d because doing no-action", pSoldier->ubID ) ); } #endif - EndAIGuysTurn(pSoldier); - // *** IAN deleted lots of interrupt related code here to simplify JA2 development } @@ -1371,137 +1267,6 @@ void CancelAIAction(SOLDIERTYPE *pSoldier, UINT8 ubForce) } - - -/* -void ActionTimeoutExceeded(SOLDIERTYPE *pSoldier, UCHAR alreadyFreedUp) -{ -int cnt; -UCHAR attackAction = FALSE; - - -#ifdef BETAVERSION -if (ConvertedMultiSave) -{ -// re-start real-time NPC action timer -EnemyTimedOut = FALSE; -EnemyTimerCnt = ENEMYWAITTOLERANCE; -return; -} -#endif - - -// check if it's a problem with a offensive combat action -if ((pSoldier->aiData.bAction == AI_ACTION_FIRE_GUN) || -(pSoldier->aiData.bAction == AI_ACTION_TOSS_PROJECTILE) || -(pSoldier->aiData.bAction == AI_ACTION_KNIFE_STAB)) -{ -// THESE ARE LESS SERIOUS, SINCE THEY LIKELY WON'T REPEAT THEMSELVES -attackAction = TRUE; -} -// OTHERS ARE VERY SERIOUS, SINCE THEY ARE LIKELY TO REPEAT THEMSELVES - - -#ifdef BETAVERSION -sprintf(tempstr,"ActionInProgress - ERROR: %s's timeout limit exceeded. Action #%d (%d)", -pSoldier->name,pSoldier->aiData.bAction,pSoldier->aiData.usActionData); - -#ifdef RECORDNET -fprintf(NetDebugFile,"\n%s\n\n",tempstr); -#endif - -PopMessage(tempstr); -SaveGame(ERROR_SAVE); -#endif - -#ifdef TESTVERSION -PopMessage("FULL SOLDIER INFORMATION DUMP COMING UP, BRACE THYSELF!"); -DumpSoldierInfo(pSoldier); -#endif - - -// re-start real-time NPC action timer -EnemyTimedOut = FALSE; -EnemyTimerCnt = ENEMYWAITTOLERANCE; - -if (attackAction) -{ -#ifdef BETAVERSION -NameMessage(pSoldier,"will now be freed up from attacking...",2000); -#endif - - -// free up ONLY players from whom we haven't received an AI_ACTION_DONE yet -// we can all agree the action is DONE and we can continue... -// (otherwise they'll be calling FreeUp... twice and get REAL screwed up) -NetSend.msgType = NET_FREE_UP_ATTACK; -NetSend.ubID = pSoldier->ubID; - -for (cnt = 0; cnt < MAXPLAYERS; cnt++) -{ -if ((cnt != Net.pnum) && Net.player[cnt].playerActive && -(Net.player[cnt].actionDone != pSoldier->ubID)) -SendNetData(cnt); -} - -if (!alreadyFreedUp) -FreeUpManFromAttacking(pSoldier->ubID,COMMUNICATE); -} -else if (pSoldier->aiData.bAction == AI_ACTION_CHANGE_FACING) -{ -#ifdef BETAVERSION -NameMessage(pSoldier,"will now be freed up from turning...",2000); -#endif - -// force him to face in the right direction (as long as it's legal) -if ((pSoldier->pathing.bDesiredDirection >= 1) && (pSoldier->pathing.bDesiredDirection <= 8)) -pSoldier->ubDirection = pSoldier->pathing.bDesiredDirection; -else -pSoldier->pathing.bDesiredDirection = pSoldier->ubDirection; - -// free up ONLY players from whom we haven't received an AI_ACTION_DONE yet -// we can all agree the action is DONE and we can continue... -// (otherwise they'll be calling FreeUp... twice and get REAL screwed up) -NetSend.msgType = NET_FREE_UP_TURN; -NetSend.ubID = pSoldier->ubID; -NetSend.misc_UCHAR = pSoldier->ubDirection; -NetSend.answer = pSoldier->pathing.bDesiredDirection; - -for (cnt = 0; cnt < MAXPLAYERS; cnt++) -{ -if ((cnt != Net.pnum) && Net.player[cnt].playerActive && -(Net.player[cnt].actionDone != pSoldier->ubID)) -SendNetData(cnt); -} - -if (!alreadyFreedUp) -// this calls FreeUpManFromTurning() -NowFacingRightWay(pSoldier,COMMUNICATE); -} -else -{ -#ifdef BETAVERSION -NameMessage(pSoldier,"is having the remainder of his turn canceled...",1000); -#endif - -// cancel the remainder of the offender's turn as a penalty! -pSoldier->bActionPoints = 0; -NPCDoesNothing(pSoldier); -} - - -// cancel whatever the current action is, force this even for escorted NPCs -CancelAIAction(pSoldier,FORCE); - - -// reset the timeout counter for next time -pSoldier->aiData.bActionTimeout = 0; -} -*/ - - - - INT16 ActionInProgress(SOLDIERTYPE *pSoldier) { // if NPC has a desired destination, but isn't currently going there @@ -1529,91 +1294,6 @@ INT16 ActionInProgress(SOLDIERTYPE *pSoldier) return(TRUE); } - - - - -/* -void RestoreMarkedMines() -{ -int gridno; - -// all tiles marked with the special NPC mine cost value must be restored -for (gridno = 0; gridno < GRIDSIZE; gridno++) -{ -if (GridCost[gridno] == NPCMINECOST) -{ -GridCost[gridno] = BackupGridCost[gridno]; - -#ifdef TESTMINEMARKING -fprintf(NetDebugFile,"\tRestoring marked mine at gridno %d back to gridCost %d\n",gridno,BackupGridCost[gridno]); -#endif -} -} - -MarkedNPCMines = FALSE; -} - - - -void MarkDetectableMines(SOLDIERTYPE *pSoldier) -{ -int gridno,detectLevel; -GRIDINFO *gpSoldier; - - -// this should happen, means we missed a clean-up cycle last time! -if (MarkedNPCMines) -{ -#ifdef BETAVERSION -sprintf(tempstr,"MarkDetectableMines: ERROR - mines still marked! Guynum %d",pSoldier->ubID); - -#ifdef RECORDNET -fprintf(NetDebugFile,"\n\t%s\n\n",tempstr); -#endif - -PopMessage(tempstr); -#endif - -RestoreMarkedMines(); -} - - -// make a backup of the current gridcosts -memcpy(BackupGridCost,GridCost,sizeof(GridCost)); - -// calculate what "level" of mines we are able to detect -detectLevel = CalcMineDetectLevel(pSoldier); - - -// check every tile, looking for BURIED mines only -for (gridno = 0,gpSoldier = &Grid[0]; gridno < GRIDSIZE; gridno++,gpSoldier++) -{ -// if there's a valid object there, and it is still "buried" -if ((gpSoldier->object < 255) && -(ObjList[gpSoldier->object].visible == BURIED) && -(ObjList[gpSoldier->object].item == MINE)) -{ -// are we bright enough to detect it (should we get there) ? -if (detectLevel >= ObjList[gpSoldier->object].trap) -{ -// bingo! Mark it as "unpassable" for the purposes of the path AI -GridCost[gridno] = NPCMINECOST; -MarkedNPCMines = TRUE; - -#ifdef TESTMINEMARKING -fprintf(NetDebugFile,"\tNPC %d, dtctLvl %d, marking mine at gridno %d, gridCost was %d\n",pSoldier->ubID,detectLevel,gridno,BackupGridCost[gridno]); -#endif -} -} -} -} - -*/ - - - - void TurnBasedHandleNPCAI(SOLDIERTYPE *pSoldier) { #ifdef ENABLE_ZOMBIES @@ -1645,150 +1325,9 @@ void TurnBasedHandleNPCAI(SOLDIERTYPE *pSoldier) lastdecisioncount = 0; } #endif - - /* - if (Status.gamePaused) - { - #ifdef DEBUGBUSY - DebugAI("HandleManAI - Skipping %d, the game is paused\n",pSoldier->ubID); - #endif - - return; - } - // - - // If man is inactive/at base/dead/unconscious - if (!pSoldier->bActive || !pSoldier->bInSector || (pSoldier->stats.bLife < OKLIFE)) - { - #ifdef DEBUGDECISIONS - AINumMessage("HandleManAI - Unavailable man, skipping guy#",pSoldier->ubID); - #endif - - NPCDoesNothing(pSoldier); - return; - } - - if (PTR_CIVILIAN && pSoldier->service && - (pSoldier->aiData.bNeutral || MedicsMissionIsEscort(pSoldier))) - { - #ifdef DEBUGDECISIONS - AINumMessage("HandleManAI - Civilian is being serviced, skipping guy#",pSoldier->ubID); - #endif - - NPCDoesNothing(pSoldier); - return; - } - */ - - - - /* - anim = pSoldier->anitype[pSoldier->anim]; - - // If man is down on the ground - if (anim < BREATHING) - { - // if he lacks the breath, or APs to get up this turn (life checked above) - // OR... (new June 13/96 Ian) he's getting first aid... - if ((pSoldier->bBreath < OKBREATH) || (pSoldier->bActionPoints < (APBPConstants[AP_GET_UP] + APBPConstants[AP_ROLL_OVER])) - || pSoldier->service) - { - #ifdef RECORDNET - fprintf(NetDebugFile,"\tAI: %d can't get up (breath %d, AP %d), ending his turn\n", - pSoldier->ubID,pSoldier->bBreath,pSoldier->bActionPoints); - #endif - #ifdef DEBUGDECISIONS - AINumMessage("HandleManAI - CAN'T GET UP, skipping guy #",pSoldier->ubID); - #endif - - NPCDoesNothing(pSoldier); - return; - } - else - { - // wait until he gets up first, only then worry about deciding his AI - - #ifdef RECORDNET - fprintf(NetDebugFile,"\tAI: waiting for %d to GET UP (breath %d, AP %d)\n", - pSoldier->ubID,pSoldier->bBreath,pSoldier->bActionPoints); - #endif - - #ifdef DEBUGBUSY - AINumMessage("HandleManAI - About to get up, skipping guy#",pSoldier->ubID); - #endif - - return; - } - } - - - // if NPC's has been forced to stop by an opponent's interrupt or similar - if (pSoldier->flags.forcedToStop) - { - #ifdef DEBUGBUSY - AINumMessage("HandleManAI - Forced to stop, skipping guy #",pSoldier->ubID); - #endif - - return; - } - - // if we are still in the midst in an uninterruptable animation - if (!AnimControl[anim].interruptable) - { - #ifdef DEBUGBUSY - AINumMessage("HandleManAI - uninterruptable animation, skipping guy #",pSoldier->ubID); - #endif - - return; // wait a while, let the animation finish first - } - - */ - // yikes, this shouldn't occur! we should be trying to finish our move! // pSoldier->flags.fNoAPToFinishMove = FALSE; - // unless in mid-move, get an up-to-date alert status for this guy - if (pSoldier->pathing.bStopped) - { - // if active team is waiting for oppChanceToDecide, that means we have NOT - // had a chance to go through NewSelectedNPC(), so do the refresh here - /* - ??? - if (gTacticalStatus.team[Net.turnActive].allowOppChanceToDecide) - { - // if mines are still marked (this could happen if we also control the - // active team that's potentially BEING interrupted), unmark them - //RestoreMarkedMines(); - - RefreshAI(pSoldier); - } - else - { - DecideAlertStatus(pSoldier); - } - */ - } - - /* - // move this clause outside of the function... - if (pSoldier->aiData.bNewSituation) - // don't force, don't want escorted mercs reacting to new opponents, etc. - CancelAIAction(pSoldier,DONTFORCE); - - */ - - - /* - if (!pSoldier->stopped) - { - #ifdef DEBUGBUSY - AINumMessage("HandleManAI - Moving, skipping guy#",pSoldier->ubID); - #endif - - return; - } - */ - // Flugente: pows don't do anything if ( pSoldier->bSoldierFlagMask & SOLDIER_POW ) { @@ -1798,38 +1337,6 @@ void TurnBasedHandleNPCAI(SOLDIERTYPE *pSoldier) if ((pSoldier->aiData.bAction != AI_ACTION_NONE) && pSoldier->aiData.bActionInProgress) { - /* - if (pSoldier->aiData.bAction == AI_ACTION_RANDOM_PATROL) - { - if (pSoldier->pathing.usPathIndex == pSoldier->pathing.usPathDataSize) - //if (pSoldier->aiData.usActionData == pSoldier->sGridNo ) - //(IC?) if (pSoldier->aiData.bAction == AI_ACTION_RANDOM_PATROL && ( pSoldier->pathing.usPathIndex == pSoldier->pathing.usPathDataSize ) ) - //(old?) if (pSoldier->aiData.bAction == AI_ACTION_RANDOM_PATROL && ( pSoldier->aiData.usActionData == pSoldier->sGridNo ) ) - { - #ifdef TESTAI - DebugMsg( TOPIC_JA2AI, DBG_LEVEL_0, String("OPPONENT %d REACHES DEST - ACTION DONE",pSoldier->ubID ) ); - #endif - ActionDone(pSoldier); - } - - //*** TRICK- TAKE INTO ACCOUNT PAUSED FOR NO TIME ( FOR NOW ) - if (pSoldier->flags.fNoAPToFinishMove) - //if (pSoldier->aiData.bAction == AI_ACTION_RANDOM_PATROL && pSoldier->flags.fNoAPToFinishMove) - { - // OK, we have a move to finish... - - #ifdef TESTAI - DebugMsg( TOPIC_JA2AI, DBG_LEVEL_0, String("GONNA TRY TO CONTINUE PATH FOR %d", pSoldier->ubID ) ); - #endif - - SoldierTriesToContinueAlongPath(pSoldier); - - // since we just gave up on our action due to running out of points, better end our turn - //EndAIGuysTurn(pSoldier); - } - } - */ - // if action should remain in progress if (ActionInProgress(pSoldier)) { @@ -1977,29 +1484,7 @@ void TurnBasedHandleNPCAI(SOLDIERTYPE *pSoldier) NPCDoesNothing(pSoldier); // sets pSoldier->moved to TRUE return; } - - - - /* - // if we somehow just caused an uninterruptable animation to occur - // This is mainly to finish a weapon_AWAY anim that preceeds a TOSS attack - if (!AnimControl[ pSoldier->anitype[pSoldier->anim] ].interruptable) - { - #ifdef DEBUGBUSY - DebugAI( String( "Uninterruptable animation %d, skipping guy %d",pSoldier->anitype[pSoldier->anim],pSoldier->ubID ) ); - #endif - - return; // wait a while, let the animation finish first - } - */ - // to get here, we MUST have an action selected, but not in progress... - - if ( CHEATER_CHEAT_LEVEL( ) ) - { - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Soldier %d decides action %d with data %d", pSoldier->ubID, pSoldier->aiData.bAction, pSoldier->aiData.usActionData ); - } - // see if we can afford to do this action if (IsActionAffordable(pSoldier)) { @@ -2175,693 +1660,651 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier) pSoldier->pathing.usPathDataSize = pSoldier->pathing.usPathIndex = pSoldier->pathing.bPathStored = 0; switch (pSoldier->aiData.bAction) - { - case AI_ACTION_NONE: // maintain current position & facing - // do nothing - break; + { + case AI_ACTION_NONE: // maintain current position & facing + // do nothing + break; - case AI_ACTION_WAIT: // hold AI_ACTION_NONE for a specified time - if (gfTurnBasedAI) - { - // probably an action set as a next-action in the realtime prior to combat - // do nothing - } - else - { - RESETTIMECOUNTER( pSoldier->timeCounters.AICounter, pSoldier->aiData.usActionData ); - if (pSoldier->ubProfile != NO_PROFILE) - { - //DebugMsg( TOPIC_JA2, DBG_LEVEL_0, String( "%s waiting %d from %d", pSoldier->name, pSoldier->timeCounters.AICounter, GetJA2Clock() ) ); - } - } - ActionDone( pSoldier ); - break; + case AI_ACTION_WAIT: // hold AI_ACTION_NONE for a specified time + if (gfTurnBasedAI) + { + // probably an action set as a next-action in the realtime prior to combat + // do nothing + } + else + { + RESETTIMECOUNTER( pSoldier->timeCounters.AICounter, pSoldier->aiData.usActionData ); + if (pSoldier->ubProfile != NO_PROFILE) + { + //DebugMsg( TOPIC_JA2, DBG_LEVEL_0, String( "%s waiting %d from %d", pSoldier->name, pSoldier->timeCounters.AICounter, GetJA2Clock() ) ); + } + } + ActionDone( pSoldier ); + break; - case AI_ACTION_CHANGE_FACING: // turn this way & that to look - // as long as we don't see anyone new, cover won't have changed - // if we see someone new, it will cause a new situation & remove this - // 0verhaul: If turning and not moving, set the final destination to the current position - pSoldier->pathing.sFinalDestination = pSoldier->sGridNo; - SkipCoverCheck = TRUE; + case AI_ACTION_CHANGE_FACING: // turn this way & that to look + // as long as we don't see anyone new, cover won't have changed + // if we see someone new, it will cause a new situation & remove this + // 0verhaul: If turning and not moving, set the final destination to the current position + pSoldier->pathing.sFinalDestination = pSoldier->sGridNo; + SkipCoverCheck = TRUE; #ifdef DEBUGDECISIONS - STR tempstr; - sprintf( tempstr, "ExecuteAction: SkipCoverCheck ON\n" ); - DebugAI (tempstr); + STR tempstr; + sprintf( tempstr, "ExecuteAction: SkipCoverCheck ON\n" ); + DebugAI (tempstr); #endif + SendSoldierSetDesiredDirectionEvent( pSoldier, pSoldier->aiData.usActionData ); + // now we'll have to wait for the turning to finish; no need to call TurnSoldier here + break; - // pSoldier->pathing.bDesiredDirection = (UINT8) ; // turn to face direction in actionData - SendSoldierSetDesiredDirectionEvent( pSoldier, pSoldier->aiData.usActionData ); - // now we'll have to wait for the turning to finish; no need to call TurnSoldier here - //pSoldier->TurnSoldier( ); - /* - if (!StartTurn(pSoldier,pSoldier->aiData.usActionData,FASTTURN)) - { - #ifdef BETAVERSION - sprintf(tempstr,"ERROR: %s tried TURN to direction %d, StartTurn failed, action %d CANCELED", - pSoldier->name,pSoldier->aiData.usActionData,pSoldier->aiData.bAction); - PopMessage(tempstr); - #endif + case AI_ACTION_PICKUP_ITEM: // grab something! + SoldierPickupItem( pSoldier, pSoldier->aiData.uiPendingActionData1, pSoldier->aiData.usActionData, 0 ); + break; - // ZAP NPC's remaining action points so this isn't likely to repeat - pSoldier->bActionPoints = 0; + case AI_ACTION_DROP_ITEM: // drop item in hand + //CHRISL: If we have a weapon in both hands, we need to drop the weapon that isn't usable + if(pSoldier->inv[HANDPOS].fFlags & OBJECT_AI_UNUSABLE) + { + SoldierDropItem( pSoldier, &(pSoldier->inv[HANDPOS]) ); + DeleteObj( &(pSoldier->inv[HANDPOS]) ); + } + if(pSoldier->inv[SECONDHANDPOS].exists() == true && Item[pSoldier->inv[SECONDHANDPOS].usItem].usItemClass == IC_GUN && pSoldier->inv[SECONDHANDPOS].fFlags & OBJECT_AI_UNUSABLE) + { + SoldierDropItem( pSoldier, &(pSoldier->inv[SECONDHANDPOS]) ); + DeleteObj( &(pSoldier->inv[SECONDHANDPOS]) ); + } + // 0verhaul: Moved into PickDropAnimation because when something is dropped while crouched there's nothing to wait for + // pSoldier->aiData.bAction = AI_ACTION_PENDING_ACTION; + break; - CancelAIAction(pSoldier,FORCE); - return(FALSE); // nothing is in progress - } - else - { - #ifdef RECORDNET - fprintf(NetDebugFile,"\tAI decides to turn guynum %d to dir %d\n",pSoldier->ubID,pSoldier->aiData.usActionData); - #endif - NetLookTowardsDir(pSoldier,pSoldier->aiData.usActionData); - } - */ - break; + // fall through + case AI_ACTION_RANDOM_PATROL: // move towards a particular location + case AI_ACTION_SEEK_FRIEND: // move towards friend in trouble + case AI_ACTION_SEEK_OPPONENT: // move towards a reported opponent + case AI_ACTION_TAKE_COVER: // run for nearest cover from threat + case AI_ACTION_GET_CLOSER: // move closer to a strategic location - case AI_ACTION_PICKUP_ITEM: // grab something! - SoldierPickupItem( pSoldier, pSoldier->aiData.uiPendingActionData1, pSoldier->aiData.usActionData, 0 ); - break; - - case AI_ACTION_DROP_ITEM: // drop item in hand - //CHRISL: If we have a weapon in both hands, we need to drop the weapon that isn't usable - if(pSoldier->inv[HANDPOS].fFlags & OBJECT_AI_UNUSABLE) - { - SoldierDropItem( pSoldier, &(pSoldier->inv[HANDPOS]) ); - DeleteObj( &(pSoldier->inv[HANDPOS]) ); - } - if(pSoldier->inv[SECONDHANDPOS].exists() == true && Item[pSoldier->inv[SECONDHANDPOS].usItem].usItemClass == IC_GUN && pSoldier->inv[SECONDHANDPOS].fFlags & OBJECT_AI_UNUSABLE) - { - SoldierDropItem( pSoldier, &(pSoldier->inv[SECONDHANDPOS]) ); - DeleteObj( &(pSoldier->inv[SECONDHANDPOS]) ); - } - // 0verhaul: Moved into PickDropAnimation because when something is dropped while crouched there's nothing to wait for - // pSoldier->aiData.bAction = AI_ACTION_PENDING_ACTION; - break; - - //case AI_ACTION_MOVE_TO_CLIMB: - // if ( pSoldier->aiData.usActionData == pSoldier->sGridNo ) - // { - // // change action to climb now and try that. - // pSoldier->aiData.bAction = AI_ACTION_CLIMB_ROOF; - // if (IsActionAffordable(pSoldier)) - // { - // return( ExecuteAction( pSoldier ) ); - // } - // else - // { - // // no action started - // return( FALSE ); - // } - // } - - // fall through - case AI_ACTION_RANDOM_PATROL: // move towards a particular location - case AI_ACTION_SEEK_FRIEND: // move towards friend in trouble - case AI_ACTION_SEEK_OPPONENT: // move towards a reported opponent - case AI_ACTION_TAKE_COVER: // run for nearest cover from threat - case AI_ACTION_GET_CLOSER: // move closer to a strategic location - - case AI_ACTION_POINT_PATROL: // move towards next patrol point - case AI_ACTION_LEAVE_WATER_GAS: // seek nearest spot of ungassed land - case AI_ACTION_SEEK_NOISE: // seek most important noise heard - case AI_ACTION_RUN_AWAY: // run away from nearby opponent(s) - // SANDRO - ENEMY TAUNTS - if (gGameSettings.fOptions[TOPTION_ALLOW_TAUNTS] == TRUE && pSoldier->bTeam == ENEMY_TEAM && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) && pSoldier->bVisible != -1 ) - { - if ( Random( 5 ) == 0 ) - { - if (pSoldier->aiData.bAction == AI_ACTION_SEEK_NOISE ) - StartEnemyTaunt( pSoldier, TAUNT_SEEK_NOISE ); - else if (pSoldier->aiData.bAction == AI_ACTION_RUN_AWAY ) - StartEnemyTaunt( pSoldier, TAUNT_RUN_AWAY ); + case AI_ACTION_POINT_PATROL: // move towards next patrol point + case AI_ACTION_LEAVE_WATER_GAS: // seek nearest spot of ungassed land + case AI_ACTION_SEEK_NOISE: // seek most important noise heard + case AI_ACTION_RUN_AWAY: // run away from nearby opponent(s) + // SANDRO - ENEMY TAUNTS + if (gGameSettings.fOptions[TOPTION_ALLOW_TAUNTS] == TRUE && pSoldier->bTeam == ENEMY_TEAM && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) && pSoldier->bVisible != -1 ) + { + if ( Random( 5 ) == 0 ) + { + if (pSoldier->aiData.bAction == AI_ACTION_SEEK_NOISE ) + StartEnemyTaunt( pSoldier, TAUNT_SEEK_NOISE ); + else if (pSoldier->aiData.bAction == AI_ACTION_RUN_AWAY ) + StartEnemyTaunt( pSoldier, TAUNT_RUN_AWAY ); #ifdef ENABLE_ZOMBIES - else if ( pSoldier->IsZombie() ) // Madd: Zombies randomly moan... - pSoldier->DoMercBattleSound( (INT8)( BATTLE_SOUND_LAUGH1 ) ); + else if ( pSoldier->IsZombie() ) // Madd: Zombies randomly moan... + pSoldier->DoMercBattleSound( (INT8)( BATTLE_SOUND_LAUGH1 ) ); #endif - } - } - case AI_ACTION_APPROACH_MERC: // walk up to someone to talk - case AI_ACTION_TRACK: // track by ground scent - case AI_ACTION_EAT: // monster approaching corpse - case AI_ACTION_SCHEDULE_MOVE: - case AI_ACTION_WALK: - case AI_ACTION_WITHDRAW: - case AI_ACTION_FLANK_LEFT: - case AI_ACTION_FLANK_RIGHT: - case AI_ACTION_RUN: - case AI_ACTION_MOVE_TO_CLIMB: - if ( pSoldier->aiData.bAction == AI_ACTION_MOVE_TO_CLIMB ) - { - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Executing: AI_ACTION_MOVE_TO_CLIMB"); - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("Soldier GridNo = %d, action data = %d ", pSoldier->sGridNo , pSoldier->aiData.usActionData)); - } + } + } + case AI_ACTION_APPROACH_MERC: // walk up to someone to talk + case AI_ACTION_TRACK: // track by ground scent + case AI_ACTION_EAT: // monster approaching corpse + case AI_ACTION_SCHEDULE_MOVE: + case AI_ACTION_WALK: + case AI_ACTION_WITHDRAW: + case AI_ACTION_FLANK_LEFT: + case AI_ACTION_FLANK_RIGHT: + case AI_ACTION_RUN: + case AI_ACTION_MOVE_TO_CLIMB: + if ( pSoldier->aiData.bAction == AI_ACTION_MOVE_TO_CLIMB ) + { + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Executing: AI_ACTION_MOVE_TO_CLIMB"); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("Soldier GridNo = %d, action data = %d ", pSoldier->sGridNo , pSoldier->aiData.usActionData)); + } - if ( gfTurnBasedAI && pSoldier->aiData.bAlertStatus <= STATUS_BLACK ) - { - if (TileIsOutOfBounds(pSoldier->sLastTwoLocations[0])) - { - pSoldier->sLastTwoLocations[0] = pSoldier->sGridNo; - } - else if (TileIsOutOfBounds(pSoldier->sLastTwoLocations[1])) - { - pSoldier->sLastTwoLocations[1] = pSoldier->sGridNo; - } - // check for loop - else if ( pSoldier->aiData.usActionData == pSoldier->sLastTwoLocations[1] && pSoldier->sGridNo == pSoldier->sLastTwoLocations[0] ) - { - DebugAI( String( "%d in movement loop, aborting turn", pSoldier->ubID ) ); + if ( gfTurnBasedAI && pSoldier->aiData.bAlertStatus <= STATUS_BLACK ) + { + if (TileIsOutOfBounds(pSoldier->sLastTwoLocations[0])) + { + pSoldier->sLastTwoLocations[0] = pSoldier->sGridNo; + } + else if (TileIsOutOfBounds(pSoldier->sLastTwoLocations[1])) + { + pSoldier->sLastTwoLocations[1] = pSoldier->sGridNo; + } + // check for loop + else if ( pSoldier->aiData.usActionData == pSoldier->sLastTwoLocations[1] && pSoldier->sGridNo == pSoldier->sLastTwoLocations[0] ) + { + DebugAI( String( "%d in movement loop, aborting turn", pSoldier->ubID ) ); - // loop found! - ActionDone( pSoldier ); - EndAIGuysTurn( pSoldier ); - } - else - { - pSoldier->sLastTwoLocations[0] = pSoldier->sLastTwoLocations[1]; - pSoldier->sLastTwoLocations[1] = pSoldier->sGridNo; - } - } + // loop found! + ActionDone( pSoldier ); + EndAIGuysTurn( pSoldier ); + } + else + { + pSoldier->sLastTwoLocations[0] = pSoldier->sLastTwoLocations[1]; + pSoldier->sLastTwoLocations[1] = pSoldier->sGridNo; + } + } - // Randomly do growl... - if ( pSoldier->ubBodyType == BLOODCAT ) - { - if ( ( gTacticalStatus.uiFlags & INCOMBAT ) ) - { - if ( Random( 2 ) == 0 ) - { - PlaySoldierJA2Sample( pSoldier->ubID, ( BLOODCAT_GROWL_1 + Random( 4 ) ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE ); - } - } - } + // Randomly do growl... + if ( pSoldier->ubBodyType == BLOODCAT ) + { + if ( ( gTacticalStatus.uiFlags & INCOMBAT ) ) + { + if ( Random( 2 ) == 0 ) + { + PlaySoldierJA2Sample( pSoldier->ubID, ( BLOODCAT_GROWL_1 + Random( 4 ) ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE ); + } + } + } - // on YELLOW/GREEN status, NPCs keep the actions from turn to turn - // (newSituation is intentionally NOT set in NewSelectedNPC()), so the - // possibility exists that NOW the actionData is no longer a valid - // NPC->pathing.sDestination (path got blocked, someone is now standing at that - // gridno, etc.) So we gotta check again that the->pathing.sDestination's legal! + // on YELLOW/GREEN status, NPCs keep the actions from turn to turn + // (newSituation is intentionally NOT set in NewSelectedNPC()), so the + // possibility exists that NOW the actionData is no longer a valid + // NPC->pathing.sDestination (path got blocked, someone is now standing at that + // gridno, etc.) So we gotta check again that the->pathing.sDestination's legal! - // optimization - Ian (if up-to-date path is known, do not check again) - if (!pSoldier->pathing.bPathStored) - { - if ( (!TileIsOutOfBounds(pSoldier->sAbsoluteFinalDestination) || gTacticalStatus.fAutoBandageMode) && !(gTacticalStatus.uiFlags & INCOMBAT) ) - { - // NPC system move, allow path through - if (LegalNPCDestination(pSoldier,pSoldier->aiData.usActionData,ENSURE_PATH,WATEROK, PATH_THROUGH_PEOPLE )) - { - // optimization - Ian: prevent another path call in SetNewCourse() - pSoldier->pathing.bPathStored = TRUE; - } - } - else - { - if (LegalNPCDestination(pSoldier,pSoldier->aiData.usActionData,ENSURE_PATH,WATEROK, 0)) - { - // optimization - Ian: prevent another path call in SetNewCourse() - pSoldier->pathing.bPathStored = TRUE; - } - } + // optimization - Ian (if up-to-date path is known, do not check again) + if (!pSoldier->pathing.bPathStored) + { + if ( (!TileIsOutOfBounds(pSoldier->sAbsoluteFinalDestination) || gTacticalStatus.fAutoBandageMode) && !(gTacticalStatus.uiFlags & INCOMBAT) ) + { + // NPC system move, allow path through + if (LegalNPCDestination(pSoldier,pSoldier->aiData.usActionData,ENSURE_PATH,WATEROK, PATH_THROUGH_PEOPLE )) + { + // optimization - Ian: prevent another path call in SetNewCourse() + pSoldier->pathing.bPathStored = TRUE; + } + } + else + { + if (LegalNPCDestination(pSoldier,pSoldier->aiData.usActionData,ENSURE_PATH,WATEROK, 0)) + { + // optimization - Ian: prevent another path call in SetNewCourse() + pSoldier->pathing.bPathStored = TRUE; + } + } - // if we STILL don't have a path - if ( !pSoldier->pathing.bPathStored ) - { - // Check if we were told to move by NPC stuff - if ( !TileIsOutOfBounds(pSoldier->sAbsoluteFinalDestination) && !(gTacticalStatus.uiFlags & INCOMBAT) ) - { - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_ERROR, L"AI %s failed to get path for dialogue-related move!", pSoldier->name ); + // if we STILL don't have a path + if ( !pSoldier->pathing.bPathStored ) + { + // Check if we were told to move by NPC stuff + if ( !TileIsOutOfBounds(pSoldier->sAbsoluteFinalDestination) && !(gTacticalStatus.uiFlags & INCOMBAT) ) + { + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_ERROR, L"AI %s failed to get path for dialogue-related move!", pSoldier->name ); - // Are we close enough? - if ( !ACTING_ON_SCHEDULE( pSoldier ) && SpacesAway( pSoldier->sGridNo, pSoldier->sAbsoluteFinalDestination ) < 4 ) - { - // This is close enough... - ReplaceLocationInNPCDataFromProfileID( pSoldier->ubProfile, pSoldier->sAbsoluteFinalDestination, pSoldier->sGridNo ); - NPCGotoGridNo( pSoldier->ubProfile, pSoldier->sGridNo, (UINT8) (pSoldier->ubQuoteRecord - 1) ); - } - else - { - // This is important, so try taking a path through people (and bumping them aside) - if (LegalNPCDestination(pSoldier,pSoldier->aiData.usActionData,ENSURE_PATH,WATEROK, PATH_THROUGH_PEOPLE)) - { - // optimization - Ian: prevent another path call in SetNewCourse() - pSoldier->pathing.bPathStored = TRUE; - } - else - { - // Have buddy wait a while... - pSoldier->aiData.bNextAction = AI_ACTION_WAIT; - pSoldier->aiData.usNextActionData = (UINT16)REALTIME_AI_DELAY; - } - } + // Are we close enough? + if ( !ACTING_ON_SCHEDULE( pSoldier ) && SpacesAway( pSoldier->sGridNo, pSoldier->sAbsoluteFinalDestination ) < 4 ) + { + // This is close enough... + ReplaceLocationInNPCDataFromProfileID( pSoldier->ubProfile, pSoldier->sAbsoluteFinalDestination, pSoldier->sGridNo ); + NPCGotoGridNo( pSoldier->ubProfile, pSoldier->sGridNo, (UINT8) (pSoldier->ubQuoteRecord - 1) ); + } + else + { + // This is important, so try taking a path through people (and bumping them aside) + if (LegalNPCDestination(pSoldier,pSoldier->aiData.usActionData,ENSURE_PATH,WATEROK, PATH_THROUGH_PEOPLE)) + { + // optimization - Ian: prevent another path call in SetNewCourse() + pSoldier->pathing.bPathStored = TRUE; + } + else + { + // Have buddy wait a while... + pSoldier->aiData.bNextAction = AI_ACTION_WAIT; + pSoldier->aiData.usNextActionData = (UINT16)REALTIME_AI_DELAY; + } + } - if (!pSoldier->pathing.bPathStored) - { - CancelAIAction(pSoldier,FORCE); - return(FALSE); // nothing is in progress - } - } - else - { - CancelAIAction(pSoldier,FORCE); - return(FALSE); // nothing is in progress - } - } - } + if (!pSoldier->pathing.bPathStored) + { + CancelAIAction(pSoldier,FORCE); + return(FALSE); // nothing is in progress + } + } + else + { + CancelAIAction(pSoldier,FORCE); + return(FALSE); // nothing is in progress + } + } + } - // add on anything necessary to traverse off map edge - switch( pSoldier->ubQuoteActionID ) - { - case QUOTE_ACTION_ID_TRAVERSE_EAST: - pSoldier->sOffWorldGridNo = pSoldier->aiData.usActionData; - AdjustSoldierPathToGoOffEdge( pSoldier, pSoldier->aiData.usActionData, EAST ); - break; - case QUOTE_ACTION_ID_TRAVERSE_SOUTH: - pSoldier->sOffWorldGridNo = pSoldier->aiData.usActionData; - AdjustSoldierPathToGoOffEdge( pSoldier, pSoldier->aiData.usActionData, SOUTH ); - break; - case QUOTE_ACTION_ID_TRAVERSE_WEST: - pSoldier->sOffWorldGridNo = pSoldier->aiData.usActionData; - AdjustSoldierPathToGoOffEdge( pSoldier, pSoldier->aiData.usActionData, WEST ); - break; - case QUOTE_ACTION_ID_TRAVERSE_NORTH: - pSoldier->sOffWorldGridNo = pSoldier->aiData.usActionData; - AdjustSoldierPathToGoOffEdge( pSoldier, pSoldier->aiData.usActionData, NORTH ); - break; - default: - break; - } + // add on anything necessary to traverse off map edge + switch( pSoldier->ubQuoteActionID ) + { + case QUOTE_ACTION_ID_TRAVERSE_EAST: + pSoldier->sOffWorldGridNo = pSoldier->aiData.usActionData; + AdjustSoldierPathToGoOffEdge( pSoldier, pSoldier->aiData.usActionData, EAST ); + break; + case QUOTE_ACTION_ID_TRAVERSE_SOUTH: + pSoldier->sOffWorldGridNo = pSoldier->aiData.usActionData; + AdjustSoldierPathToGoOffEdge( pSoldier, pSoldier->aiData.usActionData, SOUTH ); + break; + case QUOTE_ACTION_ID_TRAVERSE_WEST: + pSoldier->sOffWorldGridNo = pSoldier->aiData.usActionData; + AdjustSoldierPathToGoOffEdge( pSoldier, pSoldier->aiData.usActionData, WEST ); + break; + case QUOTE_ACTION_ID_TRAVERSE_NORTH: + pSoldier->sOffWorldGridNo = pSoldier->aiData.usActionData; + AdjustSoldierPathToGoOffEdge( pSoldier, pSoldier->aiData.usActionData, NORTH ); + break; + default: + break; + } - NewDest(pSoldier,pSoldier->aiData.usActionData); // set new->pathing.sDestination to actionData + NewDest(pSoldier,pSoldier->aiData.usActionData); // set new->pathing.sDestination to actionData - // make sure it worked (check that pSoldier->pathing.sDestination == pSoldier->aiData.usActionData) - if (pSoldier->pathing.sFinalDestination != pSoldier->aiData.usActionData) - { + // make sure it worked (check that pSoldier->pathing.sDestination == pSoldier->aiData.usActionData) + if (pSoldier->pathing.sFinalDestination != pSoldier->aiData.usActionData) + { #ifdef BETAVERSION - // this should NEVER happen, indicates AI picked an illegal spot! - sprintf(tempstr,"ExecuteAction: ERROR - %s tried MOVE to gridno %d, NewDest failed, action %d CANCELED", - pSoldier->name,pSoldier->aiData.usActionData,pSoldier->aiData.bAction); + // this should NEVER happen, indicates AI picked an illegal spot! + sprintf(tempstr,"ExecuteAction: ERROR - %s tried MOVE to gridno %d, NewDest failed, action %d CANCELED", + pSoldier->name,pSoldier->aiData.usActionData,pSoldier->aiData.bAction); #ifdef RECORDNET - fprintf(NetDebugFile,"\n%s\n\n",tempstr); + fprintf(NetDebugFile,"\n%s\n\n",tempstr); #endif - PopMessage(tempstr); + PopMessage(tempstr); - sprintf(tempstr,"BLACK-LISTING gridno %d for %s",pSoldier->aiData.usActionData,pSoldier->name); - PopMessage(tempstr); + sprintf(tempstr,"BLACK-LISTING gridno %d for %s",pSoldier->aiData.usActionData,pSoldier->name); + PopMessage(tempstr); - SaveGame(ERROR_SAVE); + SaveGame(ERROR_SAVE); #endif - // temporarily black list this gridno to stop enemy from going there - pSoldier->pathing.sBlackList = (INT16) pSoldier->aiData.usActionData; + // temporarily black list this gridno to stop enemy from going there + pSoldier->pathing.sBlackList = (INT16) pSoldier->aiData.usActionData; - DebugAI( String( "Setting blacklist for %d to %d", pSoldier->ubID, pSoldier->pathing.sBlackList ) ); + DebugAI( String( "Setting blacklist for %d to %d", pSoldier->ubID, pSoldier->pathing.sBlackList ) ); - CancelAIAction(pSoldier,FORCE); - return(FALSE); // nothing is in progress - } + CancelAIAction(pSoldier,FORCE); + return(FALSE); // nothing is in progress + } - // cancel any old black-listed gridno, got a valid new->pathing.sDestination - pSoldier->pathing.sBlackList = NOWHERE; - break; + // cancel any old black-listed gridno, got a valid new->pathing.sDestination + pSoldier->pathing.sBlackList = NOWHERE; + break; - case AI_ACTION_ESCORTED_MOVE: // go where told to by escortPlayer - // since this is a delayed move, gotta make sure that it hasn't become - // illegal since escort orders were issued (->pathing.sDestination/route blocked). - // So treat it like a CONTINUE movement, and handle errors that way - if (!TryToResumeMovement(pSoldier,pSoldier->aiData.usActionData)) - { - // don't black-list anything here, and action already got canceled - return(FALSE); // nothing is in progress - } + case AI_ACTION_ESCORTED_MOVE: // go where told to by escortPlayer + // since this is a delayed move, gotta make sure that it hasn't become + // illegal since escort orders were issued (->pathing.sDestination/route blocked). + // So treat it like a CONTINUE movement, and handle errors that way + if (!TryToResumeMovement(pSoldier,pSoldier->aiData.usActionData)) + { + // don't black-list anything here, and action already got canceled + return(FALSE); // nothing is in progress + } - // cancel any old black-listed gridno, got a valid new->pathing.sDestination - pSoldier->pathing.sBlackList = NOWHERE; - break; + // cancel any old black-listed gridno, got a valid new->pathing.sDestination + pSoldier->pathing.sBlackList = NOWHERE; + break; - case AI_ACTION_TOSS_PROJECTILE: // throw grenade at/near opponent(s) - LoadWeaponIfNeeded(pSoldier); - // drop through here... + case AI_ACTION_TOSS_PROJECTILE: // throw grenade at/near opponent(s) + LoadWeaponIfNeeded(pSoldier); + // drop through here... - case AI_ACTION_KNIFE_MOVE: // preparing to stab opponent - if (pSoldier->aiData.bAction == AI_ACTION_KNIFE_MOVE) // if statement because toss falls through - { - pSoldier->usUIMovementMode = DetermineMovementMode( pSoldier, AI_ACTION_KNIFE_MOVE ); - } + case AI_ACTION_KNIFE_MOVE: // preparing to stab opponent + if (pSoldier->aiData.bAction == AI_ACTION_KNIFE_MOVE) // if statement because toss falls through + { + pSoldier->usUIMovementMode = DetermineMovementMode( pSoldier, AI_ACTION_KNIFE_MOVE ); + } - // fall through - case AI_ACTION_FIRE_GUN: // shoot at nearby opponent - case AI_ACTION_THROW_KNIFE: // throw knife at nearby opponent - // randomly decide whether to say civ quote - if ( pSoldier->bVisible != -1 && pSoldier->bTeam != MILITIA_TEAM ) - { - // ATE: Make sure it's a person :) - if ( IS_MERC_BODY_TYPE( pSoldier ) && pSoldier->ubProfile == NO_PROFILE ) - { - // SANDRO - SOLDIER TAUNTS - if (gGameSettings.fOptions[TOPTION_ALLOW_TAUNTS] == TRUE && pSoldier->bTeam == ENEMY_TEAM && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) ) - { - if ( Random( 8 ) == 0 ) - { - if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_GUN ) - StartEnemyTaunt( pSoldier, TAUNT_FIRE_GUN ); - else if (Item[pSoldier->inv[HANDPOS].usItem].grenadelauncher || Item[pSoldier->inv[HANDPOS].usItem].mortar || Item[pSoldier->inv[HANDPOS].usItem].rocketlauncher ) - StartEnemyTaunt( pSoldier, TAUNT_FIRE_LAUNCHER ); - else if (pSoldier->aiData.bAction == AI_ACTION_TOSS_PROJECTILE && Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_THROWN && !Item[pSoldier->inv[HANDPOS].usItem].flare ) - StartEnemyTaunt( pSoldier, TAUNT_THROW ); - else if (pSoldier->aiData.bAction == AI_ACTION_KNIFE_MOVE ) - { - if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_BLADE ) - StartEnemyTaunt( pSoldier, TAUNT_CHARGE_KNIFE ); - //else if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_PUNCH ) - // StartEnemyTaunt( pSoldier, TAUNT_CHARGE_HTH ); - } - } - } - // CC, ATE here - I put in some TEMP randomness... - else if ( Random( 50 ) == 0 ) - { - StartCivQuote( pSoldier ); - } - } - } + // fall through + case AI_ACTION_FIRE_GUN: // shoot at nearby opponent + case AI_ACTION_THROW_KNIFE: // throw knife at nearby opponent + // randomly decide whether to say civ quote + if ( pSoldier->bVisible != -1 && pSoldier->bTeam != MILITIA_TEAM ) + { + // ATE: Make sure it's a person :) + if ( IS_MERC_BODY_TYPE( pSoldier ) && pSoldier->ubProfile == NO_PROFILE ) + { + // SANDRO - SOLDIER TAUNTS + if (gGameSettings.fOptions[TOPTION_ALLOW_TAUNTS] == TRUE && pSoldier->bTeam == ENEMY_TEAM && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) ) + { + if ( Random( 8 ) == 0 ) + { + if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_GUN ) + StartEnemyTaunt( pSoldier, TAUNT_FIRE_GUN ); + else if (Item[pSoldier->inv[HANDPOS].usItem].grenadelauncher || Item[pSoldier->inv[HANDPOS].usItem].mortar || Item[pSoldier->inv[HANDPOS].usItem].rocketlauncher ) + StartEnemyTaunt( pSoldier, TAUNT_FIRE_LAUNCHER ); + else if (pSoldier->aiData.bAction == AI_ACTION_TOSS_PROJECTILE && Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_THROWN && !Item[pSoldier->inv[HANDPOS].usItem].flare ) + StartEnemyTaunt( pSoldier, TAUNT_THROW ); + else if (pSoldier->aiData.bAction == AI_ACTION_KNIFE_MOVE ) + { + if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_BLADE ) + StartEnemyTaunt( pSoldier, TAUNT_CHARGE_KNIFE ); + //else if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_PUNCH ) + // StartEnemyTaunt( pSoldier, TAUNT_CHARGE_HTH ); + } + } + } + // CC, ATE here - I put in some TEMP randomness... + else if ( Random( 50 ) == 0 ) + { + StartCivQuote( pSoldier ); + } + } + } #ifdef RECORDNET - fprintf(NetDebugFile,"\tExecuteAction: %d calling HandleItem(), inHand %d, actionData %d, anitype %d, oldani %d\n", - pSoldier->ubID,pSoldier->inv[HANDPOS].item,pSoldier->aiData.usActionData,pSoldier->anitype[pSoldier->anim],pSoldier->oldani); + fprintf(NetDebugFile,"\tExecuteAction: %d calling HandleItem(), inHand %d, actionData %d, anitype %d, oldani %d\n", + pSoldier->ubID,pSoldier->inv[HANDPOS].item,pSoldier->aiData.usActionData,pSoldier->anitype[pSoldier->anim],pSoldier->oldani); #endif #ifdef TESTVERSION - if (pSoldier->aiData.bAction == AI_ACTION_KNIFE_MOVE) - { - sprintf(tempstr,"TEST MSG: %s is about to go stab %s. MAKE SURE HE DOES!", - pSoldier->name, - ExtMen[WhoIsThere(pSoldier->aiData.usActionData)].name); + if (pSoldier->aiData.bAction == AI_ACTION_KNIFE_MOVE) + { + sprintf(tempstr,"TEST MSG: %s is about to go stab %s. MAKE SURE HE DOES!", + pSoldier->name, + ExtMen[WhoIsThere(pSoldier->aiData.usActionData)].name); - SimulMessage(tempstr,3000,NODECRYPT); - } + SimulMessage(tempstr,3000,NODECRYPT); + } #endif - if ( pSoldier->aiData.bAction == AI_ACTION_TOSS_PROJECTILE && IsGrenadeLauncherAttached(&pSoldier->inv[HANDPOS]) ) - usHandItem = GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS]); + if ( pSoldier->aiData.bAction == AI_ACTION_TOSS_PROJECTILE && IsGrenadeLauncherAttached(&pSoldier->inv[HANDPOS]) ) + usHandItem = GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS]); - iRetCode = HandleItem( pSoldier, pSoldier->aiData.usActionData, pSoldier->bTargetLevel, usHandItem, FALSE ); - if ( iRetCode != ITEM_HANDLE_OK) - { - if ( iRetCode != ITEM_HANDLE_BROKEN ) // if the item broke, this is 'legal' and doesn't need reporting - { - DebugAI( String( "AI %d got error code %ld from HandleItem, doing action %d, has %d APs... aborting deadlock!", pSoldier->ubID, iRetCode, pSoldier->aiData.bAction, pSoldier->bActionPoints ) ); - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"AI %d got error code %ld from HandleItem, doing action %d... aborting deadlock!", pSoldier->ubID, iRetCode, pSoldier->aiData.bAction ); - } - CancelAIAction( pSoldier, FORCE); + iRetCode = HandleItem( pSoldier, pSoldier->aiData.usActionData, pSoldier->bTargetLevel, usHandItem, FALSE ); + if ( iRetCode != ITEM_HANDLE_OK) + { + if ( iRetCode != ITEM_HANDLE_BROKEN ) // if the item broke, this is 'legal' and doesn't need reporting + { + DebugAI( String( "AI %d got error code %ld from HandleItem, doing action %d, has %d APs... aborting deadlock!", pSoldier->ubID, iRetCode, pSoldier->aiData.bAction, pSoldier->bActionPoints ) ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"AI %d got error code %ld from HandleItem, doing action %d... aborting deadlock!", pSoldier->ubID, iRetCode, pSoldier->aiData.bAction ); + } + CancelAIAction( pSoldier, FORCE); #ifdef TESTAICONTROL - if (gfTurnBasedAI) - { - DebugAI( String("Ending turn for %d because of error from HandleItem", pSoldier->ubID ) ); - } + if (gfTurnBasedAI) + { + DebugAI( String("Ending turn for %d because of error from HandleItem", pSoldier->ubID ) ); + } #endif - EndAIGuysTurn( pSoldier ); - } - break; + EndAIGuysTurn( pSoldier ); + } + break; - case AI_ACTION_PULL_TRIGGER: // activate an adjacent panic trigger + case AI_ACTION_PULL_TRIGGER: // activate an adjacent panic trigger - // turn to face trigger first - if ( FindStructure( pSoldier->sGridNo + DirectionInc( NORTH ), STRUCTURE_SWITCH ) ) - { - SendSoldierSetDesiredDirectionEvent( pSoldier, NORTH ); - } - else - { - SendSoldierSetDesiredDirectionEvent( pSoldier, WEST ); - } + // turn to face trigger first + if ( FindStructure( pSoldier->sGridNo + DirectionInc( NORTH ), STRUCTURE_SWITCH ) ) + { + SendSoldierSetDesiredDirectionEvent( pSoldier, NORTH ); + } + else + { + SendSoldierSetDesiredDirectionEvent( pSoldier, WEST ); + } - pSoldier->EVENT_InitNewSoldierAnim( AI_PULL_SWITCH, 0 , FALSE ); + pSoldier->EVENT_InitNewSoldierAnim( AI_PULL_SWITCH, 0 , FALSE ); - DeductPoints( pSoldier, APBPConstants[AP_PULL_TRIGGER], 0 ); + DeductPoints( pSoldier, APBPConstants[AP_PULL_TRIGGER], 0 ); - //gTacticalStatus.fPanicFlags = 0; // turn all flags off - gTacticalStatus.ubTheChosenOne = NOBODY; - break; + //gTacticalStatus.fPanicFlags = 0; // turn all flags off + gTacticalStatus.ubTheChosenOne = NOBODY; + break; - case AI_ACTION_USE_DETONATOR: - //gTacticalStatus.fPanicFlags = 0; // turn all flags off - gTacticalStatus.ubTheChosenOne = NOBODY; - //gTacticalStatus.sPanicTriggerGridno = NOWHERE; + case AI_ACTION_USE_DETONATOR: + //gTacticalStatus.fPanicFlags = 0; // turn all flags off + gTacticalStatus.ubTheChosenOne = NOBODY; + //gTacticalStatus.sPanicTriggerGridno = NOWHERE; - // grab detonator and set off bomb(s) - DeductPoints( pSoldier, APBPConstants[AP_USE_REMOTE], APBPConstants[BP_USE_DETONATOR]);// pay for it! - //SetOffPanicBombs(1000,COMMUNICATE); // BOOOOOOOOOOOOOOOOOOOOM!!!!! - SetOffPanicBombs( pSoldier->ubID, 0 ); + // grab detonator and set off bomb(s) + DeductPoints( pSoldier, APBPConstants[AP_USE_REMOTE], APBPConstants[BP_USE_DETONATOR]);// pay for it! + //SetOffPanicBombs(1000,COMMUNICATE); // BOOOOOOOOOOOOOOOOOOOOM!!!!! + SetOffPanicBombs( pSoldier->ubID, 0 ); - // action completed immediately, cancel it right away - pSoldier->aiData.usActionData = NOWHERE; - pSoldier->aiData.bLastAction = pSoldier->aiData.bAction; - pSoldier->aiData.bAction = AI_ACTION_NONE; - return(FALSE); // no longer in progress + // action completed immediately, cancel it right away + pSoldier->aiData.usActionData = NOWHERE; + pSoldier->aiData.bLastAction = pSoldier->aiData.bAction; + pSoldier->aiData.bAction = AI_ACTION_NONE; + return(FALSE); // no longer in progress - break; + break; - case AI_ACTION_RED_ALERT: // tell friends opponent(s) seen - // if a computer merc, and up to now they didn't know you're here - if (!(pSoldier->flags.uiStatusFlags & SOLDIER_PC) && ( !(gTacticalStatus.Team[pSoldier->bTeam].bAwareOfOpposition) || ( ( gTacticalStatus.fPanicFlags & PANIC_TRIGGERS_HERE ) && gTacticalStatus.ubTheChosenOne == NOBODY ) ) ) - { - HandleInitialRedAlert(pSoldier->bTeam, TRUE); - } - - // SANDRO - ENEMY TAUNTS - if (gGameSettings.fOptions[TOPTION_ALLOW_TAUNTS] == TRUE && pSoldier->bTeam == ENEMY_TEAM && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) && pSoldier->bVisible != -1 ) - { - if ( Random( 4 ) == 0 ) - { - StartEnemyTaunt( pSoldier, TAUNT_ALERT ); - } - } - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Debug: AI radios your position!" ); - // DROP THROUGH HERE! - case AI_ACTION_YELLOW_ALERT: // tell friends opponent(s) heard - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Debug: AI radios about a noise!" ); - /* - NetSend.msgType = NET_RADIO_SIGHTINGS; - NetSend.ubID = pSoldier->ubID; + case AI_ACTION_RED_ALERT: // tell friends opponent(s) seen + // if a computer merc, and up to now they didn't know you're here + if (!(pSoldier->flags.uiStatusFlags & SOLDIER_PC) && ( !(gTacticalStatus.Team[pSoldier->bTeam].bAwareOfOpposition) || ( ( gTacticalStatus.fPanicFlags & PANIC_TRIGGERS_HERE ) && gTacticalStatus.ubTheChosenOne == NOBODY ) ) ) + { + HandleInitialRedAlert(pSoldier->bTeam, TRUE); + } + + // SANDRO - ENEMY TAUNTS + if (gGameSettings.fOptions[TOPTION_ALLOW_TAUNTS] == TRUE && pSoldier->bTeam == ENEMY_TEAM && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) && pSoldier->bVisible != -1 ) + { + if ( Random( 4 ) == 0 ) + { + StartEnemyTaunt( pSoldier, TAUNT_ALERT ); + } + } + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Debug: AI radios your position!" ); + // DROP THROUGH HERE! + case AI_ACTION_YELLOW_ALERT: // tell friends opponent(s) heard + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Debug: AI radios about a noise!" ); + /* + NetSend.msgType = NET_RADIO_SIGHTINGS; + NetSend.ubID = pSoldier->ubID; - SendNetData(ALL_NODES); - */ - DeductPoints(pSoldier,APBPConstants[AP_RADIO],APBPConstants[BP_RADIO], AFTERACTION_INTERRUPT); // pay for it! - - RadioSightings(pSoldier,EVERYBODY,pSoldier->bTeam); // about everybody - // action completed immediately, cancel it right away + SendNetData(ALL_NODES); + */ + DeductPoints(pSoldier,APBPConstants[AP_RADIO],APBPConstants[BP_RADIO], AFTERACTION_INTERRUPT); // pay for it! + + RadioSightings(pSoldier,EVERYBODY,pSoldier->bTeam); // about everybody + // action completed immediately, cancel it right away - // ATE: Change to an animation! - AIDecideRadioAnimation( pSoldier ); + // ATE: Change to an animation! + AIDecideRadioAnimation( pSoldier ); - break; + break; - case AI_ACTION_CREATURE_CALL: // creature calling to others + case AI_ACTION_CREATURE_CALL: // creature calling to others - DeductPoints(pSoldier,APBPConstants[AP_RADIO],APBPConstants[BP_RADIO], AFTERACTION_INTERRUPT); // pay for it! - CreatureCall( pSoldier ); + DeductPoints(pSoldier,APBPConstants[AP_RADIO],APBPConstants[BP_RADIO], AFTERACTION_INTERRUPT); // pay for it! + CreatureCall( pSoldier ); - break; + break; - case AI_ACTION_CHANGE_STANCE: // crouch - if ( gAnimControl[ pSoldier->usAnimState ].ubHeight == pSoldier->aiData.usActionData ) - { - // abort! - ActionDone( pSoldier ); - return( FALSE ); - } + case AI_ACTION_CHANGE_STANCE: // crouch + if ( gAnimControl[ pSoldier->usAnimState ].ubHeight == pSoldier->aiData.usActionData ) + { + // abort! + ActionDone( pSoldier ); + return( FALSE ); + } - SkipCoverCheck = TRUE; + SkipCoverCheck = TRUE; #ifdef DEBUGDECISIONS - sprintf( tempstr, "ExecuteAction: SkipCoverCheck ON\n" ); - DebugAI (tempstr); + sprintf( tempstr, "ExecuteAction: SkipCoverCheck ON\n" ); + DebugAI (tempstr); #endif - SendChangeSoldierStanceEvent( pSoldier, (UINT8) pSoldier->aiData.usActionData ); - break; + SendChangeSoldierStanceEvent( pSoldier, (UINT8) pSoldier->aiData.usActionData ); + break; - case AI_ACTION_COWER: - // make sure action data is set right - if ( pSoldier->flags.uiStatusFlags & SOLDIER_COWERING ) - { - // nothing to do! - ActionDone( pSoldier ); - return( FALSE ); - } - else - { - pSoldier->aiData.usActionData = ANIM_CROUCH; - pSoldier->SetSoldierCowerState( TRUE ); - } - break; + case AI_ACTION_COWER: + // make sure action data is set right + if ( pSoldier->flags.uiStatusFlags & SOLDIER_COWERING ) + { + // nothing to do! + ActionDone( pSoldier ); + return( FALSE ); + } + else + { + pSoldier->aiData.usActionData = ANIM_CROUCH; + pSoldier->SetSoldierCowerState( TRUE ); + } + break; - case AI_ACTION_STOP_COWERING: - // make sure action data is set right - if ( pSoldier->flags.uiStatusFlags & SOLDIER_COWERING ) - { - pSoldier->aiData.usActionData = ANIM_STAND; - pSoldier->SetSoldierCowerState( FALSE ); - } - else - { - // nothing to do! - ActionDone( pSoldier ); - return( FALSE ); - } - break; + case AI_ACTION_STOP_COWERING: + // make sure action data is set right + if ( pSoldier->flags.uiStatusFlags & SOLDIER_COWERING ) + { + pSoldier->aiData.usActionData = ANIM_STAND; + pSoldier->SetSoldierCowerState( FALSE ); + } + else + { + // nothing to do! + ActionDone( pSoldier ); + return( FALSE ); + } + break; - case AI_ACTION_GIVE_AID: // help injured/dying friend - //pSoldier->usUIMovementMode = RUNNING; - iRetCode = HandleItem( pSoldier, pSoldier->aiData.usActionData, 0, pSoldier->inv[HANDPOS].usItem, FALSE ); - if ( iRetCode != ITEM_HANDLE_OK) - { + case AI_ACTION_GIVE_AID: // help injured/dying friend + //pSoldier->usUIMovementMode = RUNNING; + iRetCode = HandleItem( pSoldier, pSoldier->aiData.usActionData, 0, pSoldier->inv[HANDPOS].usItem, FALSE ); + if ( iRetCode != ITEM_HANDLE_OK) + { #ifdef JA2BETAVERSION - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_ERROR, L"AI %d got error code %ld from HandleItem, doing action %d... aborting deadlock!", pSoldier->ubID, iRetCode, pSoldier->aiData.bAction ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_ERROR, L"AI %d got error code %ld from HandleItem, doing action %d... aborting deadlock!", pSoldier->ubID, iRetCode, pSoldier->aiData.bAction ); #endif - CancelAIAction( pSoldier, FORCE); + CancelAIAction( pSoldier, FORCE); #ifdef TESTAICONTROL - if (gfTurnBasedAI) - { - DebugAI( String("Ending turn for %d because of error from HandleItem", pSoldier->ubID ) ); - } + if (gfTurnBasedAI) + { + DebugAI( String("Ending turn for %d because of error from HandleItem", pSoldier->ubID ) ); + } #endif - EndAIGuysTurn( pSoldier ); - } - break; + EndAIGuysTurn( pSoldier ); + } + break; - case AI_ACTION_OPEN_OR_CLOSE_DOOR: - case AI_ACTION_UNLOCK_DOOR: - case AI_ACTION_LOCK_DOOR: - { - STRUCTURE * pStructure; - UINT8 ubDirection; - INT32 sDoorGridNo; + case AI_ACTION_OPEN_OR_CLOSE_DOOR: + case AI_ACTION_UNLOCK_DOOR: + case AI_ACTION_LOCK_DOOR: + { + STRUCTURE * pStructure; + UINT8 ubDirection; + INT32 sDoorGridNo; - ubDirection = GetDirectionFromGridNo( pSoldier->aiData.usActionData, pSoldier ); - if (ubDirection == EAST || ubDirection == SOUTH) - { - sDoorGridNo = pSoldier->sGridNo; - } - else - { - sDoorGridNo = pSoldier->sGridNo + DirectionInc( ubDirection ); - } + ubDirection = GetDirectionFromGridNo( pSoldier->aiData.usActionData, pSoldier ); + if (ubDirection == EAST || ubDirection == SOUTH) + { + sDoorGridNo = pSoldier->sGridNo; + } + else + { + sDoorGridNo = pSoldier->sGridNo + DirectionInc( ubDirection ); + } - pStructure = FindStructure( sDoorGridNo, STRUCTURE_ANYDOOR ); - if (pStructure == NULL) - { + pStructure = FindStructure( sDoorGridNo, STRUCTURE_ANYDOOR ); + if (pStructure == NULL) + { #ifdef JA2TESTVERSION - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_ERROR, L"AI %d tried to open door it could not then find in %d", pSoldier->ubID, sDoorGridNo ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_ERROR, L"AI %d tried to open door it could not then find in %d", pSoldier->ubID, sDoorGridNo ); #endif - CancelAIAction( pSoldier, FORCE); + CancelAIAction( pSoldier, FORCE); #ifdef TESTAICONTROL - if (gfTurnBasedAI) - { - DebugAI( String("Ending turn for %d because of error opening door", pSoldier->ubID ) ); - } + if (gfTurnBasedAI) + { + DebugAI( String("Ending turn for %d because of error opening door", pSoldier->ubID ) ); + } #endif - EndAIGuysTurn( pSoldier ); - } + EndAIGuysTurn( pSoldier ); + } - StartInteractiveObject( sDoorGridNo, pStructure->usStructureID, pSoldier, ubDirection ); - InteractWithInteractiveObject( pSoldier, pStructure, ubDirection ); - } - break; + StartInteractiveObject( sDoorGridNo, pStructure->usStructureID, pSoldier, ubDirection ); + InteractWithInteractiveObject( pSoldier, pStructure, ubDirection ); + } + break; - case AI_ACTION_LOWER_GUN: - // for now, just do "action done" - pSoldier->InternalSoldierReadyWeapon(pSoldier->ubDirection,TRUE,FALSE); - HandleSight(pSoldier, SIGHT_LOOK ); - ActionDone( pSoldier ); - break; + case AI_ACTION_LOWER_GUN: + // for now, just do "action done" + pSoldier->InternalSoldierReadyWeapon(pSoldier->ubDirection,TRUE,FALSE); + HandleSight(pSoldier, SIGHT_LOOK ); + ActionDone( pSoldier ); + break; - case AI_ACTION_RAISE_GUN: //Madd: action added for snipers to ready weapon and use vision range bonuses - pSoldier->SoldierReadyWeapon(); - HandleSight(pSoldier, SIGHT_LOOK | SIGHT_RADIO); + case AI_ACTION_RAISE_GUN: //Madd: action added for snipers to ready weapon and use vision range bonuses + pSoldier->SoldierReadyWeapon(); + HandleSight(pSoldier, SIGHT_LOOK | SIGHT_RADIO); - //AXP 23.03.2007: Sniper deadlock fix - //if ( pSoldier->aiData.bOrders == SNIPER && pSoldier->aiData.bLastAction == AI_ACTION_RAISE_GUN) - if ( pSoldier->aiData.bLastAction == AI_ACTION_RAISE_GUN) - { - pSoldier->aiData.bNextAction = AI_ACTION_END_TURN; - } + //AXP 23.03.2007: Sniper deadlock fix + //if ( pSoldier->aiData.bOrders == SNIPER && pSoldier->aiData.bLastAction == AI_ACTION_RAISE_GUN) + if ( pSoldier->aiData.bLastAction == AI_ACTION_RAISE_GUN) + { + pSoldier->aiData.bNextAction = AI_ACTION_END_TURN; + } - ActionDone( pSoldier ); - break; + ActionDone( pSoldier ); + break; - case AI_ACTION_CLIMB_ROOF: - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Executing: AI_ACTION_CLIMB_ROOF"); + case AI_ACTION_CLIMB_ROOF: + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Executing: AI_ACTION_CLIMB_ROOF"); - if (pSoldier->pathing.bLevel == 0) - { - pSoldier->BeginSoldierClimbUpRoof( ); - } - else - { - pSoldier->BeginSoldierClimbDownRoof( ); - } - break; + if (pSoldier->pathing.bLevel == 0) + { + pSoldier->BeginSoldierClimbUpRoof( ); + } + else + { + pSoldier->BeginSoldierClimbDownRoof( ); + } + break; - case AI_ACTION_END_TURN: - ActionDone( pSoldier ); - if (gfTurnBasedAI) - { - EndAIGuysTurn( pSoldier ); - } - return( FALSE ); // nothing is in progress + case AI_ACTION_END_TURN: + ActionDone( pSoldier ); + if (gfTurnBasedAI) + { + EndAIGuysTurn( pSoldier ); + } + return( FALSE ); // nothing is in progress - case AI_ACTION_TRAVERSE_DOWN: - if (gfTurnBasedAI) - { - EndAIGuysTurn( pSoldier ); - } - if ( pSoldier->ubProfile != NO_PROFILE ) - { - gMercProfiles[ pSoldier->ubProfile ].bSectorZ++; - gMercProfiles[ pSoldier->ubProfile ].fUseProfileInsertionInfo = FALSE; - } - TacticalRemoveSoldier( pSoldier->ubID ); - CheckForEndOfBattle( TRUE ); + case AI_ACTION_TRAVERSE_DOWN: + if (gfTurnBasedAI) + { + EndAIGuysTurn( pSoldier ); + } + if ( pSoldier->ubProfile != NO_PROFILE ) + { + gMercProfiles[ pSoldier->ubProfile ].bSectorZ++; + gMercProfiles[ pSoldier->ubProfile ].fUseProfileInsertionInfo = FALSE; + } + TacticalRemoveSoldier( pSoldier->ubID ); + CheckForEndOfBattle( TRUE ); - return( FALSE ); // nothing is in progress + return( FALSE ); // nothing is in progress - case AI_ACTION_OFFER_SURRENDER: - // start the offer of surrender! - StartCivQuote( pSoldier ); - break; - ///////////////////////////////////////////////////////////// - // SANDRO - added a possibility for enemies to try to steal your gun - case AI_ACTION_STEAL_MOVE: // preparing to steal opponents weapon - - pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; - pSoldier->usUIMovementMode = DetermineMovementMode( pSoldier, AI_ACTION_KNIFE_MOVE ); - usSoldierIndex = WhoIsThere2( pSoldier->aiData.usActionData, pSoldier->bTargetLevel); - if ( usSoldierIndex != NOBODY ) - MercStealFromMerc( pSoldier, MercPtrs[usSoldierIndex] ); + case AI_ACTION_OFFER_SURRENDER: + // start the offer of surrender! + StartCivQuote( pSoldier ); + break; + ///////////////////////////////////////////////////////////// + // SANDRO - added a possibility for enemies to try to steal your gun + case AI_ACTION_STEAL_MOVE: // preparing to steal opponents weapon + + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + pSoldier->usUIMovementMode = DetermineMovementMode( pSoldier, AI_ACTION_KNIFE_MOVE ); + usSoldierIndex = WhoIsThere2( pSoldier->aiData.usActionData, pSoldier->bTargetLevel); + if ( usSoldierIndex != NOBODY ) + MercStealFromMerc( pSoldier, MercPtrs[usSoldierIndex] ); - break; - ///////////////////////////////////////////////////////////// + break; + ///////////////////////////////////////////////////////////// - case AI_ACTION_RELOAD_GUN: - bSlot = FindAmmoToReload( pSoldier, pSoldier->aiData.usActionData, NO_SLOT ); - if(bSlot != NO_SLOT) - { - ReloadGun( pSoldier, &(pSoldier->inv[pSoldier->aiData.usActionData]), &(pSoldier->inv[bSlot]) ); - ActionDone( pSoldier ); - } - break; + case AI_ACTION_RELOAD_GUN: + bSlot = FindAmmoToReload( pSoldier, pSoldier->aiData.usActionData, NO_SLOT ); + if(bSlot != NO_SLOT) + { + ReloadGun( pSoldier, &(pSoldier->inv[pSoldier->aiData.usActionData]), &(pSoldier->inv[bSlot]) ); + ActionDone( pSoldier ); + } + break; - case AI_ACTION_JUMP_WINDOW: - { - pSoldier->BeginSoldierClimbWindow(); - } - break; + case AI_ACTION_JUMP_WINDOW: + { + pSoldier->BeginSoldierClimbWindow(); + } + break; - default: + default: #ifdef BETAVERSION - NumMessage("ExecuteAction - Illegal action type = ",pSoldier->aiData.bAction); + NumMessage("ExecuteAction - Illegal action type = ",pSoldier->aiData.bAction); #endif - return(FALSE); - } + return(FALSE); + } // return status indicating execution of action was properly started return(TRUE); @@ -3057,16 +2500,8 @@ void SetNewSituation( SOLDIERTYPE * pSoldier ) { if ( pSoldier->ubQuoteRecord == 0 && !gTacticalStatus.fAutoBandageMode && !(pSoldier->aiData.bNeutral && gTacticalStatus.uiFlags & ENGAGED_IN_CONV) ) { - // allow new situation to be set - //if (gTacticalStatus.ubAttackBusyCount > 0) - //{ - // DebugAttackBusy( "@#!% NOT setting NewSituation because still busy attacking.\n" ); - //} - //else - { - // 0verhaul: Let's see if we can do without this. - pSoldier->aiData.bNewSituation = IS_NEW_SITUATION; - } + // 0verhaul: Let's see if we can do without this. + pSoldier->aiData.bNewSituation = IS_NEW_SITUATION; if ( gTacticalStatus.ubAttackBusyCount != 0 ) { @@ -3156,3 +2591,4 @@ void HandleAITacticalTraversal( SOLDIERTYPE * pSoldier ) } CheckForEndOfBattle( TRUE ); } + diff --git a/ja2_VS2008.sln b/ja2_VS2008.sln index 2d63c64a..a7602769 100644 --- a/ja2_VS2008.sln +++ b/ja2_VS2008.sln @@ -1,22 +1,22 @@  Microsoft Visual Studio Solution File, Format Version 10.00 # Visual C++ Express 2008 -# Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ja2", "ja2_VS2008.vcproj", "{B112F6BA-AF32-489C-B405-916C0F182D10}" ProjectSection(ProjectDependencies) = postProject {0BE7070B-C8C5-409A-82DD-0701D54A1C6C} = {0BE7070B-C8C5-409A-82DD-0701D54A1C6C} - {99341DB1-FD6E-4E87-919B-25C813F08D18} = {99341DB1-FD6E-4E87-919B-25C813F08D18} - {4D6F7570-9A1E-4DB0-8FD7-B9D14DD4E821} = {4D6F7570-9A1E-4DB0-8FD7-B9D14DD4E821} - {60D5BF89-B609-4A30-A38D-9FE417FB12B6} = {60D5BF89-B609-4A30-A38D-9FE417FB12B6} - {96FA90B1-2ABD-42E7-9CAB-14804DFD3240} = {96FA90B1-2ABD-42E7-9CAB-14804DFD3240} + {DB40B90D-13F9-4FEC-8F1D-0506CC496586} = {DB40B90D-13F9-4FEC-8F1D-0506CC496586} + {4B544F1A-6188-4255-8877-69FC312D0D2C} = {4B544F1A-6188-4255-8877-69FC312D0D2C} {40475E2B-AD37-4A99-85A4-1E507010344C} = {40475E2B-AD37-4A99-85A4-1E507010344C} {8E3BD72D-8791-497B-A38E-D71B255F0A66} = {8E3BD72D-8791-497B-A38E-D71B255F0A66} {DF8C5F50-6FB1-4AFE-8EF4-6B7F360D9C28} = {DF8C5F50-6FB1-4AFE-8EF4-6B7F360D9C28} {629F0A55-6A19-4107-8B5C-5B08B2B3949C} = {629F0A55-6A19-4107-8B5C-5B08B2B3949C} - {DB40B90D-13F9-4FEC-8F1D-0506CC496586} = {DB40B90D-13F9-4FEC-8F1D-0506CC496586} - {4B544F1A-6188-4255-8877-69FC312D0D2C} = {4B544F1A-6188-4255-8877-69FC312D0D2C} + {4D6F7570-9A1E-4DB0-8FD7-B9D14DD4E821} = {4D6F7570-9A1E-4DB0-8FD7-B9D14DD4E821} {9AD14886-DB5C-4EFF-AE17-35F9BD684692} = {9AD14886-DB5C-4EFF-AE17-35F9BD684692} + {60D5BF89-B609-4A30-A38D-9FE417FB12B6} = {60D5BF89-B609-4A30-A38D-9FE417FB12B6} + {FF0A809E-A370-4640-A301-17B76D7A5B4E} = {FF0A809E-A370-4640-A301-17B76D7A5B4E} {A67922A0-0A3F-497F-A724-19B513EFC078} = {A67922A0-0A3F-497F-A724-19B513EFC078} + {99341DB1-FD6E-4E87-919B-25C813F08D18} = {99341DB1-FD6E-4E87-919B-25C813F08D18} + {96FA90B1-2ABD-42E7-9CAB-14804DFD3240} = {96FA90B1-2ABD-42E7-9CAB-14804DFD3240} {C63466D6-49B5-4C54-AA0D-864F6171FD9B} = {C63466D6-49B5-4C54-AA0D-864F6171FD9B} EndProjectSection EndProject @@ -50,6 +50,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ja2export", "ext\export\ja2 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "7z", "ext\VFS\build\7z_VS2008.vcproj", "{9AD14886-DB5C-4EFF-AE17-35F9BD684692}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ModularizedTacticalAI", "ModularizedTacticalAI\ModularizedTacticalAI.vcproj", "{FF0A809E-A370-4640-A301-17B76D7A5B4E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -214,6 +216,16 @@ Global {9AD14886-DB5C-4EFF-AE17-35F9BD684692}.Release_WithDebugInfo|Win32.Build.0 = Release_WithDebugInfo|Win32 {9AD14886-DB5C-4EFF-AE17-35F9BD684692}.Release|Win32.ActiveCfg = Release|Win32 {9AD14886-DB5C-4EFF-AE17-35F9BD684692}.Release|Win32.Build.0 = Release|Win32 + {FF0A809E-A370-4640-A301-17B76D7A5B4E}.Debug|Win32.ActiveCfg = Debug|Win32 + {FF0A809E-A370-4640-A301-17B76D7A5B4E}.Debug|Win32.Build.0 = Debug|Win32 + {FF0A809E-A370-4640-A301-17B76D7A5B4E}.MapEditor|Win32.ActiveCfg = Release|Win32 + {FF0A809E-A370-4640-A301-17B76D7A5B4E}.MapEditor|Win32.Build.0 = Release|Win32 + {FF0A809E-A370-4640-A301-17B76D7A5B4E}.MapEditorD|Win32.ActiveCfg = Release|Win32 + {FF0A809E-A370-4640-A301-17B76D7A5B4E}.MapEditorD|Win32.Build.0 = Release|Win32 + {FF0A809E-A370-4640-A301-17B76D7A5B4E}.Release_WithDebugInfo|Win32.ActiveCfg = Release|Win32 + {FF0A809E-A370-4640-A301-17B76D7A5B4E}.Release_WithDebugInfo|Win32.Build.0 = Release|Win32 + {FF0A809E-A370-4640-A301-17B76D7A5B4E}.Release|Win32.ActiveCfg = Release|Win32 + {FF0A809E-A370-4640-A301-17B76D7A5B4E}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE