mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-09 04:49:39 -10:00
Compare commits
78
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbbb4f96ac | ||
|
|
3b7ae521a9 | ||
|
|
54aaad33a3 | ||
|
|
cc80807f13 | ||
|
|
a351c7b721 | ||
|
|
1ebb04d419 | ||
|
|
d51e897ead | ||
|
|
06c355ddf0 | ||
|
|
8bb6f7f68e | ||
|
|
5b8176bb4b | ||
|
|
80cce2377c | ||
|
|
e0c9583a3b | ||
|
|
0cf3e4b408 | ||
|
|
d06b09dfd2 | ||
|
|
7151887f2e | ||
|
|
3fd955efe5 | ||
|
|
6c65202e9e | ||
|
|
2f2d33dae9 | ||
|
|
f2283dc4f3 | ||
|
|
b92dd314df | ||
|
|
cdbae474e0 | ||
|
|
c4eafa628f | ||
|
|
b8282cf074 | ||
|
|
8517ec180c | ||
|
|
1d345eb946 | ||
|
|
e981522f8a | ||
|
|
1ad8ae9b1c | ||
|
|
f67f6fb331 | ||
|
|
9627408f3a | ||
|
|
8f667bcfce | ||
|
|
6fff633d64 | ||
|
|
66c1c6b9d3 | ||
|
|
135e12df6a | ||
|
|
ff71992449 | ||
|
|
bd8a44c273 | ||
|
|
5f884aea5e | ||
|
|
c6adace344 | ||
|
|
27e6a4ca7a | ||
|
|
d516b8495e | ||
|
|
1f55d2499f | ||
|
|
8b72e3fb3b | ||
|
|
db9c33ce71 | ||
|
|
c3141364b2 | ||
|
|
c0730d572f | ||
|
|
dd0230d33b | ||
|
|
ab7663889e | ||
|
|
0461fe36c5 | ||
|
|
d09cfc624a | ||
|
|
1907fe08f8 | ||
|
|
4b11575f3f | ||
|
|
9c31fc6749 | ||
|
|
c6e3495605 | ||
|
|
4e06e5d033 | ||
|
|
a1d7d9a7d8 | ||
|
|
5591189a46 | ||
|
|
1e9d9326f7 | ||
|
|
76ce3e3a2b | ||
|
|
0f4d46a997 | ||
|
|
e151e54d9e | ||
|
|
f31301db4c | ||
|
|
930e50fa9d | ||
|
|
aad2cc2842 | ||
|
|
fba51c734f | ||
|
|
9d5a177d1a | ||
|
|
fcab17c9ea | ||
|
|
4ce7e50ad7 | ||
|
|
21cd34df25 | ||
|
|
ccfffdf5bd | ||
|
|
e18022b96a | ||
|
|
a68f03eedc | ||
|
|
e4a8b212ab | ||
|
|
d2d3585a8c | ||
|
|
1992c48b80 | ||
|
|
5aa587ad8d | ||
|
|
d30416cb51 | ||
|
|
0cf1863c22 | ||
|
|
991ca99a42 | ||
|
|
443d1671fb |
No files matched your search
@@ -1,4 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*.{h,cpp}]
|
||||
indent_style = tab
|
||||
-275
@@ -1,275 +0,0 @@
|
||||
*.o
|
||||
*.a
|
||||
.dirstamp
|
||||
libtool
|
||||
ltmain.sh
|
||||
m4/libtool.m4
|
||||
m4/ltoptions.m4
|
||||
m4/ltsugar.m4
|
||||
m4/ltversion.m4
|
||||
m4/lt~obsolete.m4
|
||||
compile
|
||||
.deps/
|
||||
code/.deps/
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
config.*
|
||||
code/fs2_open_*
|
||||
code/wxFRED2_*
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
missing
|
||||
.svn
|
||||
*.layout
|
||||
projects/Xcode/Frameworks/
|
||||
|
||||
#========
|
||||
|
||||
#OS junk files
|
||||
[Tt]humbs.db
|
||||
*.DS_Store
|
||||
|
||||
#Visual Studio files
|
||||
*.[Oo]bj
|
||||
*.user
|
||||
*.aps
|
||||
*.pch
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ncb
|
||||
*.suo
|
||||
*.tlb
|
||||
*.tlh
|
||||
*.bak
|
||||
*.[Cc]ache
|
||||
*.ilk
|
||||
*.log
|
||||
*.lib
|
||||
*.sbr
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.unsuccessfulbuild
|
||||
ipch/
|
||||
[Oo]bj/
|
||||
[Bb]in
|
||||
[Dd]ebug*/
|
||||
[Rr]elease*/
|
||||
Ankh.NoLoad
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
#MonoDevelop
|
||||
*.pidb
|
||||
*.userprefs
|
||||
|
||||
#Tooling
|
||||
_ReSharper*/
|
||||
*.resharper
|
||||
[Tt]est[Rr]esult*
|
||||
*.sass-cache
|
||||
|
||||
#Project files
|
||||
[Bb]uild/
|
||||
|
||||
#Subversion files
|
||||
.svn
|
||||
|
||||
# Office Temp Files
|
||||
~$*
|
||||
|
||||
# vim Temp Files
|
||||
*~
|
||||
|
||||
#NuGet
|
||||
packages/
|
||||
*.nupkg
|
||||
|
||||
#ncrunch
|
||||
*ncrunch*
|
||||
*crunch*.local.xml
|
||||
|
||||
# visual studio database projects
|
||||
*.dbmdl
|
||||
|
||||
#Test files
|
||||
*.testsettings
|
||||
|
||||
#===========
|
||||
|
||||
#########################
|
||||
# .gitignore file for Xcode4 and Xcode5 Source projects
|
||||
#
|
||||
# Apple bugs, waiting for Apple to fix/respond:
|
||||
#
|
||||
# 15564624 - what does the xccheckout file in Xcode5 do? Where's the documentation?
|
||||
#
|
||||
# Version 2.1
|
||||
# For latest version, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects
|
||||
#
|
||||
# 2013 updates:
|
||||
# - fixed the broken "save personal Schemes"
|
||||
# - added line-by-line explanations for EVERYTHING (some were missing)
|
||||
#
|
||||
# NB: if you are storing "built" products, this WILL NOT WORK,
|
||||
# and you should use a different .gitignore (or none at all)
|
||||
# This file is for SOURCE projects, where there are many extra
|
||||
# files that we want to exclude
|
||||
#
|
||||
#########################
|
||||
|
||||
#####
|
||||
# OS X temporary files that should never be committed
|
||||
#
|
||||
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
|
||||
|
||||
.DS_Store
|
||||
|
||||
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
|
||||
|
||||
.Trashes
|
||||
|
||||
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
|
||||
|
||||
*.swp
|
||||
|
||||
# *.lock - this is used and abused by many editors for many different things.
|
||||
# For the main ones I use (e.g. Eclipse), it should be excluded
|
||||
# from source-control, but YMMV
|
||||
|
||||
*.lock
|
||||
|
||||
#
|
||||
# profile - REMOVED temporarily (on double-checking, this seems incorrect; I can't find it in OS X docs?)
|
||||
#profile
|
||||
|
||||
|
||||
####
|
||||
# Xcode temporary files that should never be committed
|
||||
#
|
||||
# NB: NIB/XIB files still exist even on Storyboard projects, so we want this...
|
||||
|
||||
*~.nib
|
||||
|
||||
|
||||
####
|
||||
# Xcode build files -
|
||||
#
|
||||
# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData"
|
||||
|
||||
DerivedData/
|
||||
|
||||
# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build"
|
||||
|
||||
build/
|
||||
|
||||
|
||||
#####
|
||||
# Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups)
|
||||
#
|
||||
# This is complicated:
|
||||
#
|
||||
# SOMETIMES you need to put this file in version control.
|
||||
# Apple designed it poorly - if you use "custom executables", they are
|
||||
# saved in this file.
|
||||
# 99% of projects do NOT use those, so they do NOT want to version control this file.
|
||||
# ..but if you're in the 1%, comment out the line "*.pbxuser"
|
||||
|
||||
# .pbxuser: http://lists.apple.com/archives/xcode-users/2004/Jan/msg00193.html
|
||||
|
||||
*.pbxuser
|
||||
|
||||
# .mode1v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html
|
||||
|
||||
*.mode1v3
|
||||
|
||||
# .mode2v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html
|
||||
|
||||
*.mode2v3
|
||||
|
||||
# .perspectivev3: http://stackoverflow.com/questions/5223297/xcode-projects-what-is-a-perspectivev3-file
|
||||
|
||||
*.perspectivev3
|
||||
|
||||
# NB: also, whitelist the default ones, some projects need to use these
|
||||
!default.pbxuser
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.perspectivev3
|
||||
|
||||
|
||||
####
|
||||
# Xcode 4 - semi-personal settings
|
||||
#
|
||||
#
|
||||
# OPTION 1: ---------------------------------
|
||||
# throw away ALL personal settings (including custom schemes!
|
||||
# - unless they are "shared")
|
||||
#
|
||||
# NB: this is exclusive with OPTION 2 below
|
||||
xcuserdata
|
||||
|
||||
# OPTION 2: ---------------------------------
|
||||
# get rid of ALL personal settings, but KEEP SOME OF THEM
|
||||
# - NB: you must manually uncomment the bits you want to keep
|
||||
#
|
||||
# NB: this *requires* git v1.8.2 or above; you may need to upgrade to latest OS X,
|
||||
# or manually install git over the top of the OS X version
|
||||
# NB: this is exclusive with OPTION 1 above
|
||||
#
|
||||
#xcuserdata/**/*
|
||||
|
||||
# (requires option 2 above): Personal Schemes
|
||||
#
|
||||
#!xcuserdata/**/xcschemes/*
|
||||
|
||||
####
|
||||
# XCode 4 workspaces - more detailed
|
||||
#
|
||||
# Workspaces are important! They are a core feature of Xcode - don't exclude them :)
|
||||
#
|
||||
# Workspace layout is quite spammy. For reference:
|
||||
#
|
||||
# /(root)/
|
||||
# /(project-name).xcodeproj/
|
||||
# project.pbxproj
|
||||
# /project.xcworkspace/
|
||||
# contents.xcworkspacedata
|
||||
# /xcuserdata/
|
||||
# /(your name)/xcuserdatad/
|
||||
# UserInterfaceState.xcuserstate
|
||||
# /xcsshareddata/
|
||||
# /xcschemes/
|
||||
# (shared scheme name).xcscheme
|
||||
# /xcuserdata/
|
||||
# /(your name)/xcuserdatad/
|
||||
# (private scheme).xcscheme
|
||||
# xcschememanagement.plist
|
||||
#
|
||||
#
|
||||
|
||||
####
|
||||
# Xcode 4 - Deprecated classes
|
||||
#
|
||||
# Allegedly, if you manually "deprecate" your classes, they get moved here.
|
||||
#
|
||||
# We're using source-control, so this is a "feature" that we do not want!
|
||||
|
||||
*.moved-aside
|
||||
|
||||
# .xccheckout
|
||||
#
|
||||
# Per http://stackoverflow.com/questions/18340453/should-xccheckout-files-in-xcode5-be-ignored-under-vcs
|
||||
#
|
||||
|
||||
*.xccheckout
|
||||
|
||||
####
|
||||
# Documentation
|
||||
#
|
||||
documentation/doxygen/*
|
||||
!documentation/doxygen/.gitkeep
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
language: cpp
|
||||
sudo: true
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libopenal-dev
|
||||
- libogg-dev
|
||||
- libvorbis-dev
|
||||
- build-essential
|
||||
- automake
|
||||
- autoconf
|
||||
- libtheora-dev
|
||||
- libreadline6-dev
|
||||
- libpng12-dev
|
||||
- libjpeg62-dev
|
||||
- liblua5.1-0-dev
|
||||
- libjansson-dev
|
||||
- libtool
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "scp-fs2open/fs2open.github.com"
|
||||
description: "Coverity via Travis CI"
|
||||
notification_email: [email protected]
|
||||
build_command_prepend: "./autogen.sh --enable-debug"
|
||||
build_command: "make -j2"
|
||||
# must match TRAVIS_BRANCH check below
|
||||
branch_pattern: coverity_scan
|
||||
env:
|
||||
global:
|
||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
- secure: "C3wF967ZeliwwP1vC12EMIBOaC568n26Z/cPnwzn317ve59DWH3YSfPZVgvt08GzmaXITGGsJvPB+qxfGoKvQzYE4O1B73q81RpUe5pB3IhF+ThQ91VfQZIRJR5xEGJaLINUlHTTZGX5jxlkVO9wAcauVj/s3b8sQ3dvUZauPvk="
|
||||
matrix:
|
||||
include:
|
||||
# note that gcc Debug MUST be 1st for Coverity
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: CONFIGURATION="Debug"
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: CONFIGURATION="Debug"
|
||||
- os: osx
|
||||
compiler: clang
|
||||
env: CONFIGURATION="Debug" MACOSX_ARCH=x86_64
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: CONFIGURATION="Release"
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: CONFIGURATION="Release"
|
||||
- os: osx
|
||||
compiler: clang
|
||||
env: CONFIGURATION="Release" MACOSX_ARCH=x86_64
|
||||
before_install:
|
||||
# ugly hack; if running a coverity scan abort all except the 1st build
|
||||
# see note re gcc compiler above needing to be 1st
|
||||
# also note that branch_pattern & the TRAVIS_BRANCH check must match
|
||||
# unfortunately COVERITY_SCAN_BRANCH isn't defined until later in the
|
||||
# build process
|
||||
- if ([[ "${TRAVIS_JOB_NUMBER##*.}" != "1" ]] && [[ "${TRAVIS_BRANCH}" == "coverity_scan" ]]); then false ; fi
|
||||
- ./ci/travis/before_install.sh
|
||||
install:
|
||||
- ./ci/travis/install.sh
|
||||
before_script:
|
||||
- ./ci/travis/before_script.sh
|
||||
script:
|
||||
- ./ci/travis/script.sh
|
||||
@@ -1,26 +1,6 @@
|
||||
ChangeLog for fs2_open. All times are UTC.
|
||||
Updated 2002-10-31 03:46
|
||||
|
||||
Features: September 2013
|
||||
http://www.hard-light.net/forums/index.php?topic=85700.0
|
||||
|
||||
- show-subtitle-text can now display messages as well as raw text - Goober5000
|
||||
- toggle subsytem scanning, scannable, cargo revealed, hidden from sensors, stealth and friendly stealth added to the alter-ship-flag sexp - karajorma
|
||||
- Support added to add more languages besides English, French, German and Polish, leading the way to better localization! - karajorma
|
||||
- event.log can now snapshot events checked in a frame and record the status of an event the previous time it was checked as well as the current state - karajorma
|
||||
- added a player-is-cheating sexp - The E
|
||||
- allow a user-specified number of credit images - Goober5000
|
||||
- allow the specification of the positions of medals, callsigns and labels on the medal screen. - Goober5000
|
||||
- lua function to check if a ship is warp capable, and access to a ship's auto-aim FOV - zookeeper
|
||||
- is-facing now works for things that aren't ships (like waypoints!) - zookeeper
|
||||
- experimental configurations to make AVX builds (see this post for more explainations) - The E
|
||||
- new ship flag to enable smarter AI use of afterburners. Now it can use them while flying waypoints or attacking capital ships (use the free-afterburner-use flag with alter-ship-flag) - Admiral MS
|
||||
- the number of medals is now dynamic! - Goober5000
|
||||
- frame profiling code, see what exactly is slowing down FreeSpace. (Mostly for devs or coders) - Swifty + The E
|
||||
- allowing fade-in and fade-out sexps to use any color, not just black, white and red. - Goober5000
|
||||
|
||||
==================================================================
|
||||
( massive gap in updates, maybe this will be filled in someday...)
|
||||
==================================================================
|
||||
|
||||
2002-10-30 22:57 randomtiger
|
||||
|
||||
|
||||
+11
-10
@@ -2,13 +2,21 @@
|
||||
#
|
||||
# This file uses GNU Automake to generate makefiles
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
SUBDIRS = mongoose code
|
||||
SUBDIRS = code
|
||||
|
||||
|
||||
EXTRA_DIST = \
|
||||
FS2OpenSCPReadMe.doc \
|
||||
projects/MSVC_2005/Freespace2.sln \
|
||||
projects/MSVC_2005/Freespace2.vcproj \
|
||||
projects/MSVC_2005/code.vcproj \
|
||||
projects/MSVC_6/Fred2.dsp \
|
||||
projects/MSVC_6/Freespace2.dsp \
|
||||
projects/MSVC_6/Freespace2.dsw \
|
||||
projects/MSVC_6/code.dsp \
|
||||
projects/MSVC_6/libjpeg.dsp \
|
||||
projects/MSVC_6/liblua.dsp \
|
||||
projects/MSVC_6/wxFRED2.dsp \
|
||||
projects/Xcode/English.lproj/InfoPlist.strings \
|
||||
projects/Xcode/FS2_Open.icns \
|
||||
projects/Xcode/FS2_Open.xcodeproj/project.pbxproj \
|
||||
@@ -31,8 +39,6 @@ EXTRA_PROGRAMS = cfilearchiver cfileextractor
|
||||
## Begin utilitites
|
||||
##
|
||||
|
||||
CPPSOURCES=$(wildcard code/*/*.cpp code/*/*.h)
|
||||
|
||||
# cfilearchiver -- to create VPs
|
||||
cfilearchiver_SOURCES = \
|
||||
code/cfilearchiver/cfilearchiver.cpp
|
||||
@@ -48,11 +54,6 @@ tools: cfilearchiver cfileextractor
|
||||
clean-tools:
|
||||
-test -z "$(EXTRA_PROGRAMS)" || rm -f $(EXTRA_PROGRAMS)
|
||||
|
||||
## cppcheck : check for many code issues
|
||||
cppcheck: ${CPPSOURCES}
|
||||
cppcheck ${CPPSOURCES} --enable=all --platform=unix64 \
|
||||
--std=c99 --inline-suppr --quiet
|
||||
|
||||
##
|
||||
## End utilitites
|
||||
##
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
[](https://scan.coverity.com/projects/870)
|
||||
[](https://travis-ci.org/scp-fs2open/fs2open.github.com)
|
||||
|
||||
Welcome to Freespace Open!
|
||||
|
||||
In 2002 Volition released the source code for Freespace2. In the years since dedicated individuals have added countless new features to create a flexible and powerful space combat simulation engine. More info can be found on our [wiki](http://www.hard-light.net/wiki/index.php/Source_Code_Project)
|
||||
|
||||
People interested in contributing are encouraged to read [this thread](http://www.hard-light.net/forums/index.php?topic=82688.0)
|
||||
|
||||
The "projects" directory contains ready projects for:
|
||||
* Microsoft Visual C++ 6, 2005, 2008, 2010, 2011, 2013, 2015
|
||||
* Apple Xcode
|
||||
* Code::Blocks
|
||||
* Eclipse
|
||||
|
||||
|
||||
Review the commit logs to see what's new.
|
||||
|
||||
See the INSTALL file for instructions on how to build fs2_open, or open the relevant MSVC project
|
||||
+215
-14
@@ -9,7 +9,7 @@ dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
|
||||
dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
|
||||
dnl
|
||||
AC_DEFUN([AM_PATH_SDL],
|
||||
[dnl
|
||||
[dnl
|
||||
dnl Get the cflags and libraries from the sdl-config script
|
||||
dnl
|
||||
AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)],
|
||||
@@ -72,7 +72,7 @@ char*
|
||||
my_strdup (char *str)
|
||||
{
|
||||
char *new_str;
|
||||
|
||||
|
||||
if (str)
|
||||
{
|
||||
new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char));
|
||||
@@ -80,7 +80,7 @@ my_strdup (char *str)
|
||||
}
|
||||
else
|
||||
new_str = NULL;
|
||||
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ int main (int argc, char *argv[])
|
||||
fi
|
||||
if test "x$no_sdl" = x ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$2], , :, [$2])
|
||||
ifelse([$2], , :, [$2])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test "$SDL_CONFIG" = "no" ; then
|
||||
@@ -180,6 +180,207 @@ int main(int argc, char *argv[])
|
||||
])
|
||||
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Macros for wxWindows detection. Typically used in configure.in as:
|
||||
dnl
|
||||
dnl AC_ARG_ENABLE(...)
|
||||
dnl AC_ARG_WITH(...)
|
||||
dnl ...
|
||||
dnl AM_OPTIONS_WXCONFIG
|
||||
dnl ...
|
||||
dnl ...
|
||||
dnl AM_PATH_WXCONFIG(2.3.4, wxWin=1)
|
||||
dnl if test "$wxWin" != 1; then
|
||||
dnl AC_MSG_ERROR([
|
||||
dnl wxWindows must be installed on your system
|
||||
dnl but wx-config script couldn't be found.
|
||||
dnl
|
||||
dnl Please check that wx-config is in path, the directory
|
||||
dnl where wxWindows libraries are installed (returned by
|
||||
dnl 'wx-config --libs' command) is in LD_LIBRARY_PATH or
|
||||
dnl equivalent variable and wxWindows version is 2.3.4 or above.
|
||||
dnl ])
|
||||
dnl fi
|
||||
dnl CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS"
|
||||
dnl CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY"
|
||||
dnl CFLAGS="$CFLAGS $WX_CFLAGS_ONLY"
|
||||
dnl
|
||||
dnl LDFLAGS="$LDFLAGS $WX_LIBS"
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl AM_OPTIONS_WXCONFIG
|
||||
dnl
|
||||
dnl adds support for --wx-prefix, --wx-exec-prefix and --wx-config
|
||||
dnl command line options
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
AC_DEFUN([AM_OPTIONS_WXCONFIG],
|
||||
[
|
||||
AC_ARG_WITH(wx-prefix, [ --with-wx-prefix=PREFIX Prefix where wxWindows is installed (optional)],
|
||||
wx_config_prefix="$withval", wx_config_prefix="")
|
||||
AC_ARG_WITH(wx-exec-prefix,[ --with-wx-exec-prefix=PREFIX Exec prefix where wxWindows is installed (optional)],
|
||||
wx_config_exec_prefix="$withval", wx_config_exec_prefix="")
|
||||
AC_ARG_WITH(wx-config,[ --with-wx-config=CONFIG wx-config script to use (optional)],
|
||||
wx_config_name="$withval", wx_config_name="")
|
||||
])
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl AM_PATH_WXCONFIG(VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
||||
dnl
|
||||
dnl Test for wxWindows, and define WX_C*FLAGS, WX_LIBS and WX_LIBS_STATIC
|
||||
dnl (the latter is for static linking against wxWindows). Set WX_CONFIG_NAME
|
||||
dnl environment variable to override the default name of the wx-config script
|
||||
dnl to use. Set WX_CONFIG_PATH to specify the full path to wx-config - in this
|
||||
dnl case the macro won't even waste time on tests for its existence.
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
dnl
|
||||
dnl Get the cflags and libraries from the wx-config script
|
||||
dnl
|
||||
AC_DEFUN([AM_PATH_WXCONFIG],
|
||||
[
|
||||
dnl do we have wx-config name: it can be wx-config or wxd-config or ...
|
||||
if test x${WX_CONFIG_NAME+set} != xset ; then
|
||||
WX_CONFIG_NAME=wx-config
|
||||
fi
|
||||
if test "x$wx_config_name" != x ; then
|
||||
WX_CONFIG_NAME="$wx_config_name"
|
||||
fi
|
||||
|
||||
dnl deal with optional prefixes
|
||||
if test x$wx_config_exec_prefix != x ; then
|
||||
wx_config_args="$wx_config_args --exec-prefix=$wx_config_exec_prefix"
|
||||
WX_LOOKUP_PATH="$wx_config_exec_prefix/bin"
|
||||
fi
|
||||
if test x$wx_config_prefix != x ; then
|
||||
wx_config_args="$wx_config_args --prefix=$wx_config_prefix"
|
||||
WX_LOOKUP_PATH="$WX_LOOKUP_PATH:$wx_config_prefix/bin"
|
||||
fi
|
||||
|
||||
dnl don't search the PATH if WX_CONFIG_NAME is absolute filename
|
||||
if test -x "$WX_CONFIG_NAME" ; then
|
||||
AC_MSG_CHECKING(for wx-config)
|
||||
WX_CONFIG_PATH="$WX_CONFIG_NAME"
|
||||
AC_MSG_RESULT($WX_CONFIG_PATH)
|
||||
else
|
||||
AC_PATH_PROG(WX_CONFIG_PATH, $WX_CONFIG_NAME, no, "$WX_LOOKUP_PATH:$PATH")
|
||||
fi
|
||||
|
||||
if test "$WX_CONFIG_PATH" != "no" ; then
|
||||
WX_VERSION=""
|
||||
no_wx=""
|
||||
|
||||
min_wx_version=ifelse([$1], ,2.2.1,$1)
|
||||
AC_MSG_CHECKING(for wxWindows version >= $min_wx_version)
|
||||
|
||||
WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args"
|
||||
|
||||
WX_VERSION=`$WX_CONFIG_WITH_ARGS --version`
|
||||
wx_config_major_version=`echo $WX_VERSION | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
|
||||
wx_config_minor_version=`echo $WX_VERSION | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
|
||||
wx_config_micro_version=`echo $WX_VERSION | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
|
||||
|
||||
wx_requested_major_version=`echo $min_wx_version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
|
||||
wx_requested_minor_version=`echo $min_wx_version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
|
||||
wx_requested_micro_version=`echo $min_wx_version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
|
||||
|
||||
wx_ver_ok=""
|
||||
if test $wx_config_major_version -gt $wx_requested_major_version; then
|
||||
wx_ver_ok=yes
|
||||
else
|
||||
if test $wx_config_major_version -eq $wx_requested_major_version; then
|
||||
if test $wx_config_minor_version -gt $wx_requested_minor_version; then
|
||||
wx_ver_ok=yes
|
||||
else
|
||||
if test $wx_config_minor_version -eq $wx_requested_minor_version; then
|
||||
if test $wx_config_micro_version -ge $wx_requested_micro_version; then
|
||||
wx_ver_ok=yes
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$wx_ver_ok" = x ; then
|
||||
no_wx=yes
|
||||
else
|
||||
WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs`
|
||||
WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs`
|
||||
|
||||
dnl starting with version 2.2.6 wx-config has --cppflags argument
|
||||
wx_has_cppflags=""
|
||||
if test $wx_config_major_version -gt 2; then
|
||||
wx_has_cppflags=yes
|
||||
else
|
||||
if test $wx_config_major_version -eq 2; then
|
||||
if test $wx_config_minor_version -gt 2; then
|
||||
wx_has_cppflags=yes
|
||||
else
|
||||
if test $wx_config_minor_version -eq 2; then
|
||||
if test $wx_config_micro_version -ge 6; then
|
||||
wx_has_cppflags=yes
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$wx_has_cppflags" = x ; then
|
||||
dnl no choice but to define all flags like CFLAGS
|
||||
WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags`
|
||||
WX_CPPFLAGS=$WX_CFLAGS
|
||||
WX_CXXFLAGS=$WX_CFLAGS
|
||||
|
||||
WX_CFLAGS_ONLY=$WX_CFLAGS
|
||||
WX_CXXFLAGS_ONLY=$WX_CFLAGS
|
||||
else
|
||||
dnl we have CPPFLAGS included in CFLAGS included in CXXFLAGS
|
||||
WX_CPPFLAGS=`$WX_CONFIG_WITH_ARGS --cppflags`
|
||||
WX_CXXFLAGS=`$WX_CONFIG_WITH_ARGS --cxxflags`
|
||||
WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags`
|
||||
|
||||
WX_CFLAGS_ONLY=`echo $WX_CFLAGS | sed "s@^$WX_CPPFLAGS *@@"`
|
||||
WX_CXXFLAGS_ONLY=`echo $WX_CXXFLAGS | sed "s@^$WX_CFLAGS *@@"`
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$no_wx" = x ; then
|
||||
AC_MSG_RESULT(yes (version $WX_VERSION))
|
||||
ifelse([$2], , :, [$2])
|
||||
else
|
||||
if test "x$WX_VERSION" = x; then
|
||||
dnl no wx-config at all
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
AC_MSG_RESULT(no (version $WX_VERSION is not new enough))
|
||||
fi
|
||||
|
||||
WX_CFLAGS=""
|
||||
WX_CPPFLAGS=""
|
||||
WX_CXXFLAGS=""
|
||||
WX_LIBS=""
|
||||
WX_LIBS_STATIC=""
|
||||
ifelse([$3], , :, [$3])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(WX_CPPFLAGS)
|
||||
AC_SUBST(WX_CFLAGS)
|
||||
AC_SUBST(WX_CXXFLAGS)
|
||||
AC_SUBST(WX_CFLAGS_ONLY)
|
||||
AC_SUBST(WX_CXXFLAGS_ONLY)
|
||||
AC_SUBST(WX_LIBS)
|
||||
AC_SUBST(WX_LIBS_STATIC)
|
||||
AC_SUBST(WX_VERSION)
|
||||
])
|
||||
|
||||
# Configure paths for libogg
|
||||
# Jack Moffitt <[email protected]> 10-21-2000
|
||||
# Shamelessly stolen from Owen Taylor and Manish Singh
|
||||
@@ -188,7 +389,7 @@ dnl XIPH_PATH_OGG([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
||||
dnl Test for libogg, and define OGG_CFLAGS and OGG_LIBS
|
||||
dnl
|
||||
AC_DEFUN([XIPH_PATH_OGG],
|
||||
[dnl
|
||||
[dnl
|
||||
dnl Get the cflags and libraries
|
||||
dnl
|
||||
AC_ARG_WITH(ogg,[ --with-ogg=PFX Prefix where libogg is installed (optional)], ogg_prefix="$withval", ogg_prefix="")
|
||||
@@ -246,7 +447,7 @@ int main ()
|
||||
|
||||
if test "x$no_ogg" = "x" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$1], , :, [$1])
|
||||
ifelse([$1], , :, [$1])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test -f conf.oggtest ; then
|
||||
@@ -292,7 +493,7 @@ dnl XIPH_PATH_VORBIS([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
||||
dnl Test for libvorbis, and define VORBIS_CFLAGS and VORBIS_LIBS
|
||||
dnl
|
||||
AC_DEFUN([XIPH_PATH_VORBIS],
|
||||
[dnl
|
||||
[dnl
|
||||
dnl Get the cflags and libraries
|
||||
dnl
|
||||
AC_ARG_WITH(vorbis,[ --with-vorbis=PFX Prefix where libvorbis is installed (optional)], vorbis_prefix="$withval", vorbis_prefix="")
|
||||
@@ -365,7 +566,7 @@ int main ()
|
||||
|
||||
if test "x$no_vorbis" = "x" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$1], , :, [$1])
|
||||
ifelse([$1], , :, [$1])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test -f conf.vorbistest ; then
|
||||
@@ -410,7 +611,7 @@ dnl XIPH_PATH_THEORA([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
||||
dnl Test for libtheora, and define THEORA_CFLAGS and THEORA_LIBS
|
||||
dnl
|
||||
AC_DEFUN([XIPH_PATH_THEORA],
|
||||
[dnl
|
||||
[dnl
|
||||
dnl Get the cflags and libraries
|
||||
dnl
|
||||
AC_ARG_WITH(theora,[ --with-theora=PFX Prefix where libtheora is installed (optional)], theora_prefix="$withval", theora_prefix="")
|
||||
@@ -475,7 +676,7 @@ int main ()
|
||||
|
||||
if test "x$no_theora" = "x" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$1], , :, [$1])
|
||||
ifelse([$1], , :, [$1])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test -f conf.theoratest ; then
|
||||
@@ -517,7 +718,7 @@ dnl AM_PATH_OPENAL([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
||||
dnl Test for OpenAL, and define OPENAL_CFLAGS and OPENAL_LIBS
|
||||
dnl
|
||||
AC_DEFUN([AM_PATH_OPENAL],
|
||||
[dnl
|
||||
[dnl
|
||||
dnl Get the cflags and libraries
|
||||
dnl
|
||||
AC_ARG_WITH(openal,[ --with-openal=PFX Prefix where OpenAL is installed (optional)], openal_prefix="$withval", openal_prefix="")
|
||||
@@ -584,7 +785,7 @@ int main ()
|
||||
|
||||
if test "x$no_openal" = "x" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$1], , :, [$1])
|
||||
ifelse([$1], , :, [$1])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test -f conf.openaltest ; then
|
||||
@@ -625,7 +826,7 @@ dnl AM_PATH_OPENGL([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
||||
dnl Test for OpenGL, and define OPENGL_CFLAGS and OPENGL_LIBS
|
||||
dnl
|
||||
AC_DEFUN([AM_PATH_OPENGL],
|
||||
[dnl
|
||||
[dnl
|
||||
dnl Get the cflags and libraries
|
||||
dnl
|
||||
AC_ARG_WITH(opengl,[ --with-opengl=PFX Prefix where OpenGL is installed (optional)], opengl_prefix="$withval", opengl_prefix="")
|
||||
@@ -677,7 +878,7 @@ AC_ARG_ENABLE(opengltest, [ --disable-opengltest Do not try to compile an
|
||||
fi
|
||||
|
||||
if test "x$no_opengl" = "x" ; then
|
||||
ifelse([$1], , :, [$1])
|
||||
ifelse([$1], , :, [$1])
|
||||
else
|
||||
OPENGL_CFLAGS=""
|
||||
OPENGL_LIBS=""
|
||||
@@ -1,16 +0,0 @@
|
||||
version: 1.0.0.{build}
|
||||
shallow_clone: true
|
||||
environment:
|
||||
matrix:
|
||||
- VisualStudioVersion: 10.0
|
||||
PlatformToolset: v100
|
||||
ProjectPath: projects/MSVC_2010/Freespace2.vcxproj
|
||||
- VisualStudioVersion: 12.0
|
||||
PlatformToolset: v120
|
||||
ProjectPath: projects/MSVC_2013/Freespace2.vcxproj
|
||||
- VisualStudioVersion: 14.0
|
||||
PlatformToolset: v140
|
||||
ProjectPath: projects/MSVC_2015/Freespace2.vcxproj
|
||||
build_script:
|
||||
- msbuild "%ProjectPath%" /p:Configuration="Debug SSE2" /m /p:PlatformToolset="%PlatformToolset%" /verbosity:minimal
|
||||
test: off
|
||||
+7
-7
@@ -110,19 +110,19 @@ do
|
||||
( cd $dr
|
||||
aclocalinclude="$ACLOCAL_FLAGS"
|
||||
for k in $macrodirs; do
|
||||
if test -d $k; then
|
||||
if test -d $k; then
|
||||
aclocalinclude="$aclocalinclude -I $k"
|
||||
##else
|
||||
## echo "**Warning**: No such directory \`$k'. Ignored."
|
||||
fi
|
||||
done
|
||||
echo "Running autoreconf..."
|
||||
autoreconf --install
|
||||
echo "Running $ACLOCAL $aclocalinclude ..."
|
||||
"$ACLOCAL" $aclocalinclude
|
||||
echo "Running $AUTOMAKE --add-missing --copy --foreign $am_opt ..."
|
||||
"$AUTOMAKE" --add-missing --copy --foreign $am_opt
|
||||
echo "Running autoconf..."
|
||||
autoconf
|
||||
)
|
||||
# DIE if the subshell failed
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
sudo add-apt-repository --yes ppa:zoogie/sdl2-snapshots
|
||||
sudo apt-get update -qq
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
# Nothing to do here
|
||||
:
|
||||
fi
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
# Due to a bug in gcc the array bounds check isn't working correctly
|
||||
# This can be removed when gcc is updated
|
||||
AUTOGEN_CONFIG="--enable-fatal-warnings --enable-generic-architecture"
|
||||
CXXFLAGS="-Wno-array-bounds -Wno-unknown-pragmas"
|
||||
|
||||
if [ "$CONFIGURATION" = "Debug" ]; then
|
||||
AUTOGEN_CONFIG="$AUTOGEN_CONFIG --enable-debug"
|
||||
fi
|
||||
|
||||
export CXXFLAGS
|
||||
./autogen.sh $AUTOGEN_CONFIG
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
cd projects/Xcode
|
||||
tar -xvzf Frameworks.tgz
|
||||
fi
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
sudo apt-get install libsdl2-dev
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
gem install xcpretty thefox-pastebin
|
||||
fi
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
make -j 4
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
cd projects/Xcode
|
||||
|
||||
xcodebuild -project FS2_Open.xcodeproj -configuration "$CONFIGURATION" clean build | tee release.log | xcpretty
|
||||
XCODE_RET=${PIPESTATUS[0]}
|
||||
if [ "$XCODE_RET" -ne "0" ]; then
|
||||
pastebin -e 1d -f release.log
|
||||
exit $XCODE_RET
|
||||
fi
|
||||
fi
|
||||
+57
-123
@@ -185,21 +185,13 @@ EXTRA_DIST = \
|
||||
|
||||
# D_ variants are defaults and should always be used
|
||||
# FS2_ variants are for game building and wxFRED
|
||||
AM_CXXFLAGS = @D_CFLAGS@ @FS2_CXXFLAGS@ -I./$(VPATH)/../mongoose
|
||||
AM_CXXFLAGS = @D_CFLAGS@ @FS2_CXXFLAGS@
|
||||
AM_LDFLAGS = @D_LDFLAGS@ @FS2_LDFLAGS@
|
||||
|
||||
if BUILD_WXFRED
|
||||
LIBCODE=
|
||||
else
|
||||
LIBCODE=libcode.a
|
||||
endif
|
||||
noinst_LIBRARIES = $(LIBCODE)
|
||||
bin_PROGRAMS = @FS2_BINARY@
|
||||
noinst_LIBRARIES = libcode.a
|
||||
noinst_PROGRAMS = @FS2_BINARY@
|
||||
|
||||
EXTRA_PROGRAMS = fs2_open_@PACKAGE_VERSION@ \
|
||||
fs2_open_@PACKAGE_VERSION@_DEBUG \
|
||||
wxFRED2_@PACKAGE_VERSION@ \
|
||||
wxFRED2_@PACKAGE_VERSION@_DEBUG
|
||||
EXTRA_PROGRAMS = fs2_open_r fs2_open_d wxFRED2_r wxFRED2_d fs2_open_INF_r fs2_open_INF_d wxFRED2_INF_r wxFRED2_INF_d
|
||||
|
||||
###############################################################################
|
||||
##
|
||||
@@ -215,6 +207,7 @@ FS2_SOURCES = \
|
||||
ai/aigoals.cpp \
|
||||
ai/aigoals.h \
|
||||
ai/aiinternal.h \
|
||||
ai/ailocal.h \
|
||||
ai/aiturret.cpp \
|
||||
ai/ai_profiles.cpp \
|
||||
ai/ai_profiles.h \
|
||||
@@ -262,10 +255,9 @@ FS2_SOURCES = \
|
||||
debris/debris.cpp \
|
||||
debris/debris.h \
|
||||
debugconsole/console.cpp \
|
||||
debugconsole/console.h \
|
||||
debugconsole/consolecmds.cpp \
|
||||
debugconsole/consoleparse.cpp \
|
||||
debugconsole/consoleparse.h \
|
||||
debugconsole/dbugfile.h \
|
||||
debugconsole/timerbar.cpp \
|
||||
debugconsole/timerbar.h \
|
||||
exceptionhandler/exceptionhandler.cpp \
|
||||
exceptionhandler/exceptionhandler.h \
|
||||
external_dll/externalcode.h \
|
||||
@@ -299,7 +291,6 @@ FS2_SOURCES = \
|
||||
globalincs/fsmemory.h \
|
||||
globalincs/globals.h \
|
||||
globalincs/linklist.h \
|
||||
globalincs/profiling.cpp \
|
||||
globalincs/pstypes.h \
|
||||
globalincs/safe_strings.cpp \
|
||||
globalincs/safe_strings.h \
|
||||
@@ -340,7 +331,6 @@ FS2_SOURCES = \
|
||||
graphics/grstub.cpp \
|
||||
graphics/grstub.h \
|
||||
graphics/line.h \
|
||||
graphics/shadows.cpp \
|
||||
graphics/tmapper.h \
|
||||
hud/hud.cpp \
|
||||
hud/hud.h \
|
||||
@@ -385,8 +375,6 @@ FS2_SOURCES = \
|
||||
inetfile/chttpget.h \
|
||||
inetfile/inetgetfile.cpp \
|
||||
inetfile/inetgetfile.h \
|
||||
io/cursor.cpp \
|
||||
io/cursor.h \
|
||||
io/key.cpp \
|
||||
io/key.h \
|
||||
io/keycontrol.cpp \
|
||||
@@ -479,16 +467,18 @@ FS2_SOURCES = \
|
||||
missionui/missionloopbrief.h \
|
||||
missionui/missionpause.cpp \
|
||||
missionui/missionpause.h \
|
||||
missionui/missionrecommend.cpp \
|
||||
missionui/missionrecommend.h \
|
||||
missionui/missionscreencommon.cpp \
|
||||
missionui/missionscreencommon.h \
|
||||
missionui/missionshipchoice.cpp \
|
||||
missionui/missionshipchoice.h \
|
||||
missionui/missionstats.cpp \
|
||||
missionui/missionstats.h \
|
||||
missionui/missionweaponchoice.cpp \
|
||||
missionui/missionweaponchoice.h \
|
||||
missionui/redalert.cpp \
|
||||
missionui/redalert.h \
|
||||
mod_table/mod_table.cpp \
|
||||
mod_table/mod_table.h \
|
||||
model/model.h \
|
||||
model/modelanim.cpp \
|
||||
model/modelanim.h \
|
||||
@@ -497,7 +487,6 @@ FS2_SOURCES = \
|
||||
model/modelsinc.h \
|
||||
model/modeloctant.cpp \
|
||||
model/modelread.cpp \
|
||||
model/modelrender.cpp \
|
||||
nebula/neb.cpp \
|
||||
nebula/neb.h \
|
||||
nebula/neblightning.cpp \
|
||||
@@ -588,20 +577,10 @@ FS2_SOURCES = \
|
||||
object/waypoint.h \
|
||||
observer/observer.cpp \
|
||||
observer/observer.h \
|
||||
osapi/dialogs.cpp \
|
||||
osapi/dialogs.h \
|
||||
osapi/osapi.cpp \
|
||||
osapi/osapi.h \
|
||||
osapi/osregistry.cpp \
|
||||
osapi/osregistry.h \
|
||||
osapi/outwnd.cpp \
|
||||
osapi/outwnd.h \
|
||||
palman/palman.cpp \
|
||||
palman/palman.h \
|
||||
parse/encrypt.cpp \
|
||||
parse/encrypt.h \
|
||||
parse/generic_log.cpp \
|
||||
parse/generic_log.h \
|
||||
parse/lua.cpp \
|
||||
parse/lua.h \
|
||||
parse/parselo.cpp \
|
||||
@@ -614,14 +593,6 @@ FS2_SOURCES = \
|
||||
particle/particle.h \
|
||||
pcxutils/pcxutils.cpp \
|
||||
pcxutils/pcxutils.h \
|
||||
pilotfile/pilotfile.cpp \
|
||||
pilotfile/pilotfile.h \
|
||||
pilotfile/pilotfile_convert.cpp \
|
||||
pilotfile/pilotfile_convert.h \
|
||||
pilotfile/plr.cpp \
|
||||
pilotfile/csg.cpp \
|
||||
pilotfile/plr_convert.cpp \
|
||||
pilotfile/csg_convert.cpp \
|
||||
pngutils/pngutils.cpp \
|
||||
pngutils/pngutils.h \
|
||||
physics/physics.cpp \
|
||||
@@ -757,8 +728,7 @@ if FS2_OS_UNIX
|
||||
JOY_SOURCES = \
|
||||
io/joy.h \
|
||||
io/joy_ff.h \
|
||||
io/joy_ff-sdl.cpp \
|
||||
io/joy-sdl.cpp
|
||||
io/joy-unix.cpp
|
||||
endif
|
||||
|
||||
## Win32-specific sources
|
||||
@@ -778,12 +748,24 @@ WIN32_SOURCES = \
|
||||
graphics/gl/Gl.h \
|
||||
graphics/gl/Glext.h \
|
||||
graphics/gl/wglext.h \
|
||||
osapi/monopub.h
|
||||
osapi/monopub.h \
|
||||
osapi/osapi.cpp \
|
||||
osapi/osapi.h \
|
||||
osapi/osregistry.cpp \
|
||||
osapi/osregistry.h \
|
||||
osapi/outwnd.cpp \
|
||||
osapi/outwnd.h
|
||||
endif
|
||||
|
||||
## Unix-specific sources
|
||||
if FS2_OS_UNIX
|
||||
UNIX_SOURCES = \
|
||||
osapi/osapi_unix.cpp \
|
||||
osapi/osapi.h \
|
||||
osapi/osregistry_unix.cpp \
|
||||
osapi/osregistry.h \
|
||||
osapi/outwnd_unix.cpp \
|
||||
osapi/outwnd.h \
|
||||
windows_stub/stubs.cpp \
|
||||
windows_stub/config.h
|
||||
endif
|
||||
@@ -809,14 +791,22 @@ FS2OPEN_SOURCES = \
|
||||
freespace2/levelpaging.cpp \
|
||||
freespace2/levelpaging.h
|
||||
|
||||
fs2_open_@PACKAGE_VERSION@_DEBUG_SOURCES = \
|
||||
fs2_open_d_SOURCES = \
|
||||
${FS2OPEN_SOURCES}
|
||||
|
||||
fs2_open_@PACKAGE_VERSION@_SOURCES = \
|
||||
fs2_open_r_SOURCES = \
|
||||
${FS2OPEN_SOURCES}
|
||||
|
||||
fs2_open_@PACKAGE_VERSION@_DEBUG_LDADD = libcode.a ../mongoose/libmongoose.a
|
||||
fs2_open_@PACKAGE_VERSION@_LDADD = libcode.a ../mongoose/libmongoose.a
|
||||
fs2_open_INF_d_SOURCES = \
|
||||
${FS2OPEN_SOURCES}
|
||||
|
||||
fs2_open_INF_r_SOURCES = \
|
||||
${FS2OPEN_SOURCES}
|
||||
|
||||
fs2_open_d_LDADD = libcode.a
|
||||
fs2_open_r_LDADD = libcode.a
|
||||
fs2_open_INF_d_LDADD = libcode.a
|
||||
fs2_open_INF_r_LDADD = libcode.a
|
||||
|
||||
##
|
||||
## End MAIN binary
|
||||
@@ -829,86 +819,30 @@ fs2_open_@PACKAGE_VERSION@_LDADD = libcode.a ../mongoose/libmongoose.a
|
||||
##
|
||||
|
||||
wxFRED_SOURCES = \
|
||||
wxfred2/res/select.png.h \
|
||||
wxfred2/res/constz.png.h \
|
||||
wxfred2/res/constx.png.h \
|
||||
wxfred2/res/selectrot.png.h \
|
||||
wxfred2/res/constyz.png.h \
|
||||
wxfred2/res/constxy.png.h \
|
||||
wxfred2/res/wingform.png.h \
|
||||
wxfred2/res/zoomsel.png.h \
|
||||
wxfred2/res/constxz.png.h \
|
||||
wxfred2/res/consty.png.h \
|
||||
wxfred2/res/wingdisband.png.h \
|
||||
wxfred2/res/showdist.png.h \
|
||||
wxfred2/res/orbitsel.png.h \
|
||||
wxfred2/res/zoomext.png.h \
|
||||
wxfred2/res/rotlocal.png.h \
|
||||
wxfred2/res/selectmove.png.h \
|
||||
wxfred2/res/selectlock.png.h \
|
||||
wxfred2/res/selectlist.png.h \
|
||||
wxfred2/base/wxfred_base.h \
|
||||
wxfred2/base/wxfred_base.cpp \
|
||||
wxfred2/editors/dlgobjecteditor.h \
|
||||
wxfred2/editors/dlgobjecteditor.cpp \
|
||||
wxfred2/editors/dlgvoiceactingmanager.h \
|
||||
wxfred2/editors/frmdebriefingeditor.h \
|
||||
wxfred2/editors/dlgbackgroundeditor.cpp \
|
||||
wxfred2/editors/dlgmissionobjectiveseditor.cpp \
|
||||
wxfred2/editors/frmbriefingeditor.cpp \
|
||||
wxfred2/editors/frmteamloadouteditor.h \
|
||||
wxfred2/editors/dlgmissionobjectiveseditor.h \
|
||||
wxfred2/editors/dlgmissionspecseditor.h \
|
||||
wxfred2/editors/frmdebriefingeditor.cpp \
|
||||
wxfred2/editors/dlgfictionviewer.cpp \
|
||||
wxfred2/editors/dlgvoiceactingmanager.cpp \
|
||||
wxfred2/editors/dlgsoundenvironment.cpp \
|
||||
wxfred2/editors/frmcommandbriefingeditor.cpp \
|
||||
wxfred2/editors/frmbriefingeditor.h \
|
||||
wxfred2/editors/dlgshieldsystemeditor.h \
|
||||
wxfred2/editors/dlgreinforcementseditor.h \
|
||||
wxfred2/editors/dlgeventseditor.h \
|
||||
wxfred2/editors/frmteamloadouteditor.cpp \
|
||||
wxfred2/editors/frmcommandbriefingeditor.h \
|
||||
wxfred2/editors/frmwaypointeditor.h \
|
||||
wxfred2/editors/dlgasteroidfieldeditor.h \
|
||||
wxfred2/editors/dlgsetglobalshipflagseditor.cpp \
|
||||
wxfred2/editors/dlgshieldsystemeditor.cpp \
|
||||
wxfred2/editors/frmshipseditor.h \
|
||||
wxfred2/editors/dlgfictionviewer.h \
|
||||
wxfred2/editors/dlgreinforcementspicker.cpp \
|
||||
wxfred2/editors/frmcampaigneditor.cpp \
|
||||
wxfred2/editors/dlgasteroidfieldeditor.cpp \
|
||||
wxfred2/editors/dlgreinforcementspicker.h \
|
||||
wxfred2/editors/dlgreinforcementseditor.cpp \
|
||||
wxfred2/editors/frmcampaigneditor.h \
|
||||
wxfred2/editors/dlgbackgroundeditor.h \
|
||||
wxfred2/editors/frmshipseditor.cpp \
|
||||
wxfred2/editors/dlgeventseditor.cpp \
|
||||
wxfred2/editors/dlgsetglobalshipflagseditor.h \
|
||||
wxfred2/editors/frmwingeditor.h \
|
||||
wxfred2/editors/frmwingeditor.cpp \
|
||||
wxfred2/editors/frmwaypointeditor.cpp \
|
||||
wxfred2/editors/dlgsoundenvironment.h \
|
||||
wxfred2/editors/dlgmissionspecseditor.cpp \
|
||||
wxfred2/glcviewport.h \
|
||||
wxfred2/misc/dlgmissionstats.h \
|
||||
wxfred2/misc/dlgmissionstats.cpp \
|
||||
wxfred2/wxfred2.cpp \
|
||||
wxfred2/wxfred2.h \
|
||||
wxfred2/help/dlgsexphelp.h \
|
||||
wxfred2/help/dlgsexphelp.cpp \
|
||||
wxfred2/help/dlgaboutbox.h \
|
||||
wxfred2/help/dlgaboutbox.cpp \
|
||||
wxfred2/frmfred2.h \
|
||||
wxfred2/frmfred2.cpp
|
||||
wxfred2/wxfred2.cpp \
|
||||
wxfred2/wxfred2.h \
|
||||
wxfred2/fredframe.cpp \
|
||||
wxfred2/fredframe.h \
|
||||
wxfred2/wxfred_xrc.cpp \
|
||||
wxfred2/wxfred_xrc.h
|
||||
|
||||
wxFRED2_@PACKAGE_VERSION@_DEBUG_SOURCES = \
|
||||
wxFRED2_d_SOURCES = \
|
||||
${wxFRED_SOURCES}
|
||||
|
||||
wxFRED2_@PACKAGE_VERSION@_SOURCES = \
|
||||
wxFRED2_r_SOURCES = \
|
||||
${wxFRED_SOURCES}
|
||||
|
||||
wxFRED2_INF_d_SOURCES = \
|
||||
${wxFRED_SOURCES}
|
||||
|
||||
wxFRED2_INF_r_SOURCES = \
|
||||
${wxFRED_SOURCES}
|
||||
|
||||
wxFRED2_d_LDADD = libcode.a
|
||||
wxFRED2_r_LDADD = libcode.a
|
||||
wxFRED2_INF_d_LDADD = libcode.a
|
||||
wxFRED2_INF_r_LDADD = libcode.a
|
||||
|
||||
##
|
||||
## End wxFRED2 binary
|
||||
##
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ void set_wingnum(int objnum, int wingnum)
|
||||
Ai_info[ai_index].wing = wingnum;
|
||||
}
|
||||
|
||||
char *ai_get_goal_target_name(const char *name, int *index)
|
||||
char *ai_get_goal_target_name(char *name, int *index)
|
||||
{
|
||||
Assert(name != NULL);
|
||||
Assert(index != NULL);
|
||||
|
||||
+15
-25
@@ -12,29 +12,20 @@
|
||||
#ifndef _AI_H
|
||||
#define _AI_H
|
||||
|
||||
#include "ai/ai_profiles.h"
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
#include "object/waypoint.h"
|
||||
#include "ai/ai_profiles.h"
|
||||
#include "physics/physics.h"
|
||||
#include "object/waypoint.h"
|
||||
|
||||
struct ship_weapon;
|
||||
class ship_subsys;
|
||||
class object;
|
||||
class ship_info;
|
||||
struct ship_subsys;
|
||||
struct object;
|
||||
struct ship_info;
|
||||
|
||||
#define AI_DEFAULT_CLASS 3 // default AI class for new ships (Fred)
|
||||
|
||||
typedef struct ai_flag_name {
|
||||
int flag;
|
||||
char flag_name[TOKEN_LENGTH];
|
||||
int flag_list;
|
||||
} ai_flag_name;
|
||||
|
||||
#define MAX_AI_FLAG_NAMES 2
|
||||
extern ai_flag_name Ai_flag_names[];
|
||||
|
||||
#define AIF_FORMATION_WING (1 << 0) // Fly in formation as part of wing.
|
||||
#define AIF_AWAITING_REPAIR (1 << 1) // Awaiting a repair ship.
|
||||
#define AIF_BEING_REPAIRED (1 << 2) // Currently docked with repair ship.
|
||||
@@ -64,8 +55,6 @@ extern ai_flag_name Ai_flag_names[];
|
||||
#define AIF_UNLOAD_PRIMARIES (1 << 24) // Fire primaries as fast as possible!
|
||||
#define AIF_TRYING_UNSUCCESSFULLY_TO_WARP (1 << 25) // Trying to warp, but can't warp at the moment
|
||||
|
||||
#define AIF_FREE_AFTERBURNER_USE (1 << 26) // Use afterburners while following waypoints or flying towards objects
|
||||
|
||||
#define AIF_AVOID_SHOCKWAVE (AIF_AVOID_SHOCKWAVE_SHIP | AIF_AVOID_SHOCKWAVE_WEAPON)
|
||||
#define AIF_FORMATION (AIF_FORMATION_WING | AIF_FORMATION_OBJECT)
|
||||
|
||||
@@ -109,7 +98,6 @@ extern ai_flag_name Ai_flag_names[];
|
||||
#define AIGF_PURGE (1<<5) // purge this goal next time we process
|
||||
#define AIGF_GOALS_PURGED (1<<6) // this goal has already caused other goals to get purged
|
||||
#define AIGF_DEPART_SOUND_PLAYED (1<<7) // Goober5000 - replacement for AL's hack ;)
|
||||
#define AIGF_TARGET_OWN_TEAM (1<<8) // Goober5000 - removes standard precautions against AI ships taking traitorous actions
|
||||
|
||||
#define AIGF_DOCK_INDEXES_VALID (AIGF_DOCKER_INDEX_VALID|AIGF_DOCKEE_INDEX_VALID)
|
||||
|
||||
@@ -369,10 +357,10 @@ typedef struct ai_info {
|
||||
int ai_class; // Class. Might be override of default.
|
||||
|
||||
// Probably become obsolete, to be replaced by path_start, path_cur, etc.
|
||||
waypoint_list *wp_list; // waypoint list being followed
|
||||
size_t wp_index; // waypoint index in list
|
||||
waypoint_list *wp_list; // waypoint list being followed
|
||||
SCP_list<waypoint>::iterator wp_index; // waypoint index in list
|
||||
int wp_flags; // waypoint flags, see WPF_xxxx
|
||||
int waypoint_speed_cap; // -1 no cap, otherwise cap - changed to int by Goober5000
|
||||
int waypoint_speed_cap; // -1 no cap, otherwise cap - changed to int by Goober5000
|
||||
|
||||
// Path following information
|
||||
int path_start; // Index into global array, start of path.
|
||||
@@ -590,7 +578,7 @@ extern char** Ai_class_names;
|
||||
extern int Num_ai_classes;
|
||||
extern int Ai_firing_enabled;
|
||||
|
||||
extern const char *Skill_level_names(int skill_level, int translate = 1);
|
||||
extern char *Skill_level_names(int skill_level, int translate = 1);
|
||||
extern int Ai_goal_signature;
|
||||
|
||||
// need access to following data in AiBig.cpp
|
||||
@@ -616,15 +604,16 @@ void ai_process( object * obj, int ai_index, float frametime );
|
||||
int get_wingnum(int objnum);
|
||||
|
||||
void set_wingnum(int objnum, int wingnum);
|
||||
char *ai_get_goal_target_name(const char *name, int *index);
|
||||
char *ai_get_goal_target_name(char *name, int *index);
|
||||
|
||||
extern void init_ai_system(void);
|
||||
extern void ai_attack_object(object *attacker, object *attacked, ship_subsys *ssp);
|
||||
extern void ai_evade_object(object *evader, object *evaded);
|
||||
extern void ai_ignore_object(object *ignorer, object *ignored, int ignore_new);
|
||||
extern void ai_ignore_wing(object *ignorer, int wingnum);
|
||||
extern void ai_ignore_wing(object *ignorer, int wingnum, int priority);
|
||||
extern void ai_dock_with_object(object *docker, int docker_index, object *dockee, int dockee_index, int dock_type);
|
||||
extern void ai_stay_still(object *still_objp, vec3d *view_pos);
|
||||
extern void ai_set_default_behavior(object *obj, int classnum);
|
||||
extern void ai_do_default_behavior(object *obj);
|
||||
extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags);
|
||||
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_quadrant, vec3d *hit_normal);
|
||||
@@ -726,7 +715,8 @@ void process_subobjects(int objnum);
|
||||
//SUSHI: Setting ai_info stuff from both ai class and ai profile
|
||||
void init_aip_from_class_and_profile(ai_info *aip, ai_class *aicp, ai_profile_t *profile);
|
||||
|
||||
void ai_update_aim(ai_info *aip);
|
||||
//SUSHI: Updating AI aim
|
||||
void ai_update_aim(ai_info *aip, object* En_Objp);
|
||||
|
||||
//SUSHI: Random evasive sidethrust
|
||||
void do_random_sidethrust(ai_info *aip, ship_info *sip);
|
||||
|
||||
+432
-453
@@ -7,13 +7,13 @@
|
||||
|
||||
|
||||
|
||||
#include "ai/ai_profiles.h"
|
||||
#include "globalincs/def_files.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "localization/localize.h"
|
||||
#include "globalincs/def_files.h"
|
||||
#include "ai/ai_profiles.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "ship/ship.h"
|
||||
#include "localization/localize.h"
|
||||
#include "weapon/weapon.h"
|
||||
#include "ship/ship.h"
|
||||
|
||||
|
||||
// global stuff
|
||||
@@ -67,467 +67,446 @@ int ai_path_type_match(char *p)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void parse_ai_profiles_tbl(const char *filename)
|
||||
void parse_ai_profiles_tbl(char *filename)
|
||||
{
|
||||
int i;
|
||||
int i, rval;
|
||||
char profile_name[NAME_LENGTH];
|
||||
ai_profile_t dummy_profile;
|
||||
char *saved_Mp = NULL;
|
||||
char buf[NAME_LENGTH];
|
||||
|
||||
try
|
||||
// open localization
|
||||
lcl_ext_open();
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0)
|
||||
{
|
||||
if (filename == NULL)
|
||||
read_file_text_from_array(defaults_get_file("ai_profiles.tbl"));
|
||||
else
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
reset_parse();
|
||||
|
||||
|
||||
// start parsing
|
||||
required_string("#AI Profiles");
|
||||
|
||||
// new default?
|
||||
if (optional_string("$Default Profile:"))
|
||||
stuff_string(Default_profile_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// begin reading data
|
||||
while (required_string_either("#End", "$Profile Name:"))
|
||||
{
|
||||
ai_profile_t *profile = &dummy_profile;
|
||||
ai_profile_t *previous_profile = NULL;
|
||||
bool no_create = false;
|
||||
|
||||
// get the name
|
||||
required_string("$Profile Name:");
|
||||
stuff_string(profile_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// see if it exists
|
||||
for (i = 0; i < Num_ai_profiles; i++)
|
||||
{
|
||||
if (!stricmp(Ai_profiles[i].profile_name, profile_name))
|
||||
{
|
||||
previous_profile = &Ai_profiles[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// modular table stuff
|
||||
if (optional_string("+nocreate"))
|
||||
{
|
||||
no_create = true;
|
||||
|
||||
// use the previous one if possible,
|
||||
// otherwise continue to use the dummy one
|
||||
if (previous_profile != NULL)
|
||||
profile = previous_profile;
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't create multiple profiles with the same name
|
||||
if (previous_profile != NULL)
|
||||
{
|
||||
Warning(LOCATION, "An ai profile named '%s' already exists! The new one will not be created.\n", profile_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// make sure we're under the limit
|
||||
if (Num_ai_profiles >= MAX_AI_PROFILES)
|
||||
{
|
||||
Warning(LOCATION, "Too many profiles in ai_profiles.tbl! Max is %d.\n", MAX_AI_PROFILES - 1); // -1 because one is built-in
|
||||
skip_to_string("#End", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
profile = &Ai_profiles[Num_ai_profiles];
|
||||
Num_ai_profiles++;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize profile if we're not building from a previously parsed one
|
||||
if (!no_create)
|
||||
{
|
||||
// base profile, so zero it out
|
||||
if (profile == &Ai_profiles[0])
|
||||
{
|
||||
memset(profile, 0, sizeof(ai_profile_t));
|
||||
}
|
||||
// brand new profile, so set it to the base defaults
|
||||
else
|
||||
{
|
||||
memcpy(profile, &Ai_profiles[0], sizeof(ai_profile_t));
|
||||
}
|
||||
}
|
||||
|
||||
// set the name
|
||||
strcpy_s(profile->profile_name, profile_name);
|
||||
|
||||
|
||||
// fill in any and all settings; they're all optional and can be in any order
|
||||
while (!check_for_string("$Profile Name:") && !check_for_string("#End"))
|
||||
{
|
||||
if (optional_string("$Player Afterburner Recharge Scale:"))
|
||||
parse_float_list(profile->afterburner_recharge_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Beam Friendly Fire Damage:"))
|
||||
parse_float_list(profile->beam_friendly_damage_cap, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Countermeasure Life Scale:"))
|
||||
parse_float_list(profile->cmeasure_life_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Countermeasure Firing Chance:"))
|
||||
parse_float_list(profile->cmeasure_fire_chance, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI In Range Time:"))
|
||||
parse_float_list(profile->in_range_time, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Always Links Ammo Weapons:"))
|
||||
parse_float_list(profile->link_ammo_levels_always, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Maybe Links Ammo Weapons:"))
|
||||
parse_float_list(profile->link_ammo_levels_maybe, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Primary Ammo Burst Multiplier:"))
|
||||
parse_float_list(profile->primary_ammo_burst_mult, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Always Links Energy Weapons:"))
|
||||
parse_float_list(profile->link_energy_levels_always, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Maybe Links Energy Weapons:"))
|
||||
parse_float_list(profile->link_energy_levels_maybe, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Missles Locked on Player:") || optional_string("$Max Missiles Locked on Player:"))
|
||||
parse_int_list(profile->max_allowed_player_homers, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Player Attackers:"))
|
||||
parse_int_list(profile->max_attackers, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Incoming Asteroids:"))
|
||||
parse_int_list(profile->max_incoming_asteroids, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Damage Factor:") || optional_string("$AI Damage Reduction to Player Hull:"))
|
||||
parse_float_list(profile->player_damage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Subsys Damage Factor:") || optional_string("$AI Damage Reduction to Player Subsys:"))
|
||||
parse_float_list(profile->subsys_damage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
// represented in fractions of F1_0
|
||||
if (optional_string("$Predict Position Delay:"))
|
||||
{
|
||||
int iLoop;
|
||||
float temp_list[NUM_SKILL_LEVELS];
|
||||
|
||||
parse_float_list(temp_list, NUM_SKILL_LEVELS);
|
||||
|
||||
for (iLoop = 0; iLoop < NUM_SKILL_LEVELS; iLoop++)
|
||||
profile->predict_position_delay[iLoop] = fl2f(temp_list[iLoop]);
|
||||
}
|
||||
|
||||
if (optional_string("$AI Shield Manage Delay:") || optional_string("$AI Shield Manage Delays:"))
|
||||
parse_float_list(profile->shield_manage_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Friendly AI Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_delay_scale_friendly, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Hostile AI Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_delay_scale_hostile, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Friendly AI Secondary Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_secondary_delay_scale_friendly, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Hostile AI Secondary Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_secondary_delay_scale_hostile, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Turn Time Scale:"))
|
||||
parse_float_list(profile->turn_time_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Glide Attack Percent:")) {
|
||||
parse_float_list(profile->glide_attack_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_attack_percent[i] < 0.0f || profile->glide_attack_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Glide Attack Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_attack_percent[i]);
|
||||
profile->glide_attack_percent[i] = 0.0f;
|
||||
}
|
||||
profile->glide_attack_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Circle Strafe Percent:")) {
|
||||
parse_float_list(profile->circle_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->circle_strafe_percent[i] < 0.0f || profile->circle_strafe_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Circle Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->circle_strafe_percent[i]);
|
||||
profile->circle_strafe_percent[i] = 0.0f;
|
||||
}
|
||||
profile->circle_strafe_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Glide Strafe Percent:")) {
|
||||
parse_float_list(profile->glide_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_strafe_percent[i] < 0.0f || profile->glide_strafe_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Glide Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_strafe_percent[i]);
|
||||
profile->glide_strafe_percent[i] = 0.0f;
|
||||
}
|
||||
profile->glide_strafe_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Random Sidethrust Percent:")) {
|
||||
parse_float_list(profile->random_sidethrust_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->random_sidethrust_percent[i] < 0.0f || profile->random_sidethrust_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Random Sidethrust Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->random_sidethrust_percent[i]);
|
||||
profile->random_sidethrust_percent[i] = 0.0f;
|
||||
}
|
||||
profile->random_sidethrust_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Stalemate Time Threshold:"))
|
||||
parse_float_list(profile->stalemate_time_thresh, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Stalemate Distance Threshold:"))
|
||||
parse_float_list(profile->stalemate_dist_thresh, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Shield Recharge Scale:"))
|
||||
parse_float_list(profile->shield_energy_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Weapon Recharge Scale:"))
|
||||
parse_float_list(profile->weapon_energy_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Turret Target Ownage:"))
|
||||
parse_int_list(profile->max_turret_ownage_target, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Turret Player Ownage:"))
|
||||
parse_int_list(profile->max_turret_ownage_player, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Required For Kill Scale:"))
|
||||
parse_float_list(profile->kill_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Required For Assist Scale:"))
|
||||
parse_float_list(profile->assist_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Awarded For Capship Assist:"))
|
||||
parse_float_list(profile->assist_award_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Repair Penalty:"))
|
||||
parse_int_list(profile->repair_penalty, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Delay Before Allowing Bombs to Be Shot Down:"))
|
||||
parse_float_list(profile->delay_bomb_arm_timer, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Chance AI Has to Fire Missiles at Player:"))
|
||||
parse_int_list(profile->chance_to_use_missiles_on_plr, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Aim Update Delay:"))
|
||||
parse_float_list(profile->max_aim_update_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Turret Max Aim Update Delay:"))
|
||||
parse_float_list(profile->turret_max_aim_update_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Autoaim FOV:"))
|
||||
{
|
||||
float fov_list[NUM_SKILL_LEVELS];
|
||||
parse_float_list(fov_list, NUM_SKILL_LEVELS);
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++)
|
||||
{
|
||||
//Enforce range
|
||||
if (fov_list[i] < 0.0f || fov_list[i] >= 360.0f)
|
||||
{
|
||||
Warning(LOCATION, "$Player Autoaim FOV should be >= 0 and < 360.0 (read %f). Setting to 0.", fov_list[i]);
|
||||
fov_list[i] = 0.0f;
|
||||
}
|
||||
|
||||
//Convert units
|
||||
profile->player_autoaim_fov[i] = fov_list[i] * PI / 180.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Detail Distance Multiplier:"))
|
||||
parse_float_list(profile->detail_distance_mult, NUM_SKILL_LEVELS);
|
||||
|
||||
set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart primary weapon selection:", AIPF_SMART_PRIMARY_WEAPON_SELECTION, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart secondary weapon selection:", AIPF_SMART_SECONDARY_WEAPON_SELECTION, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart shield management:", AIPF_SMART_SHIELD_MANAGEMENT, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart afterburner management:", AIPF_SMART_AFTERBURNER_MANAGEMENT, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow rapid secondary dumbfire:", AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$huge turret weapons ignore bombs:", AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$don't insert random turret fire delay:", AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$shockwaves damage small ship subsystems:", AIPF_SHOCKWAVES_DAMAGE_SMALL_SHIP_SUBSYSTEMS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$navigation subsystem governs warpout capability:", AIPF_NAVIGATION_SUBSYS_GOVERNS_WARP, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AIPF_NO_MIN_DOCK_SPEED_CAP, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$disable linked fire penalty:", AIPF_DISABLE_LINKED_FIRE_PENALTY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$disable weapon damage scaling:", AIPF_DISABLE_WEAPON_DAMAGE_SCALING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use additive weapon velocity:", AIPF_USE_ADDITIVE_WEAPON_VELOCITY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use newtonian dampening:", AIPF_USE_NEWTONIAN_DAMPENING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$include beams for kills and assists:", AIPF_INCLUDE_BEAMS_IN_STAT_CALCS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$score kills based on damage caused:", AIPF_KILL_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$score assists based on damage caused:", AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow event and goal scoring in multiplayer:", AIPF_ALLOW_MULTI_EVENT_SCORING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix linked primary weapon decision bug:", AIPF_FIX_LINKED_PRIMARY_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$prevent turrets targeting too distant bombs:", AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart subsystem targeting for turrets:", AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AIPF_FIX_HEAT_SEEKER_STEALTH_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$multi allow empty primaries:", AIPF_MULTI_ALLOW_EMPTY_PRIMARIES, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$multi allow empty secondaries:", AIPF_MULTI_ALLOW_EMPTY_SECONDARIES, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow turrets target weapons freely:", AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use only single fov for turrets:", AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow vertical dodge:", AIPF_ALLOW_VERTICAL_DODGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$force beam turrets to use normal fov:", AIPF_FORCE_BEAM_TURRET_FOV, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix ai class bug:", AIPF_FIX_AI_CLASS_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$turrets ignore targets radius in range checks:", AIPF2_TURRETS_IGNORE_TARGET_RADIUS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$no extra collision avoidance vs player:", AIPF2_NO_SPECIAL_PLAYER_AVOID, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$perform fewer checks for death screams:", AIPF2_PERFORM_FEWER_SCREAM_CHECKS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$advanced turret fov edge checks:", AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$require turrets to have target in fov:", AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$ai aims from ship center:", AIPF2_AI_AIMS_FROM_SHIP_CENTER, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$allow primary link at mission start:", AIPF2_ALLOW_PRIMARY_LINK_AT_START, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$allow beams to damage bombs:", AIPF2_BEAMS_DAMAGE_WEAPONS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$disable weapon damage scaling for player:", AIPF2_PLAYER_WEAPON_SCALE_FIX, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$countermeasures affect aspect seekers:", AIPF2_ASPECT_LOCK_COUNTERMEASURE, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$ai guards specific ship in wing:", AIPF2_AI_GUARDS_SPECIFIC_SHIP_IN_WING, AIP_FLAG2);
|
||||
|
||||
profile->ai_path_mode = AI_PATH_MODE_NORMAL;
|
||||
if (optional_string("$ai path mode:"))
|
||||
{
|
||||
stuff_string(buf, F_NAME, NAME_LENGTH);
|
||||
int j = ai_path_type_match(buf);
|
||||
if (j >= 0) {
|
||||
profile->ai_path_mode = j;
|
||||
}
|
||||
else {
|
||||
Warning(LOCATION, "Invalid ai path mode '%s' specified", buf);
|
||||
}
|
||||
}
|
||||
|
||||
set_flag(profile, "$no warp camera:", AIPF2_NO_WARP_CAMERA, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$fix ai path order bug:", AIPF2_FIX_AI_PATH_ORDER_BUG, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$strict turret-tagged-only targeting:", AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$aspect bomb invulnerability fix:", AIPF2_ASPECT_INVULNERABILITY_FIX, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$glide decay requires thrust:", AIPF2_GLIDE_DECAY_REQUIRES_THRUST, AIP_FLAG2);
|
||||
|
||||
profile->bay_arrive_speed_mult = 1.0f;
|
||||
profile->bay_depart_speed_mult = 1.0f;
|
||||
if (optional_string("$bay arrive speed multiplier:")) {
|
||||
stuff_float(&profile->bay_arrive_speed_mult);
|
||||
}
|
||||
if (optional_string("$bay depart speed multiplier:")) {
|
||||
stuff_float(&profile->bay_depart_speed_mult);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
// compatibility
|
||||
if (optional_string("$perform less checks for death screams:"))
|
||||
{
|
||||
mprintf(("Warning: \"$perform less checks for death screams\" flag is deprecated in favor of \"$perform fewer checks for death screams\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
if (temp)
|
||||
profile->flags2 |= AIPF2_PERFORM_FEWER_SCREAM_CHECKS;
|
||||
else
|
||||
profile->flags2 &= ~AIPF2_PERFORM_FEWER_SCREAM_CHECKS;
|
||||
}
|
||||
if (optional_string("$allow primary link delay:"))
|
||||
{
|
||||
mprintf(("Warning: \"$allow primary link delay\" flag is deprecated in favor of \"$allow primary link at mission start\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
if (temp)
|
||||
profile->flags2 &= ~AIPF2_ALLOW_PRIMARY_LINK_AT_START;
|
||||
else
|
||||
profile->flags2 |= AIPF2_ALLOW_PRIMARY_LINK_AT_START;
|
||||
}
|
||||
|
||||
|
||||
// if we've been through once already and are at the same place, force a move
|
||||
if (saved_Mp && (saved_Mp == Mp))
|
||||
{
|
||||
char tmp[60];
|
||||
memset(tmp, 0, 60);
|
||||
strncpy(tmp, Mp, 59);
|
||||
mprintf(("WARNING: Unrecognized parameter in ai_profiles: %s\n", tmp));
|
||||
|
||||
Mp++;
|
||||
}
|
||||
|
||||
// find next valid option
|
||||
skip_to_start_of_string_either("$", "#");
|
||||
saved_Mp = Mp;
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", (filename) ? filename : "<default ai_profiles.tbl>", e.what()));
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", (filename) ? filename : "<default ai_profiles.tbl>", rval));
|
||||
lcl_ext_close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (filename == NULL)
|
||||
read_file_text_from_array(defaults_get_file("ai_profiles.tbl"));
|
||||
else
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
reset_parse();
|
||||
|
||||
|
||||
// start parsing
|
||||
required_string("#AI Profiles");
|
||||
|
||||
// new default?
|
||||
if (optional_string("$Default Profile:"))
|
||||
stuff_string(Default_profile_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// begin reading data
|
||||
while (required_string_either("#End","$Profile Name:"))
|
||||
{
|
||||
ai_profile_t *profile = &dummy_profile;
|
||||
ai_profile_t *previous_profile = NULL;
|
||||
bool no_create = false;
|
||||
|
||||
// get the name
|
||||
required_string("$Profile Name:");
|
||||
stuff_string(profile_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// see if it exists
|
||||
for (i = 0; i < Num_ai_profiles; i++)
|
||||
{
|
||||
if (!stricmp(Ai_profiles[i].profile_name, profile_name))
|
||||
{
|
||||
previous_profile = &Ai_profiles[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// modular table stuff
|
||||
if (optional_string("+nocreate"))
|
||||
{
|
||||
no_create = true;
|
||||
|
||||
// use the previous one if possible,
|
||||
// otherwise continue to use the dummy one
|
||||
if (previous_profile != NULL)
|
||||
profile = previous_profile;
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't create multiple profiles with the same name
|
||||
if (previous_profile != NULL)
|
||||
{
|
||||
Warning(LOCATION, "An ai profile named '%s' already exists! The new one will not be created.\n", profile_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// make sure we're under the limit
|
||||
if (Num_ai_profiles >= MAX_AI_PROFILES)
|
||||
{
|
||||
Warning(LOCATION, "Too many profiles in ai_profiles.tbl! Max is %d.\n", MAX_AI_PROFILES-1); // -1 because one is built-in
|
||||
skip_to_string("#End", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
profile = &Ai_profiles[Num_ai_profiles];
|
||||
Num_ai_profiles++;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize profile if we're not building from a previously parsed one
|
||||
if (!no_create)
|
||||
{
|
||||
// base profile, so zero it out
|
||||
if (profile == &Ai_profiles[0])
|
||||
{
|
||||
memset(profile, 0, sizeof(ai_profile_t));
|
||||
}
|
||||
// brand new profile, so set it to the base defaults
|
||||
else
|
||||
{
|
||||
memcpy(profile, &Ai_profiles[0], sizeof(ai_profile_t));
|
||||
}
|
||||
}
|
||||
|
||||
// set the name
|
||||
strcpy_s(profile->profile_name, profile_name);
|
||||
|
||||
|
||||
// fill in any and all settings; they're all optional and can be in any order
|
||||
while (!check_for_string("$Profile Name:") && !check_for_string("#End"))
|
||||
{
|
||||
if (optional_string("$Player Afterburner Recharge Scale:"))
|
||||
parse_float_list(profile->afterburner_recharge_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Beam Friendly Fire Damage:"))
|
||||
parse_float_list(profile->beam_friendly_damage_cap, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Countermeasure Life Scale:"))
|
||||
parse_float_list(profile->cmeasure_life_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Countermeasure Firing Chance:"))
|
||||
parse_float_list(profile->cmeasure_fire_chance, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI In Range Time:"))
|
||||
parse_float_list(profile->in_range_time, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Always Links Ammo Weapons:"))
|
||||
parse_float_list(profile->link_ammo_levels_always, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Maybe Links Ammo Weapons:"))
|
||||
parse_float_list(profile->link_ammo_levels_maybe, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Primary Ammo Burst Multiplier:"))
|
||||
parse_float_list(profile->primary_ammo_burst_mult, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Always Links Energy Weapons:"))
|
||||
parse_float_list(profile->link_energy_levels_always, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Maybe Links Energy Weapons:"))
|
||||
parse_float_list(profile->link_energy_levels_maybe, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Missles Locked on Player:"))
|
||||
parse_int_list(profile->max_allowed_player_homers, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Player Attackers:"))
|
||||
parse_int_list(profile->max_attackers, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Incoming Asteroids:"))
|
||||
parse_int_list(profile->max_incoming_asteroids, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Damage Factor:") || optional_string("$AI Damage Reduction to Player Hull:"))
|
||||
parse_float_list(profile->player_damage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Subsys Damage Factor:") || optional_string("$AI Damage Reduction to Player Subsys:"))
|
||||
parse_float_list(profile->subsys_damage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
// represented in fractions of F1_0
|
||||
if (optional_string("$Predict Position Delay:"))
|
||||
{
|
||||
int iLoop;
|
||||
float temp_list[NUM_SKILL_LEVELS];
|
||||
|
||||
parse_float_list(temp_list, NUM_SKILL_LEVELS);
|
||||
|
||||
for (iLoop = 0; iLoop < NUM_SKILL_LEVELS; iLoop++)
|
||||
profile->predict_position_delay[iLoop] = fl2f(temp_list[iLoop]);
|
||||
}
|
||||
|
||||
if (optional_string("$Player Shield Recharge Scale:"))
|
||||
parse_float_list(profile->shield_energy_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Shield Manage Delay:") || optional_string("$AI Shield Manage Delays:"))
|
||||
parse_float_list(profile->shield_manage_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Friendly AI Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_delay_scale_friendly, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Hostile AI Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_delay_scale_hostile, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Friendly AI Secondary Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_secondary_delay_scale_friendly, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Hostile AI Secondary Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_secondary_delay_scale_hostile, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Subsys Damage Factor:") || optional_string("$AI Damage Reduction to Player Subsys:"))
|
||||
parse_float_list(profile->subsys_damage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Turn Time Scale:"))
|
||||
parse_float_list(profile->turn_time_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Glide Attack Percent:")) {
|
||||
parse_float_list(profile->glide_attack_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_attack_percent[i] < 0.0f || profile->glide_attack_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Glide Attack Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_attack_percent[i]);
|
||||
profile->glide_attack_percent[i] = 0.0f;
|
||||
}
|
||||
profile->glide_attack_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Circle Strafe Percent:")) {
|
||||
parse_float_list(profile->circle_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->circle_strafe_percent[i] < 0.0f || profile->circle_strafe_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Circle Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->circle_strafe_percent[i]);
|
||||
profile->circle_strafe_percent[i] = 0.0f;
|
||||
}
|
||||
profile->circle_strafe_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Glide Strafe Percent:")) {
|
||||
parse_float_list(profile->glide_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_strafe_percent[i] < 0.0f || profile->glide_strafe_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Glide Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_strafe_percent[i]);
|
||||
profile->glide_strafe_percent[i] = 0.0f;
|
||||
}
|
||||
profile->glide_strafe_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Random Sidethrust Percent:")) {
|
||||
parse_float_list(profile->random_sidethrust_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->random_sidethrust_percent[i] < 0.0f || profile->random_sidethrust_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Random Sidethrust Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->random_sidethrust_percent[i]);
|
||||
profile->random_sidethrust_percent[i] = 0.0f;
|
||||
}
|
||||
profile->random_sidethrust_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Stalemate Time Threshold:"))
|
||||
parse_float_list(profile->stalemate_time_thresh, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Stalemate Distance Threshold:"))
|
||||
parse_float_list(profile->stalemate_dist_thresh, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Weapon Recharge Scale:"))
|
||||
parse_float_list(profile->weapon_energy_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Turret Target Ownage:"))
|
||||
parse_int_list(profile->max_turret_ownage_target, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Turret Player Ownage:"))
|
||||
parse_int_list(profile->max_turret_ownage_player, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Required For Kill Scale:"))
|
||||
parse_float_list(profile->kill_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Required For Assist Scale:"))
|
||||
parse_float_list(profile->assist_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Awarded For Capship Assist:"))
|
||||
parse_float_list(profile->assist_award_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Repair Penalty:"))
|
||||
parse_int_list(profile->repair_penalty, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Delay Before Allowing Bombs to Be Shot Down:"))
|
||||
parse_float_list(profile->delay_bomb_arm_timer, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Chance AI Has to Fire Missiles at Player:"))
|
||||
parse_int_list(profile->chance_to_use_missiles_on_plr, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Aim Update Delay:"))
|
||||
parse_float_list(profile->max_aim_update_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Turret Max Aim Update Delay:"))
|
||||
parse_float_list(profile->turret_max_aim_update_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Autoaim FOV:"))
|
||||
{
|
||||
float fov_list[NUM_SKILL_LEVELS];
|
||||
parse_float_list(fov_list, NUM_SKILL_LEVELS);
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++)
|
||||
{
|
||||
//Enforce range
|
||||
if (fov_list[i] < 0.0f || fov_list[i] >= 360.0f)
|
||||
{
|
||||
Warning(LOCATION, "$Player Autoaim FOV should be >= 0 and < 360.0 (read %f). Setting to 0.", fov_list[i]);
|
||||
fov_list[i] = 0.0f;
|
||||
}
|
||||
|
||||
//Convert units
|
||||
profile->player_autoaim_fov[i] = fov_list[i] * PI / 180.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Detail Distance Multiplier:"))
|
||||
parse_float_list(profile->detail_distance_mult, NUM_SKILL_LEVELS);
|
||||
|
||||
set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart primary weapon selection:", AIPF_SMART_PRIMARY_WEAPON_SELECTION, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart secondary weapon selection:", AIPF_SMART_SECONDARY_WEAPON_SELECTION, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart shield management:", AIPF_SMART_SHIELD_MANAGEMENT, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart afterburner management:", AIPF_SMART_AFTERBURNER_MANAGEMENT, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow rapid secondary dumbfire:", AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$huge turret weapons ignore bombs:", AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$don't insert random turret fire delay:", AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$shockwaves damage small ship subsystems:", AIPF_SHOCKWAVES_DAMAGE_SMALL_SHIP_SUBSYSTEMS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$navigation subsystem governs warpout capability:", AIPF_NAVIGATION_SUBSYS_GOVERNS_WARP, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AIPF_NO_MIN_DOCK_SPEED_CAP, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$disable linked fire penalty:", AIPF_DISABLE_LINKED_FIRE_PENALTY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$disable weapon damage scaling:", AIPF_DISABLE_WEAPON_DAMAGE_SCALING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use additive weapon velocity:", AIPF_USE_ADDITIVE_WEAPON_VELOCITY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use newtonian dampening:", AIPF_USE_NEWTONIAN_DAMPENING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$include beams for kills and assists:", AIPF_INCLUDE_BEAMS_IN_STAT_CALCS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$score kills based on damage caused:", AIPF_KILL_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$score assists based on damage caused:", AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow event and goal scoring in multiplayer:", AIPF_ALLOW_MULTI_EVENT_SCORING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix linked primary weapon decision bug:", AIPF_FIX_LINKED_PRIMARY_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$prevent turrets targeting too distant bombs:", AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart subsystem targeting for turrets:", AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AIPF_FIX_HEAT_SEEKER_STEALTH_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$multi allow empty primaries:", AIPF_MULTI_ALLOW_EMPTY_PRIMARIES, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$multi allow empty secondaries:", AIPF_MULTI_ALLOW_EMPTY_SECONDARIES, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow turrets target weapons freely:", AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use only single fov for turrets:", AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow vertical dodge:", AIPF_ALLOW_VERTICAL_DODGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$force beam turrets to use normal fov:", AIPF_FORCE_BEAM_TURRET_FOV, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix ai class bug:", AIPF_FIX_AI_CLASS_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$turrets ignore targets radius in range checks:", AIPF2_TURRETS_IGNORE_TARGET_RADIUS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$no extra collision avoidance vs player:", AIPF2_NO_SPECIAL_PLAYER_AVOID, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$perform less checks for death screams:", AIPF2_PERFORM_LESS_SCREAM_CHECKS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$advanced turret fov edge checks:", AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$require turrets to have target in fov:", AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$ai aims from ship center:", AIPF2_AI_AIMS_FROM_SHIP_CENTER, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$allow primary link delay:", AIPF2_ALLOW_PRIMARY_LINK_DELAY, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$allow beams to damage bombs:", AIPF2_BEAMS_DAMAGE_WEAPONS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$disable weapon damage scaling for player:", AIPF2_PLAYER_WEAPON_SCALE_FIX, AIP_FLAG2);
|
||||
|
||||
profile->ai_path_mode = AI_PATH_MODE_NORMAL;
|
||||
if(optional_string("$ai path mode:"))
|
||||
{
|
||||
stuff_string(buf, F_NAME, NAME_LENGTH);
|
||||
int j = ai_path_type_match(buf);
|
||||
if(j >= 0) {
|
||||
profile->ai_path_mode = j;
|
||||
} else {
|
||||
Warning(LOCATION, "Invalid ai path mode '%s' specified", buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Default weapon select effect:")) {
|
||||
char effect[NAME_LENGTH];
|
||||
stuff_string(effect, F_NAME, NAME_LENGTH);
|
||||
if (!stricmp(effect, "FS1"))
|
||||
Default_weapon_select_effect = 1;
|
||||
if (!stricmp(effect, "off"))
|
||||
Default_weapon_select_effect = 0;
|
||||
}
|
||||
|
||||
if (optional_string("$Default ship select effect:")) {
|
||||
char effect[NAME_LENGTH];
|
||||
stuff_string(effect, F_NAME, NAME_LENGTH);
|
||||
if (!stricmp(effect, "FS1"))
|
||||
Default_ship_select_effect = 1;
|
||||
if (!stricmp(effect, "off"))
|
||||
Default_ship_select_effect = 0;
|
||||
}
|
||||
|
||||
set_flag(profile, "$no warp camera:", AIPF2_NO_WARP_CAMERA, AIP_FLAG2);
|
||||
|
||||
// if we've been through once already and are at the same place, force a move
|
||||
if ( saved_Mp && (saved_Mp == Mp) )
|
||||
{
|
||||
char buf[60];
|
||||
memset(buf, 0, 60);
|
||||
strncpy(buf, Mp, 59);
|
||||
mprintf(("WARNING: Unrecognized parameter in ai_profiles: %s\n", buf));
|
||||
|
||||
Mp++;
|
||||
}
|
||||
|
||||
// find next valid option
|
||||
skip_to_start_of_string_either("$", "#");
|
||||
saved_Mp = Mp;
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
|
||||
// add tbl/tbm to multiplayer validation list
|
||||
extern void fs2netd_add_table_validation(const char *tblname);
|
||||
extern void fs2netd_add_table_validation(char *tblname);
|
||||
fs2netd_add_table_validation(filename);
|
||||
|
||||
// close localization
|
||||
lcl_ext_close();
|
||||
}
|
||||
|
||||
void ai_profiles_init()
|
||||
|
||||
+3
-14
@@ -9,8 +9,8 @@
|
||||
#ifndef _AI_PROFILES_H_
|
||||
#define _AI_PROFILES_H_
|
||||
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
|
||||
// flag int defines
|
||||
@@ -53,21 +53,15 @@
|
||||
// flags2
|
||||
#define AIPF2_TURRETS_IGNORE_TARGET_RADIUS (1 << 0)
|
||||
#define AIPF2_NO_SPECIAL_PLAYER_AVOID (1 << 1)
|
||||
#define AIPF2_PERFORM_FEWER_SCREAM_CHECKS (1 << 2)
|
||||
#define AIPF2_PERFORM_LESS_SCREAM_CHECKS (1 << 2)
|
||||
#define AIPF2_ALL_SHIPS_MANAGE_SHIELDS (1 << 3)
|
||||
#define AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS (1 << 4)
|
||||
#define AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV (1 << 5)
|
||||
#define AIPF2_AI_AIMS_FROM_SHIP_CENTER (1 << 6)
|
||||
#define AIPF2_ALLOW_PRIMARY_LINK_AT_START (1 << 7)
|
||||
#define AIPF2_ALLOW_PRIMARY_LINK_DELAY (1 << 7)
|
||||
#define AIPF2_BEAMS_DAMAGE_WEAPONS (1 << 8)
|
||||
#define AIPF2_PLAYER_WEAPON_SCALE_FIX (1 << 9)
|
||||
#define AIPF2_NO_WARP_CAMERA (1 << 10)
|
||||
#define AIPF2_ASPECT_LOCK_COUNTERMEASURE (1 << 11)
|
||||
#define AIPF2_AI_GUARDS_SPECIFIC_SHIP_IN_WING (1 << 12)
|
||||
#define AIPF2_FIX_AI_PATH_ORDER_BUG (1 << 13)
|
||||
#define AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING (1 << 14)
|
||||
#define AIPF2_ASPECT_INVULNERABILITY_FIX (1 << 15)
|
||||
#define AIPF2_GLIDE_DECAY_REQUIRES_THRUST (1 << 16)
|
||||
|
||||
// AI Path types
|
||||
#define AI_PATH_MODE_NORMAL 0
|
||||
@@ -153,11 +147,6 @@ typedef struct ai_profile_t {
|
||||
|
||||
int ai_path_mode;
|
||||
|
||||
// Ships flying bay paths will gradually accelerate/decelerate instead of
|
||||
// flying the whole path at max speed
|
||||
float bay_arrive_speed_mult;
|
||||
float bay_depart_speed_mult;
|
||||
|
||||
} ai_profile_t;
|
||||
|
||||
|
||||
|
||||
+101
-143
@@ -10,23 +10,21 @@
|
||||
|
||||
|
||||
#include "ai/aibig.h"
|
||||
#include "ai/aigoals.h"
|
||||
#include "freespace2/freespace.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "iff_defs/iff_defs.h"
|
||||
#include "io/timer.h"
|
||||
#include "math/staticrand.h"
|
||||
#include "mission/missionparse.h"
|
||||
#include "object/object.h"
|
||||
#include "ship/afterburner.h"
|
||||
#include "ship/ship.h"
|
||||
#include "ship/afterburner.h"
|
||||
#include "freespace2/freespace.h"
|
||||
#include "weapon/weapon.h"
|
||||
#include "io/timer.h"
|
||||
#include "mission/missionparse.h"
|
||||
#include "iff_defs/iff_defs.h"
|
||||
#include "math/staticrand.h"
|
||||
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma optimize("", off)
|
||||
#pragma auto_inline(off)
|
||||
#endif
|
||||
|
||||
#define SCAN_FIGHTERS_INTERVAL 2000 // how often an AI fighter/bomber should scan for enemy fighter/bombers
|
||||
// if sitting still and pounding on a big ship. If enemy fighters are
|
||||
@@ -118,6 +116,8 @@ void ai_bpap(object *objp, vec3d *attacker_objp_pos, vec3d *attacker_objp_fvec,
|
||||
if (num_tries > octp->nverts)
|
||||
num_tries = octp->nverts;
|
||||
|
||||
int best_index = -1;
|
||||
|
||||
for (i=0; i<num_tries; i++) {
|
||||
int index;
|
||||
float dist, dot;
|
||||
@@ -142,6 +142,7 @@ void ai_bpap(object *objp, vec3d *attacker_objp_pos, vec3d *attacker_objp_fvec,
|
||||
|
||||
if (in_fov) {
|
||||
if (dist < nearest_dist) {
|
||||
best_index = index;
|
||||
nearest_dist = dist;
|
||||
best_point = result_point;
|
||||
*local_attack_point = rel_point;
|
||||
@@ -172,8 +173,6 @@ done_1:
|
||||
}
|
||||
|
||||
mc_info mc;
|
||||
mc_info_init(&mc);
|
||||
|
||||
mc.model_instance_num = Ships[objp->instance].model_instance_num;
|
||||
mc.model_num = sip->model_num;
|
||||
mc.orient = &objp->orient;
|
||||
@@ -370,25 +369,20 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
|
||||
object *target_objp;
|
||||
|
||||
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
|
||||
|
||||
if ( aip->target_objnum < 0 )
|
||||
return 0;
|
||||
|
||||
target_objp = &Objects[aip->target_objnum];
|
||||
|
||||
if ( (aip->targeted_subsys != NULL) && (aip->targeted_subsys->system_info->path_num >= 0) ) {
|
||||
if ( (aip->targeted_subsys != NULL) && (aip->target_objnum >= 0) && (aip->targeted_subsys->system_info->path_num >= 0) ) {
|
||||
polymodel *pm;
|
||||
int subsys_path_num, subsys_in_sight, checked_sight;
|
||||
float dist;
|
||||
|
||||
// Get models of both source and target
|
||||
polymodel *pm = model_get( Ship_info[Ships[Pl_objp->instance].ship_info_index].model_num );
|
||||
polymodel *pm_t = model_get( Ship_info[Ships[target_objp->instance].ship_info_index].model_num );
|
||||
|
||||
// Necessary sanity check
|
||||
Assertion(aip->targeted_subsys->system_info->path_num < pm_t->n_paths, "Invalid Path number %d for subsystem %s on ship %s (Model: %s)\n", aip->targeted_subsys->system_info->path_num, aip->targeted_subsys->system_info->name, Ship_info[Ships[target_objp->instance].ship_info_index].name, pm_t->filename );
|
||||
if (aip->targeted_subsys->system_info->path_num >= pm_t->n_paths)
|
||||
pm = model_get( Ship_info[Ships[Pl_objp->instance].ship_info_index].model_num );
|
||||
//Necessary sanity check
|
||||
polymodel *pm_t;
|
||||
pm_t = model_get(Ship_info[Ships[Objects[aip->target_objnum].instance].ship_info_index].model_num);
|
||||
Assertion(aip->targeted_subsys->system_info->path_num <= pm_t->n_paths, "Invalid Path number %d for subsystem %s on ship %s (Model: %s)\n", aip->targeted_subsys->system_info->path_num, aip->targeted_subsys->system_info->name, Ship_info[Ships[Objects[aip->target_objnum].instance].ship_info_index].name, pm_t->filename );
|
||||
if (aip->targeted_subsys->system_info->path_num > pm_t->n_paths)
|
||||
return 0;
|
||||
|
||||
// If attacking a subsystem, ensure that we have an unobstructed line of sight... if not, then move
|
||||
// towards path linked to subsystem
|
||||
subsys_in_sight = 0; // assume Pl_objp doesn't have line of sight to subys
|
||||
@@ -432,7 +426,7 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
|
||||
|
||||
aip->path_goal_dist = 5;
|
||||
subsys_path_num = aip->targeted_subsys->system_info->path_num;
|
||||
if ( ((aip->path_start) == -1 || (aip->mp_index != subsys_path_num)) && subsys_path_num < pm_t->n_paths ) {
|
||||
if ( ((aip->path_start) == -1 || (aip->mp_index != subsys_path_num)) && subsys_path_num <= pm->n_paths ) {
|
||||
// maybe create a new path
|
||||
if ( subsys_path_num >= 0 ) {
|
||||
Assert(aip->target_objnum >= 0);
|
||||
@@ -604,15 +598,11 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
|
||||
|
||||
// see if Pl_objp needs to reposition to get a good shot at subsystem which is being attacked
|
||||
if ( ai_big_maybe_follow_subsys_path() ) {
|
||||
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
|
||||
afterburners_stop(Pl_objp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
vec3d *rel_pos;
|
||||
vec3d vec_to_enemy;
|
||||
float weapon_travel_dist;
|
||||
vec3d *rel_pos, vec_to_enemy;
|
||||
float weapon_travel_dist;
|
||||
|
||||
start_bank = Ships[aip->shipnum].weapons.current_primary_bank;
|
||||
|
||||
@@ -637,25 +627,11 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
|
||||
weapon_travel_dist = ai_get_weapon_dist(&Ships[Pl_objp->instance].weapons);
|
||||
|
||||
if ( aip->targeted_subsys != NULL ) {
|
||||
if (dist_to_enemy > (weapon_travel_dist-20)) {
|
||||
if (dist_to_enemy > (weapon_travel_dist-20))
|
||||
accelerate_ship(aip, 1.0f);
|
||||
|
||||
ship *shipp = &Ships[Pl_objp->instance];
|
||||
if ((aip->ai_flags & AIF_FREE_AFTERBURNER_USE) && !(shipp->flags2 & SF2_AFTERBURNER_LOCKED) && (dot_to_enemy > 0.75f)) {
|
||||
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
|
||||
afterburners_start(Pl_objp);
|
||||
aip->afterburner_stop_time = Missiontime + 3*F1_0;
|
||||
}
|
||||
} else if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
|
||||
afterburners_stop(Pl_objp);
|
||||
}
|
||||
} else {
|
||||
else {
|
||||
// AL 12-31-97: Move at least as quickly as your target is moving...
|
||||
accelerate_ship(aip, MAX(1.0f - dot_to_enemy, Objects[aip->target_objnum].phys_info.fspeed/sip->max_speed));
|
||||
|
||||
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
|
||||
afterburners_stop(Pl_objp);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -676,22 +652,10 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
|
||||
if (dist_to_enemy < ATTACK_STOP_DISTANCE) {
|
||||
// accelerate_ship(aip, accel * 0.5f);
|
||||
accelerate_ship(aip, -1.0f);
|
||||
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
|
||||
afterburners_stop(Pl_objp);
|
||||
}
|
||||
} else {
|
||||
accelerate_ship(aip, accel);
|
||||
|
||||
ship *shipp = &Ships[Pl_objp->instance];
|
||||
if ((aip->ai_flags & AIF_FREE_AFTERBURNER_USE) && !(shipp->flags2 & SF2_AFTERBURNER_LOCKED) && (accel > 0.95f)) {
|
||||
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
|
||||
afterburners_start(Pl_objp);
|
||||
aip->afterburner_stop_time = Missiontime + 3*F1_0;
|
||||
}
|
||||
} else if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
|
||||
afterburners_stop(Pl_objp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -748,77 +712,84 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f
|
||||
}
|
||||
|
||||
if (tswp->num_secondary_banks > 0) {
|
||||
if (!(En_objp->flags & OF_PROTECTED) || (aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP))) {
|
||||
|
||||
int priority1, priority2;
|
||||
|
||||
priority1 = -1;
|
||||
priority2 = -1;
|
||||
|
||||
// Maybe favor selecting a bomb.
|
||||
// Note, if you're firing a bomb, if it's aspect seeking, the firing conditions can be looser.
|
||||
if (Ship_info[Ships[En_objp->instance].ship_info_index].flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP))
|
||||
if (En_objp->phys_info.speed * dist_to_enemy < 5000.0f) // Don't select a bomb if enemy moving fast relative to distance
|
||||
priority1 = WIF_BOMB;
|
||||
|
||||
if (!(En_objp->flags & OF_PROTECTED)) {
|
||||
//ai_select_secondary_weapon(Pl_objp, tswp, priority1, priority2); // Note, need to select to get weapon speed and lifetime
|
||||
|
||||
ai_choose_secondary_weapon(Pl_objp, aip, En_objp);
|
||||
int current_bank = tswp->current_secondary_bank;
|
||||
if (current_bank > -1) {
|
||||
weapon_info *swip = &Weapon_info[tswp->secondary_bank_weapons[current_bank]];
|
||||
weapon_info *swip = &Weapon_info[tswp->secondary_bank_weapons[current_bank]];
|
||||
|
||||
if(!(En_objp->flags & OF_PROTECTED) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)) && swip->wi_flags & WIF_PUNCTURE )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil
|
||||
// If ship is protected and very low on hits, don't fire missiles.
|
||||
if (!(En_objp->flags & OF_PROTECTED) || (En_objp->hull_strength > 10*swip->damage)) {
|
||||
if (aip->ai_flags & AIF_UNLOAD_SECONDARIES) {
|
||||
if (timestamp_until(swp->next_secondary_fire_stamp[current_bank]) > swip->fire_wait*1000.0f) {
|
||||
swp->next_secondary_fire_stamp[current_bank] = timestamp((int) (swip->fire_wait*1000.0f));
|
||||
}
|
||||
}
|
||||
|
||||
if (timestamp_elapsed(swp->next_secondary_fire_stamp[current_bank])) {
|
||||
float firing_range;
|
||||
if (swip->wi_flags2 & WIF2_LOCAL_SSM)
|
||||
firing_range=swip->lssm_lock_range;
|
||||
else
|
||||
firing_range = MIN((swip->max_speed * swip->lifetime), swip->weapon_range);
|
||||
// reduce firing range of secondaries in nebula
|
||||
extern int Nebula_sec_range;
|
||||
if ((The_mission.flags & MISSION_FLAG_FULLNEB) && Nebula_sec_range) {
|
||||
firing_range *= 0.8f;
|
||||
}
|
||||
|
||||
float t = 0.25f; // default delay in seconds until next fire.
|
||||
|
||||
if (dist_to_enemy < firing_range*1.0f) {
|
||||
|
||||
|
||||
//vm_vec_scale_add(&future_enemy_pos, enemy_pos, enemy_vel, dist_to_enemy/swip->max_speed);
|
||||
//if (vm_vec_dist_quick(&future_enemy_pos, firing_pos) < firing_range * 0.8f) {
|
||||
if (ai_fire_secondary_weapon(Pl_objp)) {
|
||||
|
||||
int current_bank_adjusted = MAX_SHIP_PRIMARY_BANKS + current_bank;
|
||||
|
||||
if ((aip->ai_flags & AIF_UNLOAD_SECONDARIES) || (swip->burst_flags & WBF_FAST_FIRING)) {
|
||||
if (swip->burst_shots > swp->burst_counter[current_bank_adjusted]) {
|
||||
t = swip->burst_delay;
|
||||
swp->burst_counter[current_bank_adjusted]++;
|
||||
} else {
|
||||
t = swip->fire_wait;
|
||||
if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) {
|
||||
swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots;
|
||||
} else {
|
||||
swp->burst_counter[current_bank_adjusted] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (swip->burst_shots > swp->burst_counter[current_bank_adjusted]) {
|
||||
t = set_secondary_fire_delay(aip, temp_shipp, swip, true);
|
||||
swp->burst_counter[current_bank_adjusted]++;
|
||||
} else {
|
||||
t = set_secondary_fire_delay(aip, temp_shipp, swip, false);
|
||||
if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) {
|
||||
swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots;
|
||||
} else {
|
||||
swp->burst_counter[current_bank_adjusted] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
swp->next_secondary_fire_stamp[current_bank] = timestamp((int) (t*1000.0f));
|
||||
}
|
||||
//}
|
||||
}
|
||||
swp->next_secondary_fire_stamp[current_bank] = timestamp((int) (t*1000.0f));
|
||||
}
|
||||
// If ship is protected and very low on hits, don't fire missiles.
|
||||
if ((current_bank > -1) && (!(En_objp->flags & OF_PROTECTED) || (En_objp->hull_strength > 10*swip->damage))) {
|
||||
if (aip->ai_flags & AIF_UNLOAD_SECONDARIES) {
|
||||
if (timestamp_until(swp->next_secondary_fire_stamp[current_bank]) > swip->fire_wait*1000.0f) {
|
||||
swp->next_secondary_fire_stamp[current_bank] = timestamp((int) (swip->fire_wait*1000.0f));
|
||||
}
|
||||
}
|
||||
|
||||
if (timestamp_elapsed(swp->next_secondary_fire_stamp[current_bank])) {
|
||||
float firing_range;
|
||||
if (swip->wi_flags2 & WIF2_LOCAL_SSM)
|
||||
firing_range=swip->lssm_lock_range;
|
||||
else
|
||||
firing_range = MIN((swip->max_speed * swip->lifetime), swip->weapon_range);
|
||||
// reduce firing range of secondaries in nebula
|
||||
extern int Nebula_sec_range;
|
||||
if ((The_mission.flags & MISSION_FLAG_FULLNEB) && Nebula_sec_range) {
|
||||
firing_range *= 0.8f;
|
||||
}
|
||||
|
||||
float t = 0.25f; // default delay in seconds until next fire.
|
||||
|
||||
if (dist_to_enemy < firing_range*1.0f) {
|
||||
|
||||
|
||||
//vm_vec_scale_add(&future_enemy_pos, enemy_pos, enemy_vel, dist_to_enemy/swip->max_speed);
|
||||
//if (vm_vec_dist_quick(&future_enemy_pos, firing_pos) < firing_range * 0.8f) {
|
||||
if (ai_fire_secondary_weapon(Pl_objp)) {
|
||||
if ((aip->ai_flags & AIF_UNLOAD_SECONDARIES) || (swip->burst_flags & WBF_FAST_FIRING)) {
|
||||
if (swip->burst_shots > swp->burst_counter[current_bank]) {
|
||||
t = swip->burst_delay;
|
||||
swp->burst_counter[current_bank]++;
|
||||
} else {
|
||||
t = swip->fire_wait;
|
||||
if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) {
|
||||
swp->burst_counter[current_bank] = myrand() % swip->burst_shots;
|
||||
} else {
|
||||
swp->burst_counter[current_bank] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (swip->burst_shots > swp->burst_counter[current_bank]) {
|
||||
t = set_secondary_fire_delay(aip, temp_shipp, swip, true);
|
||||
swp->burst_counter[current_bank]++;
|
||||
} else {
|
||||
t = set_secondary_fire_delay(aip, temp_shipp, swip, false);
|
||||
if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) {
|
||||
swp->burst_counter[current_bank] = myrand() % swip->burst_shots;
|
||||
} else {
|
||||
swp->burst_counter[current_bank] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
swp->next_secondary_fire_stamp[current_bank] = timestamp((int) (t*1000.0f));
|
||||
}
|
||||
//}
|
||||
}
|
||||
swp->next_secondary_fire_stamp[current_bank] = timestamp((int) (t*1000.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -887,9 +858,6 @@ void ai_big_chase()
|
||||
aip->submode_parm0 = Missiontime; // use parm0 as time strafe mode entered (i.e. MODE start time)
|
||||
aip->submode = AIS_STRAFE_AVOID;
|
||||
aip->submode_start_time = Missiontime;
|
||||
if (Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) {
|
||||
afterburners_stop(Pl_objp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -930,12 +898,8 @@ void ai_big_chase()
|
||||
case SM_ATTACK:
|
||||
case SM_SUPER_ATTACK:
|
||||
if (vm_vec_dist_quick(&Pl_objp->pos, &predicted_enemy_pos) > 100.0f + En_objp->radius * 2.0f) {
|
||||
if (maybe_avoid_big_ship(Pl_objp, En_objp, aip, &predicted_enemy_pos, 10.0f)) {
|
||||
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
|
||||
afterburners_stop(Pl_objp);
|
||||
}
|
||||
if (maybe_avoid_big_ship(Pl_objp, En_objp, aip, &predicted_enemy_pos, 10.0f))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (aip->target_time < 2.0f)
|
||||
@@ -951,13 +915,6 @@ void ai_big_chase()
|
||||
//
|
||||
// Set turn and acceleration based on submode.
|
||||
//
|
||||
|
||||
if (((aip->submode != SM_ATTACK) && (aip->submode != SM_SUPER_ATTACK) && (aip->submode != SM_ATTACK_FOREVER) && (aip->submode != SM_EVADE_WEAPON)) || (aip->mode == AIM_STRAFE)){
|
||||
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
|
||||
afterburners_stop(Pl_objp);
|
||||
}
|
||||
}
|
||||
|
||||
switch (aip->submode) {
|
||||
case SM_CONTINUOUS_TURN:
|
||||
ai_big_chase_ct();
|
||||
@@ -1239,7 +1196,7 @@ int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos)
|
||||
float dist_to_target, dist_normal_to_target, time_to_target;
|
||||
dist_to_target = vm_vec_mag_quick(&vec_to_target);
|
||||
if (vm_vec_mag_quick(&aip->big_attack_surface_normal) > 0.9) {
|
||||
dist_normal_to_target = -vm_vec_dot(&vec_to_target, &aip->big_attack_surface_normal);
|
||||
dist_normal_to_target = -vm_vec_dotprod(&vec_to_target, &aip->big_attack_surface_normal);
|
||||
} else {
|
||||
dist_normal_to_target = 0.2f * vm_vec_mag_quick(&vec_to_target);
|
||||
}
|
||||
@@ -1264,9 +1221,10 @@ int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos)
|
||||
aip->submode = AIS_STRAFE_RETREAT1;
|
||||
aip->submode_start_time = Missiontime;
|
||||
|
||||
float box_dist;
|
||||
int is_inside;
|
||||
vec3d goal_point;
|
||||
get_world_closest_box_point_with_delta(&goal_point, En_objp, &Pl_objp->pos, &is_inside, STRAFE_RETREAT_BOX_DIST);
|
||||
box_dist = get_world_closest_box_point_with_delta(&goal_point, En_objp, &Pl_objp->pos, &is_inside, STRAFE_RETREAT_BOX_DIST);
|
||||
|
||||
// set goal point
|
||||
aip->goal_point = goal_point;
|
||||
|
||||
+2
-2
@@ -12,10 +12,10 @@
|
||||
#ifndef __AIBIG_H__
|
||||
#define __AIBIG_H__
|
||||
|
||||
class object;
|
||||
struct object;
|
||||
struct ai_info;
|
||||
struct vec3d;
|
||||
class ship_subsys;
|
||||
struct ship_subsys;
|
||||
|
||||
void ai_big_ship(object *objp);
|
||||
void ai_big_chase();
|
||||
|
||||
+548
-889
File diff suppressed because it is too large.
Load diff
+70
-74
@@ -11,18 +11,18 @@
|
||||
|
||||
|
||||
#include "ai/aigoals.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "parse/sexp.h"
|
||||
#include "mission/missionlog.h"
|
||||
#include "mission/missionparse.h"
|
||||
#include "network/multi.h"
|
||||
#include "network/multimsgs.h"
|
||||
#include "object/object.h"
|
||||
#include "object/objectdock.h"
|
||||
#include "object/waypoint.h"
|
||||
#include "parse/sexp.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "playerman/player.h"
|
||||
#include "network/multimsgs.h"
|
||||
#include "network/multi.h"
|
||||
#include "ship/ship.h"
|
||||
#include "weapon/weapon.h"
|
||||
#include "object/objectdock.h"
|
||||
#include "object/waypoint.h"
|
||||
|
||||
|
||||
// all ai goals dealt with in this code are goals that are specified through
|
||||
@@ -93,7 +93,7 @@ int Num_ai_goals = sizeof(Ai_goal_names) / sizeof(ai_goal_list);
|
||||
// HUD what a ship's current orders are. If the AI goal doesn't correspond to something that
|
||||
// ought to be printable, then NULL is used.
|
||||
// JAS: Converted to a function in order to externalize the strings
|
||||
const char *Ai_goal_text(int goal)
|
||||
char *Ai_goal_text(int goal)
|
||||
{
|
||||
switch(goal) {
|
||||
case 1:
|
||||
@@ -131,9 +131,18 @@ const char *Ai_goal_text(int goal)
|
||||
}
|
||||
|
||||
// function to maybe add the form on my wing goal for a player's starting wing. Called when a player wing arrives.
|
||||
// Goober5000 - made more generic
|
||||
void ai_maybe_add_form_goal( wing *wingp )
|
||||
{
|
||||
int j;
|
||||
char *wing_leader;
|
||||
|
||||
// if the wing leader isn't available (ie, dead/departed) then go ahead and bail now
|
||||
if (wingp->ship_index[wingp->special_ship] < 0)
|
||||
return;
|
||||
|
||||
// Goober5000 - the wing leader is now not necessarily the player
|
||||
wing_leader = Ships[wingp->ship_index[wingp->special_ship]].ship_name;
|
||||
|
||||
// iterate through the ship_index list of this wing and check for orders. We will do
|
||||
// this for all ships in the wing instead of on a wing only basis in case some ships
|
||||
@@ -143,15 +152,20 @@ void ai_maybe_add_form_goal( wing *wingp )
|
||||
|
||||
Assert( wingp->ship_index[j] != -1 ); // get Allender
|
||||
|
||||
// don't process wing leader
|
||||
if (j == wingp->special_ship)
|
||||
continue;
|
||||
|
||||
aip = &Ai_info[Ships[wingp->ship_index[j]].ai_index];
|
||||
|
||||
// don't process Player_ship
|
||||
if ( aip == Player_ai )
|
||||
continue;
|
||||
|
||||
// it is sufficient enough to check the first goal entry to see if it has a valid goal
|
||||
if ( aip->goals[0].ai_mode == AI_GOAL_NONE ) {
|
||||
// need to add a form on my wing goal here. Ships are always forming on the player's wing.
|
||||
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Player_ship->ship_name, aip );
|
||||
// need to add a form on my wing goal here
|
||||
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, wing_leader, aip );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,28 +173,38 @@ void ai_maybe_add_form_goal( wing *wingp )
|
||||
void ai_post_process_mission()
|
||||
{
|
||||
object *objp;
|
||||
int i;
|
||||
|
||||
/*
|
||||
// Goober5000 - considering that this is also done in parse_wing_create_ships,
|
||||
// it's redundant (and possibly premature for some wings) here
|
||||
|
||||
// Check ships in player starting wings. Those ships should follow these rules:
|
||||
// (1) if they have no orders, they should get a form on my wing order
|
||||
// (2) if they have an order, they are free to act on it.
|
||||
//
|
||||
// So basically, we are checking for (1)
|
||||
if ( !Fred_running ) {
|
||||
// MK, 5/9/98: Used to iterate through MAX_STARTING_WINGS, but this was too many ships forming on player.
|
||||
// Goober5000 - MK originally iterated on only the first wing; now we iterate on only the player wing
|
||||
// because the player wing may not be first
|
||||
for ( i = 0; i < MAX_STARTING_WINGS; i++ ) {
|
||||
if (Starting_wings[i] >= 0 && Starting_wings[i] == Player_ship->wingnum) {
|
||||
wing *wingp;
|
||||
if ( !Fred_running )
|
||||
{
|
||||
int i;
|
||||
|
||||
wingp = &Wings[Starting_wings[i]];
|
||||
|
||||
ai_maybe_add_form_goal( wingp );
|
||||
|
||||
}
|
||||
// Goober5000 - make all wings form on their respective leaders
|
||||
for ( i = 0; i < Num_wings; i++ )
|
||||
{
|
||||
ai_maybe_add_form_goal( &Wings[i] );
|
||||
}
|
||||
|
||||
// for ( i = 0; i < 1; i++ ) { // MK, 5/9/98: Used to iterate through MAX_STARTING_WINGS, but this was too many ships forming on player.
|
||||
// if ( Starting_wings[i] != -1 ) {
|
||||
// wing *wingp;
|
||||
//
|
||||
// wingp = &Wings[Starting_wings[i]];
|
||||
//
|
||||
// ai_maybe_add_form_goal( wingp );
|
||||
//
|
||||
// }
|
||||
// }
|
||||
}
|
||||
*/
|
||||
|
||||
// for every valid ship object, call process_mission_orders to be sure that ships start the
|
||||
// mission following the orders in the mission file right away instead of waiting N seconds
|
||||
@@ -199,17 +223,12 @@ void ai_post_process_mission()
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a goal is valid for a particular type of ship
|
||||
*
|
||||
* @param ship Ship type to test
|
||||
* @param ai_goal_type Goal type to test
|
||||
*/
|
||||
int ai_query_goal_valid( int ship, int ai_goal_type )
|
||||
// function which determines is a goal is valid for a particular type of ship
|
||||
int ai_query_goal_valid( int ship, int ai_goal )
|
||||
{
|
||||
int accepted;
|
||||
|
||||
if (ai_goal_type == AI_GOAL_NONE)
|
||||
if (ai_goal == AI_GOAL_NONE)
|
||||
return 1; // anything can have no orders.
|
||||
|
||||
accepted = 0;
|
||||
@@ -219,7 +238,7 @@ int ai_query_goal_valid( int ship, int ai_goal_type )
|
||||
int ship_type = Ship_info[Ships[ship].ship_info_index].class_type;
|
||||
if(ship_type > -1)
|
||||
{
|
||||
if(ai_goal_type & Ship_types[ship_type].ai_valid_goals) {
|
||||
if(ai_goal & Ship_types[ship_type].ai_valid_goals) {
|
||||
accepted = 1;
|
||||
}
|
||||
}
|
||||
@@ -526,14 +545,14 @@ int ai_goal_find_dockpoint(int shipnum, int dock_type)
|
||||
|
||||
// insanity?
|
||||
if (loop_count >= 100)
|
||||
Warning(LOCATION, "Too many iterations while looking for a dockpoint on %s.\n", shipp->ship_name);
|
||||
Warning(LOCATION, "Too many iterations while looking for a dockpoint on %s. Either there was a bug or this is an übership.\n", shipp->ship_name);
|
||||
|
||||
// if we're here, just return the first dockpoint
|
||||
return model_find_dock_index(Ship_info[shipp->ship_info_index].model_num, dock_type);
|
||||
}
|
||||
|
||||
// function to fix up dock point references for objects.
|
||||
// passed are the pointer to goal we are working with. aip is the ai_info pointer
|
||||
// passed are the pointer to goal we are working with. aip if the ai_info pointer
|
||||
// of the ship with the order. aigp is a pointer to the goal (of aip) of which we are
|
||||
// fixing up the docking points
|
||||
void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
|
||||
@@ -542,7 +561,6 @@ void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
|
||||
|
||||
Assert ( aip->shipnum != -1 );
|
||||
shipnum = ship_name_lookup( aigp->target_name );
|
||||
Assertion ( shipnum != -1, "Couldn't find ai goal's target_name (%s); get a coder!\n", aigp->target_name );
|
||||
docker_index = -1;
|
||||
dockee_index = -1;
|
||||
|
||||
@@ -985,16 +1003,6 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
aigp->priority = MAX_GOAL_PRIORITY;
|
||||
}
|
||||
|
||||
// Goober5000 - we now have an extra optional chase argument to allow chasing our own team
|
||||
if ( op == OP_AI_CHASE || op == OP_AI_CHASE_WING || op == OP_AI_DISABLE_SHIP || op == OP_AI_DISARM_SHIP ) {
|
||||
if ((CDDDR(node) != -1) && is_sexp_true(CDDDR(node)))
|
||||
aigp->flags |= AIGF_TARGET_OWN_TEAM;
|
||||
}
|
||||
if ( op == OP_AI_DESTROY_SUBSYS ) {
|
||||
if ((CDDDDR(node) != -1) && is_sexp_true(CDDDDR(node)))
|
||||
aigp->flags |= AIGF_TARGET_OWN_TEAM;
|
||||
}
|
||||
|
||||
// Goober5000 - since none of the goals act on the actor,
|
||||
// don't assign the goal if the actor's goal target is itself
|
||||
if (aigp->target_name != NULL && !strcmp(aigp->target_name, actor_name))
|
||||
@@ -1390,17 +1398,13 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
if (!(shipp->flags2 & SF2_NO_SUBSPACE_DRIVE))
|
||||
return AI_GOAL_ACHIEVABLE;
|
||||
|
||||
// if no subspace drive, only valid if our mothership is present
|
||||
// if no subspace drive, only valid if there's somewhere to depart to
|
||||
|
||||
// check that we have a mothership and that we can depart to it
|
||||
if (shipp->departure_location == DEPART_AT_DOCK_BAY)
|
||||
{
|
||||
int anchor_shipnum = ship_name_lookup(Parse_names[shipp->departure_anchor]);
|
||||
if (anchor_shipnum >= 0 && ship_useful_for_departure(anchor_shipnum, shipp->departure_path_mask))
|
||||
return AI_GOAL_ACHIEVABLE;
|
||||
}
|
||||
|
||||
return AI_GOAL_NOT_KNOWN;
|
||||
// locate a capital ship on the same team:
|
||||
if (ship_get_ship_with_dock_bay(shipp->team) >= 0)
|
||||
return AI_GOAL_ACHIEVABLE;
|
||||
else
|
||||
return AI_GOAL_NOT_KNOWN;
|
||||
}
|
||||
|
||||
|
||||
@@ -1466,13 +1470,8 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// for this goal to be valid).
|
||||
Assert ( aigp->ai_submode >= 0 );
|
||||
ssp = ship_get_indexed_subsys( &Ships[sindex], aigp->ai_submode );
|
||||
if (ssp != NULL) {
|
||||
status = mission_log_get_time( LOG_SHIP_SUBSYS_DESTROYED, aigp->target_name, ssp->system_info->subobj_name, NULL );
|
||||
} else {
|
||||
// not supposed to ever happen, but could if there is a mismatch between the table and model subsystems
|
||||
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, Ships[sindex].ship_name));
|
||||
status = 0;
|
||||
}
|
||||
status = mission_log_get_time( LOG_SHIP_SUBSYS_DESTROYED, aigp->target_name, ssp->system_info->subobj_name, NULL );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1499,17 +1498,13 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// checking departure and destroyed. In multiplayer, since ships can respawn,
|
||||
// they get log entries for being destroyed even though they have respawned.
|
||||
sindex = ship_name_lookup( aigp->target_name );
|
||||
if ( sindex < 0 ) {
|
||||
if ( sindex == -1 ) {
|
||||
status = mission_log_get_time( LOG_SHIP_DEPARTED, aigp->target_name, NULL, NULL);
|
||||
if ( !status ) {
|
||||
status = mission_log_get_time( LOG_SHIP_DESTROYED, aigp->target_name, NULL, NULL);
|
||||
if ( !status ) {
|
||||
status = mission_log_get_time( LOG_SELF_DESTRUCTED, aigp->target_name, NULL, NULL);
|
||||
}
|
||||
if ( status )
|
||||
return_val = AI_GOAL_NOT_ACHIEVABLE;
|
||||
}
|
||||
|
||||
if ( status )
|
||||
return_val = AI_GOAL_NOT_ACHIEVABLE;
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
@@ -1888,8 +1883,9 @@ int ai_goal_priority_compare(const void *a, const void *b)
|
||||
// Prioritize goal list.
|
||||
// First sort on priority.
|
||||
// Then sort on time for goals of equivalent priority.
|
||||
// objnum The object number to act upon. Redundant with *aip.
|
||||
// *aip The AI info to act upon. Goals are stored at aip->goals
|
||||
void prioritize_goals(ai_info *aip)
|
||||
void prioritize_goals(int objnum, ai_info *aip)
|
||||
{
|
||||
// First sort based on priority field.
|
||||
insertion_sort(aip->goals, MAX_AI_GOALS, sizeof(ai_goal), ai_goal_priority_compare);
|
||||
@@ -2005,7 +2001,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
validate_mission_goals(objnum, aip);
|
||||
|
||||
// Sort the goal array by priority and other factors.
|
||||
prioritize_goals(aip);
|
||||
prioritize_goals(objnum, aip);
|
||||
|
||||
// Make sure there's a goal to pursue, else return.
|
||||
if (aip->goals[0].signature == -1) {
|
||||
@@ -2219,7 +2215,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
break;
|
||||
|
||||
case AI_GOAL_WARP: {
|
||||
mission_do_departure( objp, true );
|
||||
mission_do_departure( objp );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2292,7 +2288,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
|
||||
}
|
||||
|
||||
void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, const char *new_name)
|
||||
void ai_update_goal_references(ai_goal *goals, int type, char *old_name, char *new_name)
|
||||
{
|
||||
int i, mode, flag, dummy;
|
||||
|
||||
@@ -2359,7 +2355,7 @@ void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, c
|
||||
}
|
||||
}
|
||||
|
||||
int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name)
|
||||
int query_referenced_in_ai_goals(ai_goal *goals, int type, char *name)
|
||||
{
|
||||
int i, mode, flag;
|
||||
|
||||
@@ -2424,7 +2420,7 @@ int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *ai_add_dock_name(const char *str)
|
||||
char *ai_add_dock_name(char *str)
|
||||
{
|
||||
char *ptr;
|
||||
int i;
|
||||
|
||||
+5
-5
@@ -86,7 +86,7 @@ extern int Num_ai_goals;
|
||||
extern int Num_ai_dock_names;
|
||||
extern char Ai_dock_names[MAX_AI_DOCK_NAMES][NAME_LENGTH];
|
||||
|
||||
extern const char *Ai_goal_text(int goal);
|
||||
extern char *Ai_goal_text(int goal);
|
||||
|
||||
// extern function definitions
|
||||
extern void ai_post_process_mission();
|
||||
@@ -117,11 +117,11 @@ extern void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip );
|
||||
extern void ai_mission_goal_complete( ai_info *aip );
|
||||
extern void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp );
|
||||
|
||||
extern void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, const char *new_name);
|
||||
extern int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name);
|
||||
extern char *ai_add_dock_name(const char *str);
|
||||
extern void ai_update_goal_references(ai_goal *goals, int type, char *old_name, char *new_name);
|
||||
extern int query_referenced_in_ai_goals(ai_goal *goals, int type, char *name);
|
||||
extern char *ai_add_dock_name(char *str);
|
||||
|
||||
extern int ai_query_goal_valid( int ship, int ai_goal_type );
|
||||
extern int ai_query_goal_valid( int ship, int ai_goal );
|
||||
|
||||
extern void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate = 1 );
|
||||
extern void ai_add_goal_wing_internal( wing *wingp, int goal_type, char *name, int immediate = 1 );
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
#ifndef _AIINTERNAL_H
|
||||
#define _AIINTERNAL_H
|
||||
|
||||
#include "ship/ship.h"
|
||||
#include "weapon/weapon.h"
|
||||
|
||||
//Returns true if the specified object is a stealth ship, false if not
|
||||
bool is_object_stealth_ship(object* objp);
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AILOCAL_H
|
||||
#define _AILOCAL_H
|
||||
|
||||
// -- Don't put anything in here --
|
||||
// Put it in ai.h!
|
||||
|
||||
#endif
|
||||
+155
-520
File diff suppressed because it is too large.
Load diff
+18
-22
@@ -10,15 +10,15 @@
|
||||
|
||||
|
||||
#include "anim/animplay.h"
|
||||
#include "anim/packunpack.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "io/timer.h"
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "render/3d.h"
|
||||
#include "pcxutils/pcxutils.h"
|
||||
#include "anim/packunpack.h"
|
||||
#include "cfile/cfile.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "io/timer.h"
|
||||
#include "pcxutils/pcxutils.h"
|
||||
#include "render/3d.h"
|
||||
|
||||
|
||||
|
||||
@@ -196,8 +196,8 @@ anim_instance *anim_play(anim_play_struct *aps)
|
||||
}
|
||||
|
||||
if(aps->base_w < 0 || aps->base_h < 0) {
|
||||
instance->base_w = gr_screen.max_w_unscaled_zoomed;
|
||||
instance->base_h = gr_screen.max_h_unscaled_zoomed;
|
||||
instance->base_w = gr_screen.max_w_unscaled;
|
||||
instance->base_h = gr_screen.max_h_unscaled;
|
||||
} else {
|
||||
instance->base_w = aps->base_w;
|
||||
instance->base_h = aps->base_h;
|
||||
@@ -254,7 +254,7 @@ anim_instance *anim_play(anim_play_struct *aps)
|
||||
int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
{
|
||||
int bitmap_id, bitmap_flags=0, new_frame_num, frame_diff=0, i, n_frames=0,frame_save;
|
||||
float percent_through, time;
|
||||
float percent_through, decompress_time, render_time, time;
|
||||
vertex image_vertex;
|
||||
int aabitmap = 0;
|
||||
int bpp = 16;
|
||||
@@ -461,6 +461,8 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
instance->file_offset = instance->parent->file_offset;
|
||||
instance->loop_count++;
|
||||
}
|
||||
|
||||
decompress_time = f2fl(t2-t1);
|
||||
|
||||
t1 = timer_get_fixed_seconds();
|
||||
if ( frame_diff == 0 && instance->last_bitmap != -1 ) {
|
||||
@@ -470,7 +472,7 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
if ( instance->last_bitmap != -1 ){
|
||||
bm_release(instance->last_bitmap);
|
||||
}
|
||||
bitmap_id = bm_create(bpp, instance->parent->width, instance->parent->height, instance->frame, bitmap_flags);
|
||||
bitmap_id = bm_create(16, instance->parent->width, instance->parent->height, instance->frame, bitmap_flags);
|
||||
}
|
||||
|
||||
if ( bitmap_id == -1 ) {
|
||||
@@ -486,20 +488,16 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
|
||||
// determine x,y to display the bitmap at
|
||||
if ( instance->world_pos == NULL ) {
|
||||
int old_max_w_unscaled = gr_screen.max_w_unscaled;
|
||||
int old_max_h_unscaled = gr_screen.max_h_unscaled;
|
||||
int old_max_w_unscaled_zoomed = gr_screen.max_w_unscaled_zoomed;
|
||||
int old_max_h_unscaled_zoomed = gr_screen.max_h_unscaled_zoomed;
|
||||
gr_set_screen_scale(instance->base_w, instance->base_h);
|
||||
gr_set_clip(0, 0, instance->base_w, instance->base_h, GR_RESIZE_MENU);
|
||||
gr_set_clip(0, 0, instance->base_w, instance->base_h, false);
|
||||
if ( instance->aa_color == NULL ) {
|
||||
gr_bitmap(instance->x, instance->y, GR_RESIZE_MENU_NO_OFFSET);
|
||||
gr_bitmap(instance->x, instance->y);
|
||||
}
|
||||
else {
|
||||
gr_set_color_fast( (color*)instance->aa_color );
|
||||
gr_aabitmap(instance->x, instance->y, GR_RESIZE_MENU_NO_OFFSET);
|
||||
gr_aabitmap(instance->x, instance->y);
|
||||
}
|
||||
gr_set_screen_scale(old_max_w_unscaled, old_max_h_unscaled, old_max_w_unscaled_zoomed, old_max_h_unscaled_zoomed);
|
||||
gr_reset_screen_scale();
|
||||
gr_reset_clip();
|
||||
}
|
||||
else {
|
||||
@@ -512,6 +510,7 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
}
|
||||
|
||||
t2 = timer_get_fixed_seconds();
|
||||
render_time = f2fl(t2-t1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -969,9 +968,6 @@ void anim_display_info(char *real_filename)
|
||||
// read the keyframe frame nums and offsets
|
||||
key_frame_nums = (int*)vm_malloc(sizeof(int)*A.num_keys);
|
||||
Assert(key_frame_nums != NULL);
|
||||
if (key_frame_nums == NULL)
|
||||
return;
|
||||
|
||||
for ( i = 0; i < A.num_keys; i++ ) {
|
||||
key_frame_nums[i] = 0;
|
||||
cfread(&key_frame_nums[i], 2, 1, fp);
|
||||
@@ -1004,7 +1000,7 @@ void anim_display_info(char *real_filename)
|
||||
printf("FPS: %d\n", A.fps);
|
||||
|
||||
#ifndef NDEBUG
|
||||
printf("Transparent RGB: (%u,%u,%u)\n", A.xparent_r, A.xparent_g, A.xparent_b);
|
||||
printf("Transparent RGB: (%d,%d,%d)\n", A.xparent_r, A.xparent_g, A.xparent_b);
|
||||
#endif
|
||||
|
||||
printf("ac version: %d\n", A.version);
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#ifndef __ANIMPLAY_H__
|
||||
#define __ANIMPLAY_H__
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "cfile/cfile.h"
|
||||
|
||||
struct anim;
|
||||
struct anim_info;
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
|
||||
|
||||
|
||||
#include "anim/animplay.h"
|
||||
#include "anim/packunpack.h"
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "anim/animplay.h"
|
||||
|
||||
|
||||
const int packer_code = PACKER_CODE;
|
||||
@@ -301,6 +301,7 @@ int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_
|
||||
|
||||
Assert(packed_size == (save-dest_start) );
|
||||
return packed_size;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -466,6 +467,7 @@ int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, in
|
||||
|
||||
Assert(packed_size == (save-dest_start) );
|
||||
return packed_size;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
+221
-302
@@ -10,39 +10,37 @@
|
||||
|
||||
|
||||
#include "asteroid/asteroid.h"
|
||||
#include "debugconsole/console.h"
|
||||
#include "fireball/fireballs.h"
|
||||
#include "object/object.h"
|
||||
#include "object/objcollide.h"
|
||||
#include "freespace2/freespace.h"
|
||||
#include "io/timer.h"
|
||||
#include "render/3d.h"
|
||||
#include "fireball/fireballs.h"
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "globalincs/compatibility.h"
|
||||
#include "particle/particle.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
#include "hud/hud.h"
|
||||
#include "hud/hudescort.h"
|
||||
#include "hud/hudgauges.h"
|
||||
#include "hud/hudtarget.h"
|
||||
#include "iff_defs/iff_defs.h"
|
||||
#include "io/timer.h"
|
||||
#include "localization/localize.h"
|
||||
#include "ship/shiphit.h"
|
||||
#include "math/staticrand.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
#include "localization/localize.h"
|
||||
#include "stats/scoring.h"
|
||||
#include "hud/hudtarget.h"
|
||||
#include "weapon/weapon.h"
|
||||
#include "ship/ship.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "math/vecmat.h"
|
||||
#include "model/model.h"
|
||||
#include "network/multi.h"
|
||||
#include "network/multimsgs.h"
|
||||
#include "network/multiutil.h"
|
||||
#include "object/objcollide.h"
|
||||
#include "object/object.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "parse/scripting.h"
|
||||
#include "particle/particle.h"
|
||||
#include "render/3d.h"
|
||||
#include "ship/ship.h"
|
||||
#include "ship/shiphit.h"
|
||||
#include "species_defs/species_defs.h"
|
||||
#include "stats/scoring.h"
|
||||
#include "weapon/weapon.h"
|
||||
|
||||
#include "iff_defs/iff_defs.h"
|
||||
#include "network/multiutil.h"
|
||||
#include "network/multimsgs.h"
|
||||
#include "network/multi.h"
|
||||
#include "parse/scripting.h"
|
||||
#include <algorithm>
|
||||
#include "globalincs/compatibility.h"
|
||||
|
||||
#define ASTEROID_OBJ_USED (1<<0) // flag used in asteroid_obj struct
|
||||
#define MAX_ASTEROID_OBJS MAX_ASTEROIDS // max number of asteroids tracked in asteroid list
|
||||
@@ -66,9 +64,6 @@ asteroid_field Asteroid_field;
|
||||
|
||||
static int Asteroid_impact_explosion_ani;
|
||||
static float Asteroid_impact_explosion_radius;
|
||||
char Asteroid_icon_closeup_model[NAME_LENGTH];
|
||||
vec3d Asteroid_icon_closeup_position;
|
||||
float Asteroid_icon_closeup_zoom;
|
||||
|
||||
#define ASTEROID_CHECK_WRAP_TIMESTAMP 2000 // how often an asteroid gets checked for wrapping
|
||||
#define ASTEROID_UPDATE_COLLIDE_TIMESTAMP 2000 // how often asteroid is checked for impending collisions with escort ships
|
||||
@@ -329,11 +324,6 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
|
||||
}
|
||||
|
||||
asp->objnum = objnum;
|
||||
asp->model_instance_num = -1;
|
||||
|
||||
if (model_get(asip->model_num[asteroid_subtype])->flags & PM_FLAG_HAS_INTRINSIC_ROTATE) {
|
||||
asp->model_instance_num = model_create_instance(false, asip->model_num[asteroid_subtype]);
|
||||
}
|
||||
|
||||
// Add to Asteroid_used_list
|
||||
asteroid_obj_list_add(objnum);
|
||||
@@ -445,7 +435,6 @@ void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec)
|
||||
*/
|
||||
void asteroid_load(int asteroid_info_index, int asteroid_subtype)
|
||||
{
|
||||
int i;
|
||||
asteroid_info *asip;
|
||||
|
||||
Assert( asteroid_info_index < (int)Asteroid_info.size() );
|
||||
@@ -462,25 +451,13 @@ void asteroid_load(int asteroid_info_index, int asteroid_subtype)
|
||||
|
||||
asip->model_num[asteroid_subtype] = model_load( asip->pof_files[asteroid_subtype], 0, NULL );
|
||||
|
||||
if (asip->model_num[asteroid_subtype] >= 0)
|
||||
{
|
||||
polymodel *pm = asip->modelp[asteroid_subtype] = model_get(asip->model_num[asteroid_subtype]);
|
||||
if (asip->model_num[asteroid_subtype] > -1) {
|
||||
asip->modelp[asteroid_subtype] = model_get(asip->model_num[asteroid_subtype]);
|
||||
|
||||
if ( asip->num_detail_levels != pm->n_detail_levels )
|
||||
{
|
||||
if ( !Is_standalone )
|
||||
{
|
||||
// just log to file for standalone servers
|
||||
Warning(LOCATION, "For asteroid '%s', detail level\nmismatch (POF needs %d)", asip->name, pm->n_detail_levels );
|
||||
}
|
||||
else
|
||||
{
|
||||
nprintf(("Warning", "For asteroid '%s', detail level mismatch (POF needs %d)", asip->name, pm->n_detail_levels));
|
||||
}
|
||||
}
|
||||
// Stuff detail level distances.
|
||||
for ( i=0; i<pm->n_detail_levels; i++ )
|
||||
pm->detail_depth[i] = (i < asip->num_detail_levels) ? i2fl(asip->detail_distance[i]) : 0.0f;
|
||||
for (int i = 0; i < asip->num_detail_levels; i++) {
|
||||
asip->modelp[asteroid_subtype]->detail_depth[i] = i2fl(asip->detail_distance[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -833,12 +810,10 @@ void asteroid_delete( object * obj )
|
||||
|
||||
asp = &Asteroids[num];
|
||||
|
||||
if (asp->model_instance_num >= 0)
|
||||
model_delete_instance(asp->model_instance_num);
|
||||
Assert( Num_asteroids >= 0 );
|
||||
|
||||
asp->flags = 0;
|
||||
Num_asteroids--;
|
||||
Assert(Num_asteroids >= 0);
|
||||
|
||||
asteroid_obj_list_remove( obj );
|
||||
}
|
||||
@@ -868,7 +843,7 @@ void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
|
||||
dist = vm_vec_normalized_dir(&vec_to_asteroid, &objp->pos, &Eye_position);
|
||||
dot = vm_vec_dot(&Eye_matrix.vec.fvec, &vec_to_asteroid);
|
||||
|
||||
if ( (dot < 0.7f) || (dist > asfieldp->bound_rad) ) {
|
||||
if ((dot < 0.7f) || (dist > 3000.0f)) {
|
||||
if (Num_asteroids > MAX_ASTEROIDS-10) {
|
||||
objp->flags |= OF_SHOULD_BE_DEAD;
|
||||
} else {
|
||||
@@ -876,11 +851,12 @@ void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
|
||||
asteroid_wrap_pos(objp, asfieldp);
|
||||
Asteroids[objp->instance].target_objnum = -1;
|
||||
|
||||
dist = vm_vec_normalized_dir(&vec_to_asteroid, &objp->pos, &Eye_position);
|
||||
vm_vec_normalized_dir(&vec_to_asteroid, &objp->pos, &Eye_position);
|
||||
dot = vm_vec_dot(&Eye_matrix.vec.fvec, &vec_to_asteroid);
|
||||
dist = vm_vec_dist_quick(&objp->pos, &Eye_position);
|
||||
|
||||
if ( (dot > 0.7f) && (dist < (asfieldp->bound_rad * 1.3f)) ) {
|
||||
// player would see asteroid pop out other side, so reverse velocity instead of wrapping
|
||||
if (( dot > 0.7f) && (dist < 3000.0f)) {
|
||||
// player would see asteroid pop out other side, so reverse velocity instead of wrapping
|
||||
objp->pos = old_asteroid_pos;
|
||||
vm_vec_copy_scale(&objp->phys_info.vel, &old_vel, -1.0f);
|
||||
objp->phys_info.desired_vel = objp->phys_info.vel;
|
||||
@@ -905,7 +881,7 @@ void lerp(float *goal, float f1, float f2, float scale)
|
||||
*goal = (f2 - f1) * scale + f1;
|
||||
}
|
||||
|
||||
void asteroid_process_pre( object *objp )
|
||||
void asteroid_process_pre( object *objp, float frame_time)
|
||||
{
|
||||
if (Asteroids_enabled) {
|
||||
// Make vel chase desired_vel
|
||||
@@ -922,7 +898,6 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
}
|
||||
|
||||
mc_info mc;
|
||||
mc_info_init(&mc);
|
||||
int num, asteroid_subtype;
|
||||
|
||||
Assert( pasteroid->type == OBJ_ASTEROID );
|
||||
@@ -937,7 +912,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
if ( asteroid_hit_info == NULL ) {
|
||||
// asteroid weapon collision
|
||||
Assert( other_obj->type == OBJ_WEAPON );
|
||||
mc.model_instance_num = Asteroids[num].model_instance_num;
|
||||
mc.model_instance_num = -1;
|
||||
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].model_num[asteroid_subtype]; // Fill in the model to check
|
||||
model_clear_instance( mc.model_num );
|
||||
mc.orient = &pasteroid->orient; // The object's orient
|
||||
@@ -953,18 +928,18 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
}
|
||||
|
||||
// asteroid ship collision -- use asteroid_hit_info to calculate physics
|
||||
object *pship_obj = other_obj;
|
||||
Assert( pship_obj->type == OBJ_SHIP );
|
||||
object *ship_obj = other_obj;
|
||||
Assert( ship_obj->type == OBJ_SHIP );
|
||||
|
||||
object* heavy = asteroid_hit_info->heavy;
|
||||
object* lighter = asteroid_hit_info->light;
|
||||
object* light = asteroid_hit_info->light;
|
||||
object *heavy_obj = heavy;
|
||||
object *light_obj = lighter;
|
||||
object *light_obj = light;
|
||||
|
||||
vec3d zero, p0, p1;
|
||||
vm_vec_zero( &zero );
|
||||
vm_vec_sub( &p0, &lighter->last_pos, &heavy->last_pos );
|
||||
vm_vec_sub( &p1, &lighter->pos, &heavy->pos );
|
||||
vm_vec_sub( &p0, &light->last_pos, &heavy->last_pos );
|
||||
vm_vec_sub( &p1, &light->pos, &heavy->pos );
|
||||
|
||||
mc.pos = &zero; // The object's position
|
||||
mc.p0 = &p0; // Point 1 of ray to check
|
||||
@@ -986,19 +961,19 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
// HACK - this applies to big ships warping in/out of asteroid fields - not sure what it does
|
||||
if (vm_vec_mag(&asteroid_hit_info->light_rel_vel) > 300) {
|
||||
asteroid_hit_info->collide_rotate = 0;
|
||||
vm_vec_sub( &asteroid_hit_info->light_rel_vel, &lighter->phys_info.vel, &heavy->phys_info.vel );
|
||||
vm_vec_sub( &asteroid_hit_info->light_rel_vel, &light->phys_info.vel, &heavy->phys_info.vel );
|
||||
}
|
||||
} else {
|
||||
asteroid_hit_info->collide_rotate = 0;
|
||||
vm_vec_sub( &asteroid_hit_info->light_rel_vel, &lighter->phys_info.vel, &heavy->phys_info.vel );
|
||||
vm_vec_sub( &asteroid_hit_info->light_rel_vel, &light->phys_info.vel, &heavy->phys_info.vel );
|
||||
}
|
||||
|
||||
int mc_ret_val = 0;
|
||||
|
||||
if ( asteroid_hit_info->heavy == pship_obj ) { // ship is heavier, so asteroid is sphere. Check sphere collision against ship poly model
|
||||
mc.model_instance_num = Ships[pship_obj->instance].model_instance_num;
|
||||
mc.model_num = Ship_info[Ships[pship_obj->instance].ship_info_index].model_num; // Fill in the model to check
|
||||
mc.orient = &pship_obj->orient; // The object's orient
|
||||
if ( asteroid_hit_info->heavy == ship_obj ) { // ship is heavier, so asteroid is sphere. Check sphere collision against ship poly model
|
||||
mc.model_instance_num = Ships[ship_obj->instance].model_instance_num;
|
||||
mc.model_num = Ship_info[Ships[ship_obj->instance].ship_info_index].model_num; // Fill in the model to check
|
||||
mc.orient = &ship_obj->orient; // The object's orient
|
||||
mc.radius = pasteroid->radius;
|
||||
mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
|
||||
|
||||
@@ -1012,6 +987,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
|
||||
|
||||
SCP_vector<int> submodel_vector;
|
||||
polymodel *pm;
|
||||
polymodel_instance *pmi;
|
||||
|
||||
if (model_collide(&mc)) {
|
||||
@@ -1025,7 +1001,8 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
model_get_rotating_submodel_list(&submodel_vector, heavy_obj);
|
||||
|
||||
// Get polymodel and turn off all rotating submodels, collide against only 1 at a time.
|
||||
pmi = model_get_instance(Ships[heavy_obj->instance].model_instance_num);
|
||||
pm = model_get(Ship_info[Ships[heavy_obj->instance].ship_info_index].model_num);
|
||||
pmi = model_get_instance(Ships[ship_obj->instance].model_instance_num);
|
||||
|
||||
// turn off all rotating submodels and test for collision
|
||||
for (size_t j=0; j<submodel_vector.size(); j++) {
|
||||
@@ -1046,10 +1023,10 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
|
||||
// find the start and end positions of the sphere in submodel RF
|
||||
pmi->submodel[submodel_vector[i]].angs = pmi->submodel[submodel_vector[i]].prev_angs;
|
||||
world_find_model_instance_point(&p0, &light_obj->last_pos, pmi, submodel_vector[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
|
||||
world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_vector[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
|
||||
|
||||
pmi->submodel[submodel_vector[i]].angs = copy_angles;
|
||||
world_find_model_instance_point(&p1, &light_obj->pos, pmi, submodel_vector[i], &heavy_obj->orient, &heavy_obj->pos);
|
||||
world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_vector[i], &heavy_obj->orient, &heavy_obj->pos);
|
||||
|
||||
mc.p0 = &p0;
|
||||
mc.p1 = &p1;
|
||||
@@ -1066,14 +1043,14 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
|
||||
// set up asteroid_hit_info for rotating submodel
|
||||
if (asteroid_hit_info->edge_hit == 0) {
|
||||
model_instance_find_obj_dir(&asteroid_hit_info->collision_normal, &mc.hit_normal, Ships[heavy_obj->instance].model_instance_num, mc.hit_submodel, &heavy_obj->orient);
|
||||
model_instance_find_obj_dir(&asteroid_hit_info->collision_normal, &mc.hit_normal, heavy_obj, mc.hit_submodel);
|
||||
}
|
||||
|
||||
// find position in submodel RF of light object at collison
|
||||
vec3d int_light_pos, diff;
|
||||
vm_vec_sub(&diff, mc.p1, mc.p0);
|
||||
vm_vec_scale_add(&int_light_pos, mc.p0, &diff, mc.hit_dist);
|
||||
model_instance_find_world_point(&asteroid_hit_info->light_collision_cm_pos, &int_light_pos, mc.model_instance_num, mc.hit_submodel, &heavy_obj->orient, &zero);
|
||||
model_instance_find_world_point(&asteroid_hit_info->light_collision_cm_pos, &int_light_pos, mc.model_num, mc.model_instance_num, mc.hit_submodel, &heavy_obj->orient, &zero);
|
||||
}
|
||||
}
|
||||
// Don't look at this submodel again
|
||||
@@ -1098,7 +1075,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
|
||||
// get collision normal if not edge hit
|
||||
if (asteroid_hit_info->edge_hit == 0) {
|
||||
model_instance_find_obj_dir(&asteroid_hit_info->collision_normal, &mc.hit_normal, Ships[heavy_obj->instance].model_instance_num, mc.hit_submodel, &heavy_obj->orient);
|
||||
model_instance_find_obj_dir(&asteroid_hit_info->collision_normal, &mc.hit_normal, heavy_obj, mc.hit_submodel);
|
||||
}
|
||||
|
||||
// find position in submodel RF of light object at collison
|
||||
@@ -1112,11 +1089,11 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
|
||||
} else {
|
||||
// Asteroid is heavier obj
|
||||
mc.model_instance_num = Asteroids[num].model_instance_num;
|
||||
mc.model_instance_num = -1;
|
||||
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].model_num[asteroid_subtype]; // Fill in the model to check
|
||||
model_clear_instance( mc.model_num );
|
||||
mc.orient = &pasteroid->orient; // The object's orient
|
||||
mc.radius = model_get_core_radius(Ship_info[Ships[pship_obj->instance].ship_info_index].model_num);
|
||||
mc.radius = model_get_core_radius(Ship_info[Ships[ship_obj->instance].ship_info_index].model_num);
|
||||
|
||||
// check for collision between asteroid model and ship sphere
|
||||
mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
|
||||
@@ -1167,12 +1144,14 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
}
|
||||
}
|
||||
|
||||
void asteroid_render(object * obj, draw_list *scene)
|
||||
void asteroid_render(object * obj)
|
||||
{
|
||||
if (Asteroids_enabled) {
|
||||
int num;
|
||||
polymodel *pm;
|
||||
asteroid *asp;
|
||||
|
||||
|
||||
pm = NULL;
|
||||
num = obj->instance;
|
||||
|
||||
Assert((num >= 0) && (num < MAX_ASTEROIDS));
|
||||
@@ -1181,13 +1160,7 @@ void asteroid_render(object * obj, draw_list *scene)
|
||||
Assert( asp->flags & AF_USED );
|
||||
|
||||
model_clear_instance( Asteroid_info[asp->asteroid_type].model_num[asp->asteroid_subtype]);
|
||||
|
||||
model_render_params render_info;
|
||||
|
||||
render_info.set_object_number( OBJ_INDEX(obj) );
|
||||
render_info.set_flags(MR_IS_ASTEROID);
|
||||
|
||||
model_render_queue(&render_info, scene, Asteroid_info[asp->asteroid_type].model_num[asp->asteroid_subtype], &obj->orient, &obj->pos); // Replace MR_NORMAL with 0x07 for big yellow blobs
|
||||
model_render(Asteroid_info[asp->asteroid_type].model_num[asp->asteroid_subtype], &obj->orient, &obj->pos, MR_NORMAL|MR_IS_ASTEROID, OBJ_INDEX(obj) ); // Replace MR_NORMAL with 0x07 for big yellow blobs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1341,42 +1314,42 @@ void asteroid_do_area_effect(object *asteroid_objp)
|
||||
/**
|
||||
* Upon asteroid asteroid_obj being hit. Apply damage and maybe make it break into smaller asteroids.
|
||||
*
|
||||
* @param pasteroid_obj pointer to asteroid object getting hit
|
||||
* @param asteroid_obj pointer to asteroid object getting hit
|
||||
* @param other_obj object that hit asteroid, can be NULL if asteroid hit by area effect
|
||||
* @param hitpos world position asteroid was hit, can be NULL if hit by area effect
|
||||
* @param damage amount of damage to apply to asteroid
|
||||
*/
|
||||
void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, float damage )
|
||||
void asteroid_hit( object * asteroid_obj, object * other_obj, vec3d * hitpos, float damage )
|
||||
{
|
||||
float explosion_life;
|
||||
asteroid *asp;
|
||||
|
||||
asp = &Asteroids[pasteroid_obj->instance];
|
||||
asp = &Asteroids[asteroid_obj->instance];
|
||||
|
||||
if (pasteroid_obj->flags & OF_SHOULD_BE_DEAD){
|
||||
if (asteroid_obj->flags & OF_SHOULD_BE_DEAD){
|
||||
return;
|
||||
}
|
||||
|
||||
if ( MULTIPLAYER_MASTER ){
|
||||
send_asteroid_hit( pasteroid_obj, other_obj, hitpos, damage );
|
||||
send_asteroid_hit( asteroid_obj, other_obj, hitpos, damage );
|
||||
}
|
||||
|
||||
pasteroid_obj->hull_strength -= damage;
|
||||
asteroid_obj->hull_strength -= damage;
|
||||
|
||||
if (pasteroid_obj->hull_strength < 0.0f) {
|
||||
if (asteroid_obj->hull_strength < 0.0f) {
|
||||
if ( asp->final_death_time <= 0 ) {
|
||||
int play_loud_collision = 0;
|
||||
|
||||
explosion_life = asteroid_create_explosion(pasteroid_obj);
|
||||
explosion_life = asteroid_create_explosion(asteroid_obj);
|
||||
|
||||
asteriod_explode_sound(pasteroid_obj, asp->asteroid_type, play_loud_collision);
|
||||
asteroid_do_area_effect(pasteroid_obj);
|
||||
asteriod_explode_sound(asteroid_obj, asp->asteroid_type, play_loud_collision);
|
||||
asteroid_do_area_effect(asteroid_obj);
|
||||
|
||||
asp->final_death_time = timestamp( fl2i(explosion_life*1000.0f)/5 ); // Wait till 30% of vclip time before breaking the asteroid up.
|
||||
if ( hitpos ) {
|
||||
asp->death_hit_pos = *hitpos;
|
||||
} else {
|
||||
asp->death_hit_pos = pasteroid_obj->pos;
|
||||
asp->death_hit_pos = asteroid_obj->pos;
|
||||
// randomize hit pos a bit, otherwise we will get a NULL vector when trying to find direction to toss child asteroids
|
||||
vec3d rand_vec;
|
||||
vm_vec_rand_vec_quick(&rand_vec);
|
||||
@@ -1395,7 +1368,7 @@ void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, f
|
||||
}
|
||||
|
||||
// evaluate any relevant player scoring implications
|
||||
scoring_eval_hit(pasteroid_obj,other_obj);
|
||||
scoring_eval_hit(asteroid_obj,other_obj);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1416,8 +1389,23 @@ void asteroid_level_close()
|
||||
Asteroid_field.num_initial_asteroids=0;
|
||||
}
|
||||
|
||||
DCF_BOOL2(asteroids, Asteroids_enabled, "enables or disables asteroids", "Usage: asteroids [bool]\nTurns asteroid system on/off. If nothing passed, then toggles it.\n");
|
||||
|
||||
DCF(asteroids,"Turns asteroids on/off")
|
||||
{
|
||||
if ( Dc_command ) {
|
||||
dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
|
||||
if ( Dc_arg_type & ARG_TRUE )
|
||||
Asteroids_enabled = 1;
|
||||
else if ( Dc_arg_type & ARG_FALSE )
|
||||
Asteroids_enabled = 0;
|
||||
else if ( Dc_arg_type & ARG_NONE )
|
||||
Asteroids_enabled ^= 1;
|
||||
}
|
||||
if ( Dc_help )
|
||||
dc_printf( "Usage: asteroids [bool]\nTurns asteroid system on/off. If nothing passed, then toggles it.\n" );
|
||||
|
||||
if ( Dc_status )
|
||||
dc_printf( "asteroids are %s\n", (Asteroids_enabled?"ON":"OFF") );
|
||||
}
|
||||
|
||||
void hud_target_asteroid()
|
||||
{
|
||||
@@ -1460,21 +1448,21 @@ int asteroid_count()
|
||||
* See if asteroid should split up.
|
||||
* We delay splitting up to allow the explosion animation to play for a bit.
|
||||
*/
|
||||
void asteroid_maybe_break_up(object *pasteroid_obj)
|
||||
void asteroid_maybe_break_up(object *asteroid_obj)
|
||||
{
|
||||
asteroid *asp;
|
||||
asteroid_info *asip;
|
||||
|
||||
asp = &Asteroids[pasteroid_obj->instance];
|
||||
asp = &Asteroids[asteroid_obj->instance];
|
||||
asip = &Asteroid_info[asp->asteroid_type];
|
||||
|
||||
if ( timestamp_elapsed(asp->final_death_time) ) {
|
||||
vec3d relvec, vfh, tvec;
|
||||
|
||||
Script_system.SetHookObject("Self", pasteroid_obj);
|
||||
if(!Script_system.IsConditionOverride(CHA_DEATH, pasteroid_obj))
|
||||
Script_system.SetHookObject("Self", asteroid_obj);
|
||||
if(!Script_system.IsConditionOverride(CHA_DEATH, asteroid_obj))
|
||||
{
|
||||
pasteroid_obj->flags |= OF_SHOULD_BE_DEAD;
|
||||
asteroid_obj->flags |= OF_SHOULD_BE_DEAD;
|
||||
|
||||
// multiplayer clients won't go through the following code. asteroid_sub_create will send
|
||||
// a create packet to the client in the above named function
|
||||
@@ -1485,29 +1473,29 @@ void asteroid_maybe_break_up(object *pasteroid_obj)
|
||||
case ASTEROID_TYPE_SMALL:
|
||||
break;
|
||||
case ASTEROID_TYPE_MEDIUM:
|
||||
asc_get_relvec(&relvec, pasteroid_obj, &asp->death_hit_pos);
|
||||
asteroid_sub_create(pasteroid_obj, ASTEROID_TYPE_SMALL, &relvec);
|
||||
asc_get_relvec(&relvec, asteroid_obj, &asp->death_hit_pos);
|
||||
asteroid_sub_create(asteroid_obj, ASTEROID_TYPE_SMALL, &relvec);
|
||||
|
||||
vm_vec_normalized_dir(&vfh, &pasteroid_obj->pos, &asp->death_hit_pos);
|
||||
vm_vec_normalized_dir(&vfh, &asteroid_obj->pos, &asp->death_hit_pos);
|
||||
vm_vec_copy_scale(&tvec, &vfh, 2.0f);
|
||||
vm_vec_sub2(&tvec, &relvec);
|
||||
asteroid_sub_create(pasteroid_obj, ASTEROID_TYPE_SMALL, &tvec);
|
||||
asteroid_sub_create(asteroid_obj, ASTEROID_TYPE_SMALL, &tvec);
|
||||
|
||||
break;
|
||||
case ASTEROID_TYPE_LARGE:
|
||||
asc_get_relvec(&relvec, pasteroid_obj, &asp->death_hit_pos);
|
||||
asteroid_sub_create(pasteroid_obj, ASTEROID_TYPE_MEDIUM, &relvec);
|
||||
asc_get_relvec(&relvec, asteroid_obj, &asp->death_hit_pos);
|
||||
asteroid_sub_create(asteroid_obj, ASTEROID_TYPE_MEDIUM, &relvec);
|
||||
|
||||
vm_vec_normalized_dir(&vfh, &pasteroid_obj->pos, &asp->death_hit_pos);
|
||||
vm_vec_normalized_dir(&vfh, &asteroid_obj->pos, &asp->death_hit_pos);
|
||||
vm_vec_copy_scale(&tvec, &vfh, 2.0f);
|
||||
vm_vec_sub2(&tvec, &relvec);
|
||||
asteroid_sub_create(pasteroid_obj, ASTEROID_TYPE_MEDIUM, &tvec);
|
||||
asteroid_sub_create(asteroid_obj, ASTEROID_TYPE_MEDIUM, &tvec);
|
||||
|
||||
while (frand() > 0.6f) {
|
||||
vec3d rvec, tvec2;
|
||||
vm_vec_rand_vec_quick(&rvec);
|
||||
vm_vec_scale_add(&tvec2, &vfh, &rvec, 0.75f);
|
||||
asteroid_sub_create(pasteroid_obj, ASTEROID_TYPE_SMALL, &tvec2);
|
||||
asteroid_sub_create(asteroid_obj, ASTEROID_TYPE_SMALL, &tvec2);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1547,8 +1535,8 @@ void asteroid_maybe_break_up(object *pasteroid_obj)
|
||||
float r = sqrt(1.0f - y*y);
|
||||
float phi = i * inc;
|
||||
|
||||
dir_vec.xyz.x = cosf(phi)*r;
|
||||
dir_vec.xyz.y = sinf(phi)*r;
|
||||
dir_vec.xyz.x = cos(phi)*r;
|
||||
dir_vec.xyz.y = sin(phi)*r;
|
||||
dir_vec.xyz.z = y;
|
||||
|
||||
// Randomize the direction a bit
|
||||
@@ -1556,24 +1544,24 @@ void asteroid_maybe_break_up(object *pasteroid_obj)
|
||||
vm_vec_random_cone(&dir_vec, &tempv, (360.0f / total_roids / 2));
|
||||
|
||||
// Make the roid inherit half of the parent's velocity
|
||||
vm_vec_copy_normalize(&parent_vel, &pasteroid_obj->phys_info.vel);
|
||||
vm_vec_copy_normalize(&parent_vel, &asteroid_obj->phys_info.vel);
|
||||
vm_vec_scale(&parent_vel, 0.5f);
|
||||
|
||||
// Make the hit position affect the direction, but only a little
|
||||
vm_vec_sub(&hit_rel_vec, &pasteroid_obj->pos, &asp->death_hit_pos);
|
||||
vm_vec_sub(&hit_rel_vec, &asteroid_obj->pos, &asp->death_hit_pos);
|
||||
vm_vec_normalize(&hit_rel_vec);
|
||||
vm_vec_scale(&hit_rel_vec, 0.25f);
|
||||
|
||||
vm_vec_avg3(&final_vec, &parent_vel, &hit_rel_vec, &dir_vec);
|
||||
vm_vec_normalize(&final_vec);
|
||||
|
||||
asteroid_sub_create(pasteroid_obj, roids_to_create[i], &final_vec);
|
||||
asteroid_sub_create(asteroid_obj, roids_to_create[i], &final_vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
asp->final_death_time = timestamp(-1);
|
||||
}
|
||||
Script_system.RunCondition(CHA_DEATH, '\0', NULL, pasteroid_obj);
|
||||
Script_system.RunCondition(CHA_DEATH, '\0', NULL, asteroid_obj);
|
||||
Script_system.RemHookVar("Self");
|
||||
}
|
||||
}
|
||||
@@ -1597,36 +1585,36 @@ int asteroid_get_random_in_cone(vec3d *pos, vec3d *dir, float ang, int danger)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_info *mc, bool lazy = false)
|
||||
void asteroid_test_collide(object *asteroid_obj, object *ship_obj, mc_info *mc, bool lazy = false)
|
||||
{
|
||||
float asteroid_ray_dist;
|
||||
vec3d asteroid_fvec, terminus;
|
||||
|
||||
// See if ray from asteroid intersects bounding box of escort ship
|
||||
asteroid_ray_dist = vm_vec_mag_quick(&pasteroid_obj->phys_info.desired_vel) * ASTEROID_MIN_COLLIDE_TIME;
|
||||
asteroid_fvec = pasteroid_obj->phys_info.desired_vel;
|
||||
asteroid_ray_dist = vm_vec_mag_quick(&asteroid_obj->phys_info.desired_vel) * ASTEROID_MIN_COLLIDE_TIME;
|
||||
asteroid_fvec = asteroid_obj->phys_info.desired_vel;
|
||||
|
||||
if(IS_VEC_NULL_SQ_SAFE(&asteroid_fvec)){
|
||||
terminus = pasteroid_obj->pos;
|
||||
terminus = asteroid_obj->pos;
|
||||
} else {
|
||||
vm_vec_normalize(&asteroid_fvec);
|
||||
vm_vec_scale_add(&terminus, &pasteroid_obj->pos, &asteroid_fvec, asteroid_ray_dist);
|
||||
vm_vec_scale_add(&terminus, &asteroid_obj->pos, &asteroid_fvec, asteroid_ray_dist);
|
||||
}
|
||||
|
||||
Assert(pship_obj->type == OBJ_SHIP);
|
||||
Assert(ship_obj->type == OBJ_SHIP);
|
||||
|
||||
mc->model_instance_num = Ships[pship_obj->instance].model_instance_num;
|
||||
mc->model_num = Ship_info[Ships[pship_obj->instance].ship_info_index].model_num; // Fill in the model to check
|
||||
mc->orient = &pship_obj->orient; // The object's orientation
|
||||
mc->pos = &pship_obj->pos; // The object's position
|
||||
mc->p0 = &pasteroid_obj->pos; // Point 1 of ray to check
|
||||
mc->model_instance_num = Ships[ship_obj->instance].model_instance_num;
|
||||
mc->model_num = Ship_info[Ships[ship_obj->instance].ship_info_index].model_num; // Fill in the model to check
|
||||
mc->orient = &ship_obj->orient; // The object's orientation
|
||||
mc->pos = &ship_obj->pos; // The object's position
|
||||
mc->p0 = &asteroid_obj->pos; // Point 1 of ray to check
|
||||
mc->p1 = &terminus; // Point 2 of ray to check
|
||||
if (lazy) {
|
||||
mc->flags = MC_CHECK_MODEL | MC_ONLY_BOUND_BOX;
|
||||
} else {
|
||||
mc->flags = MC_CHECK_MODEL | MC_CHECK_SPHERELINE;
|
||||
}
|
||||
mc->radius = pasteroid_obj->radius;
|
||||
mc->radius = asteroid_obj->radius;
|
||||
|
||||
model_collide(mc);
|
||||
|
||||
@@ -1634,17 +1622,13 @@ void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_info *mc
|
||||
mc->p1 = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if asteroid will collide with escort ship within ASTEROID_MIN_COLLIDE_TIME seconds
|
||||
*
|
||||
* @return !0 if the asteroid will collide with the escort
|
||||
*/
|
||||
int asteroid_will_collide(object *pasteroid_obj, object *escort_objp)
|
||||
// Return !0 is the asteroid will collide with the escort ship within ASTEROID_MIN_COLLIDE_TIME
|
||||
// seconds
|
||||
int asteroid_will_collide(object *asteroid_obj, object *escort_objp)
|
||||
{
|
||||
mc_info mc;
|
||||
mc_info_init(&mc);
|
||||
|
||||
asteroid_test_collide(pasteroid_obj, escort_objp, &mc);
|
||||
asteroid_test_collide(asteroid_obj, escort_objp, &mc);
|
||||
|
||||
if ( !mc.num_hits ) {
|
||||
return 0;
|
||||
@@ -1728,7 +1712,7 @@ void asteroid_verify_collide_objnum(asteroid *asp)
|
||||
}
|
||||
}
|
||||
|
||||
void asteroid_process_post(object * obj)
|
||||
void asteroid_process_post(object * obj, float frame_time)
|
||||
{
|
||||
if (Asteroids_enabled) {
|
||||
int num;
|
||||
@@ -1773,7 +1757,6 @@ float asteroid_time_to_impact(object *asteroid_objp)
|
||||
float time=-1.0f, total_dist, speed;
|
||||
asteroid *asp;
|
||||
mc_info mc;
|
||||
mc_info_init(&mc);
|
||||
|
||||
asp = &Asteroids[asteroid_objp->instance];
|
||||
|
||||
@@ -1809,11 +1792,13 @@ void asteroid_parse_section(asteroid_info *asip)
|
||||
required_string( "$POF file2:" );
|
||||
stuff_string(asip->pof_files[1], F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
if ( (stristr(asip->name, "Asteroid") != NULL) ) {
|
||||
if ( (stristr(asip->name,"Asteroid") != NULL) ) {
|
||||
required_string( "$POF file3:" );
|
||||
stuff_string(asip->pof_files[2], F_NAME, MAX_FILENAME_LEN);
|
||||
}
|
||||
|
||||
asip->num_detail_levels = 0;
|
||||
|
||||
required_string("$Detail distance:");
|
||||
asip->num_detail_levels = stuff_int_list(asip->detail_distance, MAX_ASTEROID_DETAIL_LEVELS, RAW_INTEGER_TYPE);
|
||||
|
||||
@@ -1879,171 +1864,105 @@ void asteroid_parse_section(asteroid_info *asip)
|
||||
}
|
||||
|
||||
/**
|
||||
Read in data from asteroid.tbl into Asteroid_info[] array.
|
||||
|
||||
After this function is completes, the Asteroid_info[] array will
|
||||
contain exactly three asteroids per species plus exactly three
|
||||
generic asteroids. These three asteroids are a set
|
||||
of small, medium, and large asteroids in that exact order.
|
||||
|
||||
If asteroid.tbl contains too many or too few asteroids as per
|
||||
the rules above this function will abort the engine with an
|
||||
error message stating the number expected and it will write
|
||||
to the debug.log how everything was parsed.
|
||||
|
||||
Note that by saying "asteroid" this code is talking about
|
||||
the asteroids and the debris that make up asteroid fields
|
||||
and debris fields. Which means that these debris have nothing
|
||||
to do with the debris of ships that explode, however these
|
||||
are the same debris and asteroids that get flung at a ship
|
||||
that is being protected.
|
||||
*/
|
||||
* Read in data from asteroid.tbl into Asteroid_info[] array
|
||||
*/
|
||||
void asteroid_parse_tbl()
|
||||
{
|
||||
char impact_ani_file[MAX_FILENAME_LEN];
|
||||
int *asteroid_tally = NULL;
|
||||
int i, rval;
|
||||
|
||||
// How did we get here without having any species defined?
|
||||
Assertion(Species_info.size() > 0,
|
||||
"Cannot parse asteroids/debris if there "
|
||||
"are no species for them to belong to."
|
||||
);
|
||||
|
||||
try
|
||||
{
|
||||
read_file_text("asteroid.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
// open localization
|
||||
lcl_ext_open();
|
||||
|
||||
required_string("#Asteroid Types");
|
||||
|
||||
int tally = 0;
|
||||
int max_asteroids =
|
||||
NUM_DEBRIS_SIZES + Species_info.size() * NUM_DEBRIS_SIZES;
|
||||
|
||||
#ifndef NDEBUG
|
||||
SCP_vector<SCP_string> parsed_asteroids;
|
||||
#endif
|
||||
|
||||
// parse and tally each asteroid
|
||||
while (required_string_either("#End", "$Name:"))
|
||||
{
|
||||
asteroid_info new_asteroid;
|
||||
|
||||
asteroid_parse_section(&new_asteroid);
|
||||
|
||||
int species = tally / NUM_DEBRIS_SIZES;
|
||||
if (tally >= max_asteroids)
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
// Bump the warning count in release so they get something
|
||||
// even if the message never gets displayed.
|
||||
Warning(LOCATION, "Ignoring extra asteroid/debris");
|
||||
#else
|
||||
SCP_string msg("Ignoring extra asteroid/debris '");
|
||||
msg.append(new_asteroid.name);
|
||||
msg.append("'\n");
|
||||
Warning(LOCATION, "%s", msg.c_str());
|
||||
parsed_asteroids.push_back(msg);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
SCP_string msg;
|
||||
msg.append("Parsing asteroid: '");
|
||||
msg.append(new_asteroid.name);
|
||||
msg.append("' as a '");
|
||||
msg.append((species == 0) ? "generic" : Species_info[species - 1].species_name);
|
||||
msg.append("'");
|
||||
switch (tally % NUM_DEBRIS_SIZES) {
|
||||
case ASTEROID_TYPE_SMALL:
|
||||
msg.append(" small\n");
|
||||
break;
|
||||
case ASTEROID_TYPE_MEDIUM:
|
||||
msg.append(" medium\n");
|
||||
break;
|
||||
case ASTEROID_TYPE_LARGE:
|
||||
msg.append(" large\n");
|
||||
break;
|
||||
default:
|
||||
Error(LOCATION, "Get a coder! Math has broken!\n"
|
||||
"Important numbers:\n"
|
||||
"\ttally: %d\n"
|
||||
"\tNUM_DEBRIS_SIZES: %d\n",
|
||||
tally, NUM_DEBRIS_SIZES
|
||||
);
|
||||
msg.append(" unknown\n");
|
||||
}
|
||||
parsed_asteroids.push_back(msg);
|
||||
#endif
|
||||
Asteroid_info.push_back(new_asteroid);
|
||||
}
|
||||
tally++;
|
||||
}
|
||||
required_string("#End");
|
||||
|
||||
if (tally != max_asteroids)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (SCP_vector<SCP_string>::iterator iter = parsed_asteroids.begin();
|
||||
iter != parsed_asteroids.end(); ++iter)
|
||||
{
|
||||
mprintf(("Asteroid.tbl as parsed:\n"));
|
||||
mprintf(("%s", iter->c_str()));
|
||||
}
|
||||
#endif
|
||||
Error(LOCATION,
|
||||
"Found %d asteroids/debris when %d expected\n\n"
|
||||
"<Number expected> = <Number of species> * %d + %d generic asteroids\n"
|
||||
"%d = " SIZE_T_ARG "*%d + %d\n\n"
|
||||
#ifdef NDEBUG
|
||||
"Run a debug build to see a list of all parsed asteroids\n",
|
||||
#else
|
||||
"See the debug.log for a listing of all parsed asteroids\n",
|
||||
#endif
|
||||
tally, max_asteroids,
|
||||
NUM_DEBRIS_SIZES, NUM_DEBRIS_SIZES,
|
||||
max_asteroids, Species_info.size(), NUM_DEBRIS_SIZES, NUM_DEBRIS_SIZES
|
||||
);
|
||||
}
|
||||
|
||||
Asteroid_impact_explosion_ani = -1;
|
||||
required_string("$Impact Explosion:");
|
||||
stuff_string(impact_ani_file, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
if (VALID_FNAME(impact_ani_file)) {
|
||||
int num_frames;
|
||||
Asteroid_impact_explosion_ani = bm_load_animation(impact_ani_file, &num_frames, nullptr, nullptr, nullptr, true);
|
||||
}
|
||||
|
||||
required_string("$Impact Explosion Radius:");
|
||||
stuff_float(&Asteroid_impact_explosion_radius);
|
||||
|
||||
if (optional_string("$Briefing Icon Closeup Model:")) {
|
||||
stuff_string(Asteroid_icon_closeup_model, F_NAME, NAME_LENGTH);
|
||||
}
|
||||
else {
|
||||
strcpy_s(Asteroid_icon_closeup_model, Asteroid_info[ASTEROID_TYPE_LARGE].pof_files[0]); // magic file from retail
|
||||
}
|
||||
|
||||
if (optional_string("$Briefing Icon Closeup Position:")) {
|
||||
stuff_vec3d(&Asteroid_icon_closeup_position);
|
||||
}
|
||||
else {
|
||||
vm_vec_make(&Asteroid_icon_closeup_position, 0.0f, 0.0f, -334.0f); // magic numbers from retail
|
||||
}
|
||||
|
||||
if (optional_string("$Briefing Icon Closeup Zoom:")) {
|
||||
stuff_float(&Asteroid_icon_closeup_zoom);
|
||||
}
|
||||
else {
|
||||
Asteroid_icon_closeup_zoom = 0.5f; // magic number from retail
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "asteroid.tbl", e.what()));
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "asteroid.tbl", rval));
|
||||
lcl_ext_close();
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text("asteroid.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
required_string("#Asteroid Types");
|
||||
|
||||
asteroid_tally = new int[Species_info.size() + 1];
|
||||
|
||||
memset(asteroid_tally, 0, sizeof(int) * (Species_info.size()+1));
|
||||
|
||||
while (required_string_either("#End","$Name:"))
|
||||
{
|
||||
asteroid_info new_asteroid;
|
||||
|
||||
for (i = 0; i < NUM_DEBRIS_POFS; i++)
|
||||
new_asteroid.model_num[i] = -1;
|
||||
|
||||
asteroid_parse_section( &new_asteroid );
|
||||
|
||||
Assert( Species_info.size() );
|
||||
// sanity check for debris type sizes
|
||||
for (i = (int)Species_info.size(); i >= 0; i--) {
|
||||
// must remain in proper order
|
||||
// 0 - generic debris types
|
||||
// > 0 - species specific debris types
|
||||
if ( (i == 0) || stristr(new_asteroid.name, Species_info[i-1].species_name) ) {
|
||||
Assert( asteroid_tally[i] < NUM_DEBRIS_SIZES );
|
||||
|
||||
if ( asteroid_tally[i] >= NUM_DEBRIS_SIZES ) {
|
||||
// too many sizes specified, don't increment Num_debris_types and we'll overwrite
|
||||
// the current entry with the next
|
||||
break;
|
||||
}
|
||||
|
||||
// we're safe to continue
|
||||
asteroid_tally[i]++;
|
||||
Asteroid_info.push_back( new_asteroid );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
|
||||
Asteroid_impact_explosion_ani = -1;
|
||||
required_string("$Impact Explosion:");
|
||||
stuff_string(impact_ani_file, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
if ( VALID_FNAME(impact_ani_file) ) {
|
||||
int num_frames;
|
||||
Asteroid_impact_explosion_ani = bm_load_animation( impact_ani_file, &num_frames, NULL, NULL, 1);
|
||||
}
|
||||
|
||||
required_string("$Impact Explosion Radius:");
|
||||
stuff_float(&Asteroid_impact_explosion_radius);
|
||||
|
||||
// close localization
|
||||
lcl_ext_close();
|
||||
|
||||
// check for any missing info
|
||||
char *errormsg = new char[75 + (Species_info.size() * (NAME_LENGTH))];
|
||||
bool species_missing = false;
|
||||
strcpy(errormsg, "The following species are missing debris types in asteroids.tbl:\n");
|
||||
for (i = 0; i < (int)Species_info.size(); i++)
|
||||
{
|
||||
int idx = (i+1); // offset from generic asteroids at 0..NUM_DEBRIS_SIZES
|
||||
|
||||
if (asteroid_tally[idx] < NUM_DEBRIS_SIZES)
|
||||
{
|
||||
strcat(errormsg, Species_info[i].species_name);
|
||||
strcat(errormsg, "\n");
|
||||
species_missing = true;
|
||||
}
|
||||
}
|
||||
strcat(errormsg, "\0");
|
||||
|
||||
if (species_missing)
|
||||
{
|
||||
Error(LOCATION, errormsg);
|
||||
}
|
||||
|
||||
delete[] asteroid_tally;
|
||||
delete[] errormsg;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+13
-25
@@ -12,14 +12,13 @@
|
||||
#ifndef __ASTEROID_H__
|
||||
#define __ASTEROID_H__
|
||||
|
||||
#include "globalincs/globals.h" // for NAME_LENGTH
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "globalincs/globals.h" // for NAME_LENGTH
|
||||
|
||||
|
||||
class object;
|
||||
class polymodel;
|
||||
struct object;
|
||||
struct polymodel;
|
||||
struct collision_info_struct;
|
||||
class draw_list;
|
||||
|
||||
#define MAX_ASTEROIDS 512
|
||||
|
||||
@@ -53,9 +52,7 @@ typedef struct asteroid_split_info {
|
||||
int max;
|
||||
} asteroid_split_info;
|
||||
|
||||
class asteroid_info
|
||||
{
|
||||
public:
|
||||
typedef struct asteroid_info {
|
||||
char name[NAME_LENGTH]; // name for the asteroid
|
||||
char pof_files[NUM_DEBRIS_POFS][MAX_FILENAME_LEN]; // POF files to load/associate with ship
|
||||
int num_detail_levels; // number of detail levels for this ship
|
||||
@@ -80,17 +77,13 @@ public:
|
||||
damage( 0 ), blast( 0 ), initial_asteroid_strength( 0 ),
|
||||
fireball_radius_multiplier( -1 )
|
||||
{
|
||||
name[ 0 ] = 0;
|
||||
name[ 0 ] = NULL;
|
||||
memset( pof_files, 0, sizeof( pof_files ) );
|
||||
memset( detail_distance, 0, sizeof( detail_distance ) );
|
||||
|
||||
for (int i = 0; i < NUM_DEBRIS_POFS; i++)
|
||||
{
|
||||
modelp[i] = NULL;
|
||||
model_num[i] = -1;
|
||||
pof_files[i][0] = 0;
|
||||
}
|
||||
memset( modelp, 0, sizeof( modelp ) );
|
||||
memset( model_num, 0, sizeof( model_num ) );
|
||||
}
|
||||
};
|
||||
} asteroid_info;
|
||||
|
||||
|
||||
#define AF_USED (1<<0) // Set means used.
|
||||
@@ -98,7 +91,6 @@ public:
|
||||
typedef struct asteroid {
|
||||
int flags;
|
||||
int objnum;
|
||||
int model_instance_num;
|
||||
int asteroid_type; // 0..MAX_DEBRIS_TYPES
|
||||
int asteroid_subtype; // Index in asteroid_info for modelnum and modelp
|
||||
int check_for_wrap; // timestamp to check for asteroid wrapping around field
|
||||
@@ -126,7 +118,6 @@ typedef enum {
|
||||
typedef struct asteroid_field {
|
||||
vec3d min_bound; // Minimum range of field.
|
||||
vec3d max_bound; // Maximum range of field.
|
||||
float bound_rad;
|
||||
int has_inner_bound;
|
||||
vec3d inner_min_bound;
|
||||
vec3d inner_max_bound;
|
||||
@@ -144,20 +135,17 @@ extern asteroid_field Asteroid_field;
|
||||
|
||||
extern int Num_asteroids;
|
||||
extern int Asteroids_enabled;
|
||||
extern char Asteroid_icon_closeup_model[NAME_LENGTH]; // model for asteroid field briefing icon rendering
|
||||
extern vec3d Asteroid_icon_closeup_position; // closeup position for asteroid field briefing icon rendering
|
||||
extern float Asteroid_icon_closeup_zoom; // zoom position for asteroid field briefing icon rendering
|
||||
|
||||
void asteroid_init();
|
||||
void asteroid_level_init();
|
||||
void asteroid_level_close();
|
||||
void asteroid_create_all();
|
||||
void asteroid_render(object * obj, draw_list *scene);
|
||||
void asteroid_render( object *asteroid_objp );
|
||||
void asteroid_delete( object *asteroid_objp );
|
||||
void asteroid_process_pre( object *asteroid_objp );
|
||||
void asteroid_process_post( object *asteroid_objp);
|
||||
void asteroid_process_pre( object *asteroid_objp, float frame_time);
|
||||
void asteroid_process_post( object *asteroid_objp, float frame_time);
|
||||
int asteroid_check_collision( object *asteroid_objp, object * other_obj, vec3d * hitpos, collision_info_struct *asteroid_hit_info=NULL );
|
||||
void asteroid_hit( object *pasteroid_objp, object *other_objp, vec3d *hitpos, float damage );
|
||||
void asteroid_hit( object *asteroid_objp, object *other_objp, vec3d *hitpos, float damage );
|
||||
int asteroid_count();
|
||||
int asteroid_collide_objnum(object *asteroid_objp);
|
||||
float asteroid_time_to_impact(object *asteroid_objp);
|
||||
|
||||
+125
-144
@@ -5,28 +5,28 @@
|
||||
|
||||
|
||||
|
||||
#include "autopilot/autopilot.h"
|
||||
#include "ai/ai.h"
|
||||
#include "ai/aigoals.h"
|
||||
#include "asteroid/asteroid.h"
|
||||
#include "autopilot/autopilot.h"
|
||||
#include "camera/camera.h"
|
||||
#include "cfile/cfile.h"
|
||||
#include "freespace2/freespace.h"
|
||||
#include "gamesnd/eventmusic.h"
|
||||
#include "globalincs/def_files.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "iff_defs/iff_defs.h"
|
||||
#include "io/timer.h"
|
||||
#include "localization/localize.h"
|
||||
#include "mission/missionmessage.h"
|
||||
#include "mission/missiontraining.h"
|
||||
#include "ship/ship.h"
|
||||
#include "object/object.h"
|
||||
#include "object/objcollide.h"
|
||||
#include "object/waypoint.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "parse/sexp.h"
|
||||
#include "ship/ship.h"
|
||||
#include "freespace2/freespace.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "iff_defs/iff_defs.h"
|
||||
#include "sound/audiostr.h"
|
||||
|
||||
#include "mission/missiontraining.h"
|
||||
#include "mission/missionmessage.h"
|
||||
#include "io/timer.h"
|
||||
#include "gamesnd/eventmusic.h"
|
||||
#include "cfile/cfile.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "globalincs/def_files.h"
|
||||
#include "localization/localize.h"
|
||||
#include "camera/camera.h"
|
||||
#include "asteroid/asteroid.h"
|
||||
#include <map>
|
||||
|
||||
// Extern functions/variables
|
||||
@@ -209,7 +209,7 @@ bool CanAutopilot(vec3d targetPos, bool send_msg)
|
||||
|
||||
// check for support ships
|
||||
// cannot autopilot if support ship present
|
||||
if ( ship_find_repair_ship(Player_obj) != 0 ) {
|
||||
if ( ship_find_repair_ship(Player_obj) != NULL ) {
|
||||
if (send_msg)
|
||||
send_autopilot_msgID(NP_MSG_FAIL_SUPPORT_PRESENT);
|
||||
return false;
|
||||
@@ -225,49 +225,38 @@ extern object* Autopilot_flight_leader;
|
||||
// * Control switched from player to AI
|
||||
// * Time compression to 32x
|
||||
// * Lock time compression -WMC
|
||||
// * Tell AI to fly to targeted Nav Point (for all nav-status wings/ships)
|
||||
// * Tell AI to fly to targetted Nav Point (for all nav-status wings/ships)
|
||||
// * Sets max waypoint speed to the best-speed of the slowest ship tagged
|
||||
bool StartAutopilot()
|
||||
{
|
||||
// Check for support ship and dismiss it if it is not doing anything.
|
||||
// If the support ship is doing something then tell the user such.
|
||||
for ( object *objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) )
|
||||
{
|
||||
if ((objp->type == OBJ_SHIP) && !(objp->flags & OF_SHOULD_BE_DEAD))
|
||||
{
|
||||
Assertion((objp->instance >= 0) && (objp->instance < MAX_SHIPS),
|
||||
"objp does not have a valid pointer to a ship. Pointer is %d, which is smaller than 0 or bigger than %d",
|
||||
objp->instance, MAX_SHIPS);
|
||||
ship *shipp = &Ships[objp->instance];
|
||||
|
||||
if (shipp->team != Player_ship->team)
|
||||
continue;
|
||||
|
||||
Assertion((shipp->ship_info_index >= 0) && (shipp->ship_info_index < static_cast<int>(Ship_info.size())),
|
||||
"Ship '%s' does not have a valid pointer to a ship class. Pointer is %d, which is smaller than 0 or bigger than %d",
|
||||
shipp->ship_name, shipp->ship_info_index, static_cast<int>(Ship_info.size()));
|
||||
ship_info *sip = &Ship_info[shipp->ship_info_index];
|
||||
|
||||
if ( !(sip->flags & SIF_SUPPORT) )
|
||||
continue;
|
||||
|
||||
// don't deal with dying or departing support ships
|
||||
if ( shipp->flags & (SF_DYING | SF_DEPARTING) )
|
||||
continue;
|
||||
|
||||
Assert(shipp->ai_index != -1);
|
||||
ai_info* support_ship_aip = &(Ai_info[Ships[objp->instance].ai_index]);
|
||||
|
||||
// is support ship trying to rearm-repair
|
||||
if ( ai_find_goal_index( support_ship_aip->goals, AI_GOAL_REARM_REPAIR ) == -1 ) {
|
||||
// no, so tell it to depart
|
||||
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WARP, -1, NULL, support_ship_aip );
|
||||
} else {
|
||||
// yes
|
||||
send_autopilot_msgID(NP_MSG_FAIL_SUPPORT_WORKING);
|
||||
return false;
|
||||
}
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
object* support_ship_op = ship_find_repair_ship(Player_obj);
|
||||
if ( support_ship_op == NULL ) {
|
||||
// no more
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Assert( support_ship_op->type == OBJ_SHIP );
|
||||
Assert( support_ship_op->instance >= 0 );
|
||||
Assert( support_ship_op->instance < MAX_SHIPS );
|
||||
Assert( Ships[support_ship_op->instance].ai_index != -1 );
|
||||
|
||||
ai_info* support_ship_aip = &(Ai_info[Ships[support_ship_op->instance].ai_index]);
|
||||
|
||||
// is support ship trying to rearm-repair
|
||||
if ( ai_find_goal_index( support_ship_aip->goals, AI_GOAL_REARM_REPAIR ) == -1 ) {
|
||||
// no, so tell it to depart
|
||||
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WARP, -1, NULL, support_ship_aip );
|
||||
} else {
|
||||
// yes
|
||||
send_autopilot_msgID(NP_MSG_FAIL_SUPPORT_WORKING);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
if (!CanAutopilot())
|
||||
return false;
|
||||
@@ -715,9 +704,9 @@ bool StartAutopilot()
|
||||
|
||||
vm_vec_add(&Objects[Ships[*idx].objnum].pos, &Autopilot_flight_leader->pos, &offset);
|
||||
|
||||
if (vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[*idx].objnum].pos) > distance)
|
||||
if (vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[i].objnum].pos) > distance)
|
||||
{
|
||||
distance = vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[*idx].objnum].pos);
|
||||
distance = vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[i].objnum].pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -995,7 +984,6 @@ camera* nav_get_set_camera()
|
||||
return nav_camera.getCamera();
|
||||
}
|
||||
|
||||
extern int Cmdline_old_collision_sys;
|
||||
void nav_warp(bool prewarp=false)
|
||||
{
|
||||
/* ok... find our end distance - norm1 is still a unit vector in the
|
||||
@@ -1050,11 +1038,8 @@ void nav_warp(bool prewarp=false)
|
||||
}
|
||||
|
||||
// retime all collision pairs
|
||||
if ( Cmdline_old_collision_sys ) {
|
||||
obj_all_collisions_retime();
|
||||
} else {
|
||||
obj_collide_retime_cached_pairs();
|
||||
}
|
||||
obj_all_collisions_retime();
|
||||
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
@@ -1212,7 +1197,7 @@ void NavSystem_Do()
|
||||
|
||||
void send_autopilot_msgID(int msgid)
|
||||
{
|
||||
if (msgid < 0 || msgid >= NP_NUM_MESSAGES)
|
||||
if (msgid < 0 || msgid > NP_NUM_MESSAGES)
|
||||
return;
|
||||
|
||||
send_autopilot_msg(NavMsgs[msgid].message, NavMsgs[msgid].filename);
|
||||
@@ -1251,9 +1236,7 @@ void send_autopilot_msg(char *msg, char *snd)
|
||||
// Inits the Nav System
|
||||
void NavSystem_Init()
|
||||
{
|
||||
for (int i = 0; i < MAX_NAVPOINTS; i++)
|
||||
Navs[i].clear();
|
||||
|
||||
memset((char *)&Navs, 0, sizeof(Navs));
|
||||
AutoPilotEngaged = false;
|
||||
CurrentNav = -1;
|
||||
audio_handle = -1;
|
||||
@@ -1271,69 +1254,75 @@ void NavSystem_Init()
|
||||
|
||||
void parse_autopilot_table(char *filename)
|
||||
{
|
||||
int rval;
|
||||
SCP_vector<SCP_string> lines;
|
||||
|
||||
try
|
||||
// open localization
|
||||
lcl_ext_open();
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0)
|
||||
{
|
||||
if (filename == NULL)
|
||||
read_file_text_from_array(defaults_get_file("autopilot.tbl"));
|
||||
else
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
reset_parse();
|
||||
|
||||
|
||||
required_string("#Autopilot");
|
||||
|
||||
// autopilot link distance
|
||||
required_string("$Link Distance:");
|
||||
stuff_int(&NavLinkDistance);
|
||||
|
||||
if (optional_string("$Interrupt autopilot if enemy within distance:"))
|
||||
stuff_int(&AutopilotMinEnemyDistance);
|
||||
else
|
||||
AutopilotMinEnemyDistance = 5000;
|
||||
|
||||
if (optional_string("$Interrupt autopilot if asteroid within distance:"))
|
||||
stuff_int(&AutopilotMinAsteroidDistance);
|
||||
else
|
||||
AutopilotMinAsteroidDistance = 1000;
|
||||
|
||||
if (optional_string("$Lock Weapons During Autopilot:"))
|
||||
stuff_boolean(&LockWeaponsDuringAutopilot);
|
||||
else
|
||||
LockWeaponsDuringAutopilot = false;
|
||||
|
||||
// optional no cutscene bars
|
||||
if (optional_string("+No_Cutscene_Bars"))
|
||||
UseCutsceneBars = false;
|
||||
// optional no cutscene bars
|
||||
if (optional_string("+No_Autopilot_Interrupt"))
|
||||
Cmdline_autopilot_interruptable = 0;
|
||||
|
||||
// No Nav selected message
|
||||
char *msg_tags[] = { "$No Nav Selected:", "$Gliding:",
|
||||
"$Too Close:", "$Hostiles:", "$Linked:", "$Hazard:",
|
||||
"$Support Present:", "$Support Working:" };
|
||||
for (int i = 0; i < NP_NUM_MESSAGES; i++)
|
||||
{
|
||||
required_string(msg_tags[i]);
|
||||
|
||||
required_string("+Msg:");
|
||||
stuff_string(NavMsgs[i].message, F_MESSAGE, 256);
|
||||
|
||||
required_string("+Snd File:");
|
||||
stuff_string(NavMsgs[i].filename, F_NAME, 256);
|
||||
}
|
||||
|
||||
|
||||
required_string("#END");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", (filename) ? filename : "<default autopilot.tbl>", e.what()));
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", (filename) ? filename : "<default autopilot.tbl>", rval));
|
||||
lcl_ext_close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (filename == NULL)
|
||||
read_file_text_from_array(defaults_get_file("autopilot.tbl"));
|
||||
else
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
reset_parse();
|
||||
|
||||
|
||||
required_string("#Autopilot");
|
||||
|
||||
// autopilot link distance
|
||||
required_string("$Link Distance:");
|
||||
stuff_int(&NavLinkDistance);
|
||||
|
||||
if (optional_string("$Interrupt autopilot if enemy within distance:"))
|
||||
stuff_int(&AutopilotMinEnemyDistance);
|
||||
else
|
||||
AutopilotMinEnemyDistance = 5000;
|
||||
|
||||
if (optional_string("$Interrupt autopilot if asteroid within distance:"))
|
||||
stuff_int(&AutopilotMinAsteroidDistance);
|
||||
else
|
||||
AutopilotMinAsteroidDistance = 1000;
|
||||
|
||||
if (optional_string("$Lock Weapons During Autopilot:"))
|
||||
stuff_boolean(&LockWeaponsDuringAutopilot);
|
||||
else
|
||||
LockWeaponsDuringAutopilot = false;
|
||||
|
||||
// optional no cutscene bars
|
||||
if (optional_string("+No_Cutscene_Bars"))
|
||||
UseCutsceneBars = false;
|
||||
// optional no cutscene bars
|
||||
if (optional_string("+No_Autopilot_Interrupt"))
|
||||
Cmdline_autopilot_interruptable = 0;
|
||||
|
||||
// No Nav selected message
|
||||
char *msg_tags[] = { "$No Nav Selected:", "$Gliding:",
|
||||
"$Too Close:", "$Hostiles:", "$Linked:", "$Hazard:",
|
||||
"$Support Present:", "$Support Working:" };
|
||||
for (int i = 0; i < NP_NUM_MESSAGES; i++)
|
||||
{
|
||||
required_string(msg_tags[i]);
|
||||
|
||||
required_string("+Msg:");
|
||||
stuff_string(NavMsgs[i].message, F_MESSAGE, 256);
|
||||
|
||||
required_string("+Snd File:");
|
||||
stuff_string(NavMsgs[i].filename, F_NAME, 256);
|
||||
}
|
||||
|
||||
|
||||
required_string("#END");
|
||||
|
||||
// close localization
|
||||
lcl_ext_close();
|
||||
}
|
||||
|
||||
|
||||
@@ -1343,13 +1332,20 @@ int FindNav(char *Nav)
|
||||
{
|
||||
for (int i = 0; i < MAX_NAVPOINTS; i++)
|
||||
{
|
||||
if (!stricmp(Navs[i].m_NavName, Nav))
|
||||
if (!stricmp(Navs[i].NavName, Nav))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
// Set A Nav point to "ZERO"
|
||||
void ZeroNav(int i)
|
||||
{
|
||||
memset((char *)&Navs[i], 0, sizeof(NavPoint));
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
// Removes a Nav
|
||||
bool DelNavPoint(char *Nav)
|
||||
@@ -1360,6 +1356,7 @@ bool DelNavPoint(char *Nav)
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool DelNavPoint(int nav)
|
||||
{
|
||||
if (nav != -1)
|
||||
@@ -1372,7 +1369,7 @@ bool DelNavPoint(int nav)
|
||||
}
|
||||
|
||||
}
|
||||
Navs[MAX_NAVPOINTS-1].clear();
|
||||
ZeroNav(MAX_NAVPOINTS-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1400,7 +1397,7 @@ bool AddNav_Ship(char *Nav, char *TargetName, int flags)
|
||||
// Create the NavPoint struct
|
||||
NavPoint tnav;
|
||||
|
||||
strcpy_s(tnav.m_NavName, Nav);
|
||||
strncpy(tnav.NavName, Nav, 32);
|
||||
tnav.flags = NP_SHIP | flags;
|
||||
|
||||
Assert(!(tnav.flags & NP_WAYPOINT));
|
||||
@@ -1446,7 +1443,7 @@ bool AddNav_Waypoint(char *Nav, char *WP_Path, int node, int flags)
|
||||
// Create the NavPoint struct
|
||||
NavPoint tnav;
|
||||
|
||||
strcpy_s(tnav.m_NavName, Nav);
|
||||
strncpy(tnav.NavName, Nav, 32);
|
||||
tnav.flags = NP_WAYPOINT | flags;
|
||||
|
||||
Assert(!(tnav.flags & NP_SHIP));
|
||||
@@ -1569,23 +1566,7 @@ bool Nav_UnSet_Visited(char *Nav)
|
||||
return Nav_UnSet_Flag(Nav, NP_VISITED);
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
// Selects a navpoint by name.
|
||||
void SelectNav(char *Nav)
|
||||
{
|
||||
for (int i = 0; i < MAX_NAVPOINTS; i++)
|
||||
{
|
||||
if (!stricmp(Navs[i].m_NavName, Nav))
|
||||
if (!(Nav_Get_Flags(Nav) & NP_HIDDEN || Nav_Get_Flags(Nav) & NP_NOACCESS)) CurrentNav = i;
|
||||
}
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
// Deselects any navpoint selected.
|
||||
void DeselectNav()
|
||||
{
|
||||
CurrentNav = 0;
|
||||
}
|
||||
|
||||
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "object/object.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
// milliseconds between updates
|
||||
@@ -26,10 +25,9 @@
|
||||
#define NP_NOSELECT ( NP_HIDDEN | NP_NOACCESS )
|
||||
#define NP_VALIDTYPE ( NP_WAYPOINT | NP_SHIP )
|
||||
|
||||
class NavPoint
|
||||
struct NavPoint
|
||||
{
|
||||
public:
|
||||
char m_NavName[32];
|
||||
char NavName[32];
|
||||
int flags;
|
||||
|
||||
void *target_obj;
|
||||
@@ -37,15 +35,6 @@ public:
|
||||
|
||||
vec3d *GetPosition();
|
||||
char* GetInternalName();
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_NavName[0] = 0;
|
||||
flags = 0;
|
||||
|
||||
target_obj = NULL;
|
||||
waypoint_num = -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -94,7 +83,7 @@ inline bool CanAutopilot(bool send_msg=false) { return CanAutopilot(Player_obj->
|
||||
// * Checks if Autopilot is allowed. See CanAutopilot() for conditions.
|
||||
// * Control switched from player to AI
|
||||
// * Time compression to 32x
|
||||
// * Tell AI to fly to targeted Nav Point (for all nav-status wings/ships)
|
||||
// * Tell AI to fly to targetted Nav Point (for all nav-status wings/ships)
|
||||
// * Sets max waypoint speed to the best-speed of the slowest ship tagged
|
||||
// Returns false if autopilot cannot be started. True otherwise.
|
||||
bool StartAutopilot();
|
||||
@@ -123,12 +112,6 @@ void parse_autopilot_table(char *filename);
|
||||
// Finds a Nav point by name
|
||||
int FindNav(char *Nav);
|
||||
|
||||
// Selects a Nav point by name
|
||||
void SelectNav(char *Nav);
|
||||
|
||||
// Deselects any navpoint selected.
|
||||
void DeselectNav();
|
||||
|
||||
// Set A Nav point to "ZERO"
|
||||
void ZeroNav(int i);
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bm_examples.cpp
|
||||
* This file contains example code for using bmpman.
|
||||
*/
|
||||
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "graphics/2d.h"
|
||||
|
||||
void bm_create_example() {
|
||||
static int test_inited = 0;
|
||||
static int test_bmp;
|
||||
static uint test_bmp_data[128 * 64];
|
||||
|
||||
if (!test_inited) {
|
||||
test_inited = 1;
|
||||
// Create the new bitmap and fill in its data.
|
||||
// When you're done with it completely, call
|
||||
// bm_release to free up the bitmap handle
|
||||
test_bmp = bm_create(32, 128, 64, test_bmp_data);
|
||||
int i, j;
|
||||
for (i = 0; i < 64; i++) {
|
||||
for (j = 0; j < 64; j++) {
|
||||
uint r = i * 4;
|
||||
test_bmp_data[j + i * 128] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// page out the data, so that the next bm_lock will convert the new data to
|
||||
// the correct bpp
|
||||
bm_unload(test_bmp);
|
||||
|
||||
// put in new data
|
||||
int x, y;
|
||||
gr_reset_clip();
|
||||
for (y = 0; y < 64; y++) {
|
||||
for (x = 0; x < 128; x++) {
|
||||
test_bmp_data[y * 128 + x] = 15;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the bitmap, the upper left corner is the origin (0, 0)
|
||||
gr_set_bitmap(test_bmp);
|
||||
gr_bitmap(0, 0);
|
||||
}
|
||||
+92
-66
@@ -1,105 +1,131 @@
|
||||
#ifndef __BM_INTERNAL_H__
|
||||
#define __BM_INTERNAL_H__
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bm_internal.h
|
||||
* These are functions and types used by bmpman and a few others.
|
||||
*
|
||||
* @details It is a "protected" header that requires BMPMAN_INTERNAL to be defined before it can be included. This is to
|
||||
* provide a small measure of safety since this functions can cause problems if not used correctly
|
||||
*/
|
||||
|
||||
#ifndef BMPMAN_INTERNAL
|
||||
#error The file header "bmpman/bm_internal.h" is protected. Make sure you know what you are doing!
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __BM_INTERNAL_H__
|
||||
#define __BM_INTERNAL_H__
|
||||
|
||||
|
||||
// extra check to make sure this stuff doesn't end up in normal files
|
||||
// don't use any of this unless BMPMAN_INTERNAL is defined
|
||||
#ifdef BMPMAN_INTERNAL
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "bmpman/bmpman.h"
|
||||
|
||||
union bm_extra_info {
|
||||
|
||||
// no-type ( used in: bm_bitmaps[i].type )
|
||||
#define BM_TYPE_NONE 0
|
||||
// in-memory type ( used in: bm_bitmaps[i].type )
|
||||
#define BM_TYPE_USER 1
|
||||
// file-type types ( used in: bm_bitmaps[i].type )
|
||||
#define BM_TYPE_PCX 2
|
||||
#define BM_TYPE_TGA 3 // 16 or 32 bit targa
|
||||
#define BM_TYPE_DDS 4 // generic identifier for DDS
|
||||
#define BM_TYPE_PNG 5 // PNG
|
||||
#define BM_TYPE_JPG 6 // 32 bit jpeg
|
||||
#define BM_TYPE_ANI 7 // in-house ANI format
|
||||
#define BM_TYPE_EFF 8 // specifies any type of animated image, the EFF itself is just text
|
||||
// c-type types ( used in: bm_bitmaps[i].c_type )
|
||||
#define BM_TYPE_DXT1 9 // 24 bit with switchable alpha (compressed)
|
||||
#define BM_TYPE_DXT3 10 // 32 bit with 4 bit alpha (compressed)
|
||||
#define BM_TYPE_DXT5 11 // 32 bit with 8 bit alpha (compressed)
|
||||
#define BM_TYPE_CUBEMAP_DDS 12 // generic DDS cubemap (uncompressed cubemap surface)
|
||||
#define BM_TYPE_CUBEMAP_DXT1 13 // 24-bit cubemap (compressed cubemap surface)
|
||||
#define BM_TYPE_CUBEMAP_DXT3 14 // 32-bit cubemap (compressed cubemap surface)
|
||||
#define BM_TYPE_CUBEMAP_DXT5 15 // 32-bit cubemap (compressed cubemap surface)
|
||||
// special types ( used in: bm_bitmaps[i].type )
|
||||
#define BM_TYPE_RENDER_TARGET_STATIC 16 // 24/32 bit setup internally as a static render target
|
||||
#define BM_TYPE_RENDER_TARGET_DYNAMIC 17 // 24/32 bit setup internally as a dynamic render target
|
||||
|
||||
|
||||
/// Moved from cpp file ///////////////////
|
||||
// Consider these 'protected' structures and functions that should only be used by special bitmap functions
|
||||
typedef union bm_extra_info {
|
||||
struct {
|
||||
// Stuff needed for animations
|
||||
int first_frame; //!< used for animations -- points to index of first frame
|
||||
int num_frames; //!< used for animations -- number of frames in the animation
|
||||
int keyframe; //!< used for animations -- keyframe info
|
||||
float total_time; //!< used for animations -- total animation time (not always derived from num_frames/fps)
|
||||
ubyte fps; //!< used for animations -- frames per second
|
||||
int first_frame; // used for animations -- points to index of first frame
|
||||
int num_frames; // used for animation -- number of frames in the animation
|
||||
int keyframe; // used for animation -- keyframe info
|
||||
ubyte fps; // used for animation -- frames per second
|
||||
|
||||
struct {
|
||||
// stuff for static animations
|
||||
BM_TYPE type; //!< type for individual images
|
||||
char filename[MAX_FILENAME_LEN]; //!< filename for individual images
|
||||
ubyte type; // type for individual images
|
||||
char filename[MAX_FILENAME_LEN]; // filename for individual images
|
||||
} eff;
|
||||
struct {
|
||||
bool is_apng; //!< Is this animation an APNG?
|
||||
float frame_delay; //!< cumulative frame delay
|
||||
} apng;
|
||||
} ani;
|
||||
|
||||
struct {
|
||||
// Stuff needed for user bitmaps
|
||||
void* data; //!< For user bitmaps, this is where the data comes from
|
||||
ubyte bpp; //!< For user bitmaps, this is what format the data is
|
||||
ubyte flags; //!< For user bitmaps, Flags passed to bm_create
|
||||
void *data; // For user bitmaps, this is where the data comes from
|
||||
ubyte bpp; // For user bitmaps, this is what format the data is
|
||||
ubyte flags; // Flags passed to bm_create
|
||||
} user;
|
||||
};
|
||||
} bm_extra_info;
|
||||
|
||||
struct bitmap_entry {
|
||||
|
||||
typedef struct bitmap_entry {
|
||||
// identification
|
||||
char filename[MAX_FILENAME_LEN]; //!< filename for this bitmap
|
||||
char filename[MAX_FILENAME_LEN]; // filename for this bitmap
|
||||
|
||||
uint signature; //!< a unique signature identifying the data
|
||||
uint palette_checksum; //!< checksum used to be sure bitmap is in current palette
|
||||
int handle; //!< Handle = id*MAX_BITMAPS + bitmapnum
|
||||
int last_used; //!< When this bitmap was last used
|
||||
uint signature; // a unique signature identifying the data
|
||||
uint palette_checksum; // checksum used to be sure bitmap is in current palette
|
||||
int handle; // Handle = id*MAX_BITMAPS + bitmapnum
|
||||
int last_used; // When this bitmap was last used
|
||||
|
||||
BM_TYPE type; //!< PCX, USER, ANI, etc
|
||||
BM_TYPE comp_type; //!< What sort of compressed type, BM_TYPE_NONE if not compressed
|
||||
signed char ref_count; //!< Number of locks on bitmap. Can't unload unless ref_count is 0.
|
||||
ubyte type; // PCX, USER, ANI, etc
|
||||
ubyte comp_type; // What sort of compressed type, BM_TYPE_NONE if not compressed
|
||||
signed char ref_count; // Number of locks on bitmap. Can't unload unless ref_count is 0.
|
||||
|
||||
int dir_type; //!< which directory this was loaded from (to skip other locations with same name)
|
||||
int dir_type; // which directory this was loaded from (to skip other locations with same name)
|
||||
|
||||
// compressed bitmap stuff (.dds) - RT please take a look at this and tell me if we really need it
|
||||
size_t mem_taken; //!< How much memory does this bitmap use? - UnknownPlayer
|
||||
int num_mipmaps; //!< number of mipmap levels, we need to read all of them
|
||||
int mem_taken; // How much memory does this bitmap use? - UnknownPlayer
|
||||
int num_mipmaps; // number of mipmap levels, we need to read all of them
|
||||
|
||||
// Stuff to keep track of usage
|
||||
ubyte preloaded; //!< If set, then this was loaded from the lst file
|
||||
int preload_count; //!< how many times this gets used in game, for unlocking
|
||||
ubyte used_flags; //!< What flags it was accessed thru
|
||||
int load_count;
|
||||
ubyte preloaded; // If set, then this was loaded from the lst file
|
||||
int preload_count; // how many times this gets used in game, for unlocking
|
||||
ubyte used_flags; // What flags it was accessed thru
|
||||
int load_count;
|
||||
|
||||
bitmap bm; //!< Bitmap info
|
||||
// Bitmap info
|
||||
bitmap bm;
|
||||
|
||||
bm_extra_info info; //!< Data for animations and user bitmaps
|
||||
// Data for animations and user bitmaps
|
||||
bm_extra_info info;
|
||||
|
||||
#ifdef BMPMAN_NDEBUG
|
||||
// bookeeping
|
||||
ubyte used_last_frame; // If set, then it was used last frame
|
||||
ubyte used_this_frame; // If set, then it was used this frame
|
||||
int data_size; // How much data this bitmap uses
|
||||
int used_count; // How many times it was accessed
|
||||
ubyte used_last_frame; // If set, then it was used last frame
|
||||
ubyte used_this_frame; // If set, then it was used this frame
|
||||
int data_size; // How much data this bitmap uses
|
||||
int used_count; // How many times it was accessed
|
||||
#endif
|
||||
};
|
||||
} bitmap_entry;
|
||||
|
||||
extern bitmap_entry bm_bitmaps[MAX_BITMAPS];
|
||||
|
||||
// image specific lock functions
|
||||
void bm_lock_ani( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_dds( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_png( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_apng( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_jpg( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_pcx( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_tga( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_user( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
|
||||
// image specific lock functions
|
||||
void bm_lock_ani( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags );
|
||||
void bm_lock_dds( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags );
|
||||
void bm_lock_png( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags );
|
||||
void bm_lock_jpg( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags );
|
||||
void bm_lock_pcx( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags );
|
||||
void bm_lock_tga( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags );
|
||||
void bm_lock_user( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags );
|
||||
|
||||
|
||||
#endif // BMPMAN_INTERNAL
|
||||
|
||||
#endif // __BM_INTERNAL_H__
|
||||
+2514
-2925
File diff suppressed because it is too large.
Load diff
+204
-622
@@ -1,701 +1,283 @@
|
||||
#ifndef _BMPMAN_H
|
||||
#define _BMPMAN_H
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bmpman.h
|
||||
* Header file for the bitmap manager (bmpman)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @example bm_examples.cpp
|
||||
* @brief This containes examples of bmpman usage
|
||||
*/
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#ifndef _BMPMAN_H
|
||||
#define _BMPMAN_H
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "cfile/cfile.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define BMPMAN_NDEBUG //!< Enables BMPMAN debugging code
|
||||
#define BMPMAN_NDEBUG
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup BMPMAN_CONSTANTS Macro constants used in/with bmpman.h
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#define MAX_BITMAPS 4750 // How many bitmaps the game can handle
|
||||
// NOTE: MAX_BITMAPS shouldn't need to be bumped again. With the fixed bm_release() and it's
|
||||
// proper use even the largest missions should stay under this number. With the largest retail
|
||||
// missions and wasteful content we should still have about 20% of the slots free. If it still
|
||||
// goes over then it's something the artists need to fix. For instance the Terran Mara fighter,
|
||||
// with -spec and -glow and using the Shinepack, needs 117 bitmap slots alone. 111 of those is
|
||||
// just for the glowmaps. This number can be greatly reduced if the number of ani frames for
|
||||
// another LOD than LOD0 has fewer or no ani frames. A 37 frame glow ani for LOD2 is little
|
||||
// more than a waste of resources. Future reports of texture corruption should be initially
|
||||
// approached with content as the cause and not code. If anything we could/should reduce
|
||||
// MAX_BITMAPS in the future. Where it's at now should accomidate even the largest mods.
|
||||
// -- Taylor
|
||||
|
||||
/**
|
||||
* @brief How many bitmaps the game can handle
|
||||
*
|
||||
* @attention MAX_BITMAPS shouldn't need to be bumped again. With the fixed bm_release() and it's proper use even the
|
||||
* largest missions should stay under this number. With the largest retail missions and wasteful content we should
|
||||
* still have about 20% of the slots free. If it still goes over then it's something the artists need to fix.
|
||||
* For instance the Terran Mara fighter, with -spec and -glow and using the Shinepack, needs 117 bitmap slots alone.
|
||||
* 111 of those is just for the glowmaps. This number can be greatly reduced if the number of ani frames for another
|
||||
* LOD than LOD0 has fewer or no ani frames. A 37 frame glow ani for LOD2 is little more than a waste of resources.
|
||||
* Future reports of texture corruption should be initially approached with content as the cause and not code.
|
||||
* If anything we could/should reduce MAX_BITMAPS in the future. Where it's at now should accomidate even the
|
||||
* largest mods. -- Taylor
|
||||
*/
|
||||
#define MAX_BITMAPS 4750
|
||||
|
||||
// Flag positions for bitmap.flags
|
||||
#define BMP_AABITMAP (1<<0) // antialiased bitmap
|
||||
#define BMP_TEX_XPARENT (1<<1) // transparent texture
|
||||
#define BMP_TEX_OTHER (1<<2) // so we can identify all "normal" textures
|
||||
#define BMP_TEX_DXT1 (1<<3) // dxt1 compressed 8r8g8b1a (24bit)
|
||||
#define BMP_TEX_DXT3 (1<<4) // dxt3 compressed 8r8g8b4a (32bit)
|
||||
#define BMP_TEX_DXT5 (1<<5) // dxt5 compressed 8r8g8b8a (32bit)
|
||||
#define BMP_TEX_CUBEMAP (1<<6) // a texture made for cubic environment map
|
||||
// ***** NOTE: bitmap.flags is an 8-bit value, no more BMP_TEX_* flags can be added unless the type is changed!! ******
|
||||
#define BMP_AABITMAP (1<<0) //!< antialiased bitmap
|
||||
#define BMP_TEX_XPARENT (1<<1) //!< transparent texture
|
||||
#define BMP_TEX_OTHER (1<<2) //!< so we can identify all "normal" textures
|
||||
#define BMP_TEX_DXT1 (1<<3) //!< dxt1 compressed 8r8g8b1a (24bit)
|
||||
#define BMP_TEX_DXT3 (1<<4) //!< dxt3 compressed 8r8g8b4a (32bit)
|
||||
#define BMP_TEX_DXT5 (1<<5) //!< dxt5 compressed 8r8g8b8a (32bit)
|
||||
#define BMP_TEX_CUBEMAP (1<<6) //!< a texture made for cubic environment map
|
||||
|
||||
// Combined flags
|
||||
#define BMP_TEX_COMP ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 ) //!< Compressed textures
|
||||
#define BMP_TEX_NONCOMP ( BMP_TEX_XPARENT | BMP_TEX_OTHER ) //!< Non-compressed textures
|
||||
#define BMP_TEX_ANY ( BMP_TEX_COMP | BMP_TEX_NONCOMP ) //!< Any texture
|
||||
//compressed texture types
|
||||
#define BMP_TEX_COMP ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 )
|
||||
|
||||
// Flag positions for bitmap.type
|
||||
#define BMP_FLAG_RENDER_TARGET_STATIC (1<<0) //!< Texture is a static type
|
||||
#define BMP_FLAG_RENDER_TARGET_DYNAMIC (1<<1) //!< Texture is a dynamic type (animation)
|
||||
#define BMP_FLAG_CUBEMAP (1<<2) //!< Texture is a cubemap
|
||||
//non compressed textures
|
||||
#define BMP_TEX_NONCOMP ( BMP_TEX_XPARENT | BMP_TEX_OTHER )
|
||||
|
||||
// Bitmap types
|
||||
enum BM_TYPE
|
||||
{
|
||||
BM_TYPE_NONE = 0, //!< No type
|
||||
BM_TYPE_USER, //!< in-memory
|
||||
BM_TYPE_PCX, //!< PCX
|
||||
BM_TYPE_TGA, //!< 16 or 32 bit targa
|
||||
BM_TYPE_DDS, //!< generic identifier for DDS
|
||||
BM_TYPE_PNG, //!< PNG
|
||||
BM_TYPE_JPG, //!< 32 bit jpeg
|
||||
BM_TYPE_ANI, //!< in-house ANI format
|
||||
BM_TYPE_EFF, //!< specifies any type of animated image, the EFF itself is just text
|
||||
|
||||
// special types
|
||||
BM_TYPE_RENDER_TARGET_STATIC, //!< 24/32 bit setup internally as a static render target
|
||||
BM_TYPE_RENDER_TARGET_DYNAMIC, //!< 24/32 bit setup internally as a dynamic render target
|
||||
|
||||
// Compressed types (bitmap.c_type)
|
||||
BM_TYPE_DXT1, //!< 24 bit with switchable alpha
|
||||
BM_TYPE_DXT3, //!< 32 bit with 4 bit alpha
|
||||
BM_TYPE_DXT5, //!< 32 bit with 8 bit alpha
|
||||
BM_TYPE_CUBEMAP_DDS, //!< generic DDS cubemap (uncompressed cubemap surface)
|
||||
BM_TYPE_CUBEMAP_DXT1, //!< 24-bit cubemap (compressed cubemap surface)
|
||||
BM_TYPE_CUBEMAP_DXT3, //!< 32-bit cubemap (compressed cubemap surface)
|
||||
BM_TYPE_CUBEMAP_DXT5 //!< 32-bit cubemap (compressed cubemap surface)
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
struct bitmap
|
||||
{
|
||||
short w; //!< Width, in number of pixels
|
||||
short h; //!< Height, in number of pixels
|
||||
short rowsize; //!< What you need to add to go to next row
|
||||
int bpp; //!< Requested bitdepth of each pixel. ( 7, 8, 15, 16, 24, 32)
|
||||
int true_bpp; //!< The image's actual bitdepth
|
||||
ubyte flags; //!< Various texture type flags. @see BMPMAN_CONSTANTS
|
||||
ptr_u data; //!< Pointer to data, or maybe offset into VRAM.
|
||||
ubyte *palette; /**< @brief Pointer to this bitmap's palette (if it has one).
|
||||
* @details If BMP_NO_PALETTE_MAP flag is cleared, this palette just points to the screen palette. (gr_palette)
|
||||
*/
|
||||
};
|
||||
|
||||
extern int bm_texture_ram; //!< how many bytes of textures are used.
|
||||
|
||||
extern int Bm_paging; //!< Bool type that indicates if BMPMAN is currently paging.
|
||||
|
||||
extern const BM_TYPE bm_type_list[]; //!< List of valid bitmap types
|
||||
extern const char *bm_ext_list[]; //!< List of extensions for those types
|
||||
extern const int BM_NUM_TYPES; //!< Calculated number of bitmap types
|
||||
extern const BM_TYPE bm_ani_type_list[]; //!< List of valid bitmap animation types
|
||||
extern const char *bm_ani_ext_list[]; //!< List of extensions for those types
|
||||
extern const int BM_ANI_NUM_TYPES; //!< Calculated number of bitmap animation types
|
||||
|
||||
extern int GLOWMAP; //!< References a map that is a fully lit version of its index -Bobboau
|
||||
extern int SPECMAP; //!< References a map that is for specular mapping -Bobboau
|
||||
extern int ENVMAP; //!< References a map that is for environment mapping -Bobboau
|
||||
extern int NORMMAP; //!< Normal mapping
|
||||
extern int HEIGHTMAP; //!< Height map for normal mapping
|
||||
extern int MISCMAP; //!< Utility map, to be utilized for various things shader authors can come up with
|
||||
|
||||
/**
|
||||
* @brief Initilizes the bitmap manager
|
||||
*/
|
||||
void bm_init();
|
||||
|
||||
/**
|
||||
* @brief Closes the bitmap manager, freeing any allocated memory used by bitmaps. Is called at program close.
|
||||
*/
|
||||
void bm_close();
|
||||
|
||||
/**
|
||||
* Gets the cache slot of the bitmap indexed by handle.
|
||||
*
|
||||
* @details if the bitmap is an ani, gets the first frame
|
||||
*
|
||||
* @returns The cache slot index of the bitmap if handle is valid
|
||||
*
|
||||
* @note If the handle is invalid, an Assert() fails
|
||||
*/
|
||||
int bm_get_cache_slot(int bitmap_id, int separate_ani_frames);
|
||||
|
||||
/**
|
||||
* @brief Gets the next available bitmap slot.
|
||||
*/
|
||||
int bm_get_next_handle();
|
||||
// any texture type
|
||||
#define BMP_TEX_ANY ( BMP_TEX_COMP | BMP_TEX_NONCOMP )
|
||||
|
||||
#define BMP_FLAG_RENDER_TARGET_STATIC (1<<0)
|
||||
#define BMP_FLAG_RENDER_TARGET_DYNAMIC (1<<1)
|
||||
#define BMP_FLAG_CUBEMAP (1<<2)
|
||||
#define BMP_FLAG_RENDER_TARGET_MIPMAP (1<<3)
|
||||
|
||||
/**
|
||||
* @brief Allocates memory for the given handle.
|
||||
*
|
||||
* @returns A pointer to the allocated vm if successful,
|
||||
* @returns Null, if unsuccessful
|
||||
*
|
||||
* @note z64 - This function looks fishy. Not only is handle not used in release builds, but bm_bitmaps[handle].size
|
||||
* and bm_texture_size aren't modified unless this is a debug build
|
||||
*/
|
||||
void *bm_malloc(int handle, int size);
|
||||
typedef struct bitmap {
|
||||
short w, h; // Width and height
|
||||
short rowsize; // What you need to add to go to next row
|
||||
ubyte bpp; // How many bits per pixel it is. (7,8,15,16,24,32) (what is requested)
|
||||
ubyte true_bpp; // How many bits per pixel the image actually is.
|
||||
ubyte flags; // See the BMP_???? defines for values (this isn't for the BMP_FLAG_* stuff)
|
||||
ptr_u data; // Pointer to data, or maybe offset into VRAM.
|
||||
ubyte *palette; // If bpp==8, this is pointer to palette. If the BMP_NO_PALETTE_MAP flag
|
||||
// is not set, this palette just points to the screen palette. (gr_palette)
|
||||
} bitmap;
|
||||
|
||||
|
||||
extern int Bm_paging;
|
||||
|
||||
void bm_init();
|
||||
|
||||
void bm_close();
|
||||
|
||||
int bm_get_cache_slot( int bitmap_id, int separate_ani_frames );
|
||||
|
||||
int bm_get_next_handle();
|
||||
|
||||
void *bm_malloc(int n, int size);
|
||||
|
||||
/**
|
||||
* @brief (DEBUG) Similar to bm_malloc, but only updates how much memory is used
|
||||
*
|
||||
* @note z64 - Also fishy (see bm_malloc)
|
||||
*/
|
||||
void bm_update_memory_used(int n, int size);
|
||||
|
||||
class bitmap_lookup {
|
||||
ubyte *Bitmap_data;
|
||||
// how many bytes of textures are used.
|
||||
extern int bm_texture_ram;
|
||||
|
||||
int Width;
|
||||
int Height;
|
||||
int Num_channels;
|
||||
|
||||
float map_texture_address(float address);
|
||||
public:
|
||||
bitmap_lookup(int bitmap_num);
|
||||
~bitmap_lookup();
|
||||
|
||||
bool valid();
|
||||
|
||||
float get_channel_red(float u, float v);
|
||||
float get_channel_green(float u, float v);
|
||||
float get_channel_blue(float u, float v);
|
||||
float get_channel_alpha(float u, float v);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Loads a bitmap so we can draw with it later.
|
||||
*
|
||||
* @param filename
|
||||
*
|
||||
* @returns The bitmap number if successful, else
|
||||
* @returns a negative value if not
|
||||
*/
|
||||
int bm_load(const char* filename);
|
||||
|
||||
/**
|
||||
* @brief Loads a bitmap so we can draw with it later. (Preferred version)
|
||||
*
|
||||
* @param filename
|
||||
*
|
||||
* @returns The bitmap number if successful, else
|
||||
* @returns a negative value if not
|
||||
*/
|
||||
// This loads a bitmap so we can draw with it later.
|
||||
// It returns a negative number if it couldn't load
|
||||
// the bitmap. On success, it returns the bitmap
|
||||
// number.
|
||||
int bm_load(char * filename);
|
||||
int bm_load(const SCP_string& filename);
|
||||
|
||||
/**
|
||||
* @brief Reloads a bitmap as a duplicate.
|
||||
*
|
||||
* @details This function basically allows you to load a bitmap which already exists (by filename). This is useful
|
||||
* because in some cases we need to have a bitmap which is locked in screen format _and_ texture format, such as
|
||||
* the pilot pics and squad logos
|
||||
*
|
||||
* @param filename
|
||||
*
|
||||
* @returns The bitmap number if successful, else
|
||||
* @returns a negative value if not
|
||||
*/
|
||||
int bm_load_duplicate(const char *filename);
|
||||
// special load function. basically allows you to load a bitmap which already exists (by filename).
|
||||
// this is useful because in some cases we need to have a bitmap which is locked in screen format
|
||||
// _and_ texture format, such as pilot pics and squad logos
|
||||
int bm_load_duplicate(char *filename);
|
||||
|
||||
/**
|
||||
* Loads a bitmap which exists somewhere in the RAM.
|
||||
*
|
||||
* @param bpp The bitdepth of the bitmap
|
||||
* @param w The width of the bitmap
|
||||
* @param h The height of the bitmap
|
||||
* @param[in] data The bitmap's data glob
|
||||
* @param flags
|
||||
*
|
||||
* @note The used RAM cannot be freed until bm_release is called on the created bitmap
|
||||
*/
|
||||
int bm_create(int bpp, int w, int h, void *data = NULL, int flags = 0);
|
||||
// Creates a bitmap that exists in RAM somewhere, instead
|
||||
// of coming from a disk file. You pass in a pointer to a
|
||||
// block of data. The data can be in the following formats:
|
||||
// 8 bpp (mapped into game palette)
|
||||
// 32 bpp
|
||||
// On success, it returns the bitmap number. You cannot
|
||||
// free that RAM until bm_release is called on that bitmap.
|
||||
// See example at bottom of this file
|
||||
int bm_create( int bpp, int w, int h, void *data = NULL, int flags = 0);
|
||||
|
||||
/**
|
||||
* @brief Unloads a bitmap's data, but not the bitmap info
|
||||
*
|
||||
* @details The bm number (n) may be reused once this function has been called on it. However, it will have to be paged
|
||||
* in the next time it is locked.
|
||||
// Frees up a bitmap's data, but bitmap number 'n' can
|
||||
// still be used, it will just have to be paged in next
|
||||
// time it is locked.
|
||||
int bm_unload( int n, int clear_render_targets = 0 );
|
||||
|
||||
* @param handle The index number of the bitmap to free
|
||||
* @param clear_render_targets If true, release a render target
|
||||
* @param nodebug If true, exclude certain debug messages
|
||||
*
|
||||
* @returns 0 if not successful,
|
||||
* @returns 1 if successful
|
||||
*/
|
||||
int bm_unload(int handle, int clear_render_targets = 0, bool nodebug = false);
|
||||
// like bm_unload() except that it's safe to use to free data without worrying about
|
||||
// load_count so it's safe to use in relation to bm_release() and in gr_*_texture functions
|
||||
int bm_unload_fast( int n, int clear_render_targets = 0 );
|
||||
|
||||
/**
|
||||
* @brief Quickly unloads a bitmap's data, ignoring the load_count
|
||||
*
|
||||
* @details Similar to bm_unload(), except that it can be safely used to free data without worrying about load_count.
|
||||
* It's safe to use in relation to bm_release() and in gr_*_texture functions
|
||||
*
|
||||
* @param handle The bm number of the bitmap to free
|
||||
* @param clear_render_targets If true, release a render target
|
||||
*
|
||||
* @note bm_free_data_fast() is used here and NOT bm_free_data()
|
||||
*/
|
||||
int bm_unload_fast(int handle, int clear_render_targets = 0);
|
||||
// Frees up a bitmap's data, and it's slot, so bitmap
|
||||
// number 'n' cannot be used anymore, and bm_load or
|
||||
// bm_create might reuse the slot.
|
||||
int bm_release( int n, int clear_render_targets = 0 );
|
||||
|
||||
/**
|
||||
* @brief Frees both a bitmap's data and it's associated slot.
|
||||
*
|
||||
* @details Once called, the bm number 'n' cannot be used until bm_load or bm_create is re-inits the slot.
|
||||
*
|
||||
* @param handle The index number of the bitmap to release
|
||||
* @param clear_render_targets If nonzero, also release render targets
|
||||
*
|
||||
* @returns 1 on success,
|
||||
* @returns 0 otherwise
|
||||
*
|
||||
* @note If the passed handle is that of an ANI, it frees EVERY frame. Be sure to only pass the handle of the first frame!
|
||||
*
|
||||
* @todo upgrade return type and clear_render_targets type to bools
|
||||
*/
|
||||
int bm_release(int handle, int clear_render_targets = 0);
|
||||
// This loads a bitmap sequence so we can draw with it later.
|
||||
// It returns a negative number if it couldn't load
|
||||
// the bitmap. On success, it returns the bitmap
|
||||
// number of the first frame and nframes is set.
|
||||
extern int bm_load_animation( char * filename, int * nframes = NULL, int *fps = NULL, int *keyframe = NULL, int can_drop_frames = 0, int dir_type = CF_TYPE_ANY );
|
||||
|
||||
/**
|
||||
* @brief Loads a bitmap sequance so we can draw with it.
|
||||
*
|
||||
* @param[in] filename
|
||||
* @param[out] nframes If non-null, set to the number of frames the animation has
|
||||
* @param[out] fps If non-null, set to the fps of this animation
|
||||
* @param[out] keyframe if non null, set to the keyframe index of this animation
|
||||
* @param[in] can_drop_frames If set, allows dropped frames
|
||||
* @param[in] dir_type Directory type
|
||||
*
|
||||
* @returns The bm number of the first bitmap in the sequence if successful, or
|
||||
* @returns A negative value if unsuccessful
|
||||
*/
|
||||
int bm_load_animation(const char *filename, int *nframes = nullptr, int *fps = nullptr, int *keyframe = nullptr, float *total_time = nullptr, bool can_drop_frames = 0, int dir_type = CF_TYPE_ANY);
|
||||
//Loads either animation (bm_load_animation) or still image (bm_load)
|
||||
extern int bm_load_either(char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, int can_drop_frames = 0, int dir_type = CF_TYPE_ANY);
|
||||
|
||||
/**
|
||||
* @brief Loads either animation (bm_load_animation) or still image (bm_load)
|
||||
*
|
||||
* @param[in] filename
|
||||
* @param[out] nframes If non-null and loading was successful, set to the number of frames the animation has
|
||||
* @param[out] fps If non-null and loading was successful, set to the fps of this animation
|
||||
* @param[out] keyframe if non null and loading was successful, set to the keyframe index of this animation
|
||||
* @param[in] can_drop_frames
|
||||
* @param[in] dir_type
|
||||
*
|
||||
* @returns The bm number of the first bitmap in the sequence if successful, or
|
||||
* @returns A negative value if unsuccessful
|
||||
*/
|
||||
int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, bool can_drop_frames = false, int dir_type = CF_TYPE_ANY);
|
||||
// This locks down a bitmap and returns a pointer to a bitmap
|
||||
// that can be accessed until you call bm_unlock. Only lock
|
||||
// a bitmap when you need it! This will convert it into the
|
||||
// appropriate format also.
|
||||
extern bitmap * bm_lock( int bitmapnum, ubyte bpp, ubyte flags );
|
||||
|
||||
/**
|
||||
* @brief Locks down the bitmap indexed by bitmapnum.
|
||||
*
|
||||
* @details Also converts the bitmap to the appropriate format specified by bpp and flags. Only lock a bitmap when you
|
||||
* need it!
|
||||
*
|
||||
* @param handle The number indexing the desired bitmap
|
||||
* @param bpp The desired bpp of the bitmep
|
||||
* @param flags The desired bitmap format
|
||||
* @param nodebug
|
||||
// The signature is a field that gets filled in with
|
||||
// a unique signature for each bitmap. The signature for each bitmap
|
||||
// will also change when the bitmap's data changes.
|
||||
extern uint bm_get_signature( int bitmapnum);
|
||||
|
||||
* @returns A pointer to the bitmap that's valid until bm_unlock is called if successful, or
|
||||
* @returns NULL if unsuccessful
|
||||
*/
|
||||
bitmap* bm_lock(int handle, int bpp, ubyte flags, bool nodebug = false);
|
||||
//gets the image type
|
||||
ubyte bm_get_type(int handle);
|
||||
|
||||
/**
|
||||
* @brief Returns a unique signiature for the bitmap indexed by handle
|
||||
*
|
||||
* @details A signature will change when the bitmap's data changes
|
||||
*/
|
||||
uint bm_get_signature(int handle);
|
||||
// Unlocks a bitmap
|
||||
extern void bm_unlock( int bitmapnum );
|
||||
|
||||
/**
|
||||
* @brief Returns the image type of the given bitmap handle
|
||||
*/
|
||||
BM_TYPE bm_get_type(int handle);
|
||||
//WMC - Returns 0 if invalid, nonzero if valid
|
||||
extern int bm_is_valid(int handle);
|
||||
|
||||
/**
|
||||
* @brief Unlocks a bitmap
|
||||
*
|
||||
* @details Decrements the ref_count member of the bitmap_entry struct, A bitmap can only be unloaded when the
|
||||
* ref_count is 0
|
||||
*/
|
||||
void bm_unlock(int handle);
|
||||
// Gets info. w,h,or flags,nframes or fps can be NULL if you don't care.
|
||||
//WMC - Returns -1 on failure, handle or first frame handle on success.
|
||||
int bm_get_info( int bitmapnum, int *w=NULL, int * h=NULL, ubyte * flags=NULL, int *nframes=NULL, int *fps=NULL );
|
||||
|
||||
/**
|
||||
* @brief Checks if the bitmap indexed by handle is valid
|
||||
*
|
||||
* @details Some early known false or out of range handles (such as negative) are checked within
|
||||
* an initial routine pass, followed by a more thorough check routine to ensure the
|
||||
* series of bitmaps within the bm_bitmaps[] structure have not become invalid.
|
||||
*
|
||||
* @returns Nonzero if valid, else
|
||||
* @returns Zero otherwise
|
||||
*
|
||||
* @todo z64 - Returned value is essentially a bool type, need to check all caller functions to see if it can safely
|
||||
* be updated to reflect this
|
||||
*/
|
||||
int bm_is_valid(int handle);
|
||||
// get filename
|
||||
extern void bm_get_filename(int bitmapnum, char *filename);
|
||||
|
||||
/**
|
||||
* @brief Gets info on the bitmap indexed by handle.
|
||||
*
|
||||
* @param[out] w If non-null, gets the width
|
||||
* @param[out] h If non-null, gets the heigth
|
||||
* @param[out] flags If non-null, gets the flags
|
||||
* @param[out] nframs If non-null, gets the nframes
|
||||
* @param[out] fps If non-null, gets the fps
|
||||
*
|
||||
* @returns The handle on success, or
|
||||
* @returns The handle to the first frame on success, or
|
||||
* @returns -1 on failure
|
||||
*/
|
||||
int bm_get_info(int handle, int *w = NULL, int * h = NULL, ubyte * flags = NULL, int *nframes = NULL, int *fps = NULL);
|
||||
// call to load all data for all bitmaps that have been requested to be loaded
|
||||
extern void bm_gfx_load_all();
|
||||
extern void bm_unload_all();
|
||||
|
||||
/**
|
||||
* @brief Gets the filename of the bitmap indexed by handle
|
||||
*
|
||||
* @param[out] filename The filename of the bitmap, if successful. Is set to an empty string if unseccessful
|
||||
*
|
||||
* @todo z64 - maybe deprecate this in favor of an SCP_string version
|
||||
*/
|
||||
void bm_get_filename(int bitmapnum, char *filename);
|
||||
// call to get the palette for a bitmap
|
||||
void bm_get_palette(int n, ubyte *pal, char *name);
|
||||
|
||||
/**
|
||||
* @brief Gets the filename of the bitmap indexed by handle, which must exist.
|
||||
*
|
||||
* @details If the bitmap does not exist (i.e. the handle is invalid), then an Assertion halts program execution.
|
||||
*
|
||||
* @returns A const char* to the filename of the bitmap
|
||||
*
|
||||
* @todo z64 - maybe deprecate this in favor of an SCP_string version.
|
||||
* @todo z64 - maybe combine this with the other bm_get_filename function like so:
|
||||
* void bm_get_filename(int handle, SCP_string *filename, bool must_exist = false);
|
||||
*/
|
||||
const char *bm_get_filename(int handle);
|
||||
// Hacked function to get a pixel from a bitmap.
|
||||
// Only works good in 8bpp mode.
|
||||
void bm_gfx_get_pixel( int bitmap, float u, float v, ubyte *r, ubyte *g, ubyte *b );
|
||||
|
||||
/**
|
||||
* @brief Loads all data for all bitmaps that have been requested to be loaded
|
||||
*
|
||||
* @note This function is not defined.
|
||||
*/
|
||||
void bm_gfx_load_all();
|
||||
|
||||
/**
|
||||
* @brief Unloads all used bitmaps, should only ever be called by game_shutdown()
|
||||
*
|
||||
* @todo Maybe move this declaration into bmpman.cpp and then extern this function within game_shutdown() to
|
||||
* ensure it only ever gets called there.
|
||||
*/
|
||||
void bm_unload_all();
|
||||
|
||||
/**
|
||||
* @brief Gets the palette for a given bitmap indexed by handle, and optionally the filename
|
||||
*
|
||||
* @param[out] pal Is set to reference the bitmap's palette
|
||||
* @param[out] name (optional) Is set to the bitmap's filename
|
||||
*
|
||||
* @todo Maybe get rid of the optional filename and have the callers call bm_get_filename. Less efficient, however.
|
||||
*/
|
||||
void bm_get_palette(int handle, ubyte *pal, char *name);
|
||||
|
||||
/**
|
||||
* @brief Hack to get a pixel from a bitmap
|
||||
*
|
||||
* @details only works good in 8bpp mode
|
||||
*
|
||||
* @note This function is not defined.
|
||||
*/
|
||||
void bm_gfx_get_pixel(int bitmap, float u, float v, ubyte *r, ubyte *g, ubyte *b);
|
||||
|
||||
/**
|
||||
* @brief (DEBUG) Gets memory size, in bytes, of the locked bitmaps
|
||||
*
|
||||
* @details Both params are non-optional, and must be non-null. There's currently no safety checks on either.
|
||||
*
|
||||
* @param ntotal[out] Memory size, in bytes, of the locked bitmaps
|
||||
* @param nnew[out] Memory size, in bytes, of the bitmaps that were locked since the last frame
|
||||
*
|
||||
* @note This is a debug function, and is undefined within release builds
|
||||
*/
|
||||
// Returns number of bytes of bitmaps locked this frame
|
||||
// ntotal = number of bytes of bitmaps locked this frame
|
||||
// nnew = number of bytes of bitmaps locked this frame that weren't locked last frame
|
||||
void bm_get_frame_usage(int *ntotal, int *nnew);
|
||||
|
||||
/**
|
||||
* @brief Reloads an existing bmpman slot with different bitmap
|
||||
*
|
||||
* @param[in] filename The filename of the image to load
|
||||
*
|
||||
* @returns The bitmap handle on success, or
|
||||
* @returns A negative value on failure
|
||||
*
|
||||
* @note This should only be used if you are certain the new picture is the same type, has same dimensions, etc.
|
||||
*/
|
||||
int bm_reload(int bitmap_handle, const char* filename);
|
||||
/*
|
||||
* Example on using bm_create
|
||||
*
|
||||
{
|
||||
static int test_inited = 0;
|
||||
static int test_bmp;
|
||||
static uint test_bmp_data[128*64];
|
||||
|
||||
if ( !test_inited ) {
|
||||
test_inited = 1;
|
||||
// Create the new bitmap and fill in its data.
|
||||
// When you're done with it completely, call
|
||||
// bm_release to free up the bitmap handle
|
||||
test_bmp = bm_create( 32, 128, 64, test_bmp_data );
|
||||
int i,j;
|
||||
for (i=0; i<64; i++ ) {
|
||||
for (j=0; j<64; j++ ) {
|
||||
uint r=i*4;
|
||||
test_bmp_data[j+i*128] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bm_unload(test_bmp); // this pages out the data, so that the
|
||||
// next bm_lock will convert the new data to the
|
||||
// correct bpp
|
||||
|
||||
// put in new data
|
||||
int x,y;
|
||||
gr_reset_clip();
|
||||
for (y=0; y<64; y++)
|
||||
for (x=0; x<128; x++ )
|
||||
test_bmp_data[y*128+x] = 15;
|
||||
|
||||
// Draw the bitmap to upper left corner
|
||||
gr_set_bitmap(test_bmp);
|
||||
gr_bitmap( 0,0 );
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//============================================================================
|
||||
// Paging stuff
|
||||
//============================================================================
|
||||
|
||||
/**
|
||||
* @brief Tells bmpman to start keeping track of what bitmaps are used where
|
||||
*/
|
||||
void bm_page_in_start();
|
||||
|
||||
/**
|
||||
* @brief Tells bmpman to stop paging (?)
|
||||
*/
|
||||
void bm_page_in_stop();
|
||||
|
||||
// Paging code in a library should call these functions
|
||||
// in its page in function.
|
||||
|
||||
/**
|
||||
* @brief Marks a texture as being used for this level
|
||||
*
|
||||
* @param[in] num_frames If specified, assumes this is an animated texture
|
||||
*/
|
||||
void bm_page_in_texture(int bitmapnum, int num_frames = 0);
|
||||
// Marks a texture as being used for this level
|
||||
// If num_frames is passed, assume this is an animation
|
||||
void bm_page_in_texture( int bitmapnum, int num_frames = 0 );
|
||||
|
||||
/**
|
||||
* @brief Marks a textures as being used for level and is transparant
|
||||
*
|
||||
* @param[in] num_frames If specified, assumes this is an animated texture
|
||||
*/
|
||||
void bm_page_in_xparent_texture(int bitmapnum, int num_frames = 1);
|
||||
// marks a texture as being a transparent textyre used for this level
|
||||
// Marks a texture as being used for this level
|
||||
// If num_frames is passed, assume this is an animation
|
||||
void bm_page_in_xparent_texture( int bitmapnum, int num_frames=1 );
|
||||
|
||||
/**
|
||||
* @brief Marks a texture as being used for this level, and is anti-aliased
|
||||
*
|
||||
* @param[in] num_frames If specified, assumes this is an animated texture
|
||||
*/
|
||||
void bm_page_in_aabitmap(int bitmapnum, int num_frames = 1);
|
||||
// Marks an aabitmap as being used for this level
|
||||
// If num_frames is passed, assume this is an animation
|
||||
void bm_page_in_aabitmap( int bitmapnum, int num_frames=1 );
|
||||
|
||||
/**
|
||||
* @brief Unloads the bitmap indexed by handle that was previously paged-in
|
||||
*
|
||||
* @returns 0 If the bitmap had already been released, or
|
||||
* @returns 0 If the handle is invalid, or
|
||||
* @returns 1 If successful
|
||||
*/
|
||||
bool bm_page_out(int handle);
|
||||
// unload a texture that was paged in
|
||||
int bm_page_out( int handle );
|
||||
|
||||
/**
|
||||
* @brief Sets BMPMAN's memory mode
|
||||
*
|
||||
* @details 0 = High memory;
|
||||
* 1 = Low memory (loads every other frame of ani's);
|
||||
* 2 = Debug low memory (only use first frame of each ani)
|
||||
*
|
||||
* @todo This should use an enum, or instead allow an arbitrary number to drop frames (like 1/2, 1/3, etc.)
|
||||
*/
|
||||
void bm_set_low_mem(int mode);
|
||||
//
|
||||
// Mode: 0 = High memory
|
||||
// 1 = Low memory ( every other frame of ani's)
|
||||
// 2 = Debug low memory ( only use first frame of each ani )
|
||||
void bm_set_low_mem( int mode );
|
||||
|
||||
char *bm_get_filename(int handle);
|
||||
|
||||
/**
|
||||
* @brief Sets bm_set_components and bm_get_components to reference screen format functions
|
||||
*/
|
||||
void BM_SELECT_SCREEN_FORMAT();
|
||||
|
||||
/**
|
||||
* @brief Sets bm_set_components and bm_get_components to reference texture format functions
|
||||
*/
|
||||
void BM_SELECT_TEX_FORMAT();
|
||||
|
||||
/**
|
||||
* @brief Sets bm_set_components and bm_get_components to reference texture format functions (with alpha)
|
||||
*/
|
||||
void BM_SELECT_ALPHA_TEX_FORMAT();
|
||||
|
||||
/**
|
||||
* @brief Functional pointer that references any of the bm_set_components functions.
|
||||
*
|
||||
* @details The bm_set_components functions packs the RGBA values into the ubyte array referenced by pixel, whose
|
||||
* format differs according to its bpp value and presence of an alpha channel. The RGBA values are scaled accordingly.
|
||||
*
|
||||
* @param[out] pixel The pixel to set
|
||||
* @param[in] r Red value (may not be NULL)
|
||||
* @param[in] g Green value (may not be NULL)
|
||||
* @param[in] b Blue value (may not be NULL)
|
||||
* @param[in] a Alpha value (currently ignored)
|
||||
*
|
||||
* @note z64 - These functions were made predating the introduction of C++ classes, and are basically the equivalent
|
||||
* of Pixel::set(ubyte *r, ubyte *b, ubyte *g). The original comment mentions that any of the rgba params may be
|
||||
* NULL, but this is by far _NOT_ the case, as a NULL value will cause undefined behavior (really really bad chroma
|
||||
* corruption)
|
||||
*
|
||||
* @note These functions assume the incoming bitdepth will always be >= to the outgoing bitdepth of the pixel. Should
|
||||
* the incoming bitdepth be lower, the outgoing values will appear darker than they should be
|
||||
*/
|
||||
extern void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
// set the rgba components of a pixel, any of the parameters can be NULL
|
||||
extern void (*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
extern void (*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
void bm_set_components_argb_d3d_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
void bm_set_components_argb_d3d_32_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
void bm_set_components_argb_d3d_16_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
void bm_set_components_argb_d3d_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Functional pointer that references any of the bm_set_components_32 functions.
|
||||
*
|
||||
* @details The bm_set_components functions packs the RGBA values into the ubyte array referenced by pixel, whose
|
||||
* format differs according to its bpp value and presence of an alpha channel. The RGBA values are scaled accordingly.
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
extern void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 16bpp screen pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 32bpp screen pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_32_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 16bpp texture pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_16_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 32bpp texture pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Gets the RGBA components of a pixel according to the selected mode
|
||||
*
|
||||
* @see BM_SELECT_SCREEN_FORMAT() BM_SELECT_TEX_FORMAT() BM_SELECT_ALPHA_TEX_FORMAT()
|
||||
*/
|
||||
// get the rgba components of a pixel, any of the parameters can be NULL
|
||||
void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
extern int UNLITMAP; //this holds a reference to a map that is optional used instead of the base map for unlit rendering
|
||||
extern int GLOWMAP; //this holds a reference to a map that is a fully lit version of its index -Bobboau
|
||||
extern int SPECMAP; //this holds a reference to a map that is for specular mapping -Bobboau
|
||||
extern int SPECGLOSSMAP; //this holds a reference to a map that is for specular mapping -Bobboau
|
||||
extern int ENVMAP; //this holds a reference to a map that is for environment mapping -Bobboau
|
||||
extern int NORMMAP; // normal mapping
|
||||
extern int HEIGHTMAP; // height map for normal mapping
|
||||
extern int AMBIENTMAP; // ambient occluion map. red channel affects ambient lighting, green channel affects diffuse and specular
|
||||
extern int MISCMAP; // Utility map, to be utilized for various things shader authors can come up with
|
||||
|
||||
/**
|
||||
* @brief Returns the compression type of the bitmap indexed by handle
|
||||
*/
|
||||
int bm_is_compressed(int handle);
|
||||
int bm_is_compressed(int num);
|
||||
int bm_get_tcache_type(int num);
|
||||
int bm_get_size(int num);
|
||||
int bm_get_num_mipmaps(int num);
|
||||
int bm_has_alpha_channel(int handle);
|
||||
|
||||
/**
|
||||
* @brief Gets the correct TCACHE_TYPE for compressed graphics (uncompressed are assumed TCACHE_TYPE_NORMAL)
|
||||
*/
|
||||
int bm_get_tcache_type(int handle);
|
||||
|
||||
/**
|
||||
* @brief Gets the size, in bytes, taken up by the bitmap indexed by handle
|
||||
*/
|
||||
size_t bm_get_size(int handle);
|
||||
|
||||
/**
|
||||
* @brief Gets the number of mipmaps of the indexed texture
|
||||
*/
|
||||
int bm_get_num_mipmaps(int handle);
|
||||
|
||||
/**
|
||||
* @brief Checks to see if the indexed bitmap has an alpha channel
|
||||
*
|
||||
* @note Currently just checks if the bitmap is 32bpp and is not a .PCX
|
||||
*/
|
||||
bool bm_has_alpha_channel(int handle);
|
||||
|
||||
/**
|
||||
* @brief (DEBUG) Prints all loaded bitmaps to an outwindow
|
||||
*/
|
||||
void bm_print_bitmaps();
|
||||
|
||||
/**
|
||||
* @brief Creates a render target as close to the desired resolution as possible.
|
||||
*
|
||||
* @returns the handle of an avilable render target if successful, or
|
||||
* @returns -1 if not successful
|
||||
*
|
||||
* @note BM_FLAG_RENDER_TARGET_STATIC are drawn once/infrequently, while BM_FLAG_RENDER_TARGET_DYNAMIC are drawn roughly once every frame
|
||||
*/
|
||||
int bm_make_render_target(int width, int height, int flags);
|
||||
|
||||
/**
|
||||
* @brief Checks to see if the given bitmap indexed by handle is a render target
|
||||
*
|
||||
* @returns The render type (BM_TYPE) if it is a render target, or
|
||||
* @returns 0 if it is not
|
||||
*/
|
||||
int bm_is_render_target(int handle);
|
||||
|
||||
/**
|
||||
* @brief (GR function) Calls gr_bm_set_render target for the given bitmap indexed by handle
|
||||
*
|
||||
* @returns true if successful, or
|
||||
* @returns false if unsuccessful
|
||||
*/
|
||||
bool bm_set_render_target(int handle, int face = -1);
|
||||
|
||||
/**
|
||||
* @brief Loads and parses an .EFF
|
||||
*
|
||||
* @param[in] filename The filename of the .EFF
|
||||
* @param[in] dir_type
|
||||
* @param[out] nframes (optional) If given, is set to the number of frames this .EFF has
|
||||
* @param[out] nfps (optional) If given, is set to the fps of this .EFF
|
||||
* @param[out] key (optional) If given, is set to the keyframe index of this .EFF
|
||||
* @param[out] type (optional) If given, is set to the BM_TYPE of the .EFF
|
||||
*
|
||||
* @returns true If successful
|
||||
* @returns false If not successful
|
||||
*/
|
||||
bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, BM_TYPE *type);
|
||||
|
||||
/**
|
||||
* @brief Calculates & returns the current frame of an animation
|
||||
*
|
||||
* @param[in] frame1_handle Handle of the animation
|
||||
* @param[in] elapsed_time Time in seconds since the animation started playing
|
||||
* @param[in] loop (optional) specifies if the animation should loop, default is false which causes animation to hold on the last frame
|
||||
* @param[in] divisor (optional) if greater than zero, elapsed time will be divided by this value i.e. allows "percentage complete" to be used to determine the frame instead of the animations total time derived from fps * frames
|
||||
*
|
||||
* @returns current frame of the animation (range is zero to the number of frames minus one)
|
||||
*/
|
||||
int bm_get_anim_frame(const int frame1_handle, float elapsed_time, const float divisor = 0.0f, const bool loop = false);
|
||||
int bm_make_render_target( int width, int height, int flags );
|
||||
int bm_is_render_target(int bitmap_id);
|
||||
int bm_set_render_target(int handle, int face = -1);
|
||||
|
||||
#endif
|
||||
+44
-162
@@ -1,15 +1,15 @@
|
||||
#include "camera/camera.h"
|
||||
#include "globalincs/alphacolors.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "globalincs/systemvars.h" //VM_FREECAMERA etc
|
||||
#include "graphics/font.h"
|
||||
#include "hud/hud.h" //hud_get_draw
|
||||
#include "math/vecmat.h"
|
||||
#include "mod_table/mod_table.h"
|
||||
#include "model/model.h" //polymodel, model_get
|
||||
#include "graphics/2d.h"
|
||||
#include "globalincs/alphacolors.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "physics/physics.h" //apply_physics
|
||||
#include "globalincs/systemvars.h" //VM_FREECAMERA etc
|
||||
#include "hud/hud.h" //hud_get_draw
|
||||
#include "model/model.h" //polymodel, model_get
|
||||
#include "playerman/player.h" //player_get_padlock_orient
|
||||
#include "ship/ship.h" //compute_slew_matrix
|
||||
#include "graphics/font.h"
|
||||
|
||||
//*************************IMPORTANT GLOBALS*************************
|
||||
float VIEWER_ZOOM_DEFAULT = 0.75f; // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
|
||||
@@ -80,7 +80,7 @@ void camera::reset()
|
||||
|
||||
void camera::set_name(char *in_name)
|
||||
{
|
||||
if(in_name != NULL)
|
||||
if(name != NULL)
|
||||
strncpy(name, in_name, NAME_LENGTH-1);
|
||||
}
|
||||
|
||||
@@ -109,27 +109,6 @@ void camera::set_object_host(object *objp, int n_object_host_submodel)
|
||||
|
||||
object_host = object_h(objp);
|
||||
object_host_submodel = n_object_host_submodel;
|
||||
set_custom_position_function(NULL);
|
||||
set_custom_orientation_function(NULL);
|
||||
if(n_object_host_submodel > 0)
|
||||
{
|
||||
if(objp->type == OBJ_SHIP)
|
||||
{
|
||||
ship_subsys* ssp = GET_FIRST(&Ships[objp->instance].subsys_list);
|
||||
while ( ssp != END_OF_LIST( &Ships[objp->instance].subsys_list ) )
|
||||
{
|
||||
if(ssp->system_info->subobj_num == n_object_host_submodel)
|
||||
{
|
||||
if(ssp->system_info->type == SUBSYSTEM_TURRET)
|
||||
{
|
||||
set_custom_position_function(get_turret_cam_pos);
|
||||
set_custom_orientation_function(get_turret_cam_orient);
|
||||
}
|
||||
}
|
||||
ssp = GET_NEXT( ssp );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void camera::set_object_target(object *objp, int n_object_target_submodel)
|
||||
@@ -161,7 +140,7 @@ void camera::set_custom_orientation_function(void (*n_func_custom_orientation)(c
|
||||
|
||||
void camera::set_position(vec3d *in_position, float in_translation_time, float in_translation_acceleration_time, float in_translation_deceleration_time, float in_end_velocity)
|
||||
{
|
||||
if(in_position != NULL && in_translation_time == 0.0f && in_translation_acceleration_time == 0.0f && in_translation_deceleration_time == 0.0f)
|
||||
if(in_translation_time == 0.0f && in_translation_acceleration_time == 0.0f && in_translation_deceleration_time == 0.0f)
|
||||
{
|
||||
c_pos = *in_position;
|
||||
pos_x.set(c_pos.xyz.x);
|
||||
@@ -194,7 +173,7 @@ void camera::set_translation_velocity(vec3d *in_velocity, float in_acceleration_
|
||||
|
||||
void camera::set_rotation(matrix *in_orientation, float in_rotation_time, float in_rotation_acceleration_time, float in_rotation_deceleration_time)
|
||||
{
|
||||
if(in_orientation != NULL && in_rotation_time == 0.0f && in_rotation_acceleration_time == 0.0f && in_rotation_deceleration_time == 0.0f)
|
||||
if(in_rotation_time == 0.0f && in_rotation_acceleration_time == 0.0f && in_rotation_deceleration_time == 0.0f)
|
||||
{
|
||||
c_ori = *in_orientation;
|
||||
for(int i = 0; i < 9; i++)
|
||||
@@ -291,14 +270,11 @@ float camera::get_fov()
|
||||
return c_fov;
|
||||
}
|
||||
|
||||
eye* get_submodel_eye(polymodel *pm, int submodel_num);
|
||||
void camera::get_info(vec3d *position, matrix *orientation)
|
||||
{
|
||||
if(position == NULL && orientation == NULL)
|
||||
return;
|
||||
|
||||
eye* eyep = NULL;
|
||||
vec3d host_normal;
|
||||
|
||||
//POSITION
|
||||
if(!(flags & CAM_STATIONARY_POS) || object_host.IsValid())
|
||||
{
|
||||
@@ -327,20 +303,7 @@ void camera::get_info(vec3d *position, matrix *orientation)
|
||||
}
|
||||
else
|
||||
{
|
||||
eyep = get_submodel_eye(pm, object_host_submodel);
|
||||
if(eyep)
|
||||
{
|
||||
Assertion(objp->type == OBJ_SHIP, "This part of the code expects the object to be a ship");
|
||||
|
||||
vec3d c_pos_in;
|
||||
find_submodel_instance_point_normal(&c_pos_in, &host_normal, Ships[objp->instance].model_instance_num, eyep->parent, &eyep->pnt, &eyep->norm);
|
||||
vm_vec_unrotate(&c_pos, &c_pos_in, &objp->orient);
|
||||
vm_vec_add2(&c_pos, &objp->pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
model_find_world_point( &c_pos, &pt, pm->id, object_host_submodel, &objp->orient, &objp->pos );
|
||||
}
|
||||
model_find_world_point( &c_pos, &pt, pm->id, object_host_submodel, &objp->orient, &objp->pos );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -349,7 +312,7 @@ void camera::get_info(vec3d *position, matrix *orientation)
|
||||
}
|
||||
|
||||
//Do custom position stuff, if needed
|
||||
if(func_custom_position != NULL && !eyep)
|
||||
if(func_custom_position != NULL)
|
||||
{
|
||||
func_custom_position(this, &c_pos);
|
||||
}
|
||||
@@ -361,7 +324,6 @@ void camera::get_info(vec3d *position, matrix *orientation)
|
||||
//ORIENTATION
|
||||
if(orientation != NULL)
|
||||
{
|
||||
bool target_set = false;
|
||||
if(!(flags & CAM_STATIONARY_ORI) || object_target.IsValid() || object_host.IsValid())
|
||||
{
|
||||
if(object_target.IsValid())
|
||||
@@ -391,19 +353,10 @@ void camera::get_info(vec3d *position, matrix *orientation)
|
||||
vec3d targetvec;
|
||||
vm_vec_normalized_dir(&targetvec, &target_pos, &c_pos);
|
||||
vm_vector_2_matrix(&c_ori, &targetvec, NULL, NULL);
|
||||
target_set = true;
|
||||
}
|
||||
else if(object_host.IsValid())
|
||||
{
|
||||
if(eyep)
|
||||
{
|
||||
vm_vector_2_matrix(&c_ori, &host_normal, vm_vec_same(&host_normal, &object_host.objp->orient.vec.uvec)?NULL:&object_host.objp->orient.vec.uvec, NULL);
|
||||
target_set = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ori = object_host.objp->orient;
|
||||
}
|
||||
c_ori = object_host.objp->orient;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -423,7 +376,7 @@ void camera::get_info(vec3d *position, matrix *orientation)
|
||||
vm_orthogonalize_matrix(&c_ori);
|
||||
}
|
||||
//Do custom orientation stuff, if needed
|
||||
if(func_custom_orientation != NULL && !target_set)
|
||||
if(func_custom_orientation != NULL)
|
||||
{
|
||||
func_custom_orientation(this, &c_ori);
|
||||
}
|
||||
@@ -515,8 +468,8 @@ void warp_camera::do_frame(float in_frametime)
|
||||
|
||||
float tmp_angle = frand()*PI2;
|
||||
|
||||
tmp.xyz.x = 22.0f * sinf(tmp_angle);
|
||||
tmp.xyz.y = -22.0f * cosf(tmp_angle);
|
||||
tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
|
||||
tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
|
||||
|
||||
this->set_velocity( &tmp, 0 );
|
||||
}
|
||||
@@ -540,17 +493,8 @@ void warp_camera::get_info(vec3d *position, matrix *orientation)
|
||||
//*************************subtitle*************************
|
||||
|
||||
#define MAX_SUBTITLE_LINES 64
|
||||
subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char* in_imageanim, float in_display_time,
|
||||
float in_fade_time, const color *in_text_color, int in_text_fontnum, bool center_x, bool center_y, int in_width,
|
||||
int in_height, bool in_post_shaded)
|
||||
:display_time(-1.0f), fade_time(-1.0f), text_fontnum(-1), time_displayed(-1.0f), time_displayed_end(-1.0f),
|
||||
post_shaded(false)
|
||||
subtitle::subtitle(int in_x_pos, int in_y_pos, char* in_text, char* in_imageanim, float in_display_time, float in_fade_time, color *in_text_color, int in_text_fontnum, bool center_x, bool center_y, int in_width, int in_height, bool in_post_shaded)
|
||||
{
|
||||
// Initialize color
|
||||
gr_init_color(&text_color, 0, 0, 0);
|
||||
|
||||
SCP_string text_buf;
|
||||
|
||||
// basic init, this always has to be done
|
||||
memset( imageanim, 0, sizeof(imageanim) );
|
||||
memset( &text_pos, 0, 2*sizeof(int) );
|
||||
@@ -560,16 +504,17 @@ subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char*
|
||||
if ( ((in_text != NULL) && (strlen(in_text) <= 0)) && ((in_imageanim != NULL) && (strlen(in_imageanim) <= 0)) )
|
||||
return;
|
||||
|
||||
char text_buf[256];
|
||||
if (in_text != NULL && in_text[0] != '\0')
|
||||
{
|
||||
text_buf = in_text;
|
||||
sexp_replace_variable_names_with_values(text_buf);
|
||||
in_text = text_buf.c_str();
|
||||
strcpy_s(text_buf, in_text);
|
||||
sexp_replace_variable_names_with_values(text_buf, 256);
|
||||
in_text = text_buf;
|
||||
}
|
||||
|
||||
|
||||
int num_text_lines = 0;
|
||||
const char *text_line_ptrs[MAX_SUBTITLE_LINES];
|
||||
char *text_line_ptrs[MAX_SUBTITLE_LINES];
|
||||
int text_line_lens[MAX_SUBTITLE_LINES];
|
||||
|
||||
//Setup text
|
||||
@@ -577,10 +522,11 @@ subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char*
|
||||
int split_width = (in_width > 0) ? in_width : 200;
|
||||
|
||||
num_text_lines = split_str(in_text, split_width, text_line_lens, text_line_ptrs, MAX_SUBTITLE_LINES);
|
||||
SCP_string temp_str;
|
||||
for(int i = 0; i < num_text_lines; i++)
|
||||
{
|
||||
text_buf.assign(text_line_ptrs[i], text_line_lens[i]);
|
||||
text_lines.push_back(text_buf);
|
||||
temp_str.assign(text_line_ptrs[i], text_line_lens[i]);
|
||||
text_lines.push_back(temp_str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,20 +599,20 @@ subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char*
|
||||
|
||||
//Center it?
|
||||
if(center_x)
|
||||
image_pos.x = (gr_screen.center_w - tw)/2 + gr_screen.center_offset_x;
|
||||
image_pos.x = (gr_screen.max_w - tw)/2;
|
||||
if(center_y)
|
||||
image_pos.y = (gr_screen.center_h - th)/2 + gr_screen.center_offset_y;
|
||||
image_pos.y = (gr_screen.max_h - th)/2;
|
||||
}
|
||||
|
||||
if(in_x_pos < 0 && !center_x)
|
||||
image_pos.x += gr_screen.center_offset_x + gr_screen.center_w + in_x_pos;
|
||||
image_pos.x += gr_screen.max_w + in_x_pos;
|
||||
else if(!center_x)
|
||||
image_pos.x += gr_screen.center_offset_x + in_x_pos;
|
||||
image_pos.x += in_x_pos;
|
||||
|
||||
if(in_y_pos < 0 && !center_y)
|
||||
image_pos.y += gr_screen.center_offset_y + gr_screen.center_h + in_y_pos;
|
||||
image_pos.y += gr_screen.max_h + in_y_pos;
|
||||
else if(!center_y)
|
||||
image_pos.y += gr_screen.center_offset_y + in_y_pos;
|
||||
image_pos.y += in_y_pos;
|
||||
|
||||
image_pos.w = in_width;
|
||||
image_pos.h = in_height;
|
||||
@@ -725,7 +671,7 @@ void subtitle::do_frame(float frametime)
|
||||
|
||||
for(SCP_vector<SCP_string>::iterator line = text_lines.begin(); line != text_lines.end(); ++line)
|
||||
{
|
||||
gr_string(x, y, (char*)line->c_str(), GR_RESIZE_NONE);
|
||||
gr_string(x, y, (char*)line->c_str(), false);
|
||||
y += font_height;
|
||||
}
|
||||
|
||||
@@ -746,18 +692,18 @@ void subtitle::do_frame(float frametime)
|
||||
vec3d scale;
|
||||
|
||||
bm_get_info(image_id, &orig_w, &orig_h);
|
||||
scale.xyz.x = (image_pos.w > 0) ? (image_pos.w / (float) orig_w) : 1.0f;
|
||||
scale.xyz.y = (image_pos.h > 0) ? (image_pos.h / (float) orig_h) : 1.0f;
|
||||
scale.xyz.x = image_pos.w / (float) orig_w;
|
||||
scale.xyz.y = image_pos.h / (float) orig_h;
|
||||
scale.xyz.z = 1.0f;
|
||||
|
||||
gr_push_scale_matrix(&scale);
|
||||
gr_bitmap(fl2i(image_pos.x / scale.xyz.x), fl2i(image_pos.y / scale.xyz.y), GR_RESIZE_NONE);
|
||||
gr_bitmap(image_pos.x, image_pos.y, false);
|
||||
gr_pop_scale_matrix();
|
||||
}
|
||||
// no scaling
|
||||
else
|
||||
{
|
||||
gr_bitmap(image_pos.x, image_pos.y, GR_RESIZE_NONE);
|
||||
gr_bitmap(image_pos.x, image_pos.y, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -873,9 +819,6 @@ void cam_close()
|
||||
{
|
||||
//Set Current_camera to nothing
|
||||
Current_camera = camid();
|
||||
for (auto ii = Cameras.begin(); ii != Cameras.end(); ++ii) {
|
||||
delete * ii;
|
||||
}
|
||||
Cameras.clear();
|
||||
}
|
||||
|
||||
@@ -987,15 +930,12 @@ bool cam_set_camera(camid cid)
|
||||
Viewer_mode |= VM_FREECAMERA;
|
||||
Current_camera = cid;
|
||||
|
||||
if (!Cutscene_camera_displays_hud)
|
||||
if(!Camera_hud_draw_saved)
|
||||
{
|
||||
if(!Camera_hud_draw_saved)
|
||||
{
|
||||
Camera_hud_draw_value = hud_get_draw();
|
||||
Camera_hud_draw_saved = true;
|
||||
}
|
||||
hud_set_draw(0);
|
||||
Camera_hud_draw_value = hud_get_draw();
|
||||
Camera_hud_draw_saved = true;
|
||||
}
|
||||
hud_set_draw(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1003,11 +943,8 @@ void cam_reset_camera()
|
||||
{
|
||||
Viewer_mode &= ~VM_FREECAMERA;
|
||||
|
||||
if (!Cutscene_camera_displays_hud)
|
||||
{
|
||||
hud_set_draw(Camera_hud_draw_value);
|
||||
Camera_hud_draw_saved = false;
|
||||
}
|
||||
hud_set_draw(Camera_hud_draw_value);
|
||||
Camera_hud_draw_saved = false;
|
||||
}
|
||||
|
||||
void subtitles_close()
|
||||
@@ -1033,59 +970,4 @@ void subtitles_do_frame_post_shaded(float frametime)
|
||||
if ( sub->is_post_shaded( ) )
|
||||
sub->do_frame(frametime);
|
||||
}
|
||||
}
|
||||
|
||||
vec3d normal_cache;
|
||||
|
||||
void get_turret_cam_pos(camera *cam, vec3d *pos)
|
||||
{
|
||||
object_h obj(cam->get_object_host());
|
||||
if(!obj.IsValid())
|
||||
return;
|
||||
ship* shipp = &Ships[cam->get_object_host()->instance];
|
||||
ship_subsys* ssp = GET_FIRST(&shipp->subsys_list);
|
||||
while ( ssp != END_OF_LIST( &shipp->subsys_list ) )
|
||||
{
|
||||
if(ssp->system_info->subobj_num == cam->get_object_host_submodel())
|
||||
{
|
||||
ship_get_global_turret_gun_info(cam->get_object_host(), ssp, pos, &normal_cache, 1, NULL);
|
||||
vec3d offset = vmd_zero_vector;
|
||||
offset.xyz.x = 0.0001f;
|
||||
vm_vec_add2(pos, &offset); // prevent beam turrets from crashing with a nullvec
|
||||
break;
|
||||
}
|
||||
ssp = GET_NEXT( ssp );
|
||||
}
|
||||
}
|
||||
|
||||
void get_turret_cam_orient(camera *cam, matrix *ori)
|
||||
{
|
||||
object_h obj(cam->get_object_host());
|
||||
if(!obj.IsValid())
|
||||
return;
|
||||
vm_vector_2_matrix(ori, &normal_cache, vm_vec_same(&normal_cache, &cam->get_object_host()->orient.vec.uvec)?NULL:&cam->get_object_host()->orient.vec.uvec, NULL);
|
||||
}
|
||||
|
||||
eye* get_submodel_eye(polymodel *pm, int submodel_num)
|
||||
{
|
||||
if(pm->n_view_positions > 0)
|
||||
{
|
||||
for(int i = 0; i < pm->n_view_positions; ++i)
|
||||
{
|
||||
if(pm->view_positions[i].parent == submodel_num)
|
||||
{
|
||||
return &pm->view_positions[i];
|
||||
}
|
||||
int sm = pm->submodel[submodel_num].first_child;
|
||||
while(sm > 0) //look for eyepoints attached to children, important for turret arms
|
||||
{
|
||||
if(pm->view_positions[i].parent == sm)
|
||||
{
|
||||
return &pm->view_positions[i];
|
||||
}
|
||||
sm = pm->submodel[sm].next_sibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
#ifndef _CAMERA_H
|
||||
#define _CAMERA_H
|
||||
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "object/object.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "globalincs/globals.h"
|
||||
#include "physics/physics.h" //for avd
|
||||
#include "object/object.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -137,8 +137,8 @@ private:
|
||||
|
||||
bool post_shaded;
|
||||
public:
|
||||
subtitle(int in_x_pos, int in_y_pos, const char* in_text = NULL, const char* in_imageanim = NULL,
|
||||
float in_display_time = 0, float in_fade_time = 0.0f, const color *in_text_color = NULL, int in_text_fontnum = -1,
|
||||
subtitle(int in_x_pos, int in_y_pos, char* in_text = NULL, char* in_imageanim = NULL,
|
||||
float in_display_time = 0, float in_fade_time = 0.0f, color *in_text_color = NULL, int in_text_fontnum = -1,
|
||||
bool center_x = false, bool center_y = false, int in_width = 0, int in_height = 0, bool post_shaded=false);
|
||||
~subtitle();
|
||||
|
||||
@@ -168,9 +168,6 @@ camid cam_get_camera(uint index);
|
||||
camid cam_get_current();
|
||||
uint cam_get_num();
|
||||
|
||||
void get_turret_cam_pos(camera *cam, vec3d *pos);
|
||||
void get_turret_cam_orient(camera *cam, matrix *ori);
|
||||
|
||||
void subtitles_close();
|
||||
void subtitles_do_frame(float frametime);
|
||||
void subtitles_do_frame_post_shaded(float frametime);
|
||||
|
||||
+231
-278
@@ -29,16 +29,16 @@
|
||||
#endif
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#include "cfile/cfilearchive.h"
|
||||
#include "cfile/cfilesystem.h"
|
||||
#include "osapi/osapi.h"
|
||||
#include "parse/encrypt.h"
|
||||
#include "cfile/cfilesystem.h"
|
||||
#include "cfile/cfilearchive.h"
|
||||
#include "osapi/osapi.h"
|
||||
|
||||
|
||||
|
||||
char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
|
||||
char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
|
||||
#ifdef SCP_UNIX
|
||||
char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN] = "";
|
||||
char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
|
||||
#endif
|
||||
|
||||
// During cfile_init, verify that Pathtypes[n].index == n for each item
|
||||
@@ -86,161 +86,142 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
|
||||
{ CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA },
|
||||
{ CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
|
||||
{ CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
|
||||
};
|
||||
|
||||
|
||||
#define CFILE_STACK_MAX 8
|
||||
|
||||
int cfile_inited = 0;
|
||||
static int Cfile_stack_pos = 0;
|
||||
int Cfile_stack_pos = 0;
|
||||
|
||||
static char Cfile_stack[CFILE_STACK_MAX][CFILE_ROOT_DIRECTORY_LEN];
|
||||
char Cfile_stack[CFILE_STACK_MAX][CFILE_ROOT_DIRECTORY_LEN];
|
||||
|
||||
Cfile_block Cfile_block_list[MAX_CFILE_BLOCKS];
|
||||
static CFILE Cfile_list[MAX_CFILE_BLOCKS];
|
||||
CFILE Cfile_list[MAX_CFILE_BLOCKS];
|
||||
|
||||
static const char *Cfile_cdrom_dir = NULL;
|
||||
char *Cfile_cdrom_dir = NULL;
|
||||
|
||||
//
|
||||
// Function prototypes for internally-called functions
|
||||
//
|
||||
static int cfget_cfile_block();
|
||||
static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE * fp, int type);
|
||||
static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int type, int offset, int size);
|
||||
int cfget_cfile_block();
|
||||
CFILE *cf_open_fill_cfblock(FILE * fp, int type);
|
||||
CFILE *cf_open_packed_cfblock(FILE *fp, int type, int offset, int size);
|
||||
|
||||
#if defined _WIN32
|
||||
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, HANDLE hFile, int type);
|
||||
CFILE *cf_open_mapped_fill_cfblock(HANDLE hFile, int type);
|
||||
#elif defined SCP_UNIX
|
||||
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp, int type);
|
||||
CFILE *cf_open_mapped_fill_cfblock(FILE *fp, int type);
|
||||
#endif
|
||||
|
||||
static void cf_chksum_long_init();
|
||||
void cf_chksum_long_init();
|
||||
|
||||
static void dump_opened_files()
|
||||
void cfile_close()
|
||||
{
|
||||
for (int i = 0; i < MAX_CFILE_BLOCKS; i++) {
|
||||
auto cb = &Cfile_block_list[i];
|
||||
if (cb->type != CFILE_BLOCK_UNUSED) {
|
||||
mprintf((" %s:%d\n", cb->source_file, cb->line_num));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cfile_close()
|
||||
{
|
||||
mprintf(("Still opened files:\n"));
|
||||
dump_opened_files();
|
||||
|
||||
cf_free_secondary_filelist();
|
||||
}
|
||||
|
||||
#ifdef SCP_UNIX
|
||||
#define MIN_NUM_PATH_COMPONENTS 2 /* Directory + file */
|
||||
#else
|
||||
#define MIN_NUM_PATH_COMPONENTS 3 /* Drive + directory + file */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Determine if the given path is in the root directory
|
||||
*
|
||||
* @param exe_path Path to executable
|
||||
*
|
||||
* @return true if root directory, false if not
|
||||
*/
|
||||
static bool cfile_in_root_dir(const char *exe_path)
|
||||
// determine if the given path is in a root directory (c:\ or c:\freespace2.exe or c:\fred2.exe etc)
|
||||
int cfile_in_root_dir(char *exe_path)
|
||||
{
|
||||
int new_token;
|
||||
int token_count = 0;
|
||||
const char *p = exe_path;
|
||||
char path_copy[CFILE_ROOT_DIRECTORY_LEN] = "";
|
||||
char *tok;
|
||||
|
||||
Assert(exe_path != NULL);
|
||||
// bogus
|
||||
if(exe_path == NULL){
|
||||
return 1;
|
||||
}
|
||||
|
||||
// copy the path
|
||||
memset(path_copy, 0, CFILE_ROOT_DIRECTORY_LEN);
|
||||
strncpy(path_copy, exe_path, CFILE_ROOT_DIRECTORY_LEN - 1);
|
||||
|
||||
// count how many slashes there are in the path
|
||||
tok = strtok(path_copy, DIR_SEPARATOR_STR);
|
||||
if(tok == NULL){
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
new_token = 0;
|
||||
while (*p == DIR_SEPARATOR_CHAR) {
|
||||
p++;
|
||||
}
|
||||
token_count++;
|
||||
tok = strtok(NULL, DIR_SEPARATOR_STR);
|
||||
} while(tok != NULL);
|
||||
|
||||
#ifdef SCP_UNIX
|
||||
// /freespace works, / does not
|
||||
if(token_count <= 1) {
|
||||
#else
|
||||
// C:/freespace works, C:/ does not
|
||||
if(token_count <= 2){
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((*p != '\0') && (*p != DIR_SEPARATOR_CHAR)) {
|
||||
new_token = 1;
|
||||
p++;
|
||||
}
|
||||
token_count += new_token;
|
||||
} while (*p != '\0');
|
||||
|
||||
return (token_count < MIN_NUM_PATH_COMPONENTS);
|
||||
// not-root directory
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the cfile system. Called once at application start.
|
||||
*
|
||||
* @param exe_dir Path to a file (not a directory)
|
||||
* @param cdrom_dir Path to a CD drive mount point (may be NULL)
|
||||
*
|
||||
* @return 0 On success
|
||||
* @return 1 On error
|
||||
*/
|
||||
int cfile_init(const char *exe_dir, const char *cdrom_dir)
|
||||
// cfile_init() initializes the cfile system. Called once at application start.
|
||||
//
|
||||
// returns: success ==> 0
|
||||
// error ==> non-zero
|
||||
//
|
||||
int cfile_init(char *exe_dir, char *cdrom_dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
encrypt_init(); /* initialize encryption */
|
||||
// initialize encryption
|
||||
encrypt_init();
|
||||
|
||||
if (cfile_inited) {
|
||||
return 0;
|
||||
}
|
||||
if ( !cfile_inited ) {
|
||||
char buf[CFILE_ROOT_DIRECTORY_LEN];
|
||||
|
||||
char buf[CFILE_ROOT_DIRECTORY_LEN];
|
||||
cfile_inited = 1;
|
||||
|
||||
strncpy(buf, exe_dir, CFILE_ROOT_DIRECTORY_LEN - 1);
|
||||
buf[CFILE_ROOT_DIRECTORY_LEN - 1] = '\0';
|
||||
i = strlen(buf);
|
||||
memset(buf, 0, CFILE_ROOT_DIRECTORY_LEN);
|
||||
strncpy(buf, exe_dir, CFILE_ROOT_DIRECTORY_LEN - 1);
|
||||
i = strlen(buf);
|
||||
|
||||
// are we in a root directory?
|
||||
if(cfile_in_root_dir(buf)){
|
||||
os::dialogs::Message(os::dialogs::MESSAGEBOX_ERROR, "FreeSpace2/Fred2 cannot be run from a drive root directory!");
|
||||
return 1;
|
||||
}
|
||||
// are we in a root directory?
|
||||
if(cfile_in_root_dir(buf)){
|
||||
MessageBox((HWND)NULL, "FreeSpace2/Fred2 cannot be run from a drive root directory!", "Error", MB_OK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// This needs to be set here because cf_build_secondary_filelist assumes it to be true
|
||||
cfile_inited = 1;
|
||||
|
||||
/*
|
||||
* Determine the executable's directory. Note that DIR_SEPARATOR_CHAR
|
||||
* is guaranteed to be found in the string else cfile_in_root_dir()
|
||||
* would have failed.
|
||||
*/
|
||||
while (i--) {
|
||||
if (buf[i] == DIR_SEPARATOR_CHAR){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char *p;
|
||||
if (i >= 2) {
|
||||
buf[i] = 0;
|
||||
cfile_chdir(buf);
|
||||
} else {
|
||||
MessageBox((HWND)NULL, "Error trying to determine executable root directory!", "Error", MB_OK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
p = strrchr(buf, DIR_SEPARATOR_CHAR);
|
||||
*p = '\0';
|
||||
|
||||
cfile_chdir(buf);
|
||||
|
||||
// set root directory
|
||||
strncpy(Cfile_root_dir, buf, CFILE_ROOT_DIRECTORY_LEN-1);
|
||||
strncpy(Cfile_user_dir, os_get_config_path().c_str(), CFILE_ROOT_DIRECTORY_LEN-1);
|
||||
|
||||
// set root directory
|
||||
strncpy(Cfile_root_dir, buf, CFILE_ROOT_DIRECTORY_LEN-1);
|
||||
#ifdef SCP_UNIX
|
||||
// Initialize path of old pilot files
|
||||
extern const char* Osreg_user_dir_legacy;
|
||||
snprintf(Cfile_user_dir_legacy, CFILE_ROOT_DIRECTORY_LEN-1, "%s/%s/", getenv("HOME"), Osreg_user_dir_legacy);
|
||||
snprintf(Cfile_user_dir, CFILE_ROOT_DIRECTORY_LEN-1, "%s/%s/", detect_home(), Osreg_user_dir);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAX_CFILE_BLOCKS; i++) {
|
||||
Cfile_block_list[i].type = CFILE_BLOCK_UNUSED;
|
||||
for ( i = 0; i < MAX_CFILE_BLOCKS; i++ ) {
|
||||
Cfile_block_list[i].type = CFILE_BLOCK_UNUSED;
|
||||
}
|
||||
|
||||
// 32 bit CRC table init
|
||||
cf_chksum_long_init();
|
||||
|
||||
Cfile_cdrom_dir = cdrom_dir;
|
||||
cf_build_secondary_filelist(Cfile_cdrom_dir);
|
||||
|
||||
atexit( cfile_close );
|
||||
}
|
||||
|
||||
// 32 bit CRC table init
|
||||
cf_chksum_long_init();
|
||||
|
||||
Cfile_cdrom_dir = cdrom_dir;
|
||||
cf_build_secondary_filelist(Cfile_cdrom_dir);
|
||||
|
||||
atexit(cfile_close);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -254,13 +235,13 @@ void cfile_refresh()
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// Changes to a drive if valid.. 1=A, 2=B, etc
|
||||
// If flag, then changes to it.
|
||||
// Returns 0 if not-valid, 1 if valid.
|
||||
int cfile_chdrive( int DriveNum, int flag )
|
||||
{
|
||||
int Valid = 0;
|
||||
#ifdef _WIN32
|
||||
int n, org;
|
||||
|
||||
org = -1;
|
||||
@@ -276,108 +257,99 @@ int cfile_chdrive( int DriveNum, int flag )
|
||||
|
||||
if ( (!flag) && (n != org) )
|
||||
_chdrive( org );
|
||||
#endif // _WIN32
|
||||
|
||||
return Valid;
|
||||
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
/**
|
||||
* @brief Common code for changing directory
|
||||
*
|
||||
* @param new_dir Directory to which to change
|
||||
* @param cur_dir Current directory (only used on Windows)
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval 1 Failed to change to new directory's drive (Windows only)
|
||||
* @retval 2 Failed to change to new directory
|
||||
*/
|
||||
static int _cfile_chdir(const char *new_dir, const char *cur_dir __UNUSED)
|
||||
// push current directory on a 'stack' (so we can restore it) and change the directory
|
||||
int cfile_push_chdir(int type)
|
||||
{
|
||||
int status;
|
||||
const char *path = NULL;
|
||||
const char no_dir[] = "\\.";
|
||||
int e;
|
||||
char dir[CFILE_ROOT_DIRECTORY_LEN];
|
||||
char OriginalDirectory[CFILE_ROOT_DIRECTORY_LEN];
|
||||
char *Path = NULL;
|
||||
char NoDir[] = "\\.";
|
||||
|
||||
_getcwd(OriginalDirectory, CFILE_ROOT_DIRECTORY_LEN-1);
|
||||
|
||||
Assert(Cfile_stack_pos < CFILE_STACK_MAX);
|
||||
|
||||
if ( Cfile_stack_pos >= CFILE_STACK_MAX )
|
||||
return -1;
|
||||
|
||||
strncpy(Cfile_stack[Cfile_stack_pos++], OriginalDirectory, CFILE_ROOT_DIRECTORY_LEN-1);
|
||||
|
||||
cf_create_default_path_string( dir, sizeof(dir)-1, type, NULL );
|
||||
|
||||
#ifdef _WIN32
|
||||
const char *colon = strchr(new_dir, ':');
|
||||
char *colon_pos = strchr(dir, ':');
|
||||
|
||||
if (colon) {
|
||||
if (!cfile_chdrive(tolower(*(colon - 1)) - 'a' + 1, 1))
|
||||
if (colon_pos) {
|
||||
if (!cfile_chdrive( tolower(*(colon_pos - 1)) - 'a' + 1, 1))
|
||||
return 1;
|
||||
|
||||
path = colon + 1;
|
||||
Path = colon_pos+1;
|
||||
} else
|
||||
#endif /* _WIN32 */
|
||||
#endif // _WIN32
|
||||
{
|
||||
path = new_dir;
|
||||
Path = dir;
|
||||
}
|
||||
|
||||
if (*path == '\0') {
|
||||
path = no_dir;
|
||||
if (!(*Path)) {
|
||||
Path = NoDir;
|
||||
}
|
||||
|
||||
/* This chdir might get a critical error! */
|
||||
status = _chdir(path);
|
||||
if (status != 0) {
|
||||
// This chdir might get a critical error!
|
||||
e = _chdir( Path );
|
||||
if (e) {
|
||||
#ifdef _WIN32
|
||||
cfile_chdrive(tolower(cur_dir[0]) - 'a' + 1, 1);
|
||||
#endif /* _WIN32 */
|
||||
cfile_chdrive( tolower(OriginalDirectory[0]) - 'a' + 1, 1 );
|
||||
#endif // _WIN32
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Push current directory onto a 'stack' and change to a new directory
|
||||
*
|
||||
* The current directory is pushed onto a 'stack' so that it can be easily
|
||||
* restored at a later time. The new directory is derived from @a type.
|
||||
*
|
||||
* @param type path type (CF_TYPE_xxx)
|
||||
*
|
||||
* @retval -1 'Stack' is full
|
||||
* @retval 0 Success
|
||||
* @retval 1 Failed to change to new directory's drive (Windows only)
|
||||
* @retval 2 Failed to change to new directory
|
||||
*/
|
||||
int cfile_push_chdir(int type)
|
||||
|
||||
int cfile_chdir(char *dir)
|
||||
{
|
||||
char dir[CFILE_ROOT_DIRECTORY_LEN];
|
||||
int e;
|
||||
char OriginalDirectory[CFILE_ROOT_DIRECTORY_LEN];
|
||||
char *Path = NULL;
|
||||
char NoDir[] = "\\.";
|
||||
|
||||
_getcwd(OriginalDirectory, CFILE_ROOT_DIRECTORY_LEN - 1);
|
||||
_getcwd(OriginalDirectory, CFILE_ROOT_DIRECTORY_LEN-1);
|
||||
|
||||
Assert(Cfile_stack_pos < CFILE_STACK_MAX);
|
||||
#ifdef _WIN32
|
||||
char *colon_pos = strchr(dir, ':');
|
||||
if (colon_pos) {
|
||||
if (!cfile_chdrive( tolower(*(colon_pos - 1)) - 'a' + 1, 1))
|
||||
return 1;
|
||||
|
||||
if (Cfile_stack_pos >= CFILE_STACK_MAX) {
|
||||
return -1;
|
||||
Path = colon_pos+1;
|
||||
} else
|
||||
#endif // _WIN32
|
||||
{
|
||||
Path = dir;
|
||||
}
|
||||
|
||||
strncpy(Cfile_stack[Cfile_stack_pos++], OriginalDirectory,
|
||||
CFILE_ROOT_DIRECTORY_LEN - 1);
|
||||
if (!(*Path)) {
|
||||
Path = NoDir;
|
||||
}
|
||||
|
||||
cf_create_default_path_string(dir, sizeof(dir) - 1, type, NULL);
|
||||
// This chdir might get a critical error!
|
||||
e = _chdir( Path );
|
||||
if (e) {
|
||||
#ifdef _WIN32
|
||||
cfile_chdrive( tolower(OriginalDirectory[0]) - 'a' + 1, 1 );
|
||||
#endif // _WIN32
|
||||
return 2;
|
||||
}
|
||||
|
||||
return _cfile_chdir(dir, OriginalDirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Change to the specified directory
|
||||
*
|
||||
* @param dir Directory
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval 1 Failed to change to new directory's drive (Windows only)
|
||||
* @retval 2 Failed to change to new directory
|
||||
*/
|
||||
int cfile_chdir(const char *dir)
|
||||
{
|
||||
char OriginalDirectory[CFILE_ROOT_DIRECTORY_LEN];
|
||||
|
||||
_getcwd(OriginalDirectory, CFILE_ROOT_DIRECTORY_LEN - 1);
|
||||
|
||||
return _cfile_chdir(dir, OriginalDirectory);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cfile_pop_dir()
|
||||
@@ -430,7 +402,7 @@ int cfile_flush_dir(int dir_type)
|
||||
for (unsigned int i = 0; i < globinfo.gl_pathc; i++) {
|
||||
// Determine if this is a regular file
|
||||
struct stat statbuf;
|
||||
|
||||
memset(&statbuf, 0, sizeof(statbuf));
|
||||
stat(globinfo.gl_pathv[i], &statbuf);
|
||||
if (S_ISREG(statbuf.st_mode)) {
|
||||
// delete the file
|
||||
@@ -457,7 +429,7 @@ int cfile_flush_dir(int dir_type)
|
||||
// filename = name of filename or filepath to process
|
||||
// ext = extension to add. Must start with the period
|
||||
// Returns: new filename or filepath with extension.
|
||||
char *cf_add_ext(const char *filename, const char *ext)
|
||||
char *cf_add_ext(char *filename, char *ext)
|
||||
{
|
||||
int flen, elen;
|
||||
static char path[MAX_PATH_LEN];
|
||||
@@ -474,29 +446,39 @@ char *cf_add_ext(const char *filename, const char *ext)
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delete the specified file
|
||||
*
|
||||
* @param filename Name of file to delete
|
||||
* @param path_type Path type (CF_TYPE_xxx)
|
||||
*
|
||||
* @return 0 on failure, 1 on success
|
||||
*/
|
||||
int cf_delete(const char *filename, int path_type)
|
||||
// Deletes a file. Returns 0 if an error occurs, 1 on success
|
||||
int cf_delete(char *filename, int dir_type)
|
||||
{
|
||||
char longname[MAX_PATH_LEN];
|
||||
|
||||
Assert(CF_TYPE_SPECIFIED(path_type));
|
||||
Assert( CF_TYPE_SPECIFIED(dir_type) );
|
||||
|
||||
cf_create_default_path_string(longname, sizeof(longname) - 1,
|
||||
path_type, filename);
|
||||
cf_create_default_path_string( longname, sizeof(longname)-1, dir_type, filename );
|
||||
|
||||
return (_unlink(longname) != -1);
|
||||
FILE *fp = fopen(longname, "rb");
|
||||
if (fp) {
|
||||
// delete the file
|
||||
fclose(fp);
|
||||
if(_unlink(longname) == -1)
|
||||
{
|
||||
//ERROR - file is probably read only
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//ERROR - file doesn't exist
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Same as _access function to read a file's access bits
|
||||
int cf_access(const char *filename, int dir_type, int mode)
|
||||
int cf_access(char *filename, int dir_type, int mode)
|
||||
{
|
||||
char longname[MAX_PATH_LEN];
|
||||
|
||||
@@ -510,23 +492,29 @@ int cf_access(const char *filename, int dir_type, int mode)
|
||||
|
||||
// Returns 1 if the file exists, 0 if not.
|
||||
// Checks only the file system.
|
||||
// cf_find_file_location checks the filesystem before VPs
|
||||
// If offset is 0, it was found in the filesystem, so offset is boolean false
|
||||
// If offset equates to boolean true, it was found in a VP and the logic will negate the function return
|
||||
int cf_exists(const char *filename, int dir_type)
|
||||
int cf_exists(char *filename, int dir_type)
|
||||
{
|
||||
int offset = 1;
|
||||
char longname[MAX_PATH_LEN];
|
||||
|
||||
if ( (filename == NULL) || !strlen(filename) )
|
||||
return 0;
|
||||
Assert(CF_TYPE_SPECIFIED(dir_type));
|
||||
|
||||
return (cf_find_file_location(filename, dir_type, 0, NULL, NULL, &offset) && !offset);
|
||||
cf_create_default_path_string(longname, sizeof(longname) - 1, dir_type, filename);
|
||||
|
||||
FILE *fp = fopen(longname, "rb");
|
||||
if (fp)
|
||||
{
|
||||
// Goober5000 - these were switched, causing the fclose to be unreachable
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Goober5000
|
||||
// Returns !0 if the file exists, 0 if not.
|
||||
// Checks both the file system and the VPs.
|
||||
int cf_exists_full(const char *filename, int dir_type)
|
||||
int cf_exists_full(char *filename, int dir_type)
|
||||
{
|
||||
if ( (filename == NULL) || !strlen(filename) )
|
||||
return 0;
|
||||
@@ -535,7 +523,7 @@ int cf_exists_full(const char *filename, int dir_type)
|
||||
}
|
||||
|
||||
// same as the above, but with extension check
|
||||
int cf_exists_full_ext(const char *filename, int dir_type, const int num_ext, const char **ext_list)
|
||||
int cf_exists_full_ext(char *filename, int dir_type, const int num_ext, const char **ext_list)
|
||||
{
|
||||
if ( (filename == NULL) || !strlen(filename) )
|
||||
return 0;
|
||||
@@ -547,7 +535,7 @@ int cf_exists_full_ext(const char *filename, int dir_type, const int num_ext, co
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void cf_attrib(const char *filename, int set, int clear, int dir_type)
|
||||
void cf_attrib(char *filename, int set, int clear, int dir_type)
|
||||
{
|
||||
char longname[MAX_PATH_LEN];
|
||||
|
||||
@@ -566,7 +554,7 @@ void cf_attrib(const char *filename, int set, int clear, int dir_type)
|
||||
}
|
||||
#endif
|
||||
|
||||
int cf_rename(const char *old_name, const char *name, int dir_type)
|
||||
int cf_rename(char *old_name, char *name, int dir_type)
|
||||
{
|
||||
Assert( CF_TYPE_SPECIFIED(dir_type) );
|
||||
|
||||
@@ -593,28 +581,6 @@ int cf_rename(const char *old_name, const char *name, int dir_type)
|
||||
|
||||
}
|
||||
|
||||
|
||||
// This takes a path (e.g. "C:\Games\FreeSpace2\Lots\More\Directories") and creates it in its entirety.
|
||||
// Do note that this requires the path to have normalized directory separators as defined by DIR_SEPARATOR_CHAR
|
||||
static void mkdir_recursive(const char *path) {
|
||||
size_t pre = 0, pos;
|
||||
SCP_string tmp(path);
|
||||
SCP_string dir;
|
||||
|
||||
if (tmp[tmp.size() - 1] != DIR_SEPARATOR_CHAR) {
|
||||
// force trailing / so we can handle everything in loop
|
||||
tmp += DIR_SEPARATOR_CHAR;
|
||||
}
|
||||
|
||||
while ((pos = tmp.find_first_of(DIR_SEPARATOR_CHAR, pre)) != std::string::npos) {
|
||||
dir = tmp.substr(0, pos++);
|
||||
pre = pos;
|
||||
if (dir.size() == 0) continue; // if leading / first time is 0 length
|
||||
|
||||
_mkdir(dir.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the directory path if it doesn't exist. Even creates all its
|
||||
// parent paths.
|
||||
void cf_create_directory( int dir_type )
|
||||
@@ -623,7 +589,7 @@ void cf_create_directory( int dir_type )
|
||||
int dir_tree[CF_MAX_PATH_TYPES];
|
||||
char longname[MAX_PATH_LEN];
|
||||
|
||||
Assertion( CF_TYPE_SPECIFIED(dir_type), "Invalid dir_type passed to cf_create_directory." );
|
||||
Assert( CF_TYPE_SPECIFIED(dir_type) );
|
||||
|
||||
int current_dir = dir_type;
|
||||
|
||||
@@ -640,9 +606,13 @@ void cf_create_directory( int dir_type )
|
||||
|
||||
for (i=num_dirs-1; i>=0; i-- ) {
|
||||
cf_create_default_path_string( longname, sizeof(longname)-1, dir_tree[i], NULL );
|
||||
mprintf(( "CFILE: Creating new directory '%s'\n", longname ));
|
||||
mkdir_recursive(longname);
|
||||
|
||||
if ( _mkdir(longname)==0 ) {
|
||||
mprintf(( "CFILE: Created new directory '%s'\n", longname ));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -664,7 +634,7 @@ extern int game_cd_changed();
|
||||
// error ==> NULL
|
||||
//
|
||||
|
||||
CFILE *_cfopen(const char* source, int line, const char *file_path, const char *mode, int type, int dir_type, bool localize)
|
||||
CFILE *cfopen(char *file_path, char *mode, int type, int dir_type, bool localize)
|
||||
{
|
||||
/* Bobboau, what is this doing here? 31 is way too short... - Goober5000
|
||||
if( strlen(file_path) > 31 )
|
||||
@@ -749,7 +719,7 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
|
||||
FILE *fp = fopen(longname, happy_mode);
|
||||
if (fp) {
|
||||
return cf_open_fill_cfblock(source, line, fp, dir_type);
|
||||
return cf_open_fill_cfblock(fp, dir_type);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -766,7 +736,6 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
if ( cf_find_file_location( copy_file_path, dir_type, sizeof(longname) - 1, longname, &size, &offset, localize ) ) {
|
||||
|
||||
// Fount it, now create a cfile out of it
|
||||
nprintf(("CFileDebug", "Requested file %s found at: %s\n", file_path, longname));
|
||||
|
||||
if ( type & CFILE_MEMORY_MAPPED ) {
|
||||
|
||||
@@ -778,12 +747,12 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
hFile = CreateFile(longname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
return cf_open_mapped_fill_cfblock(source, line, hFile, dir_type);
|
||||
return cf_open_mapped_fill_cfblock(hFile, dir_type);
|
||||
}
|
||||
#elif defined SCP_UNIX
|
||||
FILE *fp = fopen( longname, "rb" );
|
||||
if (fp) {
|
||||
return cf_open_mapped_fill_cfblock(source, line, fp, dir_type);
|
||||
return cf_open_mapped_fill_cfblock(fp, dir_type);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -795,10 +764,10 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
if ( fp ) {
|
||||
if ( offset ) {
|
||||
// Found it in a pack file
|
||||
return cf_open_packed_cfblock(source, line, fp, dir_type, offset, size );
|
||||
return cf_open_packed_cfblock(fp, dir_type, offset, size );
|
||||
} else {
|
||||
// Found it in a normal file
|
||||
return cf_open_fill_cfblock(source, line, fp, dir_type);
|
||||
return cf_open_fill_cfblock(fp, dir_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -819,7 +788,7 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
// returns: success ==> address of CFILE structure
|
||||
// error ==> NULL
|
||||
//
|
||||
CFILE *_cfopen_special(const char* source, int line, const char *file_path, const char *mode, const int size, const int offset, int dir_type)
|
||||
CFILE *cfopen_special(char *file_path, char *mode, const int size, const int offset, int dir_type)
|
||||
{
|
||||
if ( !cfile_inited) {
|
||||
Int3();
|
||||
@@ -844,10 +813,10 @@ CFILE *_cfopen_special(const char* source, int line, const char *file_path, cons
|
||||
|
||||
if ( offset ) {
|
||||
// it's in a pack file
|
||||
return cf_open_packed_cfblock(source, line, fp, dir_type, offset, size);
|
||||
return cf_open_packed_cfblock(fp, dir_type, offset, size);
|
||||
} else {
|
||||
// it's a normal file
|
||||
return cf_open_fill_cfblock(source, line, fp, dir_type);
|
||||
return cf_open_fill_cfblock(fp, dir_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -866,7 +835,7 @@ CFILE *ctmpfile()
|
||||
FILE *fp;
|
||||
fp = tmpfile();
|
||||
if ( fp )
|
||||
return cf_open_fill_cfblock(LOCATION, fp, 0);
|
||||
return cf_open_fill_cfblock(fp, 0);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@@ -879,7 +848,7 @@ CFILE *ctmpfile()
|
||||
// returns: success ==> index in Cfile_block_list[] array
|
||||
// failure ==> -1
|
||||
//
|
||||
static int cfget_cfile_block()
|
||||
int cfget_cfile_block()
|
||||
{
|
||||
int i;
|
||||
Cfile_block *cb;
|
||||
@@ -896,13 +865,7 @@ static int cfget_cfile_block()
|
||||
|
||||
// If we've reached this point, a free Cfile_block could not be found
|
||||
nprintf(("Warning","A free Cfile_block could not be found.\n"));
|
||||
|
||||
// Dump a list of all opened files
|
||||
mprintf(("Out of cfile blocks! Currently opened files:\n"));
|
||||
dump_opened_files();
|
||||
|
||||
Assertion(false, "There are no more free cfile blocks. This means that there are too many files opened by FSO.\n"
|
||||
"This is probably caused by a programming or scripting error where a file does not get closed."); // out of free cfile blocks
|
||||
Assert(0); // out of free cfile blocks
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -980,7 +943,7 @@ int cf_is_valid(CFILE *cfile)
|
||||
// returns: success ==> ptr to CFILE structure.
|
||||
// error ==> NULL
|
||||
//
|
||||
static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE *fp, int type)
|
||||
CFILE *cf_open_fill_cfblock(FILE *fp, int type)
|
||||
{
|
||||
int cfile_block_index;
|
||||
|
||||
@@ -999,9 +962,6 @@ static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE *fp, int t
|
||||
cfbp->fp = fp;
|
||||
cfbp->dir_type = type;
|
||||
cfbp->max_read_len = 0;
|
||||
|
||||
cfbp->source_file = source;
|
||||
cfbp->line_num = line;
|
||||
|
||||
int pos = ftell(fp);
|
||||
if(pos == -1L)
|
||||
@@ -1019,7 +979,7 @@ static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE *fp, int t
|
||||
// returns: success ==> ptr to CFILE structure.
|
||||
// error ==> NULL
|
||||
//
|
||||
static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int type, int offset, int size)
|
||||
CFILE *cf_open_packed_cfblock(FILE *fp, int type, int offset, int size)
|
||||
{
|
||||
// Found it in a pack file
|
||||
int cfile_block_index;
|
||||
@@ -1041,9 +1001,6 @@ static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int
|
||||
cfbp->dir_type = type;
|
||||
cfbp->max_read_len = 0;
|
||||
|
||||
cfbp->source_file = source;
|
||||
cfbp->line_num = line;
|
||||
|
||||
cf_init_lowlevel_read_code(cfp,offset, size, 0 );
|
||||
|
||||
return cfp;
|
||||
@@ -1059,9 +1016,9 @@ static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int
|
||||
// returns: ptr CFILE structure.
|
||||
//
|
||||
#if defined _WIN32
|
||||
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, HANDLE hFile, int type)
|
||||
CFILE *cf_open_mapped_fill_cfblock(HANDLE hFile, int type)
|
||||
#elif defined SCP_UNIX
|
||||
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp, int type)
|
||||
CFILE *cf_open_mapped_fill_cfblock(FILE *fp, int type)
|
||||
#endif
|
||||
{
|
||||
int cfile_block_index;
|
||||
@@ -1088,9 +1045,6 @@ static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp
|
||||
#endif
|
||||
cfbp->dir_type = type;
|
||||
|
||||
cfbp->source_file = source;
|
||||
cfbp->line_num = line;
|
||||
|
||||
cf_init_lowlevel_read_code(cfp, 0, 0, 0 );
|
||||
#if defined _WIN32
|
||||
cfbp->hMapFile = CreateFileMapping(cfbp->hInFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
@@ -1383,7 +1337,7 @@ int cfwrite_char(char b, CFILE *file)
|
||||
return cfwrite( &b, sizeof(b), 1, file);
|
||||
}
|
||||
|
||||
int cfwrite_string(const char *buf, CFILE *file)
|
||||
int cfwrite_string(char *buf, CFILE *file)
|
||||
{
|
||||
if ( (!buf) || (buf && !buf[0]) ) {
|
||||
return cfwrite_char(0, file);
|
||||
@@ -1521,7 +1475,7 @@ int cfputc(int c, CFILE *cfile)
|
||||
// returns: success ==> non-negative value
|
||||
// error ==> EOF
|
||||
//
|
||||
int cfputs(const char *str, CFILE *cfile)
|
||||
int cfputs(char *str, CFILE *cfile)
|
||||
{
|
||||
if(!cf_is_valid(cfile))
|
||||
return EOF;
|
||||
@@ -1626,7 +1580,7 @@ char *cfgets(char *buf, int n, CFILE *cfile)
|
||||
// CRC code for mission validation. given to us by Kevin Bentley on 7/20/98. Some sort of
|
||||
// checksumming code that he wrote a while ago.
|
||||
#define CRC32_POLYNOMIAL 0xEDB88320
|
||||
static uint CRCTable[256];
|
||||
uint CRCTable[256];
|
||||
|
||||
#define CF_CHKSUM_SAMPLE_SIZE 512
|
||||
|
||||
@@ -1663,7 +1617,7 @@ uint cf_add_chksum_long(uint seed, ubyte *buffer, int size)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static void cf_chksum_long_init()
|
||||
void cf_chksum_long_init()
|
||||
{
|
||||
int i, j;
|
||||
uint crc;
|
||||
@@ -1684,7 +1638,7 @@ static void cf_chksum_long_init()
|
||||
|
||||
// single function convenient to use for both short and long checksums
|
||||
// NOTE : only one of chk_short or chk_long must be non-NULL (indicating which checksum to perform)
|
||||
static int cf_chksum_do(CFILE *cfile, ushort *chk_short, uint *chk_long, int max_size)
|
||||
int cf_chksum_do(CFILE *cfile, ushort *chk_short, uint *chk_long, int max_size)
|
||||
{
|
||||
ubyte cf_buffer[CF_CHKSUM_SAMPLE_SIZE];
|
||||
int is_long;
|
||||
@@ -1739,7 +1693,7 @@ static int cf_chksum_do(CFILE *cfile, ushort *chk_short, uint *chk_long, int max
|
||||
}
|
||||
|
||||
// get the chksum of a pack file (VP)
|
||||
int cf_chksum_pack(const char *filename, uint *chk_long, bool full)
|
||||
int cf_chksum_pack(char *filename, uint *chk_long, bool full)
|
||||
{
|
||||
const int safe_size = 2097152; // 2 Meg
|
||||
const int header_offset = 32; // skip 32bytes for header (header is currently smaller than this though)
|
||||
@@ -1776,8 +1730,7 @@ int cf_chksum_pack(const char *filename, uint *chk_long, bool full)
|
||||
else {
|
||||
CLAMP(max_size, 0, safe_size);
|
||||
|
||||
Assertion(max_size > header_offset,
|
||||
"max_size (%d) > header_offset in packfile %s", max_size, filename);
|
||||
Assert( max_size > header_offset );
|
||||
max_size -= header_offset;
|
||||
|
||||
fseek(fp, -(max_size), SEEK_END);
|
||||
@@ -1808,7 +1761,7 @@ int cf_chksum_pack(const char *filename, uint *chk_long, bool full)
|
||||
return 1;
|
||||
}
|
||||
// get the 2 byte checksum of the passed filename - return 0 if operation failed, 1 if succeeded
|
||||
int cf_chksum_short(const char *filename, ushort *chksum, int max_size, int cf_type)
|
||||
int cf_chksum_short(char *filename, ushort *chksum, int max_size, int cf_type)
|
||||
{
|
||||
int ret_val;
|
||||
CFILE *cfile = NULL;
|
||||
@@ -1858,7 +1811,7 @@ int cf_chksum_short(CFILE *file, ushort *chksum, int max_size)
|
||||
}
|
||||
|
||||
// get the 32 bit CRC checksum of the passed filename - return 0 if operation failed, 1 if succeeded
|
||||
int cf_chksum_long(const char *filename, uint *chksum, int max_size, int cf_type)
|
||||
int cf_chksum_long(char *filename, uint *chksum, int max_size, int cf_type)
|
||||
{
|
||||
int ret_val;
|
||||
CFILE *cfile = NULL;
|
||||
|
||||
+27
-32
@@ -99,7 +99,7 @@ typedef struct {
|
||||
|
||||
// callback function used for get_file_list() to filter files to be added to list. Return 1
|
||||
// to add file to list, or 0 to not add it.
|
||||
extern int (*Get_file_list_filter)(const char *filename);
|
||||
extern int (*Get_file_list_filter)(char *filename);
|
||||
|
||||
// extra check for child directory under CF_TYPE_*
|
||||
// NOTE: if specified cf_get_file_list() will not search pack files!
|
||||
@@ -109,13 +109,13 @@ extern const char *Get_file_list_child;
|
||||
// cfile directory. valid after cfile_init() returns successfully
|
||||
#define CFILE_ROOT_DIRECTORY_LEN 256
|
||||
extern char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN];
|
||||
extern char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN];
|
||||
#ifdef SCP_UNIX
|
||||
extern char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN];
|
||||
extern char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN];
|
||||
#endif
|
||||
|
||||
//================= LOW-LEVEL FUNCTIONS ==================
|
||||
int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
|
||||
// Call this once at the beginning of the program
|
||||
int cfile_init(char *exe_dir,char *cdrom_dir=NULL);
|
||||
|
||||
// Call this if pack files got added or removed or the
|
||||
// cdrom changed. This will refresh the list of filenames
|
||||
@@ -123,23 +123,18 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
|
||||
void cfile_refresh();
|
||||
|
||||
// add an extension to a filename if it doesn't already have it
|
||||
char *cf_add_ext(const char *filename, const char *ext);
|
||||
char *cf_add_ext(char *filename, char *ext);
|
||||
|
||||
// return CF_TYPE (directory location type) of a CFILE you called cfopen() successfully on.
|
||||
int cf_get_dir_type(CFILE *cfile);
|
||||
|
||||
|
||||
// Opens the file. If no path is given, use the extension to look into the
|
||||
// default path. If mode is NULL, delete the file.
|
||||
CFILE *_cfopen(const char* source_file, int line, const char *filename, const char *mode,
|
||||
int type = CFILE_NORMAL, int dir_type = CF_TYPE_ANY, bool localize = false);
|
||||
#define cfopen(...) _cfopen(LOCATION, __VA_ARGS__) // Pass source location to the function
|
||||
CFILE *cfopen(char *filename, char *mode, int type = CFILE_NORMAL, int dir_type = CF_TYPE_ANY, bool localize = false);
|
||||
|
||||
// like cfopen(), but it accepts a fully qualified path only (ie, the result of a cf_find_file_location() call)
|
||||
// NOTE: only supports reading files!!
|
||||
CFILE *_cfopen_special(const char* source_file, int line, const char *file_path, const char *mode,
|
||||
const int size, const int offset, int dir_type = CF_TYPE_ANY);
|
||||
#define cfopen_special(...) _cfopen_special(LOCATION, __VA_ARGS__) // Pass source location to the function
|
||||
CFILE *cfopen_special(char *file_path, char *mode, const int size, const int offset, int dir_type = CF_TYPE_ANY);
|
||||
|
||||
// Flush the open file buffer
|
||||
int cflush(CFILE *cfile);
|
||||
@@ -154,21 +149,21 @@ void cf_set_version( CFILE * cfile, int version );
|
||||
void cf_set_max_read_len(CFILE *cfile, size_t len);
|
||||
|
||||
// Deletes a file. Returns 0 on error, 1 if successful
|
||||
int cf_delete(const char *filename, int dir_type);
|
||||
int cf_delete(char *filename, int dir_type);
|
||||
|
||||
// Same as _access function to read a file's access bits
|
||||
int cf_access(const char *filename, int dir_type, int mode);
|
||||
int cf_access(char *filename, int dir_type, int mode);
|
||||
|
||||
// Returns 1 if the file exists, 0 if not.
|
||||
// Checks only the file system.
|
||||
int cf_exists(const char *filename, int dir_type);
|
||||
int cf_exists(char *filename, int dir_type);
|
||||
|
||||
// Goober5000
|
||||
// Returns 1 if the file exists, 0 if not.
|
||||
// Checks both the file system and the VPs.
|
||||
int cf_exists_full(const char *filename, int dir_type);
|
||||
int cf_exists_full(char *filename, int dir_type);
|
||||
// check num_ext worth of ext_list extensions
|
||||
int cf_exists_full_ext(const char *filename, int dir_type, const int num_ext, const char **ext_list);
|
||||
int cf_exists_full_ext(char *filename, int dir_type, const int num_ext, const char **ext_list);
|
||||
|
||||
// ctmpfile() opens a temporary file stream. File is deleted automatically when closed
|
||||
CFILE *ctmpfile();
|
||||
@@ -202,7 +197,7 @@ int cftell(CFILE *fp);
|
||||
int cfputc(int c, CFILE *cfile);
|
||||
|
||||
// cfputs() writes a string to a file
|
||||
int cfputs(const char *str, CFILE *cfile);
|
||||
int cfputs(char *str, CFILE *cfile);
|
||||
|
||||
// cfgetc() reads a character to a file
|
||||
int cfgetc(CFILE *cfile);
|
||||
@@ -217,20 +212,20 @@ int cfeof(CFILE *cfile);
|
||||
void *cf_returndata(CFILE *cfile);
|
||||
|
||||
// get the 2 byte checksum of the passed filename - return 0 if operation failed, 1 if succeeded
|
||||
int cf_chksum_short(const char *filename, ushort *chksum, int max_size = -1, int cf_type = CF_TYPE_ANY );
|
||||
int cf_chksum_short(char *filename, ushort *chksum, int max_size = -1, int cf_type = CF_TYPE_ANY );
|
||||
|
||||
// get the 2 byte checksum of the passed file - return 0 if operation failed, 1 if succeeded
|
||||
// NOTE : preserves current file position
|
||||
int cf_chksum_short(CFILE *file, ushort *chksum, int max_size = -1);
|
||||
|
||||
// get the 32 bit CRC checksum of the passed filename - return 0 if operation failed, 1 if succeeded
|
||||
int cf_chksum_long(const char *filename, uint *chksum, int max_size = -1, int cf_type = CF_TYPE_ANY );
|
||||
int cf_chksum_long(char *filename, uint *chksum, int max_size = -1, int cf_type = CF_TYPE_ANY );
|
||||
|
||||
// get the 32 bit CRC checksum of the passed file - return 0 if operation failed, 1 if succeeded
|
||||
// NOTE : preserves current file position
|
||||
int cf_chksum_long(CFILE *file, uint *chksum, int max_size = -1);
|
||||
|
||||
int cf_chksum_pack(const char *filename, uint *chk_long, bool full = false);
|
||||
int cf_chksum_pack(char *filename, uint *chk_long, bool full = false);
|
||||
|
||||
// convenient for misc checksumming purposes ------------------------------------------
|
||||
|
||||
@@ -243,16 +238,16 @@ uint cf_add_chksum_long(uint seed, ubyte *buffer, int size);
|
||||
// convenient for misc checksumming purposes ------------------------------------------
|
||||
|
||||
//================= HIGH LEVEL FUNCTIONS ==================
|
||||
int cfexist(const char *filename); // Returns true if file exists on disk (1) or in hog (2).
|
||||
int cfexist(char *filename); // Returns true if file exists on disk (1) or in hog (2).
|
||||
|
||||
// rename a file, utilizing the extension to determine where file is.
|
||||
#define CF_RENAME_SUCCESS 0 // successfully renamed the file
|
||||
#define CF_RENAME_FAIL_ACCESS 1 // new name could not be created
|
||||
#define CF_RENAME_FAIL_EXIST 2 // old name does not exist
|
||||
int cf_rename(const char *old_name, const char *name, int type = CF_TYPE_ANY );
|
||||
int cf_rename(char *old_name, char *name, int type = CF_TYPE_ANY );
|
||||
|
||||
// changes the attributes of a file
|
||||
void cf_attrib(const char *name, int set, int clear, int type);
|
||||
void cf_attrib(char *name, int set, int clear, int type);
|
||||
|
||||
// flush (delete all files in) the passed directory (by type), return the # of files deleted
|
||||
// NOTE : WILL NOT DELETE READ-ONLY FILES
|
||||
@@ -299,7 +294,7 @@ int cfwrite_vector(vec3d *vec, CFILE *file);
|
||||
int cfwrite_angles(angles *ang, CFILE *file);
|
||||
|
||||
// writes variable length, null-termined string.
|
||||
int cfwrite_string(const char *buf, CFILE *file);
|
||||
int cfwrite_string(char *buf, CFILE *file);
|
||||
|
||||
/**
|
||||
* @brief Write a fixed length string (not including its null terminator), with the length stored in file
|
||||
@@ -309,9 +304,9 @@ int cfwrite_string(const char *buf, CFILE *file);
|
||||
*/
|
||||
int cfwrite_string_len(const char *buf, CFILE *file);
|
||||
|
||||
int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *filter, int sort = CF_SORT_NONE, SCP_vector<file_list_info> *info = NULL );
|
||||
int cf_get_file_list( int max, char **list, int type, const char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
|
||||
int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char **list, int type, const char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
|
||||
int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, char *filter, int sort = CF_SORT_NONE, SCP_vector<file_list_info> *info = NULL );
|
||||
int cf_get_file_list( int max, char **list, int type, char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
|
||||
int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char **list, int type, char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
|
||||
void cf_sort_filenames( int n, char **list, int sort, file_list_info *info = NULL );
|
||||
void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_list_info> *info = NULL );
|
||||
|
||||
@@ -324,7 +319,7 @@ void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_
|
||||
// size - File size
|
||||
// offset - Offset into pack file. 0 if not a packfile.
|
||||
// Returns: If not found returns 0.
|
||||
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, int *size, int *offset, bool localize = false);
|
||||
int cf_find_file_location( char *filespec, int pathtype, int max_out, char *pack_filename, int *size, int *offset, bool localize = false);
|
||||
|
||||
// Searches for a file. Follows all rules and precedence and searches
|
||||
// CD's and pack files. Searches all locations in order for first filename using ext filter list.
|
||||
@@ -338,10 +333,10 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
// offset - Offset into pack file. 0 if not a packfile.
|
||||
// Returns: If not found returns -1, else returns offset into ext_list.
|
||||
// (NOTE: This function is exponentially slow, so don't use it unless truely needed!!)
|
||||
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out = 0, char *pack_filename = NULL, int *size = NULL, int *offset = NULL, bool localize = false);
|
||||
int cf_find_file_location_ext(char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out = 0, char *pack_filename = NULL, int *size = NULL, int *offset = NULL, bool localize = false);
|
||||
|
||||
// Functions to change directories
|
||||
int cfile_chdir(const char *dir);
|
||||
int cfile_chdir(char *dir);
|
||||
|
||||
#ifdef _WIN32
|
||||
int cfile_chdrive(int DriveNum, int flag);
|
||||
@@ -392,6 +387,6 @@ namespace cfile
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __CFILE_H__ */
|
||||
@@ -39,13 +39,11 @@ typedef struct Cfile_block {
|
||||
int size; // for packed files
|
||||
|
||||
size_t max_read_len; // max read offset, for special error handling
|
||||
|
||||
const char* source_file;
|
||||
int line_num;
|
||||
} Cfile_block;
|
||||
|
||||
#define MAX_CFILE_BLOCKS 64
|
||||
extern Cfile_block Cfile_block_list[MAX_CFILE_BLOCKS];
|
||||
extern CFILE Cfile_list[MAX_CFILE_BLOCKS];
|
||||
|
||||
// Called once to setup the low-level reading code.
|
||||
void cf_init_lowlevel_read_code( CFILE * cfile, int lib_offset, int size, int pos );
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
#include <winbase.h> /* needed for memory mapping of file functions */
|
||||
#endif
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "cfile/cfile.h"
|
||||
|
||||
|
||||
void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_list_info> *info )
|
||||
|
||||
+172
-168
@@ -9,12 +9,13 @@
|
||||
|
||||
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
@@ -32,12 +33,12 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "cfile/cfile.h"
|
||||
#include "cfile/cfilesystem.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "localization/localize.h"
|
||||
#include "osapi/osapi.h"
|
||||
|
||||
|
||||
|
||||
#define CF_ROOTTYPE_PATH 0
|
||||
#define CF_ROOTTYPE_PACK 1
|
||||
@@ -95,6 +96,7 @@ typedef struct cf_file_block {
|
||||
static uint Num_files = 0;
|
||||
static cf_file_block *File_blocks[CF_MAX_FILE_BLOCKS];
|
||||
|
||||
|
||||
// Return a pointer to to file 'index'.
|
||||
cf_file *cf_get_file(int index)
|
||||
{
|
||||
@@ -218,15 +220,19 @@ int cf_get_packfile_count(cf_root *root)
|
||||
}
|
||||
|
||||
// packfile sort function
|
||||
bool cf_packfile_sort_func(const cf_root_sort &r1, const cf_root_sort &r2)
|
||||
int cf_packfile_sort_func(const void *elem1, const void *elem2)
|
||||
{
|
||||
cf_root_sort *r1, *r2;
|
||||
r1 = (cf_root_sort*)elem1;
|
||||
r2 = (cf_root_sort*)elem2;
|
||||
|
||||
// if the 2 directory types are the same, do a string compare
|
||||
if (r1.cf_type == r2.cf_type) {
|
||||
return (stricmp(r1.path, r2.path) < 0);
|
||||
if(r1->cf_type == r2->cf_type){
|
||||
return stricmp(r1->path, r2->path);
|
||||
}
|
||||
|
||||
// otherwise return them in order of CF_TYPE_* precedence
|
||||
return (r1.cf_type < r2.cf_type);
|
||||
return (r1->cf_type < r2->cf_type) ? -1 : 1;
|
||||
}
|
||||
|
||||
// Go through a root and look for pack files
|
||||
@@ -335,7 +341,7 @@ void cf_build_pack_list( cf_root *root )
|
||||
Assert(root_index == temp_root_count);
|
||||
|
||||
// sort the roots
|
||||
std::sort(temp_roots_sort, temp_roots_sort + temp_root_count, cf_packfile_sort_func);
|
||||
qsort(temp_roots_sort, temp_root_count, sizeof(cf_root_sort), cf_packfile_sort_func);
|
||||
|
||||
// now insert them all into the real root list properly
|
||||
cf_root *new_root;
|
||||
@@ -359,109 +365,107 @@ void cf_build_pack_list( cf_root *root )
|
||||
vm_free(temp_roots_sort);
|
||||
}
|
||||
|
||||
static void cf_add_mod_roots(const char* rootDirectory)
|
||||
|
||||
void cf_build_root_list(char *cdrom_dir)
|
||||
{
|
||||
if (Cmdline_mod)
|
||||
{
|
||||
for (const char* cur_pos=Cmdline_mod; strlen(cur_pos) != 0; cur_pos+= (strlen(cur_pos)+1))
|
||||
Num_roots = 0;
|
||||
Num_path_roots = 0;
|
||||
|
||||
cf_root *root;
|
||||
char str_temp[CF_MAX_PATHNAME_LENGTH], *cur_pos;
|
||||
int path_len;
|
||||
|
||||
#ifdef SCP_UNIX
|
||||
// =========================================================================
|
||||
// now look for mods under the users HOME directory to use before system ones
|
||||
if (Cmdline_mod) {
|
||||
for (cur_pos=Cmdline_mod; strlen(cur_pos) != 0; cur_pos+= (strlen(cur_pos)+1))
|
||||
{
|
||||
SCP_stringstream ss;
|
||||
ss << rootDirectory;
|
||||
memset(str_temp, 0, CF_MAX_PATHNAME_LENGTH);
|
||||
strncpy(str_temp, cur_pos, CF_MAX_PATHNAME_LENGTH-1);
|
||||
|
||||
if (rootDirectory[strlen(rootDirectory) - 1] != DIR_SEPARATOR_CHAR)
|
||||
{
|
||||
ss << DIR_SEPARATOR_CHAR;
|
||||
strncat(str_temp, DIR_SEPARATOR_STR, (CF_MAX_PATHNAME_LENGTH - strlen(str_temp) - 1));
|
||||
|
||||
// truncated string check
|
||||
if ( (strlen(Cfile_user_dir) + strlen(str_temp) + 1) >= CF_MAX_PATHNAME_LENGTH ) {
|
||||
Int3();
|
||||
}
|
||||
|
||||
ss << cur_pos << DIR_SEPARATOR_STR;
|
||||
root = cf_create_root();
|
||||
|
||||
SCP_string rootPath = ss.str();
|
||||
if (rootPath.size() + 1 >= CF_MAX_PATHNAME_LENGTH) {
|
||||
Error(LOCATION, "The length of mod directory path '%s' exceeds the maximum of %d!\n", rootPath.c_str(), CF_MAX_PATHNAME_LENGTH);
|
||||
strncpy( root->path, Cfile_user_dir, CF_MAX_PATHNAME_LENGTH-1 );
|
||||
|
||||
// do we already have a slash? as in the case of a root directory install
|
||||
if ( (strlen(root->path) < (CF_MAX_PATHNAME_LENGTH-1)) && (root->path[strlen(root->path)-1] != DIR_SEPARATOR_CHAR) ) {
|
||||
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
|
||||
}
|
||||
|
||||
cf_root* root = cf_create_root();
|
||||
|
||||
strncpy(root->path, rootPath.c_str(), CF_MAX_PATHNAME_LENGTH-1);
|
||||
strncat(root->path, str_temp, (CF_MAX_PATHNAME_LENGTH - strlen(root->path) - 1));
|
||||
|
||||
root->roottype = CF_ROOTTYPE_PATH;
|
||||
cf_build_pack_list(root);
|
||||
}
|
||||
}
|
||||
}
|
||||
// =========================================================================
|
||||
|
||||
void cf_build_root_list(const char *cdrom_dir)
|
||||
{
|
||||
Num_roots = 0;
|
||||
Num_path_roots = 0;
|
||||
// =========================================================================
|
||||
// set users HOME directory as default for loading and saving files
|
||||
root = cf_create_root();
|
||||
strncpy( root->path, Cfile_user_dir, CF_MAX_PATHNAME_LENGTH-1 );
|
||||
|
||||
cf_root *root = nullptr;
|
||||
int path_len;
|
||||
// do we already have a slash? as in the case of a root directory install
|
||||
if( (strlen(root->path) < (CF_MAX_PATHNAME_LENGTH-1)) && (root->path[strlen(root->path)-1] != DIR_SEPARATOR_CHAR) ) {
|
||||
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
|
||||
}
|
||||
root->roottype = CF_ROOTTYPE_PATH;
|
||||
|
||||
if (os_is_legacy_mode())
|
||||
{
|
||||
// =========================================================================
|
||||
#ifdef WIN32
|
||||
// Nothing to do here, Windows uses the current directory as the base
|
||||
#else
|
||||
cf_add_mod_roots(Cfile_user_dir_legacy);
|
||||
// set the default player location to here
|
||||
if ( Pilot_file_path == NULL )
|
||||
Pilot_file_path = root->path;
|
||||
|
||||
root = cf_create_root();
|
||||
strncpy(root->path, Cfile_user_dir_legacy, CF_MAX_PATHNAME_LENGTH - 1);
|
||||
|
||||
// do we already have a slash? as in the case of a root directory install
|
||||
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
|
||||
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
|
||||
}
|
||||
root->roottype = CF_ROOTTYPE_PATH;
|
||||
|
||||
// If it wasn't set before, set the pilot path
|
||||
if (Pilot_file_path == NULL)
|
||||
Pilot_file_path = root->path;
|
||||
|
||||
// Next, check any VP files under the current directory.
|
||||
cf_build_pack_list(root);
|
||||
// Next, check any VP files under the current directory.
|
||||
cf_build_pack_list(root);
|
||||
// =========================================================================
|
||||
#endif
|
||||
// =========================================================================
|
||||
}
|
||||
else if (!Cmdline_portable_mode)
|
||||
{
|
||||
// =========================================================================
|
||||
// now look for mods under the users HOME directory to use before system ones
|
||||
cf_add_mod_roots(Cfile_user_dir);
|
||||
// =========================================================================
|
||||
|
||||
// =========================================================================
|
||||
// set users HOME directory as default for loading and saving files
|
||||
root = cf_create_root();
|
||||
strncpy(root->path, Cfile_user_dir, CF_MAX_PATHNAME_LENGTH - 1);
|
||||
if(Cmdline_mod) {
|
||||
// stackable Mod support -- Kazan
|
||||
for (cur_pos=Cmdline_mod; *cur_pos != '\0'; cur_pos+= (strlen(cur_pos)+1))
|
||||
{
|
||||
memset(str_temp, 0, CF_MAX_PATHNAME_LENGTH);
|
||||
strncpy(str_temp, cur_pos, CF_MAX_PATHNAME_LENGTH-1);
|
||||
|
||||
// do we already have a slash? as in the case of a root directory install
|
||||
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
|
||||
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
|
||||
strncat(str_temp, DIR_SEPARATOR_STR, (CF_MAX_PATHNAME_LENGTH - strlen(str_temp) - 1));
|
||||
root = cf_create_root();
|
||||
|
||||
if ( !_getcwd(root->path, CF_MAX_PATHNAME_LENGTH ) ) {
|
||||
Error(LOCATION, "Can't get current working directory -- %d", errno );
|
||||
}
|
||||
|
||||
// truncated string check
|
||||
if ( (strlen(root->path) + strlen(str_temp) + 1) >= CF_MAX_PATHNAME_LENGTH ) {
|
||||
Int3();
|
||||
}
|
||||
|
||||
path_len = strlen(root->path);
|
||||
|
||||
// do we already have a slash? as in the case of a root directory install
|
||||
if ( (path_len < (CF_MAX_PATHNAME_LENGTH-1)) && (root->path[path_len-1] != DIR_SEPARATOR_CHAR) ) {
|
||||
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
|
||||
path_len++;
|
||||
}
|
||||
|
||||
strncat(root->path, str_temp, (CF_MAX_PATHNAME_LENGTH - path_len - 1));
|
||||
root->roottype = CF_ROOTTYPE_PATH;
|
||||
cf_build_pack_list(root);
|
||||
}
|
||||
root->roottype = CF_ROOTTYPE_PATH;
|
||||
|
||||
// set the default player location to here
|
||||
if (Pilot_file_path == NULL)
|
||||
Pilot_file_path = root->path;
|
||||
|
||||
// Next, check any VP files under the current directory.
|
||||
cf_build_pack_list(root);
|
||||
// =========================================================================
|
||||
}
|
||||
|
||||
char working_directory[CF_MAX_PATHNAME_LENGTH];
|
||||
|
||||
if ( !_getcwd(working_directory, CF_MAX_PATHNAME_LENGTH ) ) {
|
||||
Error(LOCATION, "Can't get current working directory -- %d", errno );
|
||||
}
|
||||
|
||||
cf_add_mod_roots(working_directory);
|
||||
|
||||
root = cf_create_root();
|
||||
|
||||
strcpy_s(root->path, working_directory);
|
||||
if ( !_getcwd(root->path, CF_MAX_PATHNAME_LENGTH ) ) {
|
||||
Error(LOCATION, "Can't get current working directory -- %d", errno );
|
||||
}
|
||||
|
||||
path_len = strlen(root->path);
|
||||
|
||||
@@ -472,7 +476,7 @@ void cf_build_root_list(const char *cdrom_dir)
|
||||
|
||||
root->roottype = CF_ROOTTYPE_PATH;
|
||||
|
||||
// If the path wasn't set before use the working directory
|
||||
// set the default path for pilot files
|
||||
if ( Pilot_file_path == NULL )
|
||||
Pilot_file_path = root->path;
|
||||
|
||||
@@ -499,11 +503,11 @@ void cf_build_root_list(const char *cdrom_dir)
|
||||
// Given a lower case list of file extensions
|
||||
// separated by spaces, return zero if ext is
|
||||
// not in the list.
|
||||
int is_ext_in_list( const char *ext_list, const char *ext )
|
||||
int is_ext_in_list( char *ext_list, char *ext )
|
||||
{
|
||||
char tmp_ext[128];
|
||||
|
||||
strcpy_s( tmp_ext, ext);
|
||||
strncpy( tmp_ext, ext, 127 );
|
||||
strlwr(tmp_ext);
|
||||
if ( strstr(ext_list, tmp_ext )) {
|
||||
return 1;
|
||||
@@ -666,11 +670,7 @@ void cf_search_root_pack(int root_index)
|
||||
VP_FILE_HEADER VP_header;
|
||||
|
||||
Assert( sizeof(VP_header) == 16 );
|
||||
if (fread(&VP_header, sizeof(VP_header), 1, fp) != 1) {
|
||||
mprintf(("Skipping VP file ('%s') because the header could not be read...\n", root->path));
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
fread(&VP_header, 1, sizeof(VP_header), fp);
|
||||
|
||||
VP_header.version = INTEL_INT( VP_header.version ); //-V570
|
||||
VP_header.index_offset = INTEL_INT( VP_header.index_offset ); //-V570
|
||||
@@ -690,15 +690,11 @@ void cf_search_root_pack(int root_index)
|
||||
for (i=0; i<VP_header.num_files; i++ ) {
|
||||
VP_FILE find;
|
||||
|
||||
if (fread( &find, sizeof(VP_FILE), 1, fp ) != 1) {
|
||||
mprintf(("Failed to read file entry (currently in directory %s)!\n", search_path));
|
||||
break;
|
||||
}
|
||||
fread( &find, sizeof(VP_FILE), 1, fp );
|
||||
|
||||
find.offset = INTEL_INT( find.offset ); //-V570
|
||||
find.size = INTEL_INT( find.size ); //-V570
|
||||
find.write_time = INTEL_INT( find.write_time ); //-V570
|
||||
find.filename[sizeof(find.filename)-1] = '\0';
|
||||
|
||||
if ( find.size == 0 ) {
|
||||
int search_path_len = strlen(search_path);
|
||||
@@ -770,7 +766,7 @@ void cf_build_file_list()
|
||||
}
|
||||
|
||||
|
||||
void cf_build_secondary_filelist(const char *cdrom_dir)
|
||||
void cf_build_secondary_filelist(char *cdrom_dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -822,25 +818,18 @@ void cf_free_secondary_filelist()
|
||||
Num_files = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a file.
|
||||
*
|
||||
* @note Follows all rules and precedence and searches CD's and pack files.
|
||||
*
|
||||
* @param filespec Filename & extension
|
||||
* @param pathtype See CF_TYPE_ defines in CFILE.H
|
||||
* @param max_out Maximum string length that should be stuffed into pack_filename
|
||||
* @param pack_filename OUTPUT: Absolute path and filename of this file. Could be a packfile or the actual file.
|
||||
* @param size OUTPUT: File size
|
||||
* @param offset OUTPUT: Offset into pack file. 0 if not a packfile.
|
||||
* @param localize Undertake localization
|
||||
*
|
||||
* @return If not found returns 0.
|
||||
*/
|
||||
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, int *size, int *offset, bool localize )
|
||||
// Searches for a file. Follows all rules and precedence and searches
|
||||
// CD's and pack files.
|
||||
// Input: filespace - Filename & extension
|
||||
// pathtype - See CF_TYPE_ defines in CFILE.H
|
||||
// max_out - Maximum string length that should be stuffed into pack_filename
|
||||
// Output: pack_filename - Absolute path and filename of this file. Could be a packfile or the actual file.
|
||||
// size - File size
|
||||
// offset - Offset into pack file. 0 if not a packfile.
|
||||
// Returns: If not found returns 0.
|
||||
int cf_find_file_location( char *filespec, int pathtype, int max_out, char *pack_filename, int *size, int *offset, bool localize )
|
||||
{
|
||||
int i;
|
||||
uint ui;
|
||||
uint i;
|
||||
int cfs_slow_search = 0;
|
||||
char longname[MAX_PATH_LEN];
|
||||
|
||||
@@ -885,7 +874,7 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
if ( CF_TYPE_SPECIFIED(pathtype) ) {
|
||||
search_order[num_search_dirs++] = pathtype;
|
||||
} else {
|
||||
for (i = CF_TYPE_ROOT; i < CF_MAX_PATH_TYPES; i++) {
|
||||
for (int i = CF_TYPE_ROOT; i < CF_MAX_PATH_TYPES; i++) {
|
||||
if (i != pathtype)
|
||||
search_order[num_search_dirs++] = i;
|
||||
}
|
||||
@@ -894,8 +883,8 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
memset( longname, 0, sizeof(longname) );
|
||||
|
||||
|
||||
for (ui=0; ui<num_search_dirs; ui++ ) {
|
||||
switch (search_order[ui])
|
||||
for (i=0; i<num_search_dirs; i++ ) {
|
||||
switch (search_order[i])
|
||||
{
|
||||
case CF_TYPE_ROOT:
|
||||
case CF_TYPE_DATA:
|
||||
@@ -914,7 +903,7 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
}
|
||||
|
||||
if (cfs_slow_search) {
|
||||
cf_create_default_path_string( longname, sizeof(longname)-1, search_order[ui], filespec, localize );
|
||||
cf_create_default_path_string( longname, sizeof(longname)-1, search_order[i], filespec, localize );
|
||||
|
||||
#if defined _WIN32
|
||||
findhandle = _findfirst(longname, &findstruct);
|
||||
@@ -955,8 +944,9 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
}
|
||||
|
||||
// Search the pak files and CD-ROM.
|
||||
for (ui = 0; ui < Num_files; ui++ ) {
|
||||
cf_file *f = cf_get_file(ui);
|
||||
|
||||
for (i = 0; i < Num_files; i++ ) {
|
||||
cf_file *f = cf_get_file(i);
|
||||
|
||||
// only search paths we're supposed to...
|
||||
if ( (pathtype != CF_TYPE_ANY) && (pathtype != f->pathtype_index) )
|
||||
@@ -1028,30 +1018,24 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
}
|
||||
|
||||
// -- from parselo.cpp --
|
||||
extern char *stristr(char *str, const char *substr);
|
||||
extern char *stristr(const char *str, const char *substr);
|
||||
|
||||
/**
|
||||
* Searches for a file.
|
||||
*
|
||||
* @note Follows all rules and precedence and searches CD's and pack files. Searches all locations in order for first filename using filter list.
|
||||
* @note This function is exponentially slow, so don't use it unless truely needed
|
||||
*
|
||||
* @param filename Filename & extension
|
||||
* @param ext_num Number of extensions to look for
|
||||
* @param ext_list Extension filter list
|
||||
* @param pathtype See CF_TYPE_ defines in CFILE.H
|
||||
* @param max_out Maximum string length that should be stuffed into pack_filename
|
||||
* @param pack_filename OUTPUT: Absolute path and filename of this file. Could be a packfile or the actual file.
|
||||
* @param size OUTPUT: File size
|
||||
* @param offset OUTPUT: Offset into pack file. 0 if not a packfile.
|
||||
* @param localize Undertake localization
|
||||
*
|
||||
* @return If not found returns -1, else returns offset into ext_list.
|
||||
*/
|
||||
int cf_find_file_location_ext( const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out, char *pack_filename, int *size, int *offset, bool localize )
|
||||
// Searches for a file. Follows all rules and precedence and searches
|
||||
// CD's and pack files. Searches all locations in order for first filename using filter list.
|
||||
// Input: filename - Filename & extension
|
||||
// ext_num - number of extensions to look for
|
||||
// ext_list - extension filter list
|
||||
// pathtype - See CF_TYPE_ defines in CFILE.H
|
||||
// max_out - Maximum string length that should be stuffed into pack_filename
|
||||
// Output: pack_filename - Absolute path and filename of this file. Could be a packfile or the actual file.
|
||||
// size - File size
|
||||
// offset - Offset into pack file. 0 if not a packfile.
|
||||
// Returns: If not found returns -1, else returns offset into ext_list.
|
||||
// (NOTE: This function is exponentially slow, so don't use it unless truely needed!!)
|
||||
int cf_find_file_location_ext( char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out, char *pack_filename, int *size, int *offset, bool localize )
|
||||
{
|
||||
int cur_ext, i;
|
||||
uint ui;
|
||||
uint i;
|
||||
int cur_ext;
|
||||
int cfs_slow_search = 0;
|
||||
char longname[MAX_PATH_LEN];
|
||||
char filespec[MAX_FILENAME_LEN];
|
||||
@@ -1085,7 +1069,7 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
if ( CF_TYPE_SPECIFIED(pathtype) ) {
|
||||
search_order[num_search_dirs++] = pathtype;
|
||||
} else {
|
||||
for (i = CF_TYPE_ROOT; i < CF_MAX_PATH_TYPES; i++)
|
||||
for (int i = CF_TYPE_ROOT; i < CF_MAX_PATH_TYPES; i++)
|
||||
search_order[num_search_dirs++] = i;
|
||||
}
|
||||
|
||||
@@ -1095,14 +1079,14 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
// strip any existing extension
|
||||
strncpy(filespec, filename, MAX_FILENAME_LEN-1);
|
||||
|
||||
for (ui = 0; ui < num_search_dirs; ui++) {
|
||||
for (i = 0; i < num_search_dirs; i++) {
|
||||
// always hit the disk if we are looking in only one path
|
||||
if (num_search_dirs == 1) {
|
||||
cfs_slow_search = 1;
|
||||
}
|
||||
// otherwise hit based on a directory type
|
||||
else {
|
||||
switch (search_order[ui])
|
||||
switch (search_order[i])
|
||||
{
|
||||
case CF_TYPE_ROOT:
|
||||
case CF_TYPE_DATA:
|
||||
@@ -1129,7 +1113,7 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
|
||||
strcat_s( filespec, ext_list[cur_ext] );
|
||||
|
||||
cf_create_default_path_string( longname, sizeof(longname)-1, search_order[ui], filespec, localize );
|
||||
cf_create_default_path_string( longname, sizeof(longname)-1, search_order[i], filespec, localize );
|
||||
|
||||
#if defined _WIN32
|
||||
findhandle = _findfirst(longname, &findstruct);
|
||||
@@ -1192,8 +1176,8 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
file_list_index.reserve( MIN(ext_num * 4, (int)Num_files) );
|
||||
|
||||
// next, run though and pick out base matches
|
||||
for (ui = 0; ui < Num_files; ui++) {
|
||||
cf_file *f = cf_get_file(ui);
|
||||
for (i = 0; i < Num_files; i++) {
|
||||
cf_file *f = cf_get_file(i);
|
||||
|
||||
// ... only search paths that we're supposed to
|
||||
if ( (num_search_dirs == 1) && (pathtype != f->pathtype_index) )
|
||||
@@ -1322,10 +1306,9 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
|
||||
|
||||
// Returns true if filename matches filespec, else zero if not
|
||||
int cf_matches_spec(const char *filespec, const char *filename)
|
||||
int cf_matches_spec(char *filespec, char *filename)
|
||||
{
|
||||
const char *src_ext;
|
||||
const char *dst_ext;
|
||||
char *src_ext, *dst_ext;
|
||||
|
||||
src_ext = strrchr(filespec, '*');
|
||||
if(!src_ext)
|
||||
@@ -1358,7 +1341,7 @@ int cf_matches_spec(const char *filespec, const char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
int (*Get_file_list_filter)(const char *filename) = NULL;
|
||||
int (*Get_file_list_filter)(char *filename) = NULL;
|
||||
const char *Get_file_list_child = NULL;
|
||||
int Skip_packfile_search = 0;
|
||||
|
||||
@@ -1387,7 +1370,7 @@ static bool verify_file_list_child()
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cf_file_already_in_list( SCP_vector<SCP_string> &list, const char *filename )
|
||||
static int cf_file_already_in_list( SCP_vector<SCP_string> &list, char *filename )
|
||||
{
|
||||
char name_no_extension[MAX_PATH_LEN];
|
||||
size_t i, size = list.size();
|
||||
@@ -1415,7 +1398,7 @@ static int cf_file_already_in_list( SCP_vector<SCP_string> &list, const char *fi
|
||||
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
|
||||
// location, 'filter' only needs to be the filter itself, with no path information.
|
||||
// See above descriptions of cf_get_file_list() for more information about how it all works.
|
||||
int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *filter, int sort, SCP_vector<file_list_info> *info )
|
||||
int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, char *filter, int sort, SCP_vector<file_list_info> *info )
|
||||
{
|
||||
char *ptr;
|
||||
uint i;
|
||||
@@ -1452,9 +1435,12 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
|
||||
find_handle = _findfirst( filespec, &find );
|
||||
if (find_handle != -1) {
|
||||
do {
|
||||
if (strcmp(strrchr(filter, '.'), strrchr(find.name,'.')) != 0)
|
||||
if (strcmp(strstr(filter, "."), strstr(find.name,".")) != 0)
|
||||
continue;
|
||||
|
||||
if ( strlen(find.name) >= MAX_FILENAME_LEN )
|
||||
continue;
|
||||
|
||||
if (!(find.attrib & _A_SUBDIR)) {
|
||||
if ( !Get_file_list_filter || (*Get_file_list_filter)(find.name) ) {
|
||||
if ( check_duplicates && cf_file_already_in_list(list, find.name) ) {
|
||||
@@ -1490,6 +1476,9 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
|
||||
dirp = opendir (filespec);
|
||||
if ( dirp ) {
|
||||
while ((dir = readdir (dirp)) != NULL) {
|
||||
if ( strlen(dir->d_name) >= MAX_FILENAME_LEN ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fnmatch(filter, dir->d_name, 0) != 0)
|
||||
continue;
|
||||
@@ -1592,7 +1581,7 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
|
||||
return (int)list.size();
|
||||
}
|
||||
|
||||
int cf_file_already_in_list( int num_files, char **list, const char *filename )
|
||||
int cf_file_already_in_list( int num_files, char **list, char *filename )
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1616,7 +1605,7 @@ int cf_file_already_in_list( int num_files, char **list, const char *filename )
|
||||
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
|
||||
// location, 'filter' only needs to be the filter itself, with no path information.
|
||||
// See above descriptions of cf_get_file_list() for more information about how it all works.
|
||||
int cf_get_file_list( int max, char **list, int pathtype, const char *filter, int sort, file_list_info *info )
|
||||
int cf_get_file_list( int max, char **list, int pathtype, char *filter, int sort, file_list_info *info )
|
||||
{
|
||||
char *ptr;
|
||||
uint i;
|
||||
@@ -1649,7 +1638,7 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
|
||||
if (num_files >= max)
|
||||
break;
|
||||
|
||||
if (strcmp(strrchr(filter, '.'), strrchr(find.name,'.')) != 0)
|
||||
if (strcmp(strstr(filter, "."), strstr(find.name,".")) != 0)
|
||||
continue;
|
||||
|
||||
if ( strlen(find.name) >= MAX_FILENAME_LEN )
|
||||
@@ -1791,7 +1780,7 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
|
||||
return num_files;
|
||||
}
|
||||
|
||||
int cf_file_already_in_list_preallocated( int num_files, char arr[][MAX_FILENAME_LEN], const char *filename )
|
||||
int cf_file_already_in_list_preallocated( int num_files, char arr[][MAX_FILENAME_LEN], char *filename )
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1815,7 +1804,7 @@ int cf_file_already_in_list_preallocated( int num_files, char arr[][MAX_FILENAME
|
||||
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
|
||||
// location, 'filter' only needs to be the filter itself, with no path information.
|
||||
// See above descriptions of cf_get_file_list() for more information about how it all works.
|
||||
int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char **list, int pathtype, const char *filter, int sort, file_list_info *info )
|
||||
int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char **list, int pathtype, char *filter, int sort, file_list_info *info )
|
||||
{
|
||||
int num_files = 0, own_flag = 0;
|
||||
|
||||
@@ -2002,7 +1991,7 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
|
||||
// filename - optional, if set, tacks the filename onto end of path.
|
||||
// Output: path - Fully qualified pathname.
|
||||
//Returns 0 if the result would be too long (invalid result)
|
||||
int cf_create_default_path_string(char *path, uint path_max, int pathtype, const char *filename, bool localize )
|
||||
int cf_create_default_path_string( char *path, uint path_max, int pathtype, char *filename, bool localize )
|
||||
{
|
||||
#ifdef SCP_UNIX
|
||||
if ( filename && strpbrk(filename,"/") ) {
|
||||
@@ -2039,6 +2028,14 @@ int cf_create_default_path_string(char *path, uint path_max, int pathtype, const
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INF_BUILD
|
||||
// keep pilot files separated for an Inferno build since they aren't compatible
|
||||
if ( pathtype == CF_TYPE_SINGLE_PLAYERS || pathtype == CF_TYPE_MULTI_PLAYERS ) {
|
||||
strcat_s(path, path_max, "inferno");
|
||||
strcat_s(path, path_max, DIR_SEPARATOR_STR);
|
||||
}
|
||||
#endif
|
||||
|
||||
// add filename
|
||||
if (filename) {
|
||||
strcat_s(path, path_max, filename);
|
||||
@@ -2074,7 +2071,7 @@ int cf_create_default_path_string(char *path, uint path_max, int pathtype, const
|
||||
// filename - optional, if set, tacks the filename onto end of path.
|
||||
// Output: path - Fully qualified pathname.
|
||||
//Returns 0 if the result would be too long (invalid result)
|
||||
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename, bool localize )
|
||||
int cf_create_default_path_string( SCP_string &path, int pathtype, char *filename, bool localize )
|
||||
{
|
||||
#ifdef SCP_UNIX
|
||||
if ( filename && strpbrk(filename,"/") ) {
|
||||
@@ -2129,11 +2126,18 @@ int cf_create_default_path_string( SCP_string &path, int pathtype, const char *f
|
||||
void cfile_spew_pack_file_crcs()
|
||||
{
|
||||
int i;
|
||||
char out_path[CFILE_ROOT_DIRECTORY_LEN+MAX_FILENAME_LEN];
|
||||
char datetime[45];
|
||||
uint chksum = 0;
|
||||
time_t my_time;
|
||||
|
||||
FILE *out = fopen(os_get_config_path("vp_crcs.txt").c_str(), "w");
|
||||
#ifdef SCP_UNIX
|
||||
sprintf(out_path, "%s%svp_crcs.txt", Cfile_user_dir, DIR_SEPARATOR_STR);
|
||||
#else
|
||||
sprintf(out_path, "%s%svp_crcs.txt", Cfile_root_dir, DIR_SEPARATOR_STR);
|
||||
#endif
|
||||
|
||||
FILE *out = fopen(out_path, "w");
|
||||
|
||||
if (out == NULL) {
|
||||
Int3();
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "cfile/cfile.h"
|
||||
|
||||
// Builds a list of all the files
|
||||
void cf_build_secondary_filelist( const char *cdrom_path );
|
||||
void cf_build_secondary_filelist( char *cdrom_path );
|
||||
void cf_free_secondary_filelist();
|
||||
|
||||
// Internal stuff
|
||||
@@ -39,7 +39,7 @@ extern cf_pathtype Pathtypes[CF_MAX_PATH_TYPES];
|
||||
// filename - optional, if set, tacks the filename onto end of path.
|
||||
// Output: path - Fully qualified pathname.
|
||||
//Returns 0 if result would be too long (invalid result)
|
||||
int cf_create_default_path_string( char *path, uint path_max, int pathtype, const char *filename=NULL, bool localize = false);
|
||||
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename=NULL, bool localize = false );
|
||||
int cf_create_default_path_string( char *path, uint path_max, int pathtype, char *filename=NULL, bool localize = false);
|
||||
int cf_create_default_path_string( SCP_string &path, int pathtype, char *filename=NULL, bool localize = false );
|
||||
|
||||
#endif //_CFILESYSTEM_H
|
||||
+518
-891
File diff suppressed because it is too large.
Load diff
+11
-24
@@ -13,8 +13,9 @@
|
||||
#define FS_CMDLINE_HEADER_FILE
|
||||
|
||||
|
||||
int parse_cmdline(int argc, char *argv[]);
|
||||
int parse_cmdline(char *cmdline);
|
||||
|
||||
int fred2_parse_cmdline(int argc, char *argv[]);
|
||||
// COMMAND LINE SETTINGS
|
||||
// This section is for reference by all the *_init() functions. For example, the multiplayer init function
|
||||
// could check to see if (int Cmdline_multi_stream_chat_to_file) has been set by the command line parser.
|
||||
@@ -47,7 +48,6 @@ extern int Cmdline_use_last_pilot;
|
||||
extern int Cmdline_window;
|
||||
extern int Cmdline_fullscreen_window;
|
||||
extern char *Cmdline_res;
|
||||
extern char *Cmdline_center_res;
|
||||
|
||||
|
||||
// FSO OPTIONS -------------------------------------------------
|
||||
@@ -76,12 +76,10 @@ extern int Cmdline_bloom_intensity;
|
||||
extern bool Cmdline_fxaa;
|
||||
extern int Cmdline_fxaa_preset;
|
||||
extern bool Cmdline_fb_explosions;
|
||||
extern bool Cmdline_no_batching;
|
||||
extern int Cmdline_shadow_quality;
|
||||
extern int Cmdline_no_deferred_lighting;
|
||||
|
||||
// Game Speed related
|
||||
extern int Cmdline_cache_bitmaps;
|
||||
extern int Cmdline_img2dds;
|
||||
extern int Cmdline_NoFPSCap;
|
||||
extern int Cmdline_no_vsync;
|
||||
|
||||
@@ -98,13 +96,11 @@ extern int Cmdline_ship_choice_3d;
|
||||
extern int Cmdline_weapon_choice_3d;
|
||||
extern int Cmdline_warp_flash;
|
||||
extern int Cmdline_autopilot_interruptable;
|
||||
extern int Cmdline_stretch_menu;
|
||||
|
||||
// Audio related
|
||||
extern int Cmdline_query_speech;
|
||||
extern int Cmdline_snd_preload;
|
||||
extern int Cmdline_voice_recognition;
|
||||
extern int Cmdline_no_enhanced_sound;
|
||||
|
||||
// MOD related
|
||||
extern char *Cmdline_mod; // DTP for mod support
|
||||
@@ -116,48 +112,39 @@ extern char *Cmdline_spew_mission_crcs;
|
||||
extern char *Cmdline_spew_table_crcs;
|
||||
extern int Cmdline_objupd;
|
||||
|
||||
// Launcher related options
|
||||
extern bool Cmdline_portable_mode;
|
||||
|
||||
// Troubleshooting
|
||||
extern int Cmdline_load_all_weapons;
|
||||
extern int Cmdline_nohtl;
|
||||
extern int Cmdline_noibx;
|
||||
extern int Cmdline_nomovies; // WMC Toggles movie playing support
|
||||
extern int Cmdline_no_set_gamma;
|
||||
extern int Cmdline_novbo;
|
||||
extern int Cmdline_no_fbo;
|
||||
extern int Cmdline_no_pbo;
|
||||
extern int Cmdline_noglsl;
|
||||
extern int Cmdline_mipmap;
|
||||
extern int Cmdline_ati_color_swap;
|
||||
extern int Cmdline_no_3d_sound;
|
||||
extern int Cmdline_no_glsl_model_rendering;
|
||||
extern int Cmdline_no_di_mouse;
|
||||
extern int Cmdline_drawelements;
|
||||
extern char* Cmdline_keyboard_layout;
|
||||
extern bool Cmdline_gl_finish;
|
||||
extern bool Cmdline_no_geo_sdr_effects;
|
||||
extern bool Cmdline_set_cpu_affinity;
|
||||
#ifdef WIN32
|
||||
extern bool Cmdline_alternate_registry_path;
|
||||
#endif
|
||||
|
||||
// Developer/Testing related
|
||||
extern char *Cmdline_start_mission;
|
||||
extern int Cmdline_old_collision_sys;
|
||||
extern int Cmdline_dis_collisions;
|
||||
extern int Cmdline_dis_weapons;
|
||||
extern int Cmdline_noparseerrors;
|
||||
#ifdef Allow_NoWarn
|
||||
extern int Cmdline_nowarn;
|
||||
#endif
|
||||
extern int Cmdline_extra_warn;
|
||||
extern int Cmdline_show_mem_usage;
|
||||
extern int Cmdline_show_pos;
|
||||
extern int Cmdline_show_stats;
|
||||
extern int Cmdline_save_render_targets;
|
||||
extern int Cmdline_debug_window;
|
||||
extern int Cmdline_verify_vps;
|
||||
#ifdef SCP_UNIX
|
||||
extern int Cmdline_no_grab;
|
||||
#endif
|
||||
extern int Cmdline_reparse_mainhall;
|
||||
extern bool Cmdline_frame_profile;
|
||||
extern bool Cmdline_profile_write_file;
|
||||
extern bool Cmdline_no_unfocus_pause;
|
||||
extern bool Cmdline_benchmark_mode;
|
||||
|
||||
#endif
|
||||
@@ -10,18 +10,17 @@
|
||||
|
||||
|
||||
#include "cmeasure/cmeasure.h"
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "hud/hud.h"
|
||||
#include "math/staticrand.h"
|
||||
#include "mission/missionparse.h"
|
||||
#include "network/multimsgs.h"
|
||||
#include "object/object.h"
|
||||
#include "ship/ship.h"
|
||||
#include "math/staticrand.h"
|
||||
#include "object/object.h"
|
||||
#include "weapon/weapon.h"
|
||||
#include "hud/hud.h"
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "network/multimsgs.h"
|
||||
#include "mission/missionparse.h"
|
||||
|
||||
int Cmeasures_homing_check = 0;
|
||||
int Countermeasures_enabled = 1; // Debug, set to 0 means no one can fire countermeasures.
|
||||
const float CMEASURE_DETONATE_DISTANCE = 40.0f;
|
||||
|
||||
//Used to set a countermeasure velocity after being launched from a ship as a countermeasure
|
||||
//ie not as a primary or secondary.
|
||||
|
||||
@@ -15,14 +15,13 @@
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
|
||||
class object;
|
||||
struct object;
|
||||
|
||||
#define CMEASURE_WAIT 333 // delay in milliseconds between countermeasure firing.
|
||||
|
||||
// Maximum distance at which a countermeasure can be tracked
|
||||
// If this value is too large, missiles will always be tracking countermeasures.
|
||||
#define MAX_CMEASURE_TRACK_DIST 300.0f
|
||||
extern const float CMEASURE_DETONATE_DISTANCE;
|
||||
|
||||
extern int Cmeasures_homing_check;
|
||||
extern int Countermeasures_enabled;
|
||||
|
||||
@@ -10,26 +10,24 @@
|
||||
|
||||
|
||||
|
||||
#include "controlconfig/controlsconfig.h"
|
||||
#include "debugconsole/console.h"
|
||||
#include "freespace2/freespace.h"
|
||||
#include "gamehelp/contexthelp.h"
|
||||
#include "controlconfig/controlsconfig.h"
|
||||
#include "gamesequence/gamesequence.h"
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "globalincs/alphacolors.h"
|
||||
#include "graphics/font.h"
|
||||
#include "hud/hudsquadmsg.h"
|
||||
#include "io/joy.h"
|
||||
#include "io/key.h"
|
||||
#include "io/timer.h"
|
||||
#include "ui/ui.h"
|
||||
#include "io/joy.h"
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "missionui/missionscreencommon.h"
|
||||
#include "graphics/font.h"
|
||||
#include "playerman/managepilot.h"
|
||||
#include "gamehelp/contexthelp.h"
|
||||
#include "popup/popup.h"
|
||||
#include "ui/uidefs.h"
|
||||
#include "globalincs/alphacolors.h"
|
||||
#include "network/multi_pmsg.h"
|
||||
#include "network/multiutil.h"
|
||||
#include "parse/scripting.h"
|
||||
#include "pilotfile/pilotfile.h"
|
||||
#include "popup/popup.h"
|
||||
#include "ui/ui.h"
|
||||
#include "ui/uidefs.h"
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
@@ -126,7 +124,7 @@ int Conflict_bright = 0;
|
||||
|
||||
static int Num_cc_lines;
|
||||
static struct {
|
||||
const char *label;
|
||||
char *label;
|
||||
int cc_index; // index into Control_config of item
|
||||
int y; // Y coordinate of line
|
||||
int kx, kw, jx, jw; // x start and width of keyboard and joystick bound text
|
||||
@@ -137,7 +135,6 @@ struct config_item_undo {
|
||||
int size;
|
||||
int *index; // array (size) of Control_config indices of replaced elements
|
||||
config_item *list; // array (size) of original elements
|
||||
int reset_to_preset; // if >=0, then we ignore the above list and simply reset to the given preset instead
|
||||
config_item_undo *next;
|
||||
};
|
||||
|
||||
@@ -177,9 +174,6 @@ static int Background_bitmap;
|
||||
static int Conflicts_tabs[NUM_TABS];
|
||||
static UI_BUTTON List_buttons[LIST_BUTTONS_MAX]; // buttons for each line of text in list
|
||||
static UI_WINDOW Ui_window;
|
||||
static unsigned int Defaults_cycle_pos; // the controls preset that was last selected
|
||||
|
||||
int Control_config_overlay_id;
|
||||
|
||||
static struct {
|
||||
int key; // index of other control in conflict with this one
|
||||
@@ -351,7 +345,7 @@ int Config_allowed[] = {
|
||||
#ifndef NDEBUG
|
||||
int Show_controls_info = 0;
|
||||
|
||||
DCF_BOOL(show_controls_info, Show_controls_info);
|
||||
DCF_BOOL(show_controls_info, Show_controls_info)
|
||||
#endif
|
||||
|
||||
static int Axes_origin[JOY_NUM_AXES];
|
||||
@@ -393,10 +387,21 @@ int control_config_detect_axis()
|
||||
|
||||
void control_config_conflict_check()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
int i, j, a, b, c, shift = -1, alt = -1;
|
||||
|
||||
for (i=0; i<CCFG_MAX; i++) {
|
||||
Conflicts[i].key = Conflicts[i].joy = -1;
|
||||
switch (Control_config[i].key_id) {
|
||||
case KEY_LSHIFT:
|
||||
case KEY_RSHIFT:
|
||||
shift = i;
|
||||
break;
|
||||
|
||||
case KEY_LALT:
|
||||
case KEY_RALT:
|
||||
alt = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<NUM_TABS; i++) {
|
||||
@@ -405,16 +410,11 @@ void control_config_conflict_check()
|
||||
|
||||
for (i=0; i<CCFG_MAX-1; i++) {
|
||||
for (j=i+1; j<CCFG_MAX; j++) {
|
||||
if ((Control_config[i].key_id >= 0) && (Control_config[i].key_id == Control_config[j].key_id)) {
|
||||
// If one of the conflicting keys is disabled, then this silently clears
|
||||
// the disabled key to prevent the conflict; a conflict is recorded only
|
||||
// if both keys are enabled
|
||||
|
||||
if (Control_config[i].disabled)
|
||||
Control_config[i].key_id = (short) -1;
|
||||
else if (Control_config[j].disabled)
|
||||
Control_config[j].key_id = (short) -1;
|
||||
else {
|
||||
if (Control_config[i].key_id >= 0) {
|
||||
c = 0;
|
||||
a = Control_config[i].key_id;
|
||||
b = Control_config[j].key_id;
|
||||
if (a == b) {
|
||||
Conflicts[i].key = j;
|
||||
Conflicts[j].key = i;
|
||||
Conflicts_tabs[ Control_config[i].tab ] = 1;
|
||||
@@ -423,18 +423,10 @@ void control_config_conflict_check()
|
||||
}
|
||||
|
||||
if ((Control_config[i].joy_id >= 0) && (Control_config[i].joy_id == Control_config[j].joy_id)) {
|
||||
// Same as above
|
||||
|
||||
if (Control_config[i].disabled)
|
||||
Control_config[i].joy_id = (short) -1;
|
||||
else if (Control_config[j].disabled)
|
||||
Control_config[j].joy_id = (short) -1;
|
||||
else {
|
||||
Conflicts[i].joy = j;
|
||||
Conflicts[j].joy = i;
|
||||
Conflicts_tabs[ Control_config[i].tab ] = 1;
|
||||
Conflicts_tabs[ Control_config[j].tab ] = 1;
|
||||
}
|
||||
Conflicts[i].joy = j;
|
||||
Conflicts[j].joy = i;
|
||||
Conflicts_tabs[ Control_config[i].tab ] = 1;
|
||||
Conflicts_tabs[ Control_config[j].tab ] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -457,12 +449,15 @@ void control_config_conflict_check()
|
||||
// do list setup required prior to rendering and checking for the controls listing. Called when list changes
|
||||
void control_config_list_prepare()
|
||||
{
|
||||
int j, y, z;
|
||||
int j, k, y, z;
|
||||
int font_height = gr_get_font_height();
|
||||
|
||||
Num_cc_lines = y = z = 0;
|
||||
while (z < CCFG_MAX) {
|
||||
if (Control_config[z].tab == Tab && !Control_config[z].disabled) {
|
||||
if (Control_config[z].tab == Tab) {
|
||||
k = Control_config[z].key_id;
|
||||
j = Control_config[z].joy_id;
|
||||
|
||||
if (Control_config[z].hasXSTR) {
|
||||
Cc_lines[Num_cc_lines].label = XSTR(Control_config[z].text, CONTROL_CONFIG_XSTR + z);
|
||||
} else {
|
||||
@@ -526,8 +521,6 @@ config_item_undo *get_undo_block(int size)
|
||||
ptr->list = NULL;
|
||||
}
|
||||
|
||||
ptr->reset_to_preset = -1;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -560,45 +553,41 @@ int control_config_undo_last()
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (Config_item_undo->reset_to_preset > -1) {
|
||||
control_config_reset_defaults(Config_item_undo->reset_to_preset);
|
||||
if (Config_item_undo->index[0] & JOY_AXIS) {
|
||||
tab = SHIP_TAB;
|
||||
} else {
|
||||
if (Config_item_undo->index[0] & JOY_AXIS) {
|
||||
tab = SHIP_TAB;
|
||||
tab = Control_config[Config_item_undo->index[0]].tab;
|
||||
}
|
||||
|
||||
for (i=1; i<Config_item_undo->size; i++) {
|
||||
if (Config_item_undo->index[i] & JOY_AXIS) {
|
||||
if (tab != SHIP_TAB) {
|
||||
tab = -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
tab = Control_config[Config_item_undo->index[0]].tab;
|
||||
}
|
||||
|
||||
for (i=1; i<Config_item_undo->size; i++) {
|
||||
if (Config_item_undo->index[i] & JOY_AXIS) {
|
||||
if (tab != SHIP_TAB) {
|
||||
tab = -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (Control_config[Config_item_undo->index[i]].tab != tab) {
|
||||
tab = -1;
|
||||
}
|
||||
if (Control_config[Config_item_undo->index[i]].tab != tab) {
|
||||
tab = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tab >= 0) {
|
||||
Tab = tab;
|
||||
}
|
||||
if (tab >= 0) {
|
||||
Tab = tab;
|
||||
}
|
||||
|
||||
for (i=0; i<Config_item_undo->size; i++) {
|
||||
z = Config_item_undo->index[i];
|
||||
if (z & JOY_AXIS) {
|
||||
config_item *ptr;
|
||||
for (i=0; i<Config_item_undo->size; i++) {
|
||||
z = Config_item_undo->index[i];
|
||||
if (z & JOY_AXIS) {
|
||||
config_item *ptr;
|
||||
|
||||
z &= ~JOY_AXIS;
|
||||
ptr = &Config_item_undo->list[i];
|
||||
Axis_map_to[z] = ptr->joy_id;
|
||||
Invert_axis[z] = ptr->used;
|
||||
z &= ~JOY_AXIS;
|
||||
ptr = &Config_item_undo->list[i];
|
||||
Axis_map_to[z] = ptr->joy_id;
|
||||
Invert_axis[z] = ptr->used;
|
||||
|
||||
} else {
|
||||
Control_config[z] = Config_item_undo->list[i];
|
||||
}
|
||||
} else {
|
||||
Control_config[z] = Config_item_undo->list[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,7 +641,7 @@ void control_config_bind_axis(int i, int axis)
|
||||
|
||||
int control_config_remove_binding()
|
||||
{
|
||||
int z;
|
||||
int z, j, k;
|
||||
config_item_undo *ptr;
|
||||
|
||||
if (Selected_line < 0) {
|
||||
@@ -682,6 +671,7 @@ int control_config_remove_binding()
|
||||
return -1;
|
||||
}
|
||||
|
||||
j = k = -1;
|
||||
ptr = get_undo_block(1);
|
||||
ptr->index[0] = z;
|
||||
ptr->list[0] = Control_config[z];
|
||||
@@ -857,25 +847,10 @@ int control_config_do_reset()
|
||||
int i, j, total = 0;
|
||||
config_item_undo *ptr;
|
||||
config_item item;
|
||||
config_item *preset;
|
||||
bool cycling_presets = false;
|
||||
|
||||
// If there are presets, then we'll cycle to the next preset and reset to that
|
||||
if (Control_config_presets.size() >= 1) {
|
||||
cycling_presets = true;
|
||||
|
||||
if (++Defaults_cycle_pos >= Control_config_presets.size())
|
||||
Defaults_cycle_pos = 0;
|
||||
|
||||
preset = Control_config_presets[Defaults_cycle_pos];
|
||||
} else {
|
||||
// If there are no presets, then we'll always reset to the hardcoded defaults
|
||||
preset = Control_config;
|
||||
}
|
||||
|
||||
|
||||
// first, determine how many bindings need to be changed
|
||||
for (i=0; i<CCFG_MAX; i++) {
|
||||
if ((Control_config[i].key_id != preset[i].key_default) || (Control_config[i].joy_id != preset[i].joy_default)) {
|
||||
if ((Control_config[i].key_id != Control_config[i].key_default) || (Control_config[i].joy_id != Control_config[i].joy_default)) {
|
||||
total++;
|
||||
}
|
||||
}
|
||||
@@ -886,7 +861,7 @@ int control_config_do_reset()
|
||||
}
|
||||
}
|
||||
|
||||
if (!total && !cycling_presets) {
|
||||
if (!total) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
@@ -894,7 +869,7 @@ int control_config_do_reset()
|
||||
// now, back up the old bindings so we can undo if we want to
|
||||
ptr = get_undo_block(total);
|
||||
for (i=j=0; i<CCFG_MAX; i++) {
|
||||
if ((Control_config[i].key_id != preset[i].key_default) || (Control_config[i].joy_id != preset[i].joy_default)) {
|
||||
if ((Control_config[i].key_id != Control_config[i].key_default) || (Control_config[i].joy_id != Control_config[i].joy_default)) {
|
||||
ptr->index[j] = i;
|
||||
ptr->list[j] = Control_config[i];
|
||||
j++;
|
||||
@@ -913,43 +888,23 @@ int control_config_do_reset()
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
Assert(j == total);
|
||||
|
||||
if (cycling_presets)
|
||||
control_config_reset_defaults(Defaults_cycle_pos);
|
||||
else
|
||||
control_config_reset_defaults();
|
||||
|
||||
control_config_reset_defaults();
|
||||
control_config_conflict_check();
|
||||
control_config_list_prepare();
|
||||
gamesnd_play_iface(SND_RESET_PRESSED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This sets all the controls to the default values in the given preset
|
||||
// If no preset is given, the hardcoded defaults of Control_config are used
|
||||
void control_config_reset_defaults(int presetnum)
|
||||
// This sets all the controls to their default values
|
||||
void control_config_reset_defaults()
|
||||
{
|
||||
int i;
|
||||
config_item *preset;
|
||||
|
||||
if (presetnum >= 0)
|
||||
preset = Control_config_presets[presetnum];
|
||||
else
|
||||
preset = Control_config;
|
||||
|
||||
// Reset keyboard defaults
|
||||
for (i=0; i<CCFG_MAX; i++) {
|
||||
// Note that key_default and joy_default are NOT overwritten here;
|
||||
// they should retain the values of the first preset because
|
||||
// for example the key-pressed SEXP works off the defaults of the first preset
|
||||
Control_config[i].key_id = preset[i].key_default;
|
||||
Control_config[i].joy_id = preset[i].joy_default;
|
||||
Control_config[i].tab = preset[i].tab;
|
||||
Control_config[i].hasXSTR = preset[i].hasXSTR;
|
||||
Control_config[i].type = preset[i].type;
|
||||
Control_config[i].disabled = preset[i].disabled;
|
||||
Control_config[i].key_id = Control_config[i].key_default;
|
||||
Control_config[i].joy_id = Control_config[i].joy_default;
|
||||
}
|
||||
|
||||
for (i=0; i<NUM_JOY_AXIS_ACTIONS; i++) {
|
||||
@@ -1248,7 +1203,7 @@ void control_config_button_pressed(int n)
|
||||
}
|
||||
}
|
||||
|
||||
const char *control_config_tooltip_handler(const char *str)
|
||||
char *control_config_tooltip_handler(char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1273,16 +1228,14 @@ void control_config_init()
|
||||
Control_config_backup[i] = Control_config[i];
|
||||
}
|
||||
|
||||
Defaults_cycle_pos = 0;
|
||||
|
||||
common_set_interface_palette(NOX("ControlConfigPalette")); // set the interface palette
|
||||
Ui_window.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0);
|
||||
Ui_window.set_mask_bmap(Conflict_background_bitmap_mask_fname[gr_screen.res]);
|
||||
Ui_window.tooltip_handler = control_config_tooltip_handler;
|
||||
|
||||
// load in help overlay bitmap
|
||||
Control_config_overlay_id = help_overlay_get_index(CONTROL_CONFIG_OVERLAY);
|
||||
help_overlay_set_state(Control_config_overlay_id,gr_screen.res,0);
|
||||
help_overlay_load(CONTROL_CONFIG_OVERLAY);
|
||||
help_overlay_set_state(CONTROL_CONFIG_OVERLAY,0);
|
||||
|
||||
// reset conflict flashing
|
||||
Conflict_stamp = -1;
|
||||
@@ -1372,6 +1325,9 @@ void control_config_close()
|
||||
while (Config_item_undo){
|
||||
free_undo_block();
|
||||
}
|
||||
|
||||
// unload the overlay bitmap
|
||||
help_overlay_unload(CONTROL_CONFIG_OVERLAY);
|
||||
|
||||
if (Background_bitmap){
|
||||
bm_release(Background_bitmap);
|
||||
@@ -1381,12 +1337,7 @@ void control_config_close()
|
||||
common_free_interface_palette(); // restore game palette
|
||||
hud_squadmsg_save_keys(); // rebuild map for saving/restoring keys in squadmsg mode
|
||||
game_flush();
|
||||
|
||||
if (Game_mode & GM_MULTIPLAYER) {
|
||||
Pilot.save_player();
|
||||
} else {
|
||||
Pilot.save_savefile();
|
||||
}
|
||||
write_pilot_file();
|
||||
|
||||
// free strings
|
||||
for(idx=0; idx<NUM_JOY_AXIS_ACTIONS; idx++){
|
||||
@@ -1423,9 +1374,8 @@ void control_config_close()
|
||||
|
||||
void control_config_do_frame(float frametime)
|
||||
{
|
||||
const char *str;
|
||||
char buf[256];
|
||||
int i, j, k, w, x, y, z, line, conflict;
|
||||
char buf[256], *str, *jptr;
|
||||
int i, j, k, w, x, y, z, len, line, conflict;
|
||||
int font_height = gr_get_font_height();
|
||||
int select_tease_line = -1; // line mouse is down on, but won't be selected until button released
|
||||
static float timer = 0.0f;
|
||||
@@ -1483,7 +1433,7 @@ void control_config_do_frame(float frametime)
|
||||
}
|
||||
|
||||
} else {
|
||||
if (help_overlay_active(Control_config_overlay_id)) {
|
||||
if (help_overlay_active(CONTROL_CONFIG_OVERLAY)) {
|
||||
CC_Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
|
||||
Ui_window.set_ignore_gadgets(1);
|
||||
}
|
||||
@@ -1493,14 +1443,14 @@ void control_config_do_frame(float frametime)
|
||||
Ui_window.process(0);
|
||||
|
||||
if ( (k > 0) || B1_JUST_RELEASED ) {
|
||||
if (help_overlay_active(Control_config_overlay_id)) {
|
||||
help_overlay_set_state(Control_config_overlay_id, gr_screen.res, 0);
|
||||
if (help_overlay_active(CONTROL_CONFIG_OVERLAY)) {
|
||||
help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 0);
|
||||
Ui_window.set_ignore_gadgets(0);
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !help_overlay_active(Control_config_overlay_id) ) {
|
||||
if ( !help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
|
||||
Ui_window.set_ignore_gadgets(0);
|
||||
}
|
||||
|
||||
@@ -1527,7 +1477,7 @@ void control_config_do_frame(float frametime)
|
||||
}
|
||||
|
||||
if ((k > 0) && !Config_allowed[k & KEY_MASK]) {
|
||||
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR( "That is a non-bindable key. Please try again.", 207));
|
||||
popup(0, 1, POPUP_OK, XSTR( "That is a non-bindable key. Please try again.", 207));
|
||||
k = 0;
|
||||
}
|
||||
|
||||
@@ -1594,7 +1544,7 @@ void control_config_do_frame(float frametime)
|
||||
}
|
||||
|
||||
} else if (Search_mode) {
|
||||
if (help_overlay_active(Control_config_overlay_id)) {
|
||||
if (help_overlay_active(CONTROL_CONFIG_OVERLAY)) {
|
||||
CC_Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
|
||||
Ui_window.set_ignore_gadgets(1);
|
||||
}
|
||||
@@ -1604,14 +1554,14 @@ void control_config_do_frame(float frametime)
|
||||
Ui_window.process(0);
|
||||
|
||||
if ( (k > 0) || B1_JUST_RELEASED ) {
|
||||
if ( help_overlay_active(Control_config_overlay_id) ) {
|
||||
help_overlay_set_state(Control_config_overlay_id, gr_screen.res, 0);
|
||||
if ( help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
|
||||
help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 0);
|
||||
Ui_window.set_ignore_gadgets(0);
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !help_overlay_active(Control_config_overlay_id) ) {
|
||||
if ( !help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
|
||||
Ui_window.set_ignore_gadgets(0);
|
||||
}
|
||||
|
||||
@@ -1660,8 +1610,8 @@ void control_config_do_frame(float frametime)
|
||||
for (i=0; i<CCFG_MAX; i++) {
|
||||
if (Control_config[i].joy_id == j) {
|
||||
z = i;
|
||||
for (size_t buttonid=0; buttonid<NUM_BUTTONS; buttonid++){
|
||||
CC_Buttons[gr_screen.res][buttonid].button.reset();
|
||||
for (j=0; j<NUM_BUTTONS; j++){
|
||||
CC_Buttons[gr_screen.res][j].button.reset();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1705,7 +1655,7 @@ void control_config_do_frame(float frametime)
|
||||
|
||||
CC_Buttons[gr_screen.res][UNDO_BUTTON].button.enable(Config_item_undo != NULL);
|
||||
|
||||
if ( help_overlay_active(Control_config_overlay_id) ) {
|
||||
if ( help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
|
||||
CC_Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
|
||||
Ui_window.set_ignore_gadgets(1);
|
||||
}
|
||||
@@ -1713,14 +1663,14 @@ void control_config_do_frame(float frametime)
|
||||
k = Ui_window.process();
|
||||
|
||||
if ( (k > 0) || B1_JUST_RELEASED ) {
|
||||
if ( help_overlay_active(Control_config_overlay_id) ) {
|
||||
help_overlay_set_state(Control_config_overlay_id, gr_screen.res, 0);
|
||||
if ( help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
|
||||
help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 0);
|
||||
Ui_window.set_ignore_gadgets(0);
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !help_overlay_active(Control_config_overlay_id) ) {
|
||||
if ( !help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
|
||||
Ui_window.set_ignore_gadgets(0);
|
||||
}
|
||||
|
||||
@@ -1826,7 +1776,7 @@ void control_config_do_frame(float frametime)
|
||||
GR_MAYBE_CLEAR_RES(Background_bitmap);
|
||||
if (Background_bitmap >= 0) {
|
||||
gr_set_bitmap(Background_bitmap);
|
||||
gr_bitmap(0, 0, GR_RESIZE_MENU);
|
||||
gr_bitmap(0, 0);
|
||||
}
|
||||
|
||||
// highlight tab with conflict
|
||||
@@ -1860,7 +1810,7 @@ void control_config_do_frame(float frametime)
|
||||
int sw, sh;
|
||||
gr_get_string_size(&sw, &sh, conflict_str);
|
||||
|
||||
gr_string((gr_screen.max_w / 2) - (sw / 2), Conflict_warning_coords[gr_screen.res][1], conflict_str, GR_RESIZE_MENU);
|
||||
gr_string((gr_screen.max_w / 2) - (sw / 2), Conflict_warning_coords[gr_screen.res][1], conflict_str);
|
||||
|
||||
gr_set_font(FONT1);
|
||||
} else {
|
||||
@@ -1916,7 +1866,7 @@ void control_config_do_frame(float frametime)
|
||||
if (t % 2) {
|
||||
gr_set_color_fast(&Color_text_normal);
|
||||
gr_get_string_size(&w, NULL, XSTR( "?", 208));
|
||||
gr_printf_menu(x - w / 2, y - font_height / 2, XSTR( "?", 208));
|
||||
gr_printf(x - w / 2, y - font_height / 2, XSTR( "?", 208));
|
||||
}
|
||||
|
||||
} else if (!(z & JOY_AXIS) && ((Conflicts[z].key >= 0) || (Conflicts[z].joy >= 0))) {
|
||||
@@ -1928,7 +1878,7 @@ void control_config_do_frame(float frametime)
|
||||
gr_set_color_fast(&Color_text_normal);
|
||||
str = XSTR( "Control conflicts with:", 209);
|
||||
gr_get_string_size(&w, NULL, str);
|
||||
gr_printf_menu(x - w / 2, y - font_height, str);
|
||||
gr_printf(x - w / 2, y - font_height, str);
|
||||
|
||||
if (Control_config[i].hasXSTR) {
|
||||
strcpy_s(buf, XSTR(Control_config[i].text, CONTROL_CONFIG_XSTR + i));
|
||||
@@ -1938,12 +1888,12 @@ void control_config_do_frame(float frametime)
|
||||
|
||||
gr_force_fit_string(buf, 255, Conflict_wnd_coords[gr_screen.res][CONTROL_W_COORD]);
|
||||
gr_get_string_size(&w, NULL, buf);
|
||||
gr_printf_menu(x - w / 2, y, buf);
|
||||
gr_printf(x - w / 2, y, buf);
|
||||
|
||||
} else if (*bound_string) {
|
||||
gr_set_color_fast(&Color_text_normal);
|
||||
gr_get_string_size(&w, NULL, bound_string);
|
||||
gr_printf_menu(x - w / 2, y - font_height / 2, bound_string);
|
||||
gr_printf(x - w / 2, y - font_height / 2, bound_string);
|
||||
if (timestamp_elapsed(bound_timestamp)) {
|
||||
*bound_string = 0;
|
||||
}
|
||||
@@ -1951,7 +1901,7 @@ void control_config_do_frame(float frametime)
|
||||
|
||||
if (Cc_lines[Num_cc_lines - 1].y + font_height > Cc_lines[Scroll_offset].y + Control_list_coords[gr_screen.res][CONTROL_H_COORD]) {
|
||||
gr_set_color_fast(&Color_white);
|
||||
gr_printf_menu(Control_more_coords[gr_screen.res][CONTROL_X_COORD], Control_more_coords[gr_screen.res][CONTROL_Y_COORD], XSTR( "More...", 210));
|
||||
gr_printf(Control_more_coords[gr_screen.res][CONTROL_X_COORD], Control_more_coords[gr_screen.res][CONTROL_Y_COORD], XSTR( "More...", 210));
|
||||
}
|
||||
|
||||
conflict = 0;
|
||||
@@ -1977,18 +1927,19 @@ void control_config_do_frame(float frametime)
|
||||
if (Cc_lines[line].label) {
|
||||
strcpy_s(buf, Cc_lines[line].label);
|
||||
gr_force_fit_string(buf, 255, Control_list_ctrl_w[gr_screen.res]);
|
||||
gr_printf_menu(Control_list_coords[gr_screen.res][CONTROL_X_COORD], y, buf);
|
||||
gr_printf(Control_list_coords[gr_screen.res][CONTROL_X_COORD], y, buf);
|
||||
}
|
||||
|
||||
if (!(z & JOY_AXIS)) {
|
||||
k = Control_config[z].key_id;
|
||||
j = Control_config[z].joy_id;
|
||||
x = Control_list_key_x[gr_screen.res];
|
||||
jptr = NULL;
|
||||
*buf = 0;
|
||||
|
||||
if ((k < 0) && (j < 0)) {
|
||||
gr_set_color_fast(&Color_grey);
|
||||
gr_printf_menu(x, y, XSTR( "None", 211));
|
||||
gr_printf(x, y, XSTR( "None", 211));
|
||||
|
||||
} else {
|
||||
if (k >= 0) {
|
||||
@@ -2008,8 +1959,9 @@ void control_config_do_frame(float frametime)
|
||||
gr_set_color_fast(c);
|
||||
}
|
||||
|
||||
gr_printf_menu(x, y, buf);
|
||||
gr_printf(x, y, buf);
|
||||
|
||||
len = strlen(buf);
|
||||
Cc_lines[line].kx = x - Control_list_coords[gr_screen.res][CONTROL_X_COORD];
|
||||
gr_get_string_size(&w, NULL, buf);
|
||||
Cc_lines[line].kw = w;
|
||||
@@ -2017,7 +1969,7 @@ void control_config_do_frame(float frametime)
|
||||
|
||||
if (j >= 0) {
|
||||
gr_set_color_fast(&Color_text_normal);
|
||||
gr_printf_menu(x, y, XSTR( ", ", 212));
|
||||
gr_printf(x, y, XSTR( ", ", 212));
|
||||
gr_get_string_size(&w, NULL, XSTR( ", ", 212));
|
||||
x += w;
|
||||
}
|
||||
@@ -2041,7 +1993,7 @@ void control_config_do_frame(float frametime)
|
||||
}
|
||||
|
||||
gr_force_fit_string(buf, 255, Control_list_key_w[gr_screen.res] + Control_list_key_x[gr_screen.res] - x);
|
||||
gr_printf_menu(x, y, buf);
|
||||
gr_printf(x, y, buf);
|
||||
|
||||
Cc_lines[line].jx = x - Control_list_coords[gr_screen.res][CONTROL_X_COORD];
|
||||
gr_get_string_size(&Cc_lines[line].jw, NULL, buf);
|
||||
@@ -2057,7 +2009,7 @@ void control_config_do_frame(float frametime)
|
||||
|
||||
if (j < 0) {
|
||||
gr_set_color_fast(&Color_grey);
|
||||
gr_printf_menu(x, y, XSTR( "None", 211));
|
||||
gr_printf(x, y, XSTR( "None", 211));
|
||||
|
||||
} else {
|
||||
if (Conflicts_axes[z & ~JOY_AXIS] >= 0) {
|
||||
@@ -2076,7 +2028,7 @@ void control_config_do_frame(float frametime)
|
||||
gr_set_color_fast(c);
|
||||
}
|
||||
|
||||
gr_string(x, y, Joy_axis_text[j], GR_RESIZE_MENU);
|
||||
gr_string(x, y, Joy_axis_text[j]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2090,47 +2042,8 @@ void control_config_do_frame(float frametime)
|
||||
List_buttons[i++].disable();
|
||||
}
|
||||
|
||||
// If multiple controls presets are provided, display which one is in use
|
||||
if (Control_config_presets.size() > 1) {
|
||||
SCP_string preset_str;
|
||||
int matching_preset = -1;
|
||||
|
||||
for (i=0; i<(int)Control_config_presets.size(); i++) {
|
||||
bool this_preset_matches = true;
|
||||
config_item *this_preset = Control_config_presets[i];
|
||||
|
||||
for (j=0; j<CCFG_MAX; j++) {
|
||||
if (!Control_config[j].disabled && Control_config[j].key_id != this_preset[j].key_default) {
|
||||
this_preset_matches = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this_preset_matches) {
|
||||
matching_preset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (matching_preset >= 0) {
|
||||
sprintf(preset_str, "Controls: %s", Control_config_preset_names[matching_preset].c_str());
|
||||
} else {
|
||||
sprintf(preset_str, "Controls: custom");
|
||||
|
||||
}
|
||||
|
||||
gr_get_string_size(&w, NULL, preset_str.c_str());
|
||||
gr_set_color_fast(&Color_text_normal);
|
||||
|
||||
if (gr_screen.res == GR_640) {
|
||||
gr_string(16, (24 - font_height) / 2, preset_str.c_str(), GR_RESIZE_MENU);
|
||||
} else {
|
||||
gr_string(24, (40 - font_height) / 2, preset_str.c_str(), GR_RESIZE_MENU);
|
||||
}
|
||||
}
|
||||
|
||||
// blit help overlay if active
|
||||
help_overlay_maybe_blit(Control_config_overlay_id, gr_screen.res);
|
||||
help_overlay_maybe_blit(CONTROL_CONFIG_OVERLAY);
|
||||
|
||||
gr_flip();
|
||||
}
|
||||
@@ -2155,8 +2068,6 @@ float check_control_timef(int id)
|
||||
|
||||
// first, see if control actually used (makes sure modifiers match as well)
|
||||
if (!check_control(id)) {
|
||||
Control_config[id].continuous_ongoing = false;
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@@ -2171,11 +2082,6 @@ float check_control_timef(int id)
|
||||
}
|
||||
|
||||
if (t1 + t2) {
|
||||
// We want to set this to true only after visiting control_used() (above)
|
||||
// to allow it to tell the difference between an ongoing continuous action
|
||||
// started before and a continuous action being started right now.
|
||||
Control_config[id].continuous_ongoing = true;
|
||||
|
||||
return t1 + t2;
|
||||
}
|
||||
|
||||
@@ -2187,14 +2093,14 @@ void control_check_indicate()
|
||||
#ifndef NDEBUG
|
||||
if (Show_controls_info) {
|
||||
gr_set_color_fast(&HUD_color_debug);
|
||||
gr_printf_no_resize(gr_screen.center_offset_x + gr_screen.center_w - 154, gr_screen.center_offset_y + 5, NOX("Ctrls checked: %d"), Control_check_count);
|
||||
gr_printf(490, 15, NOX("Ctrls checked: %d"), Control_check_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
Control_check_count = 0;
|
||||
}
|
||||
|
||||
int check_control_used(int id, int key)
|
||||
int check_control(int id, int key)
|
||||
{
|
||||
int z, mask;
|
||||
static int last_key = 0;
|
||||
@@ -2211,9 +2117,6 @@ int check_control_used(int id, int key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Control_config[id].disabled)
|
||||
return 0;
|
||||
|
||||
if (Control_config[id].type == CC_TYPE_CONTINUOUS) {
|
||||
if (joy_down(Control_config[id].joy_id) || joy_down_count(Control_config[id].joy_id, 1)) {
|
||||
control_used(id);
|
||||
@@ -2249,16 +2152,17 @@ int check_control_used(int id, int key)
|
||||
z &= KEY_MASK;
|
||||
|
||||
if (keyd_pressed[z] || key_down_count(z)) {
|
||||
control_used(id);
|
||||
return 1;
|
||||
if ( !hud_squadmsg_read_key(z) ) {
|
||||
control_used(id);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((Control_config[id].key_id == key) || joy_down_count(Control_config[id].joy_id, 1) ||
|
||||
((Control_config[id].joy_id >= 0) && (Control_config[id].joy_id < MOUSE_NUM_BUTTONS) && mouse_down_count(1 << Control_config[id].joy_id))) {
|
||||
if ((Control_config[id].key_id == key) || joy_down_count(Control_config[id].joy_id, 1) || mouse_down_count(1 << Control_config[id].joy_id)) {
|
||||
//mprintf(("Key used %d", key));
|
||||
control_used(id);
|
||||
return 1;
|
||||
@@ -2267,35 +2171,6 @@ int check_control_used(int id, int key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for check_control_used. Allows the game to ignore the key if told to do so by the ignore-key SEXP.
|
||||
*/
|
||||
int check_control(int id, int key)
|
||||
{
|
||||
if (check_control_used(id, key)) {
|
||||
if (Ignored_keys[id]) {
|
||||
if (Ignored_keys[id] > 0) {
|
||||
Ignored_keys[id]--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (Control_config[id].continuous_ongoing) {
|
||||
// If we reach this point, then it means this is a continuous control
|
||||
// which has just been released
|
||||
|
||||
Script_system.SetHookVar("Action", 's', Control_config[id].text);
|
||||
Script_system.RunCondition(CHA_ONACTIONSTOPPED, '\0', NULL, NULL, id);
|
||||
Script_system.RemHookVar("Action");
|
||||
|
||||
Control_config[id].continuous_ongoing = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get heading, pitch, bank, throttle abs. and throttle rel. values.
|
||||
void control_get_axes_readings(int *h, int *p, int *b, int *ta, int *tr)
|
||||
{
|
||||
@@ -2348,7 +2223,6 @@ void control_get_axes_readings(int *h, int *p, int *b, int *ta, int *tr)
|
||||
return;
|
||||
}
|
||||
|
||||
int Last_frame_timestamp;
|
||||
void control_used(int id)
|
||||
{
|
||||
// if we have set this key to be ignored, ignore it
|
||||
@@ -2356,20 +2230,7 @@ void control_used(int id)
|
||||
return;
|
||||
}
|
||||
|
||||
// This check needs to be done because the control code might call this function more than once per frame,
|
||||
// and we don't want to run the hooks more than once per frame
|
||||
if (Control_config[id].used < Last_frame_timestamp) {
|
||||
if (!Control_config[id].continuous_ongoing) {
|
||||
Script_system.SetHookVar("Action", 's', Control_config[id].text);
|
||||
Script_system.RunCondition(CHA_ONACTION, '\0', NULL, NULL, id);
|
||||
Script_system.RemHookVar("Action");
|
||||
|
||||
if (Control_config[id].type == CC_TYPE_CONTINUOUS)
|
||||
Control_config[id].continuous_ongoing = true;
|
||||
}
|
||||
|
||||
Control_config[id].used = timestamp();
|
||||
}
|
||||
Control_config[id].used = timestamp();
|
||||
}
|
||||
|
||||
void control_config_clear_used_status()
|
||||
|
||||
@@ -5,79 +5,55 @@
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef CONTROLS_CONFIG_H
|
||||
#define CONTROLS_CONFIG_H
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#define CONTROL_CONFIG_XSTR 507
|
||||
|
||||
/*!
|
||||
* These are used to index a corresponding joystick axis value from an array.
|
||||
* Currently only used by ::Axis_map_to[] and ::Axis_map_to_defaults[]
|
||||
*/
|
||||
enum Joy_axis_index {
|
||||
JOY_X_AXIS =0,
|
||||
JOY_Y_AXIS,
|
||||
JOY_Z_AXIS,
|
||||
JOY_RX_AXIS,
|
||||
JOY_RY_AXIS,
|
||||
JOY_RZ_AXIS
|
||||
};
|
||||
#define JOY_X_AXIS 0
|
||||
#define JOY_Y_AXIS 1
|
||||
#define JOY_Z_AXIS 2
|
||||
#define JOY_RX_AXIS 3
|
||||
#define JOY_RY_AXIS 4
|
||||
#define JOY_RZ_AXIS 5
|
||||
|
||||
#define NUM_JOY_AXIS_ACTIONS 5
|
||||
|
||||
/*!
|
||||
* These are used to index a corresponding (analog) action, namely controlling the orientation angles and throttle.
|
||||
*/
|
||||
enum Joy_axis_action_index {
|
||||
JOY_HEADING_AXIS =0,
|
||||
JOY_PITCH_AXIS,
|
||||
JOY_BANK_AXIS,
|
||||
JOY_ABS_THROTTLE_AXIS,
|
||||
JOY_REL_THROTTLE_AXIS,
|
||||
#define JOY_HEADING_AXIS 0
|
||||
#define JOY_PITCH_AXIS 1
|
||||
#define JOY_BANK_AXIS 2
|
||||
#define JOY_ABS_THROTTLE_AXIS 3
|
||||
#define JOY_REL_THROTTLE_AXIS 4
|
||||
|
||||
/*!
|
||||
* This must always be below the last defined item
|
||||
*/
|
||||
NUM_JOY_AXIS_ACTIONS //!< The total number of actions an axis may map to
|
||||
};
|
||||
// --------------------------------------------------
|
||||
// different types of controls that can be assigned
|
||||
// --------------------------------------------------
|
||||
|
||||
#define CC_TYPE_TRIGGER 0
|
||||
#define CC_TYPE_CONTINUOUS 1
|
||||
|
||||
|
||||
/*!
|
||||
* Control Configuration Types. Namely differ in how the control is activated
|
||||
*/
|
||||
enum CC_type {
|
||||
CC_TYPE_TRIGGER =0, //!< A normal, one-shot type control that is activated when a key is or button is pressed
|
||||
CC_TYPE_CONTINUOUS //!< A continous control that is activated as long as the key or button is held down
|
||||
};
|
||||
|
||||
/*!
|
||||
* Control configuration item type.
|
||||
*/
|
||||
typedef struct config_item {
|
||||
short key_default; //!< default key bound to action
|
||||
short joy_default; //!< default joystick button bound to action
|
||||
char tab; //!< what tab (category) it belongs in
|
||||
bool hasXSTR; //!< whether we should translate this with an XSTR
|
||||
char *text; //!< describes the action in the config screen
|
||||
char type; //!< manner control should be checked in
|
||||
short key_id; //!< actual key bound to action
|
||||
short joy_id; //!< joystick button bound to action
|
||||
int used; //!< has control been used yet in mission? If so, this is the timestamp
|
||||
bool disabled; //!< whether this action should be available at all
|
||||
bool continuous_ongoing;//!< whether this action is a continuous one and is currently ongoing
|
||||
short key_default; // default key bound to action
|
||||
short joy_default; // default joystick button bound to action
|
||||
char tab; // what tab (category) it belongs in
|
||||
bool hasXSTR; // whether we should translate this with an XSTR
|
||||
char *text; // describes the action in the config screen
|
||||
char type; // manner control should be checked in
|
||||
short key_id; // actual key bound to action
|
||||
short joy_id; // joystick button bound to action
|
||||
int used; // has control been used yet in mission? If so, this is the timestamp
|
||||
} config_item;
|
||||
|
||||
/*!
|
||||
/**
|
||||
* All available actions
|
||||
* This is the value of the id field in config_item
|
||||
* The first group of items are ship targeting.
|
||||
*/
|
||||
enum IoActionId {
|
||||
// targeting a ship
|
||||
TARGET_NEXT =0, //!< target next
|
||||
TARGET_PREV =1, //!< target previous
|
||||
TARGET_NEXT_CLOSEST_HOSTILE =2, //!< target the next hostile target
|
||||
@@ -90,23 +66,17 @@ enum IoActionId {
|
||||
TARGET_LAST_TRANMISSION_SENDER =9, //!< TARGET_LAST_TRANMISSION_SENDER
|
||||
STOP_TARGETING_SHIP =10, //!< stop targeting ship
|
||||
|
||||
//!< @n
|
||||
//!< Targeting a Ship's Subsystem
|
||||
//!< ------------------------------
|
||||
// targeting a ship's subsystem
|
||||
TARGET_SUBOBJECT_IN_RETICLE =11, //!< target ships subsystem in reticle
|
||||
TARGET_NEXT_SUBOBJECT =12, //!< target next subsystem on current target
|
||||
TARGET_PREV_SUBOBJECT =13, //!< TARGET_PREV_SUBOBJECT
|
||||
STOP_TARGETING_SUBSYSTEM =14, //!< stop targeting subsystems on ship
|
||||
|
||||
//!< @n
|
||||
//!< Speed Matching
|
||||
//!< ----------------
|
||||
// speed matching
|
||||
MATCH_TARGET_SPEED =15, //!< match target speed
|
||||
TOGGLE_AUTO_MATCH_TARGET_SPEED =16, //!< toggle auto-match target speed
|
||||
|
||||
//!< @n
|
||||
//!< Weapons
|
||||
//!< ---------
|
||||
// weapons
|
||||
FIRE_PRIMARY =17, //!< FIRE_PRIMARY
|
||||
FIRE_SECONDARY =18, //!< FIRE_SECONDARY
|
||||
CYCLE_NEXT_PRIMARY =19, //!< cycle to next primary weapon
|
||||
@@ -115,9 +85,7 @@ enum IoActionId {
|
||||
CYCLE_NUM_MISSLES =22, //!< cycle number of missiles fired from secondary bank
|
||||
LAUNCH_COUNTERMEASURE =23, //!< LAUNCH_COUNTERMEASURE
|
||||
|
||||
//!< @n
|
||||
//!< Controls
|
||||
//!< ----------
|
||||
// controls
|
||||
FORWARD_THRUST =24, //!< FORWARD_THRUST
|
||||
REVERSE_THRUST =25, //!< REVERSE_THRUST
|
||||
BANK_LEFT =26, //!< BANK_LEFT
|
||||
@@ -127,9 +95,7 @@ enum IoActionId {
|
||||
YAW_LEFT =30, //!< YAW_LEFT
|
||||
YAW_RIGHT =31, //!< YAW_RIGHT
|
||||
|
||||
//!< @n
|
||||
//!< Throttle Control
|
||||
//!< ------------------
|
||||
// throttle control
|
||||
ZERO_THROTTLE =32, //!< ZERO_THROTTLE
|
||||
MAX_THROTTLE =33, //!< MAX_THROTTLE
|
||||
ONE_THIRD_THROTTLE =34, //!< ONE_THIRD_THROTTLE
|
||||
@@ -137,9 +103,7 @@ enum IoActionId {
|
||||
PLUS_5_PERCENT_THROTTLE =36, //!< PLUS_5_PERCENT_THROTTLE
|
||||
MINUS_5_PERCENT_THROTTLE =37, //!< MINUS_5_PERCENT_THROTTLE
|
||||
|
||||
//!< @n
|
||||
//!< Squadmate Messaging Keys
|
||||
//!< --------------------------
|
||||
// squadmate messaging keys
|
||||
ATTACK_MESSAGE =38, //!< wingman message: attack current target
|
||||
DISARM_MESSAGE =39, //!< wingman message: disarm current target
|
||||
DISABLE_MESSAGE =40, //!< wingman message: disable current target
|
||||
@@ -154,9 +118,7 @@ enum IoActionId {
|
||||
REARM_MESSAGE =49, //!< REARM_MESSAGE
|
||||
TARGET_CLOSEST_SHIP_ATTACKING_SELF =50, //!< target closest ship that is attacking player
|
||||
|
||||
//!< @n
|
||||
//!< Views
|
||||
//!< -------
|
||||
// Views
|
||||
VIEW_CHASE =51, //!< VIEW_CHASE
|
||||
VIEW_EXTERNAL =52, //!< VIEW_EXTERNAL
|
||||
VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK =53, //!< VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK
|
||||
@@ -170,9 +132,6 @@ enum IoActionId {
|
||||
PADLOCK_LEFT =61, //!< PADLOCK_LEFT
|
||||
PADLOCK_RIGHT =62, //!< PADLOCK_RIGHT
|
||||
|
||||
//!< @n
|
||||
//!< Misc Controls 1
|
||||
//!< -----------------
|
||||
RADAR_RANGE_CYCLE =63, //!< cycle to next radar range
|
||||
SQUADMSG_MENU =64, //!< toggle the squadmate messaging menu
|
||||
SHOW_GOALS =65, //!< show the mission goals screen
|
||||
@@ -180,9 +139,6 @@ enum IoActionId {
|
||||
TARGET_TARGETS_TARGET =67, //!< target your target's target
|
||||
AFTERBURNER =68, //!< AFTERBURNER
|
||||
|
||||
//!< @n
|
||||
//!< ETS
|
||||
//!< -----
|
||||
INCREASE_WEAPON =69, //!< increase weapon recharge rate
|
||||
DECREASE_WEAPON =70, //!< decrease weapon recharge rate
|
||||
INCREASE_SHIELD =71, //!< increase shield recharge rate
|
||||
@@ -195,42 +151,34 @@ enum IoActionId {
|
||||
SHIELD_XFER_BOTTOM =78, //!< transfer shield energy to rear
|
||||
SHIELD_XFER_LEFT =79, //!< transfer shield energy to left
|
||||
SHIELD_XFER_RIGHT =80, //!< transfer shield energy to right
|
||||
|
||||
XFER_SHIELD =81, //!< transfer energy to shield from weapons
|
||||
XFER_LASER =82, //!< transfer energy to weapons from shield
|
||||
|
||||
//!< @n
|
||||
//!< Misc Controls 2
|
||||
//!< -----------------
|
||||
//Backslash -- this was a convenient place for Glide When Pressed, since Show Damage Popup isn't used
|
||||
GLIDE_WHEN_PRESSED =83, //!< GLIDE_WHEN_PRESSED
|
||||
//!< @remark Backslash -- this was a convenient place for Glide When Pressed, since Show Damage Popup isn't used
|
||||
BANK_WHEN_PRESSED =84, //!< BANK_WHEN_PRESSED
|
||||
SHOW_NAVMAP =85, //!< SHOW_NAVMAP
|
||||
ADD_REMOVE_ESCORT =86, //!< ADD_REMOVE_ESCORT
|
||||
ESCORT_CLEAR =87, //!< ESCORT_CLEAR
|
||||
|
||||
TARGET_NEXT_ESCORT_SHIP =88, //!< TARGET_NEXT_ESCORT_SHIP
|
||||
TARGET_CLOSEST_REPAIR_SHIP =89, //!< target the closest repair ship
|
||||
TARGET_NEXT_UNINSPECTED_CARGO =90, //!< TARGET_NEXT_UNINSPECTED_CARGO
|
||||
TARGET_PREV_UNINSPECTED_CARGO =91, //!< TARGET_PREV_UNINSPECTED_CARGO
|
||||
TARGET_NEWEST_SHIP =92, //!< TARGET_NEWEST_SHIP
|
||||
|
||||
TARGET_NEXT_LIVE_TURRET =93, //!< TARGET_NEXT_LIVE_TURRET
|
||||
TARGET_PREV_LIVE_TURRET =94, //!< TARGET_PREV_LIVE_TURRET
|
||||
|
||||
TARGET_NEXT_BOMB =95, //!< TARGET_NEXT_BOMB
|
||||
TARGET_PREV_BOMB =96, //!< TARGET_PREV_BOMB
|
||||
|
||||
//!< @n
|
||||
//!< Multiplayer messaging keys
|
||||
//!< ----------------------------
|
||||
// multiplayer messaging keys
|
||||
MULTI_MESSAGE_ALL =97, //!< message all netplayers
|
||||
MULTI_MESSAGE_FRIENDLY =98, //!< message all friendlies
|
||||
MULTI_MESSAGE_HOSTILE =99, //!< message all hostiles
|
||||
MULTI_MESSAGE_TARGET =100, //!< message targeted ship (if player)
|
||||
|
||||
//!< @n
|
||||
//!< Multiplayer misc keys
|
||||
//!< -----------------------
|
||||
// multiplayer misc keys
|
||||
MULTI_OBSERVER_ZOOM_TO =101, //!< if i'm an observer, zoom to my targeted object
|
||||
|
||||
TIME_SPEED_UP =102, //!< TIME_SPEED_UP
|
||||
@@ -242,9 +190,6 @@ enum IoActionId {
|
||||
|
||||
MULTI_SELF_DESTRUCT =106, //!< self destruct (multiplayer only)
|
||||
|
||||
//!< @n
|
||||
//!< Misc Controls 3
|
||||
//!< -----------------
|
||||
TOGGLE_HUD =107, //!< TOGGLE_HUD
|
||||
RIGHT_SLIDE_THRUST =108, //!< RIGHT_SLIDE_THRUST
|
||||
LEFT_SLIDE_THRUST =109, //!< LEFT_SLIDE_THRUST
|
||||
@@ -254,24 +199,15 @@ enum IoActionId {
|
||||
VIEW_TOPDOWN =113, //!< VIEW_TOPDOWN
|
||||
VIEW_TRACK_TARGET =114, //!< VIEW_TRACK_TARGET
|
||||
|
||||
//!< @n
|
||||
//!< AutoPilot - Kazan
|
||||
//!< -------------------
|
||||
//AutoPilot - Kazan
|
||||
AUTO_PILOT_TOGGLE =115, //!< Autopilot key control
|
||||
NAV_CYCLE =116, //!< NAV_CYCLE
|
||||
|
||||
//!< @n
|
||||
//!< Gliding
|
||||
//!< ---------
|
||||
//Gliding
|
||||
TOGGLE_GLIDING =117, //!< TOGGLE_GLIDING
|
||||
|
||||
//!< @n
|
||||
//!< Additional weapon controls
|
||||
//!< ----------------------------
|
||||
CYCLE_PRIMARY_WEAPON_SEQUENCE =118, //!< cycle num primaries to fire at once
|
||||
|
||||
/*!
|
||||
* This must always be below the last defined item
|
||||
/**
|
||||
* This must always be below the last defined action
|
||||
*/
|
||||
CCFG_MAX //!< The total number of defined control actions (or last define + 1)
|
||||
};
|
||||
@@ -288,16 +224,12 @@ extern int Axis_map_to[];
|
||||
extern int Invert_axis[];
|
||||
extern int Invert_axis_defaults[];
|
||||
|
||||
extern int Control_config_overlay_id;
|
||||
|
||||
extern config_item Control_config[]; //!< Stores the keyboard configuration
|
||||
extern SCP_vector<config_item*> Control_config_presets; // tabled control presets; pointers to config_item arrays
|
||||
extern SCP_vector<SCP_string> Control_config_preset_names; // names for Control_config_presets (identical order of items)
|
||||
extern config_item Control_config[]; // stores the keyboard configuration
|
||||
extern char **Scan_code_text;
|
||||
extern char **Joy_button_text;
|
||||
|
||||
void control_config_common_init(); //!< initialize common control config stuff - call at game startup after localization has been initialized
|
||||
void control_config_common_close(); //!< close common control config stuff - call at game shutdown
|
||||
// initialize common control config stuff - call at game startup after localization has been initialized
|
||||
void control_config_common_init();
|
||||
|
||||
void control_config_init();
|
||||
void control_config_do_frame(float frametime);
|
||||
@@ -305,8 +237,8 @@ void control_config_close();
|
||||
|
||||
void control_config_cancel_exit();
|
||||
|
||||
void control_config_reset_defaults(int presetnum=-1);
|
||||
int translate_key_to_index(const char *key, bool find_override=true);
|
||||
void control_config_reset_defaults();
|
||||
int translate_key_to_index(char *key);
|
||||
char *translate_key(char *key);
|
||||
char *textify_scancode(int code);
|
||||
float check_control_timef(int id);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+78
-79
@@ -10,17 +10,17 @@
|
||||
|
||||
|
||||
#include "cutscene/cutscenes.h"
|
||||
#include "freespace2/freespace.h"
|
||||
#include "gamesequence/gamesequence.h"
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "globalincs/alphacolors.h"
|
||||
#include "io/key.h"
|
||||
#include "localization/localize.h"
|
||||
#include "menuui/mainhallmenu.h"
|
||||
#include "movie.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "popup/popup.h"
|
||||
#include "ui/ui.h"
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "gamesequence/gamesequence.h"
|
||||
#include "freespace2/freespace.h"
|
||||
#include "io/key.h"
|
||||
#include "movie.h"
|
||||
#include "popup/popup.h"
|
||||
#include "menuui/mainhallmenu.h"
|
||||
#include "globalincs/alphacolors.h"
|
||||
#include "localization/localize.h"
|
||||
#include "parse/parselo.h"
|
||||
|
||||
|
||||
extern int Cmdline_nomovies;
|
||||
@@ -35,16 +35,16 @@ char *Cutscene_mask_name[GR_NUM_RESOLUTIONS] = {
|
||||
"2_ViewFootage-m"
|
||||
};
|
||||
|
||||
int Cutscenes_viewable;
|
||||
int Description_index;
|
||||
SCP_vector<cutscene_info> Cutscenes;
|
||||
|
||||
//extern int All_movies_enabled; // If set, all movies may be viewed. Keyed off cheat code.
|
||||
void cutscene_close()
|
||||
{
|
||||
for(SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut)
|
||||
if(cut->description != NULL) {
|
||||
if(cut->description)
|
||||
vm_free(cut->description);
|
||||
cut->description = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// initialization stuff for cutscenes
|
||||
@@ -52,61 +52,54 @@ void cutscene_init()
|
||||
{
|
||||
atexit(cutscene_close);
|
||||
char buf[MULTITEXT_LENGTH];
|
||||
cutscene_info cutinfo;
|
||||
int rval;
|
||||
cutscene_info cutinfo;
|
||||
|
||||
try
|
||||
{
|
||||
read_file_text("cutscenes.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
// open localization
|
||||
lcl_ext_open();
|
||||
|
||||
// parse in all the cutscenes
|
||||
Cutscenes.clear();
|
||||
skip_to_string("#Cutscenes");
|
||||
ignore_white_space();
|
||||
|
||||
bool isFirstCutscene = true;
|
||||
|
||||
while (required_string_either("#End", "$Filename:"))
|
||||
{
|
||||
required_string("$Filename:");
|
||||
stuff_string(cutinfo.filename, F_PATHNAME, MAX_FILENAME_LEN);
|
||||
|
||||
required_string("$Name:");
|
||||
stuff_string(cutinfo.name, F_NAME, NAME_LENGTH);
|
||||
|
||||
required_string("$Description:");
|
||||
stuff_string(buf, F_MULTITEXT, sizeof(buf));
|
||||
drop_white_space(buf);
|
||||
compact_multitext_string(buf);
|
||||
cutinfo.description = vm_strdup(buf);
|
||||
|
||||
if (optional_string("$cd:"))
|
||||
stuff_int(&cutinfo.cd);
|
||||
else
|
||||
cutinfo.cd = 0;
|
||||
|
||||
cutinfo.viewable = false;
|
||||
|
||||
if (isFirstCutscene) {
|
||||
isFirstCutscene = false;
|
||||
// The original code assumes the first movie is the intro, so always viewable
|
||||
cutinfo.viewable = true;
|
||||
}
|
||||
|
||||
if (optional_string("$Always Viewable:")) {
|
||||
stuff_boolean(&cutinfo.viewable);
|
||||
}
|
||||
|
||||
Cutscenes.push_back(cutinfo);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "cutscenes.tbl", e.what()));
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "cutscenes.tbl", rval));
|
||||
lcl_ext_close();
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text("cutscenes.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// parse in all the cutscenes
|
||||
Cutscenes.clear();
|
||||
skip_to_string("#Cutscenes");
|
||||
ignore_white_space();
|
||||
|
||||
while ( required_string_either("#End", "$Filename:") )
|
||||
{
|
||||
memset(&cutinfo, 0, sizeof(cutscene_info));
|
||||
|
||||
required_string("$Filename:");
|
||||
stuff_string( cutinfo.filename, F_PATHNAME, MAX_FILENAME_LEN );
|
||||
|
||||
required_string("$Name:");
|
||||
stuff_string( cutinfo.name, F_NAME, NAME_LENGTH );
|
||||
|
||||
required_string("$Description:");
|
||||
stuff_string(buf, F_MULTITEXT, sizeof(buf));
|
||||
drop_white_space(buf);
|
||||
compact_multitext_string(buf);
|
||||
cutinfo.description = vm_strdup(buf);
|
||||
|
||||
required_string("$cd:");
|
||||
stuff_int( &cutinfo.cd );
|
||||
|
||||
Cutscenes.push_back(cutinfo);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
|
||||
Cutscenes_viewable = INTRO_CUTSCENE_FLAG;
|
||||
|
||||
// close localization
|
||||
lcl_ext_close();
|
||||
}
|
||||
|
||||
// function to return 0 based index of which CD a particular movie is on
|
||||
@@ -147,13 +140,11 @@ void cutscene_mark_viewable(char *filename)
|
||||
|
||||
// see if the stripped filename matches the cutscene filename
|
||||
if ( strstr(cut_file, file) != NULL ) {
|
||||
cut->viewable = true;
|
||||
Cutscenes_viewable |= (1<<i);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
Warning(LOCATION, "Could not find cutscene '%s' in listing; cannot mark it viewable...", filename);
|
||||
}
|
||||
|
||||
#define NUM_BUTTONS 8
|
||||
@@ -252,7 +243,7 @@ int Cutscene_max_text_lines[GR_NUM_RESOLUTIONS] = {
|
||||
static int Text_size;
|
||||
static int Text_offset = 0;
|
||||
static int Text_line_size[MAX_TEXT_LINES];
|
||||
static const char *Text_lines[MAX_TEXT_LINES];
|
||||
static char *Text_lines[MAX_TEXT_LINES];
|
||||
|
||||
|
||||
int cutscenes_validate_cd(char *mve_name, int prompt_for_cd)
|
||||
@@ -260,7 +251,7 @@ int cutscenes_validate_cd(char *mve_name, int prompt_for_cd)
|
||||
int cd_present = 0;
|
||||
int cd_drive_num;
|
||||
int cd_mve_is_on;
|
||||
char volume_name[MAX_PATH_LEN];
|
||||
char volume_name[128];
|
||||
|
||||
int num_attempts = 0;
|
||||
|
||||
@@ -320,7 +311,7 @@ void cutscenes_screen_play()
|
||||
strcpy_s(name, Cutscenes[which_cutscene].filename );
|
||||
// full_name = cf_add_ext(name, NOX(".mve"));
|
||||
|
||||
main_hall_stop_music(true);
|
||||
main_hall_stop_music();
|
||||
main_hall_stop_ambient();
|
||||
int rval = movie_play(name);
|
||||
main_hall_start_music();
|
||||
@@ -329,11 +320,11 @@ void cutscenes_screen_play()
|
||||
char str[256];
|
||||
|
||||
if (Cmdline_nomovies)
|
||||
strcpy_s(str, XSTR("Movies are currently disabled.", 1574));
|
||||
sprintf(str, XSTR("Movies are currently disabled.", -1));
|
||||
else
|
||||
sprintf(str, XSTR("Unable to play movie %s.", 204), Cutscenes[which_cutscene].name);
|
||||
|
||||
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, str );
|
||||
popup(0, 1, POPUP_OK, str );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -482,12 +473,20 @@ void cutscenes_screen_init()
|
||||
Scroll_offset = Selected_line = 0;
|
||||
Description_index = -1;
|
||||
|
||||
// when doing a debug version, just put all of the movie files here.
|
||||
#ifndef NDEBUG
|
||||
//Cutscenes_viewable = 0xffffffff; // makes all cutscenes viewble.
|
||||
#endif
|
||||
|
||||
// if (All_movies_enabled)
|
||||
// Cutscenes_viewable = 0xffffffff; // Cheat code enables all movies.
|
||||
|
||||
Cutscene_list.clear();
|
||||
|
||||
int u = 0;
|
||||
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut, u++) {
|
||||
if ( (*cut).viewable ) {
|
||||
Cutscene_list.push_back(u);
|
||||
size_t size = Cutscenes.size();
|
||||
for (size_t j=0;j < size;j++) {
|
||||
if ( Cutscenes_viewable & (1<<j) ) {
|
||||
Cutscene_list.push_back((int)j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -580,7 +579,7 @@ void cutscenes_screen_do_frame()
|
||||
GR_MAYBE_CLEAR_RES(Background_bitmap);
|
||||
if (Background_bitmap >= 0) {
|
||||
gr_set_bitmap(Background_bitmap);
|
||||
gr_bitmap(0, 0, GR_RESIZE_MENU);
|
||||
gr_bitmap(0, 0);
|
||||
}
|
||||
|
||||
Ui_window.draw();
|
||||
@@ -610,7 +609,7 @@ void cutscenes_screen_do_frame()
|
||||
gr_set_color_fast(&Color_text_normal);
|
||||
}
|
||||
|
||||
gr_printf_menu(Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1] + y, Cutscenes[Cutscene_list[z]].name);
|
||||
gr_printf(Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1] + y, Cutscenes[Cutscene_list[z]].name);
|
||||
|
||||
y += font_height;
|
||||
z++;
|
||||
@@ -649,7 +648,7 @@ void cutscenes_screen_do_frame()
|
||||
|
||||
strncpy(line, Text_lines[z], len);
|
||||
line[len] = 0;
|
||||
gr_string(Cutscene_desc_coords[gr_screen.res][0], Cutscene_desc_coords[gr_screen.res][1] + y, line, GR_RESIZE_MENU);
|
||||
gr_string(Cutscene_desc_coords[gr_screen.res][0], Cutscene_desc_coords[gr_screen.res][1] + y, line);
|
||||
|
||||
y += font_height;
|
||||
z++;
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _FREESPACE_CUTSCENES_SCREEN_HEADER_FILE
|
||||
#define _FREESPACE_CUTSCENES_SCREEN_HEADER_FILE
|
||||
@@ -13,20 +15,25 @@
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
typedef struct cutscene_info {
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
char name[NAME_LENGTH];
|
||||
char *description;
|
||||
// this cutscene is always available.
|
||||
#define INTRO_CUTSCENE_FLAG (1<<0)
|
||||
|
||||
typedef struct cutscene_info
|
||||
{
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
char name[NAME_LENGTH];
|
||||
char *description;
|
||||
int cd;
|
||||
bool viewable;
|
||||
} cutscene_info;
|
||||
|
||||
extern SCP_vector<cutscene_info> Cutscenes;
|
||||
extern int Cutscenes_viewable;
|
||||
|
||||
// initializa table data
|
||||
void cutscene_init();
|
||||
int cutscene_get_cd_num(char *filename);
|
||||
|
||||
|
||||
void cutscenes_screen_init();
|
||||
void cutscenes_screen_close();
|
||||
void cutscenes_screen_do_frame();
|
||||
|
||||
@@ -15,7 +15,7 @@ static void genLoopkupTable();
|
||||
|
||||
void decodeFrame16(ubyte *pFrame, ubyte *pMap, int mapRemain, unsigned char *pData, int dataRemain)
|
||||
{
|
||||
ubyte *pOrig, *pOffData, op;
|
||||
ubyte *pOrig, *pOffData, *pEnd, op;
|
||||
ushort offset;
|
||||
int length = 0, i, j, xb, yb;
|
||||
|
||||
@@ -32,6 +32,7 @@ void decodeFrame16(ubyte *pFrame, ubyte *pMap, int mapRemain, unsigned char *pDa
|
||||
offset = pData[0]|(pData[1]<<8);
|
||||
|
||||
pOffData = pData + offset;
|
||||
pEnd = pData + offset;
|
||||
|
||||
pData += 2;
|
||||
|
||||
@@ -54,8 +55,7 @@ void decodeFrame16(ubyte *pFrame, ubyte *pMap, int mapRemain, unsigned char *pDa
|
||||
}
|
||||
|
||||
if ((length-(pData-pOrig)) != 0) {
|
||||
nprintf(("MVE", "DEBUG: junk left over: " PTRDIFF_T_ARG ",%d," PTRDIFF_T_ARG "\n",
|
||||
(pData-pOrig), length, (length-(pData-pOrig))));
|
||||
nprintf(("MVE", "DEBUG: junk left over: %d,%d,%d\n", (pData-pOrig), length, (length-(pData-pOrig))));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-15
@@ -13,21 +13,18 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "cutscene/cutscenes.h" // cutscene_mark_viewable()
|
||||
#include "graphics/2d.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
#include "cutscene/movie.h"
|
||||
#include "osapi/osapi.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "cfile/cfile.h"
|
||||
#include "cutscene/cutscenes.h" // cutscene_mark_viewable()
|
||||
#include "cutscene/mvelib.h"
|
||||
#include "cutscene/oggplayer.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "osapi/osapi.h"
|
||||
|
||||
extern int Game_mode;
|
||||
|
||||
const char *movie_ext_list[] = { ".ogg", ".mve" };
|
||||
const int NUM_MOVIE_EXT = sizeof(movie_ext_list) / sizeof(char*);
|
||||
|
||||
|
||||
#define MOVIE_NONE -1
|
||||
#define MOVIE_OGG 0
|
||||
@@ -45,6 +42,8 @@ int movie_find(char *filename, char *out_name)
|
||||
char full_path[MAX_PATH];
|
||||
char tmp_name[MAX_PATH];
|
||||
int size, offset = 0;
|
||||
const int NUM_EXT = 2;
|
||||
const char *movie_ext[NUM_EXT] = { ".ogg", ".mve" };
|
||||
|
||||
if (out_name == NULL)
|
||||
return MOVIE_NONE;
|
||||
@@ -58,7 +57,7 @@ int movie_find(char *filename, char *out_name)
|
||||
char *p = strrchr(tmp_name, '.');
|
||||
if ( p ) *p = 0;
|
||||
|
||||
int rc = cf_find_file_location_ext(tmp_name, NUM_MOVIE_EXT, movie_ext_list, CF_TYPE_ANY, sizeof(full_path) - 1, full_path, &size, &offset, 0);
|
||||
int rc = cf_find_file_location_ext(tmp_name, NUM_EXT, movie_ext, CF_TYPE_ANY, sizeof(full_path) - 1, full_path, &size, &offset, 0);
|
||||
|
||||
if (rc == MOVIE_NONE)
|
||||
return MOVIE_NONE;
|
||||
@@ -78,6 +77,7 @@ bool movie_play(char *name)
|
||||
cutscene_mark_viewable(name);
|
||||
}
|
||||
|
||||
extern int Mouse_hidden;
|
||||
extern int Is_standalone;
|
||||
|
||||
if (Cmdline_nomovies || Is_standalone)
|
||||
@@ -101,8 +101,7 @@ bool movie_play(char *name)
|
||||
}
|
||||
|
||||
// clear the screen and hide the mouse cursor
|
||||
io::mouse::CursorManager::get()->pushStatus();
|
||||
io::mouse::CursorManager::get()->showCursor(false);
|
||||
Mouse_hidden++;
|
||||
gr_reset_clip();
|
||||
gr_set_color(255, 255, 255);
|
||||
gr_set_clear_color(0, 0, 0);
|
||||
@@ -128,7 +127,6 @@ bool movie_play(char *name)
|
||||
} else {
|
||||
// uh-oh, movie is invalid... Abory, Retry, Fail?
|
||||
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
|
||||
io::mouse::CursorManager::get()->popStatus();
|
||||
return false;
|
||||
}
|
||||
} else if (rc == MOVIE_MVE) {
|
||||
@@ -145,13 +143,12 @@ bool movie_play(char *name)
|
||||
} else {
|
||||
// uh-oh, movie is invalid... Abory, Retry, Fail?
|
||||
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
|
||||
io::mouse::CursorManager::get()->popStatus();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// show the mouse cursor again
|
||||
io::mouse::CursorManager::get()->popStatus();
|
||||
Mouse_hidden--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
#ifndef _MOVIE_HEADER_FILE
|
||||
#define _MOVIE_HEADER_FILE
|
||||
|
||||
extern const char *movie_ext_list[];
|
||||
extern const int NUM_MOVIE_EXT;
|
||||
|
||||
bool movie_play(char *name);
|
||||
void movie_play_two(char *name1, char *name2);
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#include "cutscene/mvelib.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "cutscene/mvelib.h"
|
||||
#include "cfile/cfile.h"
|
||||
|
||||
|
||||
static const char MVE_HEADER[] = "Interplay MVE File\x1A";
|
||||
|
||||
+52
-57
@@ -6,23 +6,22 @@
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "cutscene/movie.h"
|
||||
#include "cutscene/mvelib.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "graphics/gropengl.h"
|
||||
#include "graphics/gropengldraw.h"
|
||||
#include "graphics/gropengltexture.h"
|
||||
#include "graphics/gropenglextension.h"
|
||||
#include "graphics/gropenglstate.h"
|
||||
#include "graphics/gropenglshader.h"
|
||||
#include "graphics/gropengltexture.h"
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "cutscene/mvelib.h"
|
||||
#include "cutscene/movie.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "io/key.h"
|
||||
#include "io/timer.h"
|
||||
#include "osapi/osapi.h"
|
||||
#include "sound/openal.h"
|
||||
#include "io/timer.h"
|
||||
#include "sound/sound.h"
|
||||
#include "sound/openal.h"
|
||||
#include "bmpman/bmpman.h"
|
||||
//#include "sound/audiostr.h"
|
||||
|
||||
|
||||
extern int Cmdline_noscalevid;
|
||||
@@ -68,13 +67,12 @@ void *g_vBuffers = NULL;
|
||||
void *g_vBackBuf1, *g_vBackBuf2;
|
||||
ushort *pixelbuf = NULL;
|
||||
static GLuint GLtex = 0;
|
||||
static GLfloat gl_screenYH = 0;
|
||||
static GLfloat gl_screenXW = 0;
|
||||
static GLint gl_screenYH = 0;
|
||||
static GLint gl_screenXW = 0;
|
||||
static GLfloat gl_screenU = 0;
|
||||
static GLfloat gl_screenV = 0;
|
||||
static GLfloat glVertices[4][4] = {{0}};
|
||||
static int g_screenWidth, g_screenHeight;
|
||||
static float g_screenX, g_screenY;
|
||||
static int g_screenX, g_screenY;
|
||||
static int g_truecolor = 0;
|
||||
static ubyte g_palette[768];
|
||||
static ubyte *g_pCurMap = NULL;
|
||||
@@ -230,7 +228,7 @@ void mve_audio_createbuf(ubyte minor, ubyte *data)
|
||||
return;
|
||||
}
|
||||
|
||||
int flags, sample_rate;
|
||||
int flags, desired_buffer, sample_rate;
|
||||
|
||||
mas = (mve_audio_t *) vm_malloc ( sizeof(mve_audio_t) );
|
||||
memset(mas, 0, sizeof(mve_audio_t));
|
||||
@@ -239,6 +237,7 @@ void mve_audio_createbuf(ubyte minor, ubyte *data)
|
||||
|
||||
flags = mve_get_ushort(data + 2);
|
||||
sample_rate = mve_get_ushort(data + 4);
|
||||
desired_buffer = mve_get_int(data + 6);
|
||||
|
||||
mas->channels = (flags & 0x0001) ? 2 : 1;
|
||||
mas->bitsize = (flags & 0x0002) ? 16 : 8;
|
||||
@@ -306,7 +305,7 @@ void mve_audio_play()
|
||||
// call this in shutdown to stop and close audio
|
||||
static void mve_audio_stop()
|
||||
{
|
||||
if (!audiobuf_created || mas == NULL) {
|
||||
if (!audiobuf_created) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -420,10 +419,16 @@ int mve_video_createbuf(ubyte minor, ubyte *data)
|
||||
}
|
||||
|
||||
short w, h;
|
||||
short truecolor;
|
||||
short count, truecolor;
|
||||
w = mve_get_short(data);
|
||||
h = mve_get_short(data+2);
|
||||
|
||||
if (minor > 0) {
|
||||
count = mve_get_short(data+4);
|
||||
} else {
|
||||
count = 1;
|
||||
}
|
||||
|
||||
if (minor > 1) {
|
||||
truecolor = mve_get_short(data+6);
|
||||
} else {
|
||||
@@ -454,13 +459,13 @@ int mve_video_createbuf(ubyte minor, ubyte *data)
|
||||
if (gr_screen.mode == GR_OPENGL) {
|
||||
GLfloat scale_by = 1.0f;
|
||||
|
||||
float screen_ratio = (float)gr_screen.center_w / (float)gr_screen.center_h;
|
||||
float screen_ratio = (float)gr_screen.max_w / (float)gr_screen.max_h;
|
||||
float movie_ratio = (float)g_width / (float)g_height;
|
||||
|
||||
if (screen_ratio > movie_ratio) {
|
||||
scale_by = (float)gr_screen.center_h / (float)g_height;
|
||||
scale_by = (float)gr_screen.max_h / (float)g_height;
|
||||
} else {
|
||||
scale_by = (float)gr_screen.center_w / (float)g_width;
|
||||
scale_by = (float)gr_screen.max_w / (float)g_width;
|
||||
}
|
||||
|
||||
// don't bother setting anything if we aren't going to need it
|
||||
@@ -474,12 +479,12 @@ int mve_video_createbuf(ubyte minor, ubyte *data)
|
||||
}
|
||||
|
||||
if (mve_scale_video) {
|
||||
g_screenX = ((ceil((gr_screen.center_w / scale_by) - 0.5f) - g_width) / 2) + ceil((gr_screen.center_offset_x / scale_by) - 0.5f);
|
||||
g_screenY = ((ceil((gr_screen.center_h / scale_by) - 0.5f) - g_height) / 2) + ceil((gr_screen.center_offset_y / scale_by) - 0.5f);
|
||||
g_screenX = ((fl2i(gr_screen.max_w / scale_by + 0.5f) - g_width) / 2);
|
||||
g_screenY = ((fl2i(gr_screen.max_h / scale_by + 0.5f) - g_height) / 2);
|
||||
} else {
|
||||
// centers on 1024x768, fills on 640x480
|
||||
g_screenX = ((float)(gr_screen.center_w - g_width) / 2.0f) + gr_screen.center_offset_x;
|
||||
g_screenY = ((float)(gr_screen.center_h - g_height) / 2.0f) + gr_screen.center_offset_y;
|
||||
g_screenX = ((gr_screen.max_w - g_width) / 2);
|
||||
g_screenY = ((gr_screen.max_h - g_height) / 2);
|
||||
}
|
||||
|
||||
// set additional values for screen width/height and UV coords
|
||||
@@ -490,35 +495,6 @@ int mve_video_createbuf(ubyte minor, ubyte *data)
|
||||
gl_screenU = i2fl(g_width) / i2fl(wp2);
|
||||
gl_screenV = i2fl(g_height) / i2fl(hp2);
|
||||
}
|
||||
|
||||
glVertices[0][0] = g_screenX;
|
||||
glVertices[0][1] = g_screenY;
|
||||
glVertices[0][2] = 0;
|
||||
glVertices[0][3] = 0;
|
||||
|
||||
glVertices[1][0] = g_screenX;
|
||||
glVertices[1][1] = gl_screenYH;
|
||||
glVertices[1][2] = 0;
|
||||
glVertices[1][3] = gl_screenV;
|
||||
|
||||
glVertices[2][0] = gl_screenXW;
|
||||
glVertices[2][1] = g_screenY;
|
||||
glVertices[2][2] = gl_screenU;
|
||||
glVertices[2][3] = 0;
|
||||
|
||||
glVertices[3][0] = gl_screenXW;
|
||||
glVertices[3][1] = gl_screenYH;
|
||||
glVertices[3][2] = gl_screenU;
|
||||
glVertices[3][3] = gl_screenV;
|
||||
|
||||
GL_state.Array.BindArrayBuffer(0);
|
||||
|
||||
vertex_layout vertex_def;
|
||||
|
||||
vertex_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(glVertices[0]), glVertices);
|
||||
vertex_def.add_vertex_component(vertex_format_data::TEX_COORD, sizeof(glVertices[0]), &(glVertices[0][2]));
|
||||
|
||||
opengl_bind_vertex_layout(vertex_def);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -604,14 +580,24 @@ void mve_video_display()
|
||||
if (gr_screen.mode == GR_OPENGL) {
|
||||
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, g_width, g_height, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixelbuf);
|
||||
|
||||
opengl_shader_set_passthrough(true);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2i(g_screenX, g_screenY);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glTexCoord2f(0, gl_screenV);
|
||||
glVertex2i(g_screenX, gl_screenYH);
|
||||
|
||||
glTexCoord2f(gl_screenU, gl_screenV);
|
||||
glVertex2i(gl_screenXW, gl_screenYH);
|
||||
|
||||
glTexCoord2f(gl_screenU, 0);
|
||||
glVertex2i(gl_screenXW, g_screenY);
|
||||
glEnd();
|
||||
} else {
|
||||
// DDOI - This is probably really fricking slow
|
||||
int bitmap = bm_create (16, g_screenWidth, g_screenHeight, pixelbuf, 0);
|
||||
gr_set_bitmap (bitmap);
|
||||
gr_bitmap ((int)g_screenX, (int)g_screenY, GR_RESIZE_FULL);
|
||||
gr_bitmap (g_screenX, g_screenY, true);
|
||||
bm_release (bitmap);
|
||||
}
|
||||
|
||||
@@ -697,7 +683,7 @@ int mve_video_init(ubyte *data)
|
||||
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RGB5_A1, wp2, hp2, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
|
||||
|
||||
// set our color so that we can make sure that it's correct
|
||||
GL_state.Color(255, 255, 255, 255);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
memset(g_palette, 0, 768);
|
||||
@@ -722,9 +708,18 @@ void mve_video_codemap(ubyte *data, int len)
|
||||
|
||||
void mve_video_data(ubyte *data, int len)
|
||||
{
|
||||
short nFrameHot, nFrameCold;
|
||||
short nXoffset, nYoffset;
|
||||
short nXsize, nYsize;
|
||||
ushort nFlags;
|
||||
ubyte *temp;
|
||||
|
||||
nFrameHot = mve_get_short(data);
|
||||
nFrameCold = mve_get_short(data+2);
|
||||
nXoffset = mve_get_short(data+4);
|
||||
nYoffset = mve_get_short(data+6);
|
||||
nXsize = mve_get_short(data+8);
|
||||
nYsize = mve_get_short(data+10);
|
||||
nFlags = mve_get_ushort(data+12);
|
||||
|
||||
if (nFlags & 1) {
|
||||
|
||||
+82
-59
@@ -9,23 +9,22 @@
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "cfile/cfile.h"
|
||||
#include "cutscene/oggplayer.h"
|
||||
#include "globalincs/def_files.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "globalincs/def_files.h"
|
||||
#include "cfile/cfile.h"
|
||||
#include "graphics/gropengl.h"
|
||||
#include "graphics/gropengldraw.h"
|
||||
#include "graphics/gropengltexture.h"
|
||||
#include "graphics/gropenglextension.h"
|
||||
#include "graphics/gropenglshader.h"
|
||||
#include "graphics/gropenglstate.h"
|
||||
#include "graphics/gropengltexture.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "io/key.h"
|
||||
#include "io/timer.h"
|
||||
#include "osapi/osapi.h"
|
||||
#include "sound/openal.h"
|
||||
#include "sound/sound.h"
|
||||
#include "sound/openal.h"
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "cutscene/oggplayer.h"
|
||||
#include "io/timer.h"
|
||||
|
||||
#include "theora/theora.h"
|
||||
#include "vorbis/codec.h"
|
||||
@@ -51,7 +50,6 @@ static GLint gl_screenYH = 0;
|
||||
static GLint gl_screenXW = 0;
|
||||
static GLfloat gl_screenU = 0;
|
||||
static GLfloat gl_screenV = 0;
|
||||
static GLfloat glVertices[4][4] = {{0}};
|
||||
|
||||
// video externs from API graphics functions
|
||||
extern void opengl_tcache_get_adjusted_texture_size(int w_in, int h_in, int *w_out, int *h_out);
|
||||
@@ -332,6 +330,8 @@ static void OGG_video_init(theora_info *tinfo)
|
||||
{
|
||||
float scale_by = 0.0f;
|
||||
|
||||
GLhandleARB shader_id = 0;
|
||||
|
||||
if (video_inited)
|
||||
return;
|
||||
|
||||
@@ -345,7 +345,7 @@ static void OGG_video_init(theora_info *tinfo)
|
||||
opengl_set_texture_target(GL_TEXTURE_2D);
|
||||
opengl_tcache_get_adjusted_texture_size(g_screenWidth, g_screenHeight, &wp2, &hp2);
|
||||
|
||||
if(!is_minimum_GLSL_version())
|
||||
if(!Use_GLSL)
|
||||
use_shaders = false;
|
||||
|
||||
if(use_shaders) {
|
||||
@@ -364,11 +364,52 @@ static void OGG_video_init(theora_info *tinfo)
|
||||
return;
|
||||
}
|
||||
|
||||
int sdr_handle = gr_maybe_create_shader(SDR_TYPE_VIDEO_PROCESS, 0);
|
||||
char *vert = NULL, *frag = NULL;
|
||||
opengl_shader_t new_shader;
|
||||
|
||||
// choose appropriate files
|
||||
char *vert_name = "video-v.sdr";
|
||||
char *frag_name = "video-f.sdr";
|
||||
|
||||
if ( sdr_handle >= 0)
|
||||
opengl_shader_set_current(sdr_handle);
|
||||
else
|
||||
mprintf(("Compiling video-processing shader ... \n"));
|
||||
|
||||
// read vertex shader
|
||||
CFILE *cf_shader = cfopen(vert_name, "rt", CFILE_NORMAL, CF_TYPE_EFFECTS);
|
||||
|
||||
if (cf_shader != NULL) {
|
||||
int len = cfilelength(cf_shader);
|
||||
vert = (char*) vm_malloc(len + 1);
|
||||
cfread(vert, len + 1, 1, cf_shader);
|
||||
cfclose(cf_shader);
|
||||
} else {
|
||||
mprintf((" Loading built-in default shader for: %s\n", vert_name));
|
||||
vert = defaults_get_file(vert_name);
|
||||
}
|
||||
|
||||
if(!vert)
|
||||
use_shaders = false;
|
||||
|
||||
// read fragment shader
|
||||
cf_shader = cfopen(frag_name, "rt", CFILE_NORMAL, CF_TYPE_EFFECTS);
|
||||
|
||||
if (cf_shader != NULL) {
|
||||
int len = cfilelength(cf_shader);
|
||||
frag = (char*) vm_malloc(len + 1);
|
||||
cfread(frag, len + 1, 1, cf_shader);
|
||||
cfclose(cf_shader);
|
||||
} else {
|
||||
mprintf((" Loading built-in default shader for: %s\n", frag_name));
|
||||
frag = defaults_get_file(frag_name);
|
||||
}
|
||||
|
||||
if(!vert)
|
||||
use_shaders = false;
|
||||
Verify( vert != NULL );
|
||||
Verify( frag != NULL );
|
||||
|
||||
shader_id = opengl_shader_create(vert, frag);
|
||||
vglUseProgramObjectARB(shader_id);
|
||||
if (!shader_id)
|
||||
use_shaders = false;
|
||||
}
|
||||
|
||||
@@ -435,13 +476,13 @@ static void OGG_video_init(theora_info *tinfo)
|
||||
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
|
||||
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_LUMINANCE8, 1024, 1024, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
|
||||
}
|
||||
float screen_ratio = (float)gr_screen.center_w / (float)gr_screen.center_h;
|
||||
float screen_ratio = (float)gr_screen.max_w / (float)gr_screen.max_h;
|
||||
float movie_ratio = (float)g_screenWidth / (float)g_screenHeight;
|
||||
|
||||
if (screen_ratio > movie_ratio)
|
||||
scale_by = (float)gr_screen.center_h / (float)g_screenHeight;
|
||||
scale_by = (float)gr_screen.max_h / (float)g_screenHeight;
|
||||
else
|
||||
scale_by = (float)gr_screen.center_w / (float)g_screenWidth;
|
||||
scale_by = (float)gr_screen.max_w / (float)g_screenWidth;
|
||||
|
||||
// don't bother setting anything if we aren't going to need it
|
||||
if (!Cmdline_noscalevid && (scale_by != 1.0f)) {
|
||||
@@ -454,7 +495,7 @@ static void OGG_video_init(theora_info *tinfo)
|
||||
}
|
||||
|
||||
// set our color so that we can make sure that it's correct
|
||||
GL_state.Color(255, 255, 255, 255);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
if(!use_shaders) {
|
||||
@@ -470,12 +511,12 @@ static void OGG_video_init(theora_info *tinfo)
|
||||
|
||||
|
||||
if (scale_video) {
|
||||
g_screenX = ((fl2i(gr_screen.center_w / scale_by + 0.5f) - g_screenWidth) / 2) + fl2i(gr_screen.center_offset_x / scale_by + 0.5f);
|
||||
g_screenY = ((fl2i(gr_screen.center_h / scale_by + 0.5f) - g_screenHeight) / 2) + fl2i(gr_screen.center_offset_y / scale_by + 0.5f);
|
||||
g_screenX = ((fl2i(gr_screen.max_w / scale_by + 0.5f) - g_screenWidth) / 2);
|
||||
g_screenY = ((fl2i(gr_screen.max_h / scale_by + 0.5f) - g_screenHeight) / 2);
|
||||
} else {
|
||||
// centers on 1024x768, fills on 640x480
|
||||
g_screenX = ((gr_screen.center_w - g_screenWidth) / 2) + gr_screen.center_offset_x;
|
||||
g_screenY = ((gr_screen.center_h - g_screenHeight) / 2) + gr_screen.center_offset_y;
|
||||
g_screenX = ((gr_screen.max_w - g_screenWidth) / 2);
|
||||
g_screenY = ((gr_screen.max_h - g_screenHeight) / 2);
|
||||
}
|
||||
|
||||
// set additional values for screen width/height and UV coords
|
||||
@@ -490,39 +531,10 @@ static void OGG_video_init(theora_info *tinfo)
|
||||
gl_screenU = i2fl(tinfo->frame_width-1) / i2fl(2048) ;
|
||||
gl_screenV = i2fl(tinfo->frame_height-1) / i2fl(2048);
|
||||
GL_state.Texture.SetShaderMode(GL_TRUE);
|
||||
GL_state.Uniform.setUniformi("ytex", 0);
|
||||
GL_state.Uniform.setUniformi("utex", 1);
|
||||
GL_state.Uniform.setUniformi("vtex", 2);
|
||||
vglUniform1iARB( vglGetUniformLocationARB(shader_id, "ytex"), 0 );
|
||||
vglUniform1iARB( vglGetUniformLocationARB(shader_id, "utex"), 1 );
|
||||
vglUniform1iARB( vglGetUniformLocationARB(shader_id, "vtex"), 2 );
|
||||
}
|
||||
|
||||
glVertices[0][0] = (GLfloat)g_screenX;
|
||||
glVertices[0][1] = (GLfloat)g_screenY;
|
||||
glVertices[0][2] = 0.0f;
|
||||
glVertices[0][3] = 0.0f;
|
||||
|
||||
glVertices[1][0] = (GLfloat)g_screenX;
|
||||
glVertices[1][1] = (GLfloat)gl_screenYH;
|
||||
glVertices[1][2] = 0.0f;
|
||||
glVertices[1][3] = gl_screenV;
|
||||
|
||||
glVertices[2][0] = (GLfloat)gl_screenXW;
|
||||
glVertices[2][1] = (GLfloat)g_screenY;
|
||||
glVertices[2][2] = gl_screenU;
|
||||
glVertices[2][3] = 0.0f;
|
||||
|
||||
glVertices[3][0] = (GLfloat)gl_screenXW;
|
||||
glVertices[3][1] = (GLfloat)gl_screenYH;
|
||||
glVertices[3][2] = gl_screenU;
|
||||
glVertices[3][3] = gl_screenV;
|
||||
|
||||
GL_state.Array.BindArrayBuffer(0);
|
||||
|
||||
vertex_layout vert_def;
|
||||
|
||||
vert_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(glVertices[0]), glVertices);
|
||||
vert_def.add_vertex_component(vertex_format_data::TEX_COORD, sizeof(glVertices[0]), &(glVertices[0][2]));
|
||||
|
||||
opengl_bind_vertex_layout(vert_def);
|
||||
}
|
||||
if(!use_shaders && tinfo->frame_height > 450) {
|
||||
mprintf(("VIDEO: No shader support and hd video is beeing played this can get choppy."));
|
||||
@@ -559,7 +571,7 @@ static void OGG_video_close()
|
||||
ytex = utex = vtex = 0;
|
||||
GLtex = 0;
|
||||
GL_state.Texture.SetShaderMode(GL_FALSE);
|
||||
opengl_shader_set_current();
|
||||
opengl_shader_set_current( 0 );
|
||||
}
|
||||
|
||||
if (pixelbuf != NULL) {
|
||||
@@ -668,10 +680,21 @@ static void OGG_video_draw(theora_state *tstate)
|
||||
} else {
|
||||
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, g_screenWidth, g_screenHeight, GL_BGR, GL_UNSIGNED_BYTE, pixelbuf);
|
||||
}
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2i(g_screenX, g_screenY);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glTexCoord2f(0, gl_screenV);
|
||||
glVertex2i(g_screenX, gl_screenYH);
|
||||
|
||||
glTexCoord2f(gl_screenU, gl_screenV);
|
||||
glVertex2i(gl_screenXW, gl_screenYH);
|
||||
|
||||
glTexCoord2f(gl_screenU, 0);
|
||||
glVertex2i(gl_screenXW, g_screenY);
|
||||
glEnd();
|
||||
}
|
||||
io::mouse::CursorManager::get()->showCursor(false);
|
||||
Mouse_hidden = 1;
|
||||
gr_flip();
|
||||
os_poll();
|
||||
|
||||
@@ -752,7 +775,7 @@ THEORAFILE *theora_open(char *filename)
|
||||
|
||||
// lower case filename for checking
|
||||
memset( lower_name, 0, sizeof(lower_name) );
|
||||
strncpy( lower_name, filename, sizeof(lower_name)-1 );
|
||||
strncpy( lower_name, filename, strlen(filename) );
|
||||
strlwr(lower_name);
|
||||
|
||||
char *p = strchr( lower_name, '.' );
|
||||
|
||||
@@ -27,7 +27,7 @@ static inline int is_power_of_two(int w, int h)
|
||||
}
|
||||
|
||||
|
||||
int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *height, int *bpp, int *compression_type, int *levels, int *size, ubyte *palette)
|
||||
int dds_read_header(char *filename, CFILE *img_cfp, int *width, int *height, int *bpp, int *compression_type, int *levels, int *size, ubyte *palette)
|
||||
{
|
||||
DDSURFACEDESC2 dds_header;
|
||||
int code = 0;
|
||||
@@ -36,7 +36,7 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
|
||||
int retval = DDS_ERROR_NONE;
|
||||
int ct = DDS_UNCOMPRESSED;
|
||||
int bits = 0;
|
||||
int i, is_cubemap = 0;
|
||||
int i, trash, is_cubemap = 0;
|
||||
int d_width = 0, d_height = 0, d_depth = 0, d_size = 0;
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
|
||||
|
||||
// skip over the crap we don't care about
|
||||
for (i = 0; i < 11; i++)
|
||||
cfread_uint(ddsfile);
|
||||
trash = cfread_uint(ddsfile);
|
||||
|
||||
dds_header.ddpfPixelFormat.dwSize = cfread_uint(ddsfile);
|
||||
dds_header.ddpfPixelFormat.dwFlags = cfread_uint(ddsfile);
|
||||
@@ -272,7 +272,7 @@ Done:
|
||||
}
|
||||
|
||||
//reads pixel info from a dds file
|
||||
int dds_read_bitmap(const char *filename, ubyte *data, ubyte *bpp, int cf_type)
|
||||
int dds_read_bitmap(char *filename, ubyte *data, ubyte *bpp, int cf_type)
|
||||
{
|
||||
int retval;
|
||||
int w,h,ct,lvl;
|
||||
@@ -321,7 +321,7 @@ int dds_read_bitmap(const char *filename, ubyte *data, ubyte *bpp, int cf_type)
|
||||
|
||||
// save some image data as a DDS image
|
||||
// NOTE: we only support, uncompressed, 24-bit RGB and 32-bit RGBA images here!!
|
||||
void dds_save_image(int width, int height, int bpp, int num_mipmaps, ubyte *data, int cubemap, const char *filename)
|
||||
void dds_save_image(int width, int height, int bpp, int num_mipmaps, ubyte *data, int cubemap, char *filename)
|
||||
{
|
||||
DDSURFACEDESC2 dds_header;
|
||||
char real_filename[MAX_FILENAME_LEN];
|
||||
|
||||
@@ -138,14 +138,14 @@ typedef struct _DDSURFACEDESC2
|
||||
//reads a dds header
|
||||
//returns one of the error values
|
||||
//'compression_type' comes back as one of the DDS_DXTC* defines
|
||||
int dds_read_header(const char *filename, CFILE *img_cfp = NULL, int *width = 0, int *height = 0, int *bpp = 0, int *compression_type = 0, int *levels = 0, int *size = 0, ubyte *palette = NULL);
|
||||
int dds_read_header(char *filename, CFILE *img_cfp = NULL, int *width = 0, int *height = 0, int *bpp = 0, int *compression_type = 0, int *levels = 0, int *size = 0, ubyte *palette = NULL);
|
||||
|
||||
//reads bitmap
|
||||
//size of the data it stored in size
|
||||
int dds_read_bitmap(const char *filename, ubyte *data, ubyte *bpp = NULL, int cf_type = CF_TYPE_ANY);
|
||||
int dds_read_bitmap(char *filename, ubyte *data, ubyte *bpp = NULL, int cf_type = CF_TYPE_ANY);
|
||||
|
||||
// writes a DDS file using given data
|
||||
void dds_save_image(int width, int height, int bpp, int num_mipmaps, ubyte *data = NULL, int cubemap = 0, const char *filename = NULL);
|
||||
void dds_save_image(int width, int height, int bpp, int num_mipmaps, ubyte *data = NULL, int cubemap = 0, char *filename = NULL);
|
||||
|
||||
//returns a string from a DDS error code
|
||||
const char *dds_error_string(int code);
|
||||
|
||||
+99
-118
@@ -9,27 +9,27 @@
|
||||
|
||||
|
||||
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "debris/debris.h"
|
||||
#include "render/3d.h"
|
||||
#include "fireball/fireballs.h"
|
||||
#include "freespace2/freespace.h"
|
||||
#include "radar/radar.h"
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "object/objectsnd.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "particle/particle.h"
|
||||
#include "freespace2/freespace.h"
|
||||
#include "object/objcollide.h"
|
||||
#include "io/timer.h"
|
||||
#include "species_defs/species_defs.h"
|
||||
#include "ship/ship.h"
|
||||
#include "ship/shipfx.h"
|
||||
#include "radar/radarsetup.h"
|
||||
#include "network/multi.h"
|
||||
#include "network/multimsgs.h"
|
||||
#include "network/multiutil.h"
|
||||
#include "object/objcollide.h"
|
||||
#include "object/objectsnd.h"
|
||||
#include "particle/particle.h"
|
||||
#include "radar/radar.h"
|
||||
#include "radar/radarsetup.h"
|
||||
#include "render/3d.h"
|
||||
#include "ship/ship.h"
|
||||
#include "ship/shipfx.h"
|
||||
#include "species_defs/species_defs.h"
|
||||
#include "weapon/weapon.h"
|
||||
|
||||
|
||||
#define MAX_LIFE 10.0f
|
||||
#define MIN_RADIUS_FOR_PERSISTANT_DEBRIS 50 // ship radius at which debris from it becomes persistant
|
||||
#define DEBRIS_SOUND_DELAY 2000 // time to start debris sound after created
|
||||
@@ -101,7 +101,6 @@ void debris_init()
|
||||
for (i=0; i<MAX_DEBRIS_PIECES; i++ ) {
|
||||
Debris[i].flags = 0;
|
||||
Debris[i].sound_delay = 0;
|
||||
Debris[i].objnum = -1;
|
||||
}
|
||||
|
||||
Num_hull_pieces = 0;
|
||||
@@ -144,6 +143,64 @@ void debris_page_in()
|
||||
MONITOR(NumSmallDebrisRend)
|
||||
MONITOR(NumHullDebrisRend)
|
||||
|
||||
/**
|
||||
* Render debris
|
||||
*/
|
||||
void debris_render(object * obj)
|
||||
{
|
||||
int i, num, swapped;
|
||||
polymodel *pm;
|
||||
debris *db;
|
||||
|
||||
|
||||
swapped = -1;
|
||||
pm = NULL;
|
||||
num = obj->instance;
|
||||
|
||||
Assert(num >= 0 && num < MAX_DEBRIS_PIECES);
|
||||
db = &Debris[num];
|
||||
|
||||
Assert(db->flags & DEBRIS_USED);
|
||||
|
||||
texture_info *tbase = NULL;
|
||||
|
||||
// Swap in a different texture depending on the species
|
||||
if (db->species >= 0)
|
||||
{
|
||||
pm = model_get( db->model_num );
|
||||
|
||||
//WMC - Someday, we should have glowing debris.
|
||||
if ( pm != NULL && (pm->n_textures == 1) ) {
|
||||
tbase = &pm->maps[0].textures[TM_BASE_TYPE];
|
||||
swapped = tbase->GetTexture();
|
||||
tbase->SetTexture(Species_info[db->species].debris_texture.bitmap_id);
|
||||
}
|
||||
}
|
||||
|
||||
model_clear_instance( db->model_num );
|
||||
|
||||
// Only render electrical arcs if within 500m of the eye (for a 10m piece)
|
||||
if ( vm_vec_dist_quick( &obj->pos, &Eye_position ) < obj->radius*50.0f ) {
|
||||
for (i=0; i<MAX_DEBRIS_ARCS; i++ ) {
|
||||
if ( timestamp_valid( db->arc_timestamp[i] ) ) {
|
||||
model_add_arc( db->model_num, db->submodel_num, &db->arc_pts[i][0], &db->arc_pts[i][1], MARC_TYPE_NORMAL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( db->is_hull ) {
|
||||
MONITOR_INC(NumHullDebrisRend,1);
|
||||
submodel_render( db->model_num, db->submodel_num, &obj->orient, &obj->pos );
|
||||
} else {
|
||||
MONITOR_INC(NumSmallDebrisRend,1);
|
||||
submodel_render( db->model_num, db->submodel_num, &obj->orient, &obj->pos, MR_NO_LIGHTING );
|
||||
}
|
||||
|
||||
if (tbase != NULL && (swapped!=-1) && pm) {
|
||||
tbase->SetTexture(swapped);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removed the ::DEBRIS_EXPIRE flag, and remove item from ::Hull_debris_list
|
||||
*/
|
||||
@@ -180,7 +237,6 @@ void debris_delete( object * obj )
|
||||
}
|
||||
|
||||
db->flags = 0;
|
||||
db->objnum = -1;
|
||||
Num_debris_pieces--;
|
||||
}
|
||||
|
||||
@@ -268,14 +324,8 @@ void debris_process_post(object * obj, float frame_time)
|
||||
int n, n_arcs = ((rand()>>5) % 3)+1; // Create 1-3 sparks
|
||||
|
||||
vec3d v1, v2, v3, v4;
|
||||
|
||||
if ( Cmdline_old_collision_sys ) {
|
||||
submodel_get_two_random_points( db->model_num, db->submodel_num, &v1, &v2 );
|
||||
submodel_get_two_random_points( db->model_num, db->submodel_num, &v3, &v4 );
|
||||
} else {
|
||||
submodel_get_two_random_points_better( db->model_num, db->submodel_num, &v1, &v2 );
|
||||
submodel_get_two_random_points_better( db->model_num, db->submodel_num, &v3, &v4 );
|
||||
}
|
||||
submodel_get_two_random_points( db->model_num, db->submodel_num, &v1, &v2 );
|
||||
submodel_get_two_random_points( db->model_num, db->submodel_num, &v3, &v4 );
|
||||
|
||||
n = 0;
|
||||
|
||||
@@ -350,13 +400,7 @@ void debris_process_post(object * obj, float frame_time)
|
||||
int mr = myrand();
|
||||
if ( mr < RAND_MAX/5 ) {
|
||||
vec3d v1, v2;
|
||||
|
||||
if ( Cmdline_old_collision_sys ) {
|
||||
submodel_get_two_random_points( db->model_num, db->submodel_num, &v1, &v2 );
|
||||
} else {
|
||||
submodel_get_two_random_points_better( db->model_num, db->submodel_num, &v1, &v2 );
|
||||
}
|
||||
|
||||
submodel_get_two_random_points( db->model_num, db->submodel_num, &v1, &v2 );
|
||||
db->arc_pts[i][mr % 2] = v1;
|
||||
}
|
||||
}
|
||||
@@ -468,11 +512,11 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
|
||||
// Create Debris piece n!
|
||||
if ( hull_flag ) {
|
||||
if (rand() < RAND_MAX/6) // Make some pieces blow up shortly after explosion.
|
||||
db->lifeleft = 2.0f * (myrand() * RAND_MAX_1f) + 0.5f;
|
||||
db->lifeleft = 2.0f * ((float) myrand()/(float) RAND_MAX) + 0.5f;
|
||||
else
|
||||
db->lifeleft = -1.0f; // large hull pieces stay around forever
|
||||
} else {
|
||||
db->lifeleft = (myrand() * RAND_MAX_1f) * 2.0f + 0.1f;
|
||||
db->lifeleft = (i2fl(myrand())/i2fl(RAND_MAX))*2.0f+0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,7 +549,6 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
|
||||
db->is_hull = hull_flag;
|
||||
db->source_objnum = parent_objnum;
|
||||
db->source_sig = source_obj->signature;
|
||||
db->damage_type_idx = shipp->debris_damage_type_idx;
|
||||
db->ship_info_index = shipp->ship_info_index;
|
||||
db->team = shipp->team;
|
||||
db->fire_timeout = 0; // if not changed, timestamp_elapsed() will return false
|
||||
@@ -646,7 +689,7 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
|
||||
// displacement fromt the center of the parent object to the center of the debris piece
|
||||
vec3d world_rotvel, vel_from_rotvel;
|
||||
vm_vec_unrotate ( &world_rotvel, &source_obj->phys_info.rotvel, &source_obj->orient );
|
||||
vm_vec_cross ( &vel_from_rotvel, &world_rotvel, &to_center );
|
||||
vm_vec_crossprod ( &vel_from_rotvel, &world_rotvel, &to_center );
|
||||
vm_vec_scale ( &vel_from_rotvel, DEBRIS_ROTVEL_SCALE);
|
||||
|
||||
vm_vec_add (&obj->phys_info.vel, &radial_vel, &source_obj->phys_info.vel);
|
||||
@@ -750,7 +793,6 @@ void debris_hit(object *debris_obj, object *other_obj, vec3d *hitpos, float dama
|
||||
int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, collision_info_struct *debris_hit_info)
|
||||
{
|
||||
mc_info mc;
|
||||
mc_info_init(&mc);
|
||||
int num;
|
||||
|
||||
Assert( pdebris->type == OBJ_DEBRIS );
|
||||
@@ -779,25 +821,25 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
}
|
||||
|
||||
weapon *wp = &Weapons[other_obj->instance];
|
||||
wp->collisionInfo = new mc_info; // The weapon will free this memory later
|
||||
memcpy(wp->collisionInfo, &mc, sizeof(mc_info));
|
||||
wp->collisionOccured = true;
|
||||
wp->collisionInfo = mc_info(mc);
|
||||
|
||||
return mc.num_hits;
|
||||
}
|
||||
|
||||
// debris ship collision -- use debris_hit_info to calculate physics
|
||||
object *pship_obj = other_obj;
|
||||
Assert( pship_obj->type == OBJ_SHIP );
|
||||
object *ship_obj = other_obj;
|
||||
Assert( ship_obj->type == OBJ_SHIP );
|
||||
|
||||
object *heavy = debris_hit_info->heavy;
|
||||
object *lighter = debris_hit_info->light;
|
||||
object *light = debris_hit_info->light;
|
||||
object *heavy_obj = heavy;
|
||||
object *light_obj = lighter;
|
||||
object *light_obj = light;
|
||||
|
||||
vec3d zero, p0, p1;
|
||||
vm_vec_zero(&zero);
|
||||
vm_vec_sub(&p0, &lighter->last_pos, &heavy->last_pos);
|
||||
vm_vec_sub(&p1, &lighter->pos, &heavy->pos);
|
||||
vm_vec_sub(&p0, &light->last_pos, &heavy->last_pos);
|
||||
vm_vec_sub(&p1, &light->pos, &heavy->pos);
|
||||
|
||||
mc.pos = &zero; // The object's position
|
||||
mc.p0 = &p0; // Point 1 of ray to check
|
||||
@@ -818,15 +860,15 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
vm_vec_scale(&debris_hit_info->light_rel_vel, 1/flFrametime);
|
||||
} else {
|
||||
debris_hit_info->collide_rotate = 0;
|
||||
vm_vec_sub(&debris_hit_info->light_rel_vel, &lighter->phys_info.vel, &heavy->phys_info.vel);
|
||||
vm_vec_sub(&debris_hit_info->light_rel_vel, &light->phys_info.vel, &heavy->phys_info.vel);
|
||||
}
|
||||
|
||||
int mc_ret_val = 0;
|
||||
|
||||
if ( debris_hit_info->heavy == pship_obj ) { // ship is heavier, so debris is sphere. Check sphere collision against ship poly model
|
||||
mc.model_instance_num = Ships[pship_obj->instance].model_instance_num;
|
||||
mc.model_num = Ship_info[Ships[pship_obj->instance].ship_info_index].model_num; // Fill in the model to check
|
||||
mc.orient = &pship_obj->orient; // The object's orient
|
||||
if ( debris_hit_info->heavy == ship_obj ) { // ship is heavier, so debris is sphere. Check sphere collision against ship poly model
|
||||
mc.model_instance_num = Ships[ship_obj->instance].model_instance_num;
|
||||
mc.model_num = Ship_info[Ships[ship_obj->instance].ship_info_index].model_num; // Fill in the model to check
|
||||
mc.orient = &ship_obj->orient; // The object's orient
|
||||
mc.radius = pdebris->radius;
|
||||
mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
|
||||
|
||||
@@ -840,8 +882,11 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
|
||||
|
||||
SCP_vector<int> submodel_vector;
|
||||
polymodel *pm;
|
||||
polymodel_instance *pmi;
|
||||
|
||||
ship_model_start(ship_obj);
|
||||
|
||||
if (model_collide(&mc)) {
|
||||
|
||||
// Set earliest hit time
|
||||
@@ -855,6 +900,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
model_get_rotating_submodel_list(&submodel_vector, heavy_obj);
|
||||
|
||||
// Get polymodel and turn off all rotating submodels, collide against only 1 at a time.
|
||||
pm = model_get(Ship_info[Ships[heavy_obj->instance].ship_info_index].model_num);
|
||||
pmi = model_get_instance(Ships[heavy_obj->instance].model_instance_num);
|
||||
|
||||
// turn off all rotating submodels and test for collision
|
||||
@@ -865,10 +911,6 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
|
||||
mc.flags = copy_flags | MC_SUBMODEL_INSTANCE;
|
||||
|
||||
if (Ship_info[Ships[pship_obj->instance].ship_info_index].collision_lod > -1) {
|
||||
mc.lod = Ship_info[Ships[pship_obj->instance].ship_info_index].collision_lod;
|
||||
}
|
||||
|
||||
// check each submodel in turn
|
||||
for (smv = submodel_vector.begin(); smv != submodel_vector.end(); ++smv) {
|
||||
// turn on submodel for collision test
|
||||
@@ -879,10 +921,10 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
|
||||
// find the start and end positions of the sphere in submodel RF
|
||||
pmi->submodel[*smv].angs = pmi->submodel[*smv].prev_angs;
|
||||
world_find_model_instance_point(&p0, &light_obj->last_pos, pmi, *smv, &heavy_obj->last_orient, &heavy_obj->last_pos);
|
||||
world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, *smv, &heavy_obj->last_orient, &heavy_obj->last_pos);
|
||||
|
||||
pmi->submodel[*smv].angs = copy_angles;
|
||||
world_find_model_instance_point(&p1, &light_obj->pos, pmi, *smv, &heavy_obj->orient, &heavy_obj->pos);
|
||||
world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, *smv, &heavy_obj->orient, &heavy_obj->pos);
|
||||
|
||||
mc.p0 = &p0;
|
||||
mc.p1 = &p1;
|
||||
@@ -896,18 +938,18 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
|
||||
// set up debris_hit_info common
|
||||
set_hit_struct_info(debris_hit_info, &mc, SUBMODEL_ROT_HIT);
|
||||
model_instance_find_world_point(&debris_hit_info->hit_pos, &mc.hit_point, mc.model_instance_num, mc.hit_submodel, &heavy_obj->orient, &zero);
|
||||
model_instance_find_world_point(&debris_hit_info->hit_pos, &mc.hit_point, mc.model_num, mc.model_instance_num, mc.hit_submodel, &heavy_obj->orient, &zero);
|
||||
|
||||
// set up debris_hit_info for rotating submodel
|
||||
if (debris_hit_info->edge_hit == 0) {
|
||||
model_instance_find_obj_dir(&debris_hit_info->collision_normal, &mc.hit_normal, mc.model_instance_num, mc.hit_submodel, &heavy_obj->orient);
|
||||
model_instance_find_obj_dir(&debris_hit_info->collision_normal, &mc.hit_normal, heavy_obj, mc.hit_submodel);
|
||||
}
|
||||
|
||||
// find position in submodel RF of light object at collison
|
||||
vec3d int_light_pos, diff;
|
||||
vm_vec_sub(&diff, mc.p1, mc.p0);
|
||||
vm_vec_scale_add(&int_light_pos, mc.p0, &diff, mc.hit_dist);
|
||||
model_instance_find_world_point(&debris_hit_info->light_collision_cm_pos, &int_light_pos, mc.model_instance_num, mc.hit_submodel, &heavy_obj->orient, &zero);
|
||||
model_instance_find_world_point(&debris_hit_info->light_collision_cm_pos, &int_light_pos, mc.model_num, mc.model_instance_num, mc.hit_submodel, &heavy_obj->orient, &zero);
|
||||
}
|
||||
}
|
||||
// Don't look at this submodel again
|
||||
@@ -931,7 +973,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
|
||||
// get collision normal if not edge hit
|
||||
if (debris_hit_info->edge_hit == 0) {
|
||||
model_instance_find_obj_dir(&debris_hit_info->collision_normal, &mc.hit_normal, Ships[heavy_obj->instance].model_instance_num, mc.hit_submodel, &heavy_obj->orient);
|
||||
model_instance_find_obj_dir(&debris_hit_info->collision_normal, &mc.hit_normal, heavy_obj, mc.hit_submodel);
|
||||
}
|
||||
|
||||
// find position in submodel RF of light object at collison
|
||||
@@ -950,7 +992,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
mc.submodel_num = Debris[num].submodel_num;
|
||||
model_clear_instance( mc.model_num );
|
||||
mc.orient = &pdebris->orient; // The object's orient
|
||||
mc.radius = model_get_core_radius(Ship_info[Ships[pship_obj->instance].ship_info_index].model_num);
|
||||
mc.radius = model_get_core_radius(Ship_info[Ships[ship_obj->instance].ship_info_index].model_num);
|
||||
|
||||
// check for collision between debris model and ship sphere
|
||||
mc.flags = (MC_CHECK_MODEL | MC_SUBMODEL | MC_CHECK_SPHERELINE);
|
||||
@@ -1037,64 +1079,3 @@ void calc_debris_physics_properties( physics_info *pi, vec3d *mins, vec3d *maxs
|
||||
pi->I_body_inv.vec.fvec.xyz.y = 0.0f;
|
||||
pi->I_body_inv.vec.fvec.xyz.z = 12.0f / (pi->mass * (dx*dx + dy*dy));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders debris
|
||||
*/
|
||||
void debris_render(object * obj, draw_list *scene)
|
||||
{
|
||||
int i, num, swapped;
|
||||
polymodel *pm;
|
||||
debris *db;
|
||||
|
||||
|
||||
swapped = -1;
|
||||
pm = NULL;
|
||||
num = obj->instance;
|
||||
|
||||
Assert(num >= 0 && num < MAX_DEBRIS_PIECES);
|
||||
db = &Debris[num];
|
||||
|
||||
Assert(db->flags & DEBRIS_USED);
|
||||
|
||||
texture_info *tbase = NULL;
|
||||
|
||||
model_clear_instance( db->model_num );
|
||||
|
||||
// Swap in a different texture depending on the species
|
||||
if (db->species >= 0)
|
||||
{
|
||||
pm = model_get( db->model_num );
|
||||
|
||||
//WMC - Someday, we should have glowing debris.
|
||||
if ( pm != NULL && (pm->n_textures == 1) ) {
|
||||
tbase = &pm->maps[0].textures[TM_BASE_TYPE];
|
||||
swapped = tbase->GetTexture();
|
||||
tbase->SetTexture(Species_info[db->species].debris_texture.bitmap_id);
|
||||
}
|
||||
}
|
||||
|
||||
// Only render electrical arcs if within 500m of the eye (for a 10m piece)
|
||||
if ( vm_vec_dist_quick( &obj->pos, &Eye_position ) < obj->radius*50.0f ) {
|
||||
for (i=0; i<MAX_DEBRIS_ARCS; i++ ) {
|
||||
if ( timestamp_valid( db->arc_timestamp[i] ) ) {
|
||||
model_add_arc( db->model_num, db->submodel_num, &db->arc_pts[i][0], &db->arc_pts[i][1], MARC_TYPE_NORMAL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model_render_params render_info;
|
||||
|
||||
if ( db->is_hull ) {
|
||||
MONITOR_INC(NumHullDebrisRend, 1);
|
||||
} else {
|
||||
MONITOR_INC(NumSmallDebrisRend, 1);
|
||||
render_info.set_flags(MR_NO_LIGHTING);
|
||||
}
|
||||
|
||||
submodel_render_queue( &render_info, scene, db->model_num, db->submodel_num, &obj->orient, &obj->pos );
|
||||
|
||||
if (tbase != NULL && (swapped!=-1) && pm) {
|
||||
tbase->SetTexture(swapped);
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,8 @@
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
class object;
|
||||
struct object;
|
||||
struct CFILE;
|
||||
class draw_list;
|
||||
|
||||
#define MAX_DEBRIS_ARCS 8 // Must be less than MAX_ARC_EFFECTS in model.h
|
||||
|
||||
@@ -25,7 +24,6 @@ typedef struct debris {
|
||||
int flags; // See DEBRIS_??? defines
|
||||
int source_objnum; // What object this came from
|
||||
int source_sig; // Signature of the source object
|
||||
int damage_type_idx; // Damage type of this debris
|
||||
int ship_info_index; // Ship info index of the ship type debris came from
|
||||
int team; // Team of the ship where the debris came from
|
||||
int objnum; // What object this is linked to
|
||||
@@ -63,7 +61,7 @@ extern int Num_debris_pieces;
|
||||
struct collision_info_struct;
|
||||
|
||||
void debris_init();
|
||||
void debris_render(object * obj, draw_list *scene);
|
||||
void debris_render( object * obj );
|
||||
void debris_delete( object * obj );
|
||||
void debris_process_post( object * obj, float frame_time);
|
||||
object *debris_create( object * source_obj, int model_num, int submodel_num, vec3d *pos, vec3d *exp_center, int hull_flag, float exp_force );
|
||||
|
||||
+616
-481
File diff suppressed because it is too large.
Load diff
@@ -1,279 +0,0 @@
|
||||
#ifndef _CONSOLE_H
|
||||
#define _CONSOLE_H
|
||||
/*
|
||||
* z64555's debug console, created for the FreeSpace Source Code project
|
||||
*
|
||||
* Portions of this source code are based on works by Volition, Inc. circa 1999. You may not sell or otherwise
|
||||
* commercially exploit the source or things you created based on the source.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file console.h
|
||||
* @brief An overhauled/updated debug console to allow monitoring, testing, and general debugging of new features.
|
||||
*
|
||||
* @details
|
||||
* Of key interest is Volition's DCF macro, which adds the function argument to the available command list in the
|
||||
* debug console. These functions may be defined in the .cpp file that they are related to, but it is recommended
|
||||
* that they be in their own .cpp if they have multiple sub-arguments (ex: Git has its sub-arguments delimited by
|
||||
* a pair of -'s, or --)
|
||||
*/
|
||||
|
||||
#include "debugconsole/consoleparse.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "globalincs/vmallocator.h"
|
||||
|
||||
#define DC_MAX_COMMANDS 300
|
||||
|
||||
class debug_command;
|
||||
|
||||
/**
|
||||
* @def DCF
|
||||
*
|
||||
* @brief The potent DCF macro, used to define new debug commands for the console.
|
||||
*
|
||||
* @param function_name[in] The name of the function, as shown in the debug console
|
||||
* @param help_txt[in] The short-help text, as shown as listed from the 'help' command
|
||||
*
|
||||
* @details
|
||||
* Each DCF is responsible for getting data from the debug console's command line. The parsing functions for the
|
||||
* command line have been set up to have similar syntax and usage as the parselo commands. (see consoleparse.h)
|
||||
* Most, if not all, argument and subcommand strings should be parsed by the dc_optional_string functions.
|
||||
* Usage example:
|
||||
* DCF(toggle_it, "description")
|
||||
* {
|
||||
* if (dc_optional_string_either("help", "--help")) {
|
||||
* dc_printf("Usage: sample. Toggles This_var on/off\n");
|
||||
*
|
||||
* } else if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
|
||||
* dc_printf("This_var is %s\n", (This_var ? "ON" : "OFF"));
|
||||
*
|
||||
* } else {
|
||||
* This_var = !This_var;
|
||||
*
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* In the console, the command would be listed as 'toggle_it', and dcf_help would display it as:
|
||||
* toggle_it - Usage: sample. Toggles This_var on/off.
|
||||
* Note: The only allowed function type is a void fn( void )
|
||||
*/
|
||||
#define DCF(function_name, help_text) \
|
||||
void dcf_##function_name(); \
|
||||
debug_command dcmd_##function_name(#function_name, help_text, dcf_##function_name); \
|
||||
void dcf_##function_name()
|
||||
|
||||
/**
|
||||
* @def Shortcut for debug commands that toggle a bool, such as Show_lightning
|
||||
*
|
||||
* @param [in] function_name Name of the function, as shown in the debug console
|
||||
* @param [in] bool_variable Name of the variable to allow toggling.
|
||||
*/
|
||||
#define DCF_BOOL(function_name, bool_variable) \
|
||||
void dcf_##function_name(); \
|
||||
debug_command dcmd_##function_name(#function_name, "Sets or toggles the boolean: "#bool_variable, dcf_##function_name ); \
|
||||
void dcf_##function_name() { \
|
||||
bool bool_tmp = bool_variable != 0; \
|
||||
if (dc_optional_string_either("help", "--help")) { \
|
||||
dc_printf( "Usage: %s [bool]\nSets %s to true or false. If nothing passed, then toggles it.\n", #function_name, #bool_variable ); \
|
||||
return; \
|
||||
} \
|
||||
if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
|
||||
dc_printf("%s = %s\n", #bool_variable, (bool_variable ? "TRUE" : "FALSE")); \
|
||||
return; \
|
||||
} \
|
||||
if (!dc_maybe_stuff_boolean(&bool_tmp)) { \
|
||||
if (bool_variable != 0) \
|
||||
bool_variable = 0; \
|
||||
else \
|
||||
bool_variable = 1; \
|
||||
} else { \
|
||||
if (bool_tmp) \
|
||||
bool_variable = 1; \
|
||||
else \
|
||||
bool_variable = 0; \
|
||||
} \
|
||||
dc_printf("%s set to %s\n", #bool_variable, (bool_variable != 0 ? "TRUE" : "FALSE")); \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @def Same as DCF_BOOL, but with custom help strings
|
||||
*
|
||||
* @param [in] function_name Name of the function, as shown in the debug console
|
||||
* @param [in] bool_variable Name of the variable to allow toggling.
|
||||
*/
|
||||
#define DCF_BOOL2(function_name, bool_variable, short_help, long_help) \
|
||||
void dcf_##function_name(); \
|
||||
debug_command dcmd_##function_name(#function_name, short_help, dcf_##function_name ); \
|
||||
void dcf_##function_name() { \
|
||||
if (dc_optional_string_either("help", "--help")) { \
|
||||
dc_printf( #long_help ); \
|
||||
return; \
|
||||
} \
|
||||
if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
|
||||
dc_printf("%s = %s\n", #function_name, (bool_variable ? "TRUE" : "FALSE")); \
|
||||
return; \
|
||||
} \
|
||||
if (!dc_maybe_stuff_boolean(&bool_variable)) { \
|
||||
bool_variable = !bool_variable; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* @def Shortcut for single-variable setters/monitors
|
||||
*
|
||||
* @param [in] function_name
|
||||
* @param [in] float_variable
|
||||
* @param [in] short_help
|
||||
*/
|
||||
#define DCF_FLOAT(function_name, float_variable, short_help) \
|
||||
void dcf_##function_name(); \
|
||||
debug_command dcmd_##function_name(#function_name, short_help, dcf_##function_name ); \
|
||||
void dcf_##function_name() { \
|
||||
float value; \
|
||||
if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
|
||||
dc_printf("%s = %f\n", #float_variable, float_variable); \
|
||||
return; \
|
||||
} \
|
||||
dc_stuff_float(&value); \
|
||||
float_variable = value; \
|
||||
dc_printf("%s set to %f\n", #float_variable, float_variable); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @def Shortcut for single-variable setters/monitors with lower/upper bounds clamping
|
||||
*
|
||||
* @param [in] function_name
|
||||
* @param [in] float_variable
|
||||
* @param [in] lower_bounds
|
||||
* @param [in] upper_bounds
|
||||
* @param [in] short_help
|
||||
*/
|
||||
#define DCF_FLOAT2(function_name, float_variable, lower_bounds, upper_bounds, short_help) \
|
||||
void dcf_##function_name(); \
|
||||
debug_command dcmd_##function_name(#function_name, short_help, dcf_##function_name ); \
|
||||
void dcf_##function_name() { \
|
||||
float value; \
|
||||
if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
|
||||
dc_printf("%s = %f\n", #float_variable, float_variable); \
|
||||
return; \
|
||||
} \
|
||||
dc_stuff_float(&value); \
|
||||
CLAMP(float_variable, lower_bounds, upper_bounds); \
|
||||
float_variable = value; \
|
||||
dc_printf("%s set to %f\n", #float_variable, float_variable); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @def Shortcut for single-variable setters/monitors
|
||||
*
|
||||
* @param [in] function_name
|
||||
* @param [in] int_variable
|
||||
* @param [in] short_help
|
||||
*/
|
||||
#define DCF_INT(function_name, int_variable, short_help) \
|
||||
void dcf_##function_name(); \
|
||||
debug_command dcmd_##function_name(#function_name, short_help, dcf_##function_name ); \
|
||||
void dcf_##function_name() { \
|
||||
int value; \
|
||||
if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
|
||||
dc_printf("%s = %i\n", #int_variable, int_variable); \
|
||||
return; \
|
||||
} \
|
||||
dc_stuff_int(&value); \
|
||||
int_variable = value; \
|
||||
dc_printf("%s set to %i\n", #int_variable, int_variable); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @def Shortcut for single-variable setters/monitors with lower/upper bounds clamping
|
||||
*
|
||||
* @param [in] function_name
|
||||
* @param [in] int_variable
|
||||
* @param [in] lower_bounds
|
||||
* @param [in] upper_bounds
|
||||
* @param [in] short_help
|
||||
*/
|
||||
#define DCF_INT2(function_name, int_variable, lower_bounds, upper_bounds, short_help) \
|
||||
void dcf_##function_name(); \
|
||||
debug_command dcmd_##function_name(#function_name, short_help, dcf_##function_name ); \
|
||||
void dcf_##function_name() { \
|
||||
int value; \
|
||||
if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) { \
|
||||
dc_printf("%s = %i\n", #int_variable, int_variable); \
|
||||
return; \
|
||||
} \
|
||||
dc_stuff_int(&value); \
|
||||
CLAMP(int_variable, lower_bounds, upper_bounds); \
|
||||
int_variable = value; \
|
||||
dc_printf("%s set to %i\n", #int_variable, int_variable); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @class debug_command
|
||||
* @brief Class to aggregate a debug command with its name (as shown in the console) and short help.
|
||||
*
|
||||
* @details
|
||||
* Note: Long help, as evoked by '<command> help', should be handled by the function itself. It is recommended
|
||||
* that arguments that have sub-arguments be in their own function, so as to aide in organization and to keep the
|
||||
* size of the command function down.
|
||||
*/
|
||||
class debug_command {
|
||||
public:
|
||||
const char *name; //!< The name of the command, as shown in the debug console
|
||||
const char *help; //!< The short help string, as shown by 'help <command>'
|
||||
void (*func)(); //!< Pointer to the function that to run when this command is evoked
|
||||
|
||||
debug_command();
|
||||
|
||||
/**
|
||||
* @brief Adds a debug command to the debug_commands map, if it isn't in there already.
|
||||
*
|
||||
* @details The DCF macro more or less guarantees that a command won't be duplicated on compile time. But no harm in
|
||||
* some extra caution.
|
||||
*/
|
||||
debug_command(const char *name, const char *help, void (*func)());
|
||||
};
|
||||
|
||||
/**
|
||||
* @class is_dcmd
|
||||
* @brief Predicate class used to search for a dcmd by name
|
||||
*/
|
||||
class is_dcmd {
|
||||
public:
|
||||
const char *name;
|
||||
|
||||
is_dcmd(const char *_name) : name(_name) {}
|
||||
|
||||
bool operator() (debug_command* dcmd)
|
||||
{
|
||||
return (strcmp(name, dcmd->name) == 0);
|
||||
}
|
||||
};
|
||||
|
||||
extern bool Dc_debug_on;
|
||||
extern int dc_commands_size;
|
||||
extern uint lastline;
|
||||
extern SCP_string dc_command_str; // The rest of the command line, from the end of the last processed arg on.
|
||||
|
||||
/**
|
||||
* @brief Pauses the output of a command and allows user to scroll through the output history.
|
||||
*
|
||||
* @details Returns true if user has pressed Esc, returns false otherwise. Use this in your function to (safely?) break
|
||||
* out of the loop it's presumably in.
|
||||
*/
|
||||
bool dc_pause_output(void);
|
||||
|
||||
/**
|
||||
* @brief Prints the given char string to the debug console
|
||||
* @details See the doc for std::printf() for formating and more details
|
||||
*/
|
||||
void dc_printf(const char *format, ...);
|
||||
|
||||
/**
|
||||
* @brief Opens and processes the debug console. (Blocking call)
|
||||
* @details TODO: Make this a non-blocking call so that the game can still run while the debug console is open.
|
||||
*/
|
||||
void debug_console(void (*func)(void) = NULL);
|
||||
|
||||
#endif // _CONSOLE_H
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
* z64555's debug console
|
||||
* Created for the FreeSpace Source Code project
|
||||
*
|
||||
* Portions of this source code are based on works by Volition, Inc. circa
|
||||
* 1999. You may not sell or otherwise commercially exploit the source or things you
|
||||
* created based on the source
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file consolecmds.cpp
|
||||
*
|
||||
* @brief This file contains the "built-in" commands for the debug console, and is listed by the 'help' and '?' commands
|
||||
*
|
||||
* @details
|
||||
* All other debug commands should be in their respective files and added to the console with the DCF macro. For
|
||||
* further documentation, please see console.h
|
||||
*/
|
||||
|
||||
#include "debugconsole/console.h"
|
||||
#include "debugconsole/consoleparse.h"
|
||||
#include "io/key.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// ========================= GLOBALS =========================
|
||||
debug_command *dc_commands[DC_MAX_COMMANDS];
|
||||
int dc_commands_size = 0;
|
||||
|
||||
// ========================= LOCALS ==========================
|
||||
// dcf_shell commands
|
||||
void dc_shell_font( void );
|
||||
void dc_shell_resize( void );
|
||||
void dc_shell_resize_buf( void );
|
||||
|
||||
// =================== class debug_command ===================
|
||||
debug_command::debug_command()
|
||||
: name(""), help(""), func(NULL) {
|
||||
};
|
||||
|
||||
debug_command::debug_command(const char *_name, const char *_help, void(*_func)())
|
||||
: name(_name), help(_help), func(_func) {
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (dc_commands_size >= DC_MAX_COMMANDS) {
|
||||
Error(LOCATION, "Too many debug console commands! Please inform a coder to increase DC_MAX_COMMANDS.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the insertion sort by finding where to stick the debug command
|
||||
for (; i < dc_commands_size; ++i) {
|
||||
ret = stricmp(dc_commands[i]->name, _name);
|
||||
|
||||
if (ret == 0) {
|
||||
Error(LOCATION, "Debug Command %s already exists! Please inform a coder immediately.", _name);
|
||||
return;
|
||||
} else if (ret > 0) {
|
||||
// Insert the command here
|
||||
break;
|
||||
} // Else, do nothing
|
||||
}
|
||||
|
||||
// Then, do the insertion
|
||||
if (i < dc_commands_size) {
|
||||
for (int j = dc_commands_size; j > i; --j) {
|
||||
dc_commands[j] = dc_commands[j - 1];
|
||||
}
|
||||
dc_commands[i] = this;
|
||||
dc_commands_size++;
|
||||
} else {
|
||||
dc_commands[dc_commands_size] = this;
|
||||
dc_commands_size++;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================== IMPLEMENTATIONS =============================
|
||||
|
||||
DCF(debug, "Runs a command in debug mode.")
|
||||
{
|
||||
int i;
|
||||
SCP_string command = "";
|
||||
|
||||
Dc_debug_on = true;
|
||||
|
||||
dc_stuff_string_white(command);
|
||||
|
||||
if (command == "") {
|
||||
dc_printf("<debug> No command given\n");
|
||||
return;
|
||||
} // Else, command is present.
|
||||
|
||||
for (i = 0; i < dc_commands_size; ++i) {
|
||||
if (stricmp(dc_commands[i]->name, command.c_str()) == 0) {
|
||||
break;
|
||||
} // Else, continue
|
||||
}
|
||||
|
||||
if (i == dc_commands_size) {
|
||||
dc_printf("<debug> Command not found: '%s'\n", command.c_str());
|
||||
return;
|
||||
} // Else, we found our command
|
||||
|
||||
dc_printf("<debug> Executing command: '%s'\n", command.c_str());
|
||||
// try {
|
||||
dc_commands[i]->func();
|
||||
// } catch {
|
||||
// }
|
||||
|
||||
Dc_debug_on = false;
|
||||
}
|
||||
|
||||
DCF(help, "Displays the help list." )
|
||||
{
|
||||
extern uint DROWS;
|
||||
|
||||
int i;
|
||||
SCP_string command = "";
|
||||
|
||||
dc_maybe_stuff_string_white(command);
|
||||
if ((command == "help") || (command == "man"))
|
||||
{
|
||||
// Moron filter :D
|
||||
dc_printf("GTVA Command: Sorry pilot. You're on your own.\n");
|
||||
return;
|
||||
|
||||
} else if (command != "") {
|
||||
for (i = 0; i < dc_commands_size; ++i) {
|
||||
if (stricmp(dc_commands[i]->name, command.c_str()) == 0) {
|
||||
break;
|
||||
} // Else, continue
|
||||
}
|
||||
|
||||
if (i == dc_commands_size) {
|
||||
dc_printf("Command not found: '%s'\n", command.c_str());
|
||||
return;
|
||||
} // Else, we found our command
|
||||
|
||||
dc_printf("%s\n", dc_commands[i]->help);
|
||||
return;
|
||||
} // Else, command line is empty, print out the help list
|
||||
|
||||
dc_printf("FreeSpace Open Debug Console\n");
|
||||
dc_printf(" These commands are defined internally.\n");
|
||||
dc_printf(" Typing 'help function_name' will give the short help on the function.\n");
|
||||
dc_printf(" Some functions may have detailed help, try passing \"help\" or \"--help\" to them.");
|
||||
dc_printf(" F3 selects last command line. Up and Down arrow keys scroll through the command history\n");
|
||||
dc_printf("\n");
|
||||
|
||||
dc_printf(" Available commands:\n");
|
||||
for (i = 0; i < dc_commands_size; ++i) {
|
||||
if (((lastline % DROWS) == 0) && (lastline != 0)) {
|
||||
dc_pause_output();
|
||||
}
|
||||
|
||||
dc_printf(" %s - %s\n", dc_commands[i]->name, dc_commands[i]->help);
|
||||
}
|
||||
}
|
||||
|
||||
debug_command dc_man("man", "Also displays the help list", dcf_help);
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,460 +0,0 @@
|
||||
#ifndef _CONSOLEPARSE_H
|
||||
#define _CONSOLEPARSE_H
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Command-line parsing functions for z64555's debug console, created for the FreeSpace Source Code project
|
||||
//
|
||||
// Portions of this source code are based on works by Volition, Inc. circa 1999. You may not sell or otherwise
|
||||
// commercially exploit the source or things you created based on the source.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @file consoleparse.h
|
||||
* @brief Parsing functions for the command line. Previously known as the command line scanner
|
||||
*
|
||||
* @details A lot of functions here are blatently copied from parselo.h :D
|
||||
*/
|
||||
|
||||
#include "debugconsole/console.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
#define MAX_CLI_LEN 512
|
||||
#define MAX_TOKEN_LENGTH 255
|
||||
|
||||
enum dc_token {
|
||||
DCT_NONE = 0, //!< No token
|
||||
DCT_STRING, //!< String
|
||||
DCT_FLOAT, //!< Floating point
|
||||
DCT_INT, //!< Integral
|
||||
DCT_UINT, //!< Unsigned Integral
|
||||
DCT_BYTE, //!< Integral with values between -128 and 127
|
||||
DCT_UBYTE, //!< Integral with values between 0 and 255
|
||||
DCT_BOOL, //!< Integral or string evaluated as a boolean
|
||||
|
||||
DCT_MAX_ITEMS //!< Maximum number of dc_token elements. Primarily used as an end value in loops
|
||||
};
|
||||
|
||||
/**
|
||||
* @class errParse
|
||||
*
|
||||
* @brief Class thrown when a required token is not found
|
||||
*
|
||||
* @details This is a basic parser error, it contains the token (a single word) that was found, and the expected token
|
||||
* type. Some DCT's, such as the DCT_STRING's, have their own specific requirements for error handling, and as
|
||||
* such get their own class derived from errParse. The catching routines should be able to catch the derived error
|
||||
* objects, but if not, they can be caught by a routine looking for the base class and then be casted to their
|
||||
* proper type.
|
||||
*/
|
||||
class errParse {
|
||||
public:
|
||||
SCP_string found_token;
|
||||
dc_token expected_type;
|
||||
|
||||
/**
|
||||
* @brief Invalid/Unexpected token constructor
|
||||
* @param [in] found_str The token that was found
|
||||
* @param [in] expected_dct The token type that was expected
|
||||
*/
|
||||
errParse(const char *found_str, dc_token expected_dct)
|
||||
: found_token(found_str), expected_type(expected_dct)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class errParseString
|
||||
*
|
||||
* @brief Class thrown when an expected string was not found. Can/should contain all of the expected strings.
|
||||
*/
|
||||
class errParseString : public errParse
|
||||
{
|
||||
public:
|
||||
SCP_vector<SCP_string> expected_tokens;
|
||||
|
||||
/**
|
||||
* @brief Invalid/Unexpected token constructor.
|
||||
*
|
||||
* @param [in] found_str The string that was found
|
||||
* @param [in] str The token that was expected
|
||||
*/
|
||||
errParseString(const char *found_str, char *str)
|
||||
: errParse(found_str, DCT_STRING)
|
||||
{
|
||||
expected_tokens.push_back(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Invalid/Unexpected token constructor.
|
||||
*
|
||||
* @param [in] found_str The string that was found
|
||||
* @param [in] str1 The first token that was expected
|
||||
* @param [in] str2 The second token that was expected
|
||||
*/
|
||||
errParseString(const char *found_str, char *str1, char *str2)
|
||||
: errParse(found_str, DCT_STRING)
|
||||
{
|
||||
expected_tokens.push_back(str1);
|
||||
expected_tokens.push_back(str2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Invalid/Unexpected token constructor.
|
||||
*
|
||||
* @param [in] found_str The string that was found
|
||||
* @param [in] strings The strings that were expected
|
||||
*/
|
||||
errParseString(const char *found_str, SCP_vector<SCP_string> &strings)
|
||||
: errParse(found_str, DCT_STRING), expected_tokens(strings)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class errParseOverflow
|
||||
*
|
||||
* @brief Class thrown when the parsed string or token could not be stuffed into the smaller destination container
|
||||
*
|
||||
* @var found_str Contains the first 'len' valid characters.
|
||||
*/
|
||||
class errParseOverflow : public errParse
|
||||
{
|
||||
public:
|
||||
size_t len; //!< The size of the destination container
|
||||
|
||||
errParseOverflow(const char *found_str, size_t _len)
|
||||
: errParse(found_str, DCT_STRING), len(_len)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initializes the DC command line parser
|
||||
*/
|
||||
void dc_parse_init(SCP_string &str);
|
||||
|
||||
/**
|
||||
* @brief Advances the parser past whitespace characters
|
||||
*/
|
||||
void dc_ignore_white_space(void);
|
||||
|
||||
/**
|
||||
* @brief Advances the parser past grayspace characters
|
||||
*/
|
||||
void dc_ignore_gray_space(void);
|
||||
|
||||
// Required/Optional Token
|
||||
/**
|
||||
* @brief Searches for a specified required string, throwing an errParse if not found.
|
||||
*
|
||||
* @param[in] pstr The string to search for
|
||||
*
|
||||
* @throws errParseString with the required string
|
||||
*/
|
||||
void dc_required_string(char *pstr);
|
||||
|
||||
/**
|
||||
* @brief Searchs for either of the specified required strings, throwing an errParse if neither are found
|
||||
*
|
||||
* @param[in] str1 The first string to search for
|
||||
* @param[in] str2 The second string to search for
|
||||
*
|
||||
* @retval 0 if str1 was found, or
|
||||
* @retval 1 if str2 was found
|
||||
*
|
||||
* @throws errParseString with the required strings
|
||||
*/
|
||||
int dc_required_string_either(char *str1, char *str2);
|
||||
|
||||
/**
|
||||
* @brief Searches for specified required strings
|
||||
*
|
||||
* @param[in] n The number of char[] or c_str's given
|
||||
* @param[in] ... A comma delimited list of one or more required strings.
|
||||
*
|
||||
* @returns The index of the specified required strings (as if they were an array)
|
||||
*
|
||||
* @throws errParseString with the required strings
|
||||
*/
|
||||
uint dc_required_string_any(const uint n, ...);
|
||||
|
||||
/**
|
||||
* @brief Searches for an optional string
|
||||
*
|
||||
* @param[in] pstr The char[] to look for
|
||||
*
|
||||
* @retval true if the string was found,
|
||||
* @retval false otherwise
|
||||
*/
|
||||
bool dc_optional_string(const char *pstr);
|
||||
|
||||
/**
|
||||
* @brief Searches for an optional string and it's alias
|
||||
*
|
||||
* @param[in] str1 The char[] to look for
|
||||
* @param[in] str2 The alternative char[] to look for
|
||||
*
|
||||
* @retval true if the string was found,
|
||||
* @retval false otherwise
|
||||
*/
|
||||
bool dc_optional_string_either(const char *str1, const char *str2);
|
||||
|
||||
|
||||
// ==========================
|
||||
// Stuffers
|
||||
// ==========================
|
||||
|
||||
/**
|
||||
* @brief Stuffs a float to the given variable.
|
||||
*
|
||||
* @param[in] f The float variable to stuff to
|
||||
*
|
||||
* @throws errParse if an unexpected or otherwise malformed float string is found.
|
||||
* @throws errParse if nothing was found
|
||||
*/
|
||||
void dc_stuff_float(float *f);
|
||||
|
||||
/**
|
||||
* @brief Stuffs an int to the given variable. Supports binary (0b), hexadecimal (0x), and octal (0o) formats
|
||||
*
|
||||
* @param[in] i The int variable to stuff to
|
||||
*
|
||||
* @details The binary, hexadecimal, and octal formats must be prefixed by their associated string.
|
||||
* Ex: "0xDEADBEEF" would be parsed properly while "DEADBEEF" would throw an error
|
||||
*
|
||||
* @throws errParse if an unexpected or otherwise malformed float string is found.
|
||||
* @throws errParse if nothing was found
|
||||
*/
|
||||
void dc_stuff_int(int *i);
|
||||
|
||||
/**
|
||||
* @brief Stuffs an unsigned int to the given variable. Supports binary (0b), hexadecimal (0x), and octal (0o) formats
|
||||
*
|
||||
* @param[in] i The unsigned int variable to stuff to
|
||||
*
|
||||
* @details The binary, hexadecimal, and octal formats must be prefixed by their associated string.
|
||||
* Ex: "0xDEADBEEF" would be parsed properly while "DEADBEEF" would throw an error
|
||||
*
|
||||
* @throws errParse if an unexpected or otherwise malformed float string is found.
|
||||
* @throws errParse if nothing was found
|
||||
*/
|
||||
void dc_stuff_uint(uint *i);
|
||||
|
||||
/**
|
||||
* @brief Stuffs an unsigned byte to the given variable. Supports binary (0b), hexadecimal (0x), and octal (0o) formats
|
||||
*
|
||||
* @param[in] i The ubyte variable to stuff to
|
||||
*
|
||||
* @details The binary, hexadecimal, and octal formats must be prefixed by their associated string.
|
||||
* Ex: "0x0F" would be parsed properly while "0F" would throw an error
|
||||
*
|
||||
* @throws errParse if an unexpected or otherwise malformed float string is found.
|
||||
* @throws errParse if nothing was found
|
||||
*/
|
||||
void dc_stuff_ubyte(ubyte *i);
|
||||
|
||||
/**
|
||||
* @brief stuffs a boolean evaluated integer or string into the given variable.
|
||||
*
|
||||
* @param[in] b The bool variable to stuff to
|
||||
*
|
||||
* @details Supports a number of literal strings as true and false, including "true", "false", "yes", "no" and the
|
||||
* yes/no equivalents in other languages supported in localization.
|
||||
* TODO: Make a static string map to handle this instead of being hard-coded
|
||||
*
|
||||
* @throws errParse if an unexpected or otherwise malformed float string is found.
|
||||
* @throws errParse if nothing was found
|
||||
*/
|
||||
void dc_stuff_boolean(bool *b);
|
||||
|
||||
/**
|
||||
* @brief stuffs a boolean evaluated integer or string into the given variable.
|
||||
*
|
||||
* @param[in] i The int variable to stuff to. 0 is false, 1 is true
|
||||
*
|
||||
* @details Supports a number of literal strings as true and false, including "true", "false", "yes", "no" and the
|
||||
* yes/no equivalents in other languages supported in localization.
|
||||
* TODO: Make a static string map to handle this instead of being hard-coded
|
||||
*
|
||||
* @throws errParse if an unexpected or otherwise malformed float string is found.
|
||||
* @throws errParse if nothing was found
|
||||
*/
|
||||
void dc_stuff_boolean(int *i);
|
||||
|
||||
/**
|
||||
* @brief Stuffs a string to out_str from the command line, stopping at the end of the command line
|
||||
*
|
||||
* @param[out] str Destination string
|
||||
* @param[in] maxlen Maximum length to copy. (maxlen <= sizeof(str)) && (maxlen <= MAX_TOKEN_LENGTH)
|
||||
*
|
||||
* @throws errParse when nothing left was found on the command line
|
||||
* @throws errParseOverflow when parser cannot stuff the entirety of the found string into out_str
|
||||
*/
|
||||
void dc_stuff_string(char *str, size_t maxlen);
|
||||
|
||||
/**
|
||||
* @brief Stuffs a string to out_str from the command line, stopping at the end of the command line
|
||||
*
|
||||
* @param[out] str Destination string
|
||||
*
|
||||
* @throws errParse when nothing left was found on the command line
|
||||
*/
|
||||
void dc_stuff_string(SCP_string &str);
|
||||
|
||||
/**
|
||||
* @brief Stuffs a whitespace delimited string to out_str from the command line, stopping at the end of the command line
|
||||
*
|
||||
* @param[out] str Destination string
|
||||
* @param[in] len Maximum length to copy. (len <= sizeof(str)) && (len <= MAX_TOKEN_LENGTH)
|
||||
*
|
||||
* @throws errParse when nothing left was found on the command line
|
||||
* @throws errParseOverflow when parser cannot stuff the entirety of the found string into out_str
|
||||
*/
|
||||
void dc_stuff_string_white(char *str, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Stuffs a whitespace delimited string to out_str from the command line, stopping at the end of the command line
|
||||
*
|
||||
* @param[out] str Destination string
|
||||
*
|
||||
* @throws errParse when nothing left was found on the command line
|
||||
*/
|
||||
void dc_stuff_string_white(SCP_string &str);
|
||||
|
||||
/**
|
||||
* @brief Tries to stuff a float from the Command_string.
|
||||
*
|
||||
* @param[in] f The float variable to maybe stuff.
|
||||
*
|
||||
* @details
|
||||
* If there's nothing on the command line, *f = 0 and false is returned
|
||||
*
|
||||
* If there's something on the command line, and we're able to convert it, *f = the converted value, true is
|
||||
* returned, and the parser is advanced past the token
|
||||
*
|
||||
* If there's something on command line, but we can't convert it, an errParse is thrown
|
||||
*/
|
||||
bool dc_maybe_stuff_float(float *f);
|
||||
|
||||
/**
|
||||
* @brief Tries to stuff an int from the Command_string.
|
||||
*
|
||||
* @param[in] i The int variable to maybe stuff.
|
||||
*
|
||||
* @details
|
||||
* If there's nothing on the command line, *i = 0 and false is returned
|
||||
*
|
||||
* If there's something on the command line, and we're able to convert it, *i = the converted value, true is
|
||||
* returned, and the parser is advanced past the token
|
||||
*
|
||||
* If there's something on command line, but we can't convert it, an errParse is thrown
|
||||
*/
|
||||
bool dc_maybe_stuff_int(int *i);
|
||||
|
||||
/**
|
||||
* @brief Tries to stuff an uint from the Command_string.
|
||||
*
|
||||
* @param[in] i The uint variable to maybe stuff.
|
||||
*
|
||||
* @details
|
||||
* If there's nothing on the command line, *i = 0 and false is returned
|
||||
*
|
||||
* If there's something on the command line, and we're able to convert it, *i = the converted value, true is
|
||||
* returned, and the parser is advanced past the token
|
||||
*
|
||||
* If there's something on command line, but we can't convert it, an errParse is thrown
|
||||
*/
|
||||
bool dc_maybe_stuff_uint(uint *i);
|
||||
|
||||
/**
|
||||
* @brief Tries to stuff an ubyte from the Command_string.
|
||||
*
|
||||
* @param[in] i The ubyte variable to maybe stuff.
|
||||
*
|
||||
* @details
|
||||
* If there's nothing on the command line, *i = 0 and false is returned
|
||||
*
|
||||
* If there's something on the command line, and we're able to convert it, *i = the converted value, true is
|
||||
* returned, and the parser is advanced past the token
|
||||
*
|
||||
* If there's something on command line, but we can't convert it, an errParse is thrown
|
||||
*/
|
||||
bool dc_maybe_stuff_ubyte(ubyte *i);
|
||||
|
||||
/**
|
||||
* @brief Tries to stuff a bool from the Command_string.
|
||||
*
|
||||
* @param[in] b The bool variable to maybe stuff.
|
||||
*
|
||||
* @details
|
||||
* If there's nothing on the command line, *b = false and false is returned
|
||||
*
|
||||
* If there's something on the command line, and we're able to convert it, *b = the converted value, true is
|
||||
* returned, and the parser is advanced past the token
|
||||
*
|
||||
* If there's something on command line, but we can't convert it, an errParse is thrown
|
||||
*/
|
||||
bool dc_maybe_stuff_boolean(bool *b);
|
||||
|
||||
/**
|
||||
* @brief Tries to stuff an int with a bool value from the Command_string.
|
||||
*
|
||||
* @param[in] i The int variable to maybe stuff.
|
||||
*
|
||||
* @details
|
||||
* If there's nothing on the command line, *i = 0 and false is returned
|
||||
*
|
||||
* If there's something on the command line, and we're able to convert it, *i = the converted value, true is
|
||||
* returned, and the parser is advanced past the token
|
||||
*
|
||||
* If there's something on command line, but we can't convert it, an errParse is thrown
|
||||
*/
|
||||
bool dc_maybe_stuff_boolean(int *i);
|
||||
|
||||
/**
|
||||
* @brief Tries to stuff a string to out_str from the command line, stopping at the end of the command line
|
||||
*
|
||||
* @param[out] str Destination string. If nothing was found, str = ""
|
||||
* @param[in] len Maximum length to copy. (len <= sizeof(str)) && (len <= MAX_TOKEN_LENGTH)
|
||||
*
|
||||
* @retval true if the operation was successful,
|
||||
* @retval false otherwise
|
||||
*
|
||||
* @throws errParseOverflow when parser cannot stuff the entirety of the found string into out_str
|
||||
*/
|
||||
bool dc_maybe_stuff_string(char *str, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Tries to stuff a string to out_str from the command line, stopping at the end of the command line
|
||||
*
|
||||
* @param[out] str Destination string. If nothing was found, str = ""
|
||||
*
|
||||
* @retval true if the operation was successful,
|
||||
* @retval false otherwise
|
||||
*/
|
||||
bool dc_maybe_stuff_string(SCP_string &str);
|
||||
|
||||
/**
|
||||
* @brief Tries to stuff a whitespace delimited string to out_str from the command line, stopping at the end of the command line
|
||||
*
|
||||
* @param[out] str Destination string. If nothing was found, str = ""
|
||||
* @param[in] len Maximum length to copy. (maxlen <= sizeof(str)) && (maxlen <= MAX_TOKEN_LENGTH)
|
||||
*
|
||||
* @retval true if the operation was successful,
|
||||
* @retval false otherwise
|
||||
*
|
||||
* @throws errParseOverflow when parser cannot stuff the entirety of the found string into out_str
|
||||
*/
|
||||
bool dc_maybe_stuff_string_white(char *str, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Tries to stuff a whitespace delimited string to out_str from the command line, stopping at the end of the command line
|
||||
*
|
||||
* @param[out] str Destination string. If nothing was found, str = ""
|
||||
*
|
||||
* @retval true if the operation was successful,
|
||||
* @retval false otherwise
|
||||
*/
|
||||
bool dc_maybe_stuff_string_white(SCP_string &str);
|
||||
|
||||
#endif // _CONSOLEPARSE_H
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Code created by Thomas Whittaker (RT) for a FreeSpace 2 source code project
|
||||
*
|
||||
* You may not sell or otherwise commercially exploit the source or things you
|
||||
* created based on the source.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module is intended as a debug tool to measure the speed of blocks of code and display
|
||||
* that information as coloured bars across the top of the screen.
|
||||
*
|
||||
* This allows interactive measuring of components of the code, very useful for optimisztion.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
#include "timerbar.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
|
||||
// Internal structure for handling frame data
|
||||
typedef struct
|
||||
{
|
||||
LARGE_INTEGER start_value;
|
||||
LARGE_INTEGER total_value;
|
||||
|
||||
LARGE_INTEGER average;
|
||||
LARGE_INTEGER frame_total;
|
||||
|
||||
} timerbar_profile;
|
||||
|
||||
timerbar_profile profiles[MAX_NUM_TIMERBARS];
|
||||
int timerbar_current_profile = 0;
|
||||
|
||||
LARGE_INTEGER timerbar_ultimate_start_value;
|
||||
LARGE_INTEGER timerbar_last_start_value;
|
||||
|
||||
// Data needed for push and pop functionality
|
||||
const int MAX_TB_STACK_SIZE = 100;
|
||||
|
||||
int timerbar_stack[MAX_TB_STACK_SIZE];
|
||||
int timerbar_current_stack_layer = 0;
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
void timerbar_push(int value)
|
||||
{
|
||||
if(timerbar_current_stack_layer >= MAX_TB_STACK_SIZE)
|
||||
{
|
||||
// To many pushs, this must be a bug
|
||||
// Someone is letting code miss the pops, check for early retuns
|
||||
Assert(!(timerbar_current_stack_layer >= MAX_TB_STACK_SIZE));
|
||||
return;
|
||||
}
|
||||
|
||||
timerbar_stack[timerbar_current_stack_layer] = timerbar_current_profile;
|
||||
timerbar_current_stack_layer++;
|
||||
|
||||
timerbar_switch_type(value);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
void timerbar_pop()
|
||||
{
|
||||
timerbar_current_stack_layer--;
|
||||
if(timerbar_current_stack_layer < 0)
|
||||
{
|
||||
Assert(!(timerbar_current_stack_layer < 0));
|
||||
timerbar_current_stack_layer = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
timerbar_switch_type(timerbar_stack[timerbar_current_stack_layer]);
|
||||
}
|
||||
|
||||
// This pointer holds the draw function to use or NULL
|
||||
void (*draw_func_ptr)(int colour, float x, float y, float w, float h) = NULL;
|
||||
|
||||
void timerbar_start_frame()
|
||||
{
|
||||
timerbar_current_stack_layer = 0;
|
||||
timerbar_current_profile = 0;
|
||||
|
||||
if(QueryPerformanceCounter(&timerbar_ultimate_start_value) == FALSE)
|
||||
{
|
||||
// DBUGFILE_OUTPUT_0("QueryPerformanceCounter not supported by hardware");
|
||||
draw_func_ptr = NULL;
|
||||
}
|
||||
|
||||
timerbar_last_start_value = timerbar_ultimate_start_value;
|
||||
|
||||
}
|
||||
|
||||
// Constants need for timerbar_conv_and_draw calculations
|
||||
const int WIDTH = 480;
|
||||
const float WIDTHF = ((float) WIDTH) * 1.01f;
|
||||
|
||||
/**
|
||||
* Internal conversion function to convert draw data into bars for the screen
|
||||
*
|
||||
* @param colour Colour index (>=0)
|
||||
* @param xpos X position to start bar on
|
||||
* @param xwidth Width of bar
|
||||
* @param yrow Index of row bar belongs to
|
||||
*/
|
||||
void timerbar_conv_and_draw(int colour, int xpos, int xwidth, int yrow)
|
||||
{
|
||||
float fxpos = (float) xpos;
|
||||
float fxwidth = (float) xwidth;
|
||||
|
||||
draw_func_ptr(colour,
|
||||
fxpos / WIDTHF,
|
||||
yrow * 0.01f,
|
||||
fxwidth / WIDTHF,
|
||||
0.005f);
|
||||
}
|
||||
|
||||
void timerbar_end_frame()
|
||||
{
|
||||
// Now we want to draw the bars
|
||||
if(draw_func_ptr == NULL)
|
||||
{
|
||||
// we have not been given a draw function so we are going to have to quit
|
||||
return;
|
||||
}
|
||||
|
||||
timerbar_switch_type(-1);
|
||||
|
||||
int last_xpos = 0;
|
||||
int y_pos = 0;
|
||||
|
||||
|
||||
for(int i = 0; i < MAX_NUM_TIMERBARS; i++)
|
||||
{
|
||||
// Nothing to render this frame
|
||||
if(profiles[i].frame_total.QuadPart == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int xsize = (int) profiles[i].frame_total.QuadPart / 90;
|
||||
|
||||
// break condition in else
|
||||
while(1)
|
||||
{
|
||||
// if bar runs over
|
||||
if(last_xpos + xsize > WIDTH)
|
||||
{
|
||||
int rem_len = WIDTH - last_xpos;
|
||||
|
||||
// Draw from current position to the end of the bar
|
||||
timerbar_conv_and_draw(i, last_xpos, rem_len, y_pos);
|
||||
|
||||
xsize -= rem_len;
|
||||
last_xpos = 0;
|
||||
y_pos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw whats left and break for the next bar
|
||||
timerbar_conv_and_draw(i,last_xpos, xsize, y_pos);
|
||||
|
||||
last_xpos += xsize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// reset for next frame
|
||||
profiles[i].frame_total.QuadPart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void timerbar_switch_type(int num)
|
||||
{
|
||||
if(num >= MAX_NUM_TIMERBARS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate old profile's total
|
||||
LARGE_INTEGER now;
|
||||
if(QueryPerformanceCounter(&now) == FALSE)
|
||||
{
|
||||
// DBUGFILE_OUTPUT_0("QueryPerformanceCounter not supported by hardware");
|
||||
}
|
||||
|
||||
profiles[timerbar_current_profile].frame_total.QuadPart +=
|
||||
(now.QuadPart - timerbar_last_start_value.QuadPart);
|
||||
|
||||
if(num != -1)
|
||||
{
|
||||
// Switch to new profile
|
||||
timerbar_current_profile = num;
|
||||
}
|
||||
|
||||
// Update time to count from
|
||||
if(QueryPerformanceCounter(&timerbar_last_start_value) == FALSE)
|
||||
{
|
||||
// DBUGFILE_OUTPUT_0("QueryPerformanceCounter not supported by hardware");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param (*new_draw_func_ptr)(int colour, float x, float y, float w, float h) Pointer to draw function
|
||||
*
|
||||
* Sets the draw function used to output the timer data, designed to be generic allowing any API
|
||||
* to take advantage of this module. Set to NULL to disable drawing.
|
||||
*
|
||||
* By default the draw function is set to NULL
|
||||
*/
|
||||
void timerbar_set_draw_func(void (*new_draw_func_ptr)(int colour, float x, float y, float w, float h))
|
||||
{
|
||||
draw_func_ptr = new_draw_func_ptr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Code created by Thomas Whittaker (RT) for a FreeSpace 2 source code project
|
||||
*
|
||||
* You may not sell or otherwise commercially exploit the source or things you
|
||||
* created based on the source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _TIMERBAR_HEADER_
|
||||
#define _TIMERBAR_HEADER_
|
||||
|
||||
const int MAX_NUM_TIMERBARS = 20;
|
||||
|
||||
#include "cmdline/cmdline.h"
|
||||
|
||||
// These functions should never be used directly, always use macros below
|
||||
void timerbar_start_frame();
|
||||
void timerbar_end_frame();
|
||||
void timerbar_set_draw_func(void (*new_draw_func_ptr)(int colour, float x, float y, float w, float h));
|
||||
|
||||
void timerbar_push(int value);
|
||||
void timerbar_pop();
|
||||
|
||||
// This function shouldnt not be used any more or it will break push and pop calls
|
||||
void timerbar_switch_type(int num);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -308,7 +308,7 @@ static char* GetFilePart(char *source)
|
||||
//
|
||||
// --------------------
|
||||
|
||||
SCP_string safe_string;
|
||||
extern char safe_string[512];
|
||||
|
||||
// Entry point into the main exception handling routine. This routine is put into an except()
|
||||
// statment at the beginning of a thread and is called anytime that there is a program exception
|
||||
@@ -494,8 +494,8 @@ int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS data, const char *Message)
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!safe_string.empty())
|
||||
hprintf(LogFile, "Last safe point: %s\r\n", safe_string.c_str());
|
||||
if (safe_string[0])
|
||||
hprintf(LogFile, "Last safe point: %s\r\n", safe_string);
|
||||
#endif
|
||||
|
||||
RecordModuleList(LogFile);
|
||||
@@ -509,4 +509,4 @@ int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS data, const char *Message)
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
#endif
|
||||
#endif
|
||||
@@ -69,4 +69,4 @@ int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS data, const char *Message);
|
||||
|
||||
|
||||
#endif // __EXCEPTION_HANDLER_H
|
||||
#endif
|
||||
#endif
|
||||
@@ -3,52 +3,65 @@
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
/* We must have windows.h anywhere SCP_ExternalCode is used under windows */
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/* This class loads external libraries for FSO use.
|
||||
* Uses SDL to do the actual loading so this should be supported on most platforms
|
||||
*/
|
||||
* Different platforms have different ways of doing this, so use your ifdefs!
|
||||
*/
|
||||
class SCP_ExternalCode
|
||||
{
|
||||
public:
|
||||
SCP_ExternalCode() : m_dll(NULL)
|
||||
SCP_ExternalCode( )
|
||||
#ifdef _WIN32
|
||||
: m_dll( NULL )
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~SCP_ExternalCode()
|
||||
virtual ~SCP_ExternalCode( )
|
||||
{
|
||||
if (m_dll)
|
||||
SDL_UnloadObject(m_dll);
|
||||
#ifdef _WIN32
|
||||
if ( m_dll )
|
||||
::FreeLibrary( m_dll );
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
bool LoadExternal(const char* externlib)
|
||||
BOOL LoadExternal( const char* externlib )
|
||||
{
|
||||
if (!externlib)
|
||||
return false;
|
||||
if ( !externlib )
|
||||
return FALSE;
|
||||
|
||||
#ifdef _WIN32
|
||||
m_dll = ::LoadLibrary( externlib );
|
||||
|
||||
if ( m_dll )
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
m_dll = SDL_LoadObject(externlib);
|
||||
|
||||
if (m_dll)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void* LoadFunction(const char* functionname)
|
||||
void* LoadFunction( const char* functionname )
|
||||
{
|
||||
if (m_dll != NULL && functionname != NULL)
|
||||
return SDL_LoadFunction(m_dll, functionname);
|
||||
|
||||
#ifdef _WIN32
|
||||
if ( m_dll != NULL && functionname != NULL )
|
||||
return ::GetProcAddress( m_dll, functionname );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
private:
|
||||
void* m_dll;
|
||||
#ifdef _WIN32
|
||||
HMODULE m_dll;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* These are available if you're compiling an external DLL
|
||||
* So far we have trackir, and speech is on the way
|
||||
*/
|
||||
* So far we have trackir, and speech is on the way
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
# define SCP_EXT_CALLCONV __cdecl
|
||||
# ifdef SCPDLL_EXTERNAL_LIB
|
||||
@@ -57,8 +70,8 @@ private:
|
||||
# define SCPDLL_EXTERNAL __declspec( dllimport )
|
||||
# endif
|
||||
/* Must be in a CPP file in your DLL code
|
||||
* If you want to write your own, you shouldn't.
|
||||
*/
|
||||
* If you want to write your own, you shouldn't.
|
||||
*/
|
||||
# define SCPDLL_DLLMAIN( ) \
|
||||
SCP_EXTERN_C BOOL APIENTRY DllMain( HANDLE, DWORD, LPVOID ) { return TRUE; }
|
||||
#else
|
||||
@@ -81,7 +94,7 @@ typedef struct _SCPDLL_Version
|
||||
int patch;
|
||||
} SCPDLL_Version;
|
||||
|
||||
typedef int (SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version*);
|
||||
typedef int ( SCP_EXT_CALLCONV *SCPDLL_PFVERSION )( SCPDLL_Version* );
|
||||
|
||||
/* Must be in a CPP file in your DLL code */
|
||||
#define SCPDLL_VERSION_FUNCTION( Major, Minor, Patch ) \
|
||||
@@ -90,4 +103,4 @@ typedef int (SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version*);
|
||||
v->major = Major; v->minor = Minor; v->patch = Patch;\
|
||||
return 0; }
|
||||
|
||||
#endif /* EXTERNALCODE_H_INCLUDED_ */
|
||||
#endif /* EXTERNALCODE_H_INCLUDED_ */
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "trackirpublic.h"
|
||||
|
||||
/* The TrackIR Interface */
|
||||
TrackIRDLL gTirDll_TrackIR;
|
||||
TrackIRDLL gTirDll_TrackIR;
|
||||
@@ -1,13 +1,8 @@
|
||||
#ifndef TRACKIRPUBLIC_H_INCLUDED_
|
||||
#define TRACKIRPUBLIC_H_INCLUDED_
|
||||
|
||||
#ifdef WIN32
|
||||
# include "SDL_syswm.h" // For SDL_SysWMinfo
|
||||
#endif
|
||||
|
||||
#include "external_dll/externalcode.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "osapi/osapi.h"
|
||||
|
||||
#define TRACKIRBRIDGEDLLNAME "scptrackir.dll"
|
||||
|
||||
@@ -88,26 +83,10 @@ public:
|
||||
}
|
||||
|
||||
/* Returns 0 on success */
|
||||
int Init( SDL_Window* window )
|
||||
int Init( HWND hwnd )
|
||||
{
|
||||
// This is only supported on windows
|
||||
#ifdef WIN32
|
||||
if (m_Init)
|
||||
{
|
||||
SDL_SysWMinfo info;
|
||||
SDL_VERSION(&info.version); // initialize info structure with SDL version info
|
||||
|
||||
if (SDL_GetWindowWMInfo(os_get_window(), &info)) { // the call returns true on success
|
||||
// success
|
||||
return m_Init(info.info.win.window);
|
||||
}
|
||||
else {
|
||||
// call failed
|
||||
mprintf(("TrackIR: Couldn't get window information: %s\n", SDL_GetError()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( m_Init )
|
||||
return m_Init( hwnd );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+183
-160
@@ -9,17 +9,18 @@
|
||||
|
||||
|
||||
|
||||
#include "asteroid/asteroid.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "fireball/fireballs.h"
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "graphics/tmapper.h"
|
||||
#include "localization/localize.h"
|
||||
#include "render/3d.h"
|
||||
#include "model/model.h"
|
||||
#include "object/object.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "render/3d.h"
|
||||
#include "ship/ship.h"
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "localization/localize.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "asteroid/asteroid.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -75,7 +76,7 @@ void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
|
||||
|
||||
if(fb->warp_open_sound_index > -1) {
|
||||
sound_index = fb->warp_open_sound_index;
|
||||
} else if ((ship_class >= 0) && (ship_class < static_cast<int>(Ship_info.size()))) {
|
||||
} else if((ship_class >= 0) && (ship_class < Num_ship_classes)){
|
||||
if ( Ship_info[ship_class].flags & SIF_HUGE_SHIP ) {
|
||||
sound_index = SND_CAPITAL_WARP_IN;
|
||||
fb->flags |= FBF_WARP_CAPITAL_SIZE;
|
||||
@@ -156,95 +157,93 @@ static void fireball_set_default_color(int idx)
|
||||
*
|
||||
* NOTE: we can't be too trusting here so a tbm will only modify the LOD count, not add an entry
|
||||
*/
|
||||
void parse_fireball_tbl(const char *filename)
|
||||
void parse_fireball_tbl(char *filename)
|
||||
{
|
||||
int rval;
|
||||
lod_checker lod_check;
|
||||
color fb_color;
|
||||
|
||||
try
|
||||
{
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
// open localization
|
||||
lcl_ext_open();
|
||||
|
||||
required_string("#Start");
|
||||
|
||||
while (required_string_either("#End", "$Name:")) {
|
||||
memset(&lod_check, 0, sizeof(lod_checker));
|
||||
|
||||
// base filename
|
||||
required_string("$Name:");
|
||||
stuff_string(lod_check.filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
lod_check.override = -1;
|
||||
|
||||
// these entries should only be in TBMs, and it has to include at least one
|
||||
if (Parsing_modular_table) {
|
||||
if (optional_string("+Explosion_Medium")) {
|
||||
lod_check.override = FIREBALL_EXPLOSION_MEDIUM;
|
||||
}
|
||||
else if (optional_string("+Warp_Effect")) {
|
||||
lod_check.override = FIREBALL_WARP;
|
||||
}
|
||||
else if (optional_string("+Knossos_Effect")) {
|
||||
lod_check.override = FIREBALL_KNOSSOS;
|
||||
}
|
||||
else if (optional_string("+Asteroid")) {
|
||||
lod_check.override = FIREBALL_ASTEROID;
|
||||
}
|
||||
else if (optional_string("+Explosion_Large1")) {
|
||||
lod_check.override = FIREBALL_EXPLOSION_LARGE1;
|
||||
}
|
||||
else if (optional_string("+Explosion_Large2")){
|
||||
lod_check.override = FIREBALL_EXPLOSION_LARGE2;
|
||||
}
|
||||
else {
|
||||
required_string("+Custom_Fireball");
|
||||
stuff_int(&lod_check.override);
|
||||
}
|
||||
}
|
||||
|
||||
lod_check.num_lods = 1;
|
||||
|
||||
// Do we have an LOD num
|
||||
if (optional_string("$LOD:")) {
|
||||
stuff_int(&lod_check.num_lods);
|
||||
}
|
||||
|
||||
if (lod_check.num_lods > MAX_FIREBALL_LOD) {
|
||||
lod_check.num_lods = MAX_FIREBALL_LOD;
|
||||
}
|
||||
|
||||
// check for particular lighting color
|
||||
if (optional_string("$Light color:")) {
|
||||
int r, g, b;
|
||||
|
||||
stuff_int(&r);
|
||||
stuff_int(&g);
|
||||
stuff_int(&b);
|
||||
|
||||
CLAMP(r, 0, 255);
|
||||
CLAMP(g, 0, 255);
|
||||
CLAMP(b, 0, 255);
|
||||
|
||||
gr_init_color(&fb_color, r, g, b);
|
||||
}
|
||||
else {
|
||||
// to keep things simple, we just use 0 alpha to indicate that a default value should be used
|
||||
memset(&fb_color, 0, sizeof(color));
|
||||
}
|
||||
|
||||
// we may use one filename for multiple entries so we'll have to handle dupes post parse
|
||||
LOD_checker.push_back(lod_check);
|
||||
LOD_color.push_back(fb_color);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
lcl_ext_close();
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
required_string("#Start");
|
||||
|
||||
while (required_string_either("#End", "$Name:")) {
|
||||
memset( &lod_check, 0, sizeof(lod_checker) );
|
||||
|
||||
// base filename
|
||||
required_string("$Name:");
|
||||
stuff_string(lod_check.filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
lod_check.override = -1;
|
||||
|
||||
// these entries should only be in TBMs, and it has to include at least one
|
||||
if ( Parsing_modular_table ) {
|
||||
if (optional_string("+Explosion_Medium")) {
|
||||
lod_check.override = FIREBALL_EXPLOSION_MEDIUM;
|
||||
} else if (optional_string("+Warp_Effect")) {
|
||||
lod_check.override = FIREBALL_WARP;
|
||||
} else if (optional_string("+Knossos_Effect")) {
|
||||
lod_check.override = FIREBALL_KNOSSOS;
|
||||
} else if (optional_string("+Asteroid")) {
|
||||
lod_check.override = FIREBALL_ASTEROID;
|
||||
} else if (optional_string("+Explosion_Large1")) {
|
||||
lod_check.override = FIREBALL_EXPLOSION_LARGE1;
|
||||
} else if (optional_string("+Explosion_Large2")){
|
||||
lod_check.override = FIREBALL_EXPLOSION_LARGE2;
|
||||
} else {
|
||||
required_string("+Custom_Fireball");
|
||||
stuff_int(&lod_check.override);
|
||||
}
|
||||
}
|
||||
|
||||
lod_check.num_lods = 1;
|
||||
|
||||
// Do we have an LOD num
|
||||
if (optional_string("$LOD:")) {
|
||||
stuff_int(&lod_check.num_lods);
|
||||
}
|
||||
|
||||
if (lod_check.num_lods > MAX_FIREBALL_LOD) {
|
||||
lod_check.num_lods = MAX_FIREBALL_LOD;
|
||||
}
|
||||
|
||||
// check for particular lighting color
|
||||
if ( optional_string("$Light color:") ) {
|
||||
int r, g, b;
|
||||
|
||||
stuff_int(&r);
|
||||
stuff_int(&g);
|
||||
stuff_int(&b);
|
||||
|
||||
CLAMP(r, 0, 255);
|
||||
CLAMP(g, 0, 255);
|
||||
CLAMP(b, 0, 255);
|
||||
|
||||
gr_init_color(&fb_color, r, g, b);
|
||||
} else {
|
||||
// to keep things simple, we just use 0 alpha to indicate that a default value should be used
|
||||
memset( &fb_color, 0, sizeof(color) );
|
||||
}
|
||||
|
||||
// we may use one filename for multiple entries so we'll have to handle dupes post parse
|
||||
LOD_checker.push_back(lod_check);
|
||||
LOD_color.push_back(fb_color);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
|
||||
// close localization
|
||||
lcl_ext_close();
|
||||
}
|
||||
|
||||
void fireball_parse_tbl()
|
||||
@@ -323,7 +322,7 @@ void fireball_load_data()
|
||||
if ( (i == FIREBALL_WARP) && (idx > MAX_WARP_LOD) )
|
||||
continue;
|
||||
|
||||
fd->lod[idx].bitmap_id = bm_load_animation( fd->lod[idx].filename, &fd->lod[idx].num_frames, &fd->lod[idx].fps, nullptr, nullptr, true );
|
||||
fd->lod[idx].bitmap_id = bm_load_animation( fd->lod[idx].filename, &fd->lod[idx].num_frames, &fd->lod[idx].fps, NULL, 1 );
|
||||
if ( fd->lod[idx].bitmap_id < 0 ) {
|
||||
Error(LOCATION, "Could not load %s anim file\n", fd->lod[idx].filename);
|
||||
}
|
||||
@@ -374,6 +373,83 @@ void fireball_init()
|
||||
|
||||
MONITOR( NumFireballsRend )
|
||||
|
||||
void fireball_render(object * obj)
|
||||
{
|
||||
int num;
|
||||
vertex p;
|
||||
fireball *fb;
|
||||
fireball_info *fd;
|
||||
|
||||
MONITOR_INC( NumFireballsRend, 1 );
|
||||
|
||||
num = obj->instance;
|
||||
fb = &Fireballs[num];
|
||||
fd = &Fireball_info[fb->fireball_info_index];
|
||||
|
||||
if ( Fireballs[num].current_bitmap < 0 )
|
||||
return;
|
||||
|
||||
// turn off fogging
|
||||
if(The_mission.flags & MISSION_FLAG_FULLNEB){
|
||||
gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0);
|
||||
}
|
||||
|
||||
if(Cmdline_nohtl) {
|
||||
g3_rotate_vertex(&p, &obj->pos );
|
||||
}else{
|
||||
g3_transfer_vertex(&p, &obj->pos);
|
||||
}
|
||||
|
||||
switch( fb->fireball_render_type ) {
|
||||
|
||||
case FIREBALL_MEDIUM_EXPLOSION:
|
||||
batch_add_bitmap (
|
||||
Fireballs[num].current_bitmap,
|
||||
TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_SOFT_QUAD,
|
||||
&p,
|
||||
fb->orient,
|
||||
obj->radius
|
||||
);
|
||||
break;
|
||||
|
||||
case FIREBALL_LARGE_EXPLOSION:
|
||||
// Make the big explosions rotate with the viewer.
|
||||
batch_add_bitmap_rotated (
|
||||
Fireballs[num].current_bitmap,
|
||||
TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_SOFT_QUAD,
|
||||
&p,
|
||||
(i2fl(fb->orient)*PI)/180.0f,
|
||||
obj->radius
|
||||
);
|
||||
break;
|
||||
|
||||
case FIREBALL_WARP_EFFECT: {
|
||||
|
||||
float percent_life = fb->time_elapsed / fb->total_time;
|
||||
|
||||
float rad;
|
||||
|
||||
// Code to make effect grow/shrink.
|
||||
float t = fb->time_elapsed;
|
||||
|
||||
if ( t < WARPHOLE_GROW_TIME ) {
|
||||
rad = (float)pow(t/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
|
||||
} else if ( t < fb->total_time - WARPHOLE_GROW_TIME ) {
|
||||
rad = obj->radius;
|
||||
} else {
|
||||
rad = (float)pow((fb->total_time - t)/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
|
||||
}
|
||||
|
||||
warpin_render(obj, &obj->orient, &obj->pos, Fireballs[num].current_bitmap, rad, percent_life, obj->radius, (Fireballs[num].flags & FBF_WARP_3D) );
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
Int3();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a fireball.
|
||||
* Called by object_delete() code... do not call directly.
|
||||
@@ -430,7 +506,13 @@ void fireball_set_framenum(int num)
|
||||
}
|
||||
|
||||
if ( fb->fireball_render_type == FIREBALL_WARP_EFFECT ) {
|
||||
framenum = bm_get_anim_frame(fl->bitmap_id, fb->time_elapsed, 0.0f, true);
|
||||
float total_time = i2fl(fl->num_frames) / fl->fps; // in seconds
|
||||
|
||||
framenum = fl2i(fb->time_elapsed * fl->num_frames / total_time + 0.5);
|
||||
|
||||
if ( framenum < 0 ) framenum = 0;
|
||||
|
||||
framenum = framenum % fl->num_frames;
|
||||
|
||||
if ( fb->orient ) {
|
||||
// warp out effect plays backwards
|
||||
@@ -440,8 +522,16 @@ void fireball_set_framenum(int num)
|
||||
fb->current_bitmap = fl->bitmap_id + framenum;
|
||||
}
|
||||
} else {
|
||||
// ignore setting of OF_SHOULD_BE_DEAD, see fireball_process_post
|
||||
framenum = bm_get_anim_frame(fl->bitmap_id, fb->time_elapsed, fb->total_time);
|
||||
|
||||
framenum = fl2i(fb->time_elapsed / fb->total_time * fl->num_frames + 0.5);
|
||||
|
||||
// ensure we don't go past the number of frames of animation
|
||||
if ( framenum > (fl->num_frames-1) ) {
|
||||
framenum = (fl->num_frames-1);
|
||||
Objects[fb->objnum].flags |= OF_SHOULD_BE_DEAD;
|
||||
}
|
||||
|
||||
if ( framenum < 0 ) framenum = 0;
|
||||
fb->current_bitmap = fl->bitmap_id + framenum;
|
||||
}
|
||||
}
|
||||
@@ -960,70 +1050,3 @@ float fireball_wormhole_intensity( object *obj )
|
||||
}
|
||||
return rad;
|
||||
}
|
||||
|
||||
void fireball_render(object* obj, draw_list *scene)
|
||||
{
|
||||
int num;
|
||||
vertex p;
|
||||
fireball *fb;
|
||||
|
||||
MONITOR_INC( NumFireballsRend, 1 );
|
||||
|
||||
num = obj->instance;
|
||||
fb = &Fireballs[num];
|
||||
|
||||
if ( Fireballs[num].current_bitmap < 0 )
|
||||
return;
|
||||
|
||||
g3_transfer_vertex(&p, &obj->pos);
|
||||
|
||||
switch ( fb->fireball_render_type ) {
|
||||
|
||||
case FIREBALL_MEDIUM_EXPLOSION: {
|
||||
batch_add_bitmap (
|
||||
Fireballs[num].current_bitmap,
|
||||
TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_SOFT_QUAD | TMAP_FLAG_EMISSIVE,
|
||||
&p,
|
||||
fb->orient,
|
||||
obj->radius
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case FIREBALL_LARGE_EXPLOSION: {
|
||||
// Make the big explosions rotate with the viewer.
|
||||
batch_add_bitmap_rotated (
|
||||
Fireballs[num].current_bitmap,
|
||||
TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_SOFT_QUAD | TMAP_FLAG_EMISSIVE,
|
||||
&p,
|
||||
(i2fl(fb->orient)*PI)/180.0f,
|
||||
obj->radius
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case FIREBALL_WARP_EFFECT: {
|
||||
float percent_life = fb->time_elapsed / fb->total_time;
|
||||
|
||||
float rad;
|
||||
|
||||
// Code to make effect grow/shrink.
|
||||
float t = fb->time_elapsed;
|
||||
|
||||
if ( t < WARPHOLE_GROW_TIME ) {
|
||||
rad = (float)pow(t/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
|
||||
} else if ( t < fb->total_time - WARPHOLE_GROW_TIME ) {
|
||||
rad = obj->radius;
|
||||
} else {
|
||||
rad = (float)pow((fb->total_time - t)/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
|
||||
}
|
||||
|
||||
warpin_queue_render(scene, obj, &obj->orient, &obj->pos, Fireballs[num].current_bitmap, rad, percent_life, obj->radius, (Fireballs[num].flags & FBF_WARP_3D) );
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
Int3();
|
||||
}
|
||||
}
|
||||
@@ -13,11 +13,10 @@
|
||||
#define _FIREBALLS_H
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "model/modelrender.h"
|
||||
|
||||
class object;
|
||||
class ship_info;
|
||||
class asteroid_info;
|
||||
struct object;
|
||||
struct ship_info;
|
||||
struct asteroid_info;
|
||||
|
||||
// values correspond to the fireball render types
|
||||
#define FIREBALL_MEDIUM_EXPLOSION 0
|
||||
@@ -77,7 +76,7 @@ typedef struct fireball {
|
||||
// end move
|
||||
|
||||
void fireball_init();
|
||||
void fireball_render(object* obj, draw_list *scene);
|
||||
void fireball_render(object * obj);
|
||||
void fireball_delete( object * obj );
|
||||
void fireball_process_post(object * obj, float frame_time);
|
||||
|
||||
@@ -115,8 +114,6 @@ float fireball_wormhole_intensity( object *obj );
|
||||
// internal function to draw warp grid.
|
||||
extern void warpin_render(object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, int warp_3d = 0 );
|
||||
|
||||
extern void warpin_queue_render(draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, int warp_3d);
|
||||
|
||||
extern int Warp_model;
|
||||
|
||||
// Goober5000
|
||||
|
||||
+31
-172
@@ -10,15 +10,17 @@
|
||||
|
||||
|
||||
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "graphics/tmapper.h"
|
||||
#include "math/vecmat.h"
|
||||
#include "mission/missionparse.h"
|
||||
#include "model/model.h"
|
||||
#include "nebula/neb.h"
|
||||
#include "graphics/tmapper.h"
|
||||
#include "render/3d.h"
|
||||
#include "fireball/fireballs.h"
|
||||
#include "mission/missionparse.h"
|
||||
#include "nebula/neb.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "model/model.h"
|
||||
#include "ship/ship.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
|
||||
|
||||
extern int Warp_model;
|
||||
extern int Warp_glow_bitmap;
|
||||
@@ -45,25 +47,6 @@ void draw_face( vertex *v1, vertex *v2, vertex *v3 )
|
||||
|
||||
}
|
||||
|
||||
void warpin_batch_draw_face( int texture, vertex *v1, vertex *v2, vertex *v3 )
|
||||
{
|
||||
vec3d norm;
|
||||
vertex vertlist[3];
|
||||
|
||||
vm_vec_perp(&norm,&v1->world, &v2->world, &v3->world);
|
||||
if ( vm_vec_dot(&norm, &v1->world ) >= 0.0 ) {
|
||||
vertlist[0] = *v3;
|
||||
vertlist[1] = *v2;
|
||||
vertlist[2] = *v1;
|
||||
} else {
|
||||
vertlist[0] = *v1;
|
||||
vertlist[1] = *v2;
|
||||
vertlist[2] = *v3;
|
||||
}
|
||||
|
||||
batch_add_tri(texture, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_EMISSIVE, vertlist, 1.0f);
|
||||
}
|
||||
|
||||
void warpin_render(object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, int warp_3d)
|
||||
{
|
||||
vec3d center;
|
||||
@@ -75,7 +58,6 @@ void warpin_render(object *obj, matrix *orient, vec3d *pos, int texture_bitmap_n
|
||||
|
||||
vm_vec_scale_add( ¢er, pos, &orient->vec.fvec, -(max_radius/2.5f)/3.0f );
|
||||
|
||||
memset(verts, 0, sizeof(verts));
|
||||
|
||||
if (Warp_glow_bitmap >= 0) {
|
||||
float r = radius;
|
||||
@@ -112,7 +94,11 @@ void warpin_render(object *obj, matrix *orient, vec3d *pos, int texture_bitmap_n
|
||||
vecs[4] = center;
|
||||
verts[4].texture_position.u = 0.5f; verts[4].texture_position.v = 0.5f;
|
||||
|
||||
g3_transfer_vertex( &verts[4], &vecs[4] );
|
||||
if (Cmdline_nohtl) {
|
||||
g3_rotate_vertex( &verts[4], &vecs[4] );
|
||||
} else {
|
||||
g3_transfer_vertex( &verts[4], &vecs[4] );
|
||||
}
|
||||
|
||||
float alpha = (The_mission.flags & MISSION_FLAG_FULLNEB) ? (1.0f - neb2_get_fog_intensity(obj)) : 1.0f;
|
||||
gr_set_bitmap( Warp_glow_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, alpha );
|
||||
@@ -122,18 +108,15 @@ void warpin_render(object *obj, matrix *orient, vec3d *pos, int texture_bitmap_n
|
||||
}
|
||||
|
||||
if ( (Warp_model >= 0) && (warp_3d || Cmdline_3dwarp) ) {
|
||||
model_render_params render_info;
|
||||
|
||||
vec3d scale;
|
||||
scale.xyz.z = scale.xyz.y = scale.xyz.x = radius / 25.0f;
|
||||
render_info.set_warp_params(texture_bitmap_num, radius/max_radius, scale);
|
||||
float scale = radius / 25.0f;
|
||||
model_set_warp_globals(scale, scale, scale, texture_bitmap_num, (radius/max_radius) );
|
||||
|
||||
float dist = vm_vec_dist_quick( pos, &Eye_position );
|
||||
render_info.set_detail_level_lock((int)(dist / (radius * 10.0f)));
|
||||
model_set_detail_level((int)(dist / (radius * 10.0f)));
|
||||
|
||||
render_info.set_flags(MR_NO_LIGHTING | MR_NORMAL | MR_NO_FOGGING | MR_NO_CULL | MR_NO_BATCH);
|
||||
model_render( Warp_model, orient, pos, MR_LOCK_DETAIL | MR_NO_LIGHTING | MR_NORMAL | MR_NO_FOGGING | MR_NO_CULL );
|
||||
|
||||
model_render_immediate( &render_info, Warp_model, orient, pos );
|
||||
model_set_warp_globals();
|
||||
} else {
|
||||
float Grid_depth = radius/2.5f;
|
||||
|
||||
@@ -173,11 +156,19 @@ void warpin_render(object *obj, matrix *orient, vec3d *pos, int texture_bitmap_n
|
||||
verts[4].texture_position.u = 0.5f;
|
||||
verts[4].texture_position.v = 0.5f;
|
||||
|
||||
g3_transfer_vertex( &verts[0], &vecs[0] );
|
||||
g3_transfer_vertex( &verts[1], &vecs[1] );
|
||||
g3_transfer_vertex( &verts[2], &vecs[2] );
|
||||
g3_transfer_vertex( &verts[3], &vecs[3] );
|
||||
g3_transfer_vertex( &verts[4], &vecs[4] );
|
||||
if (Cmdline_nohtl) {
|
||||
g3_rotate_vertex( &verts[0], &vecs[0] );
|
||||
g3_rotate_vertex( &verts[1], &vecs[1] );
|
||||
g3_rotate_vertex( &verts[2], &vecs[2] );
|
||||
g3_rotate_vertex( &verts[3], &vecs[3] );
|
||||
g3_rotate_vertex( &verts[4], &vecs[4] );
|
||||
} else {
|
||||
g3_transfer_vertex( &verts[0], &vecs[0] );
|
||||
g3_transfer_vertex( &verts[1], &vecs[1] );
|
||||
g3_transfer_vertex( &verts[2], &vecs[2] );
|
||||
g3_transfer_vertex( &verts[3], &vecs[3] );
|
||||
g3_transfer_vertex( &verts[4], &vecs[4] );
|
||||
}
|
||||
|
||||
int cull = gr_set_cull(0); // fixes rendering problem in D3D - taylor
|
||||
draw_face( &verts[0], &verts[4], &verts[1] );
|
||||
@@ -205,135 +196,3 @@ void warpin_render(object *obj, matrix *orient, vec3d *pos, int texture_bitmap_n
|
||||
|
||||
gr_zbuffer_set( saved_gr_zbuffering );
|
||||
}
|
||||
|
||||
void warpin_queue_render(draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, int warp_3d)
|
||||
{
|
||||
vec3d center;
|
||||
vec3d vecs[5];
|
||||
vertex verts[5];
|
||||
|
||||
vm_vec_scale_add( ¢er, pos, &orient->vec.fvec, -(max_radius/2.5f)/3.0f );
|
||||
|
||||
|
||||
if (Warp_glow_bitmap >= 0) {
|
||||
float r = radius;
|
||||
bool render_it = true;
|
||||
|
||||
#define OUT_PERCENT1 0.80f
|
||||
#define OUT_PERCENT2 0.90f
|
||||
|
||||
#define IN_PERCENT1 0.10f
|
||||
#define IN_PERCENT2 0.20f
|
||||
|
||||
if (Cmdline_warp_flash)
|
||||
{
|
||||
if ( (life_percent >= IN_PERCENT1) && (life_percent < IN_PERCENT2) ) {
|
||||
r *= (life_percent - IN_PERCENT1) / (IN_PERCENT2 - IN_PERCENT1);
|
||||
//render_it = true;
|
||||
} else if ( (life_percent >= OUT_PERCENT1) && (life_percent < OUT_PERCENT2) ) {
|
||||
r *= (OUT_PERCENT2 - life_percent) / (OUT_PERCENT2 - OUT_PERCENT1);
|
||||
//render_it = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (render_it) {
|
||||
// Add in noise
|
||||
int noise_frame = fl2i(Missiontime/15.0f) % NOISE_NUM_FRAMES;
|
||||
|
||||
r *= (0.40f + Noise[noise_frame] * 0.30f);
|
||||
|
||||
// Bobboau's warp thingie, toggled by cmdline
|
||||
if (Cmdline_warp_flash) {
|
||||
r += powf((2.0f * life_percent) - 1.0f, 24.0f) * max_radius * 1.5f;
|
||||
}
|
||||
|
||||
vecs[4] = center;
|
||||
verts[4].texture_position.u = 0.5f; verts[4].texture_position.v = 0.5f;
|
||||
|
||||
g3_transfer_vertex( &verts[4], &vecs[4] );
|
||||
|
||||
float alpha = (The_mission.flags & MISSION_FLAG_FULLNEB) ? (1.0f - neb2_get_fog_intensity(obj)) : 1.0f;
|
||||
|
||||
batch_add_bitmap(Warp_glow_bitmap, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_EMISSIVE , &verts[4], 0, r, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
if ( (Warp_model >= 0) && (warp_3d || Cmdline_3dwarp) ) {
|
||||
model_render_params render_info;
|
||||
|
||||
float scale = radius / 25.0f;
|
||||
|
||||
vec3d warp_scale;
|
||||
|
||||
warp_scale.xyz.x = warp_scale.xyz.y = warp_scale.xyz.z = scale;
|
||||
|
||||
float dist = vm_vec_dist_quick( pos, &Eye_position );
|
||||
|
||||
render_info.set_warp_params(texture_bitmap_num, radius/max_radius, warp_scale);
|
||||
render_info.set_detail_level_lock((int)(dist / (radius * 10.0f)));
|
||||
render_info.set_flags(MR_NO_LIGHTING | MR_NORMAL | MR_NO_FOGGING | MR_NO_CULL | MR_NO_BATCH);
|
||||
|
||||
model_render_queue( &render_info, scene, Warp_model, orient, pos);
|
||||
} else {
|
||||
float Grid_depth = radius/2.5f;
|
||||
|
||||
// gr_set_bitmap( texture_bitmap_num, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f );
|
||||
|
||||
vm_vec_scale_add( &vecs[0], ¢er, &orient->vec.uvec, radius );
|
||||
vm_vec_scale_add2( &vecs[0], &orient->vec.rvec, -radius );
|
||||
vm_vec_scale_add2( &vecs[0], &orient->vec.fvec, Grid_depth );
|
||||
|
||||
vm_vec_scale_add( &vecs[1], ¢er, &orient->vec.uvec, radius );
|
||||
vm_vec_scale_add2( &vecs[1], &orient->vec.rvec, radius );
|
||||
vm_vec_scale_add2( &vecs[1], &orient->vec.fvec, Grid_depth );
|
||||
|
||||
vm_vec_scale_add( &vecs[2], ¢er, &orient->vec.uvec, -radius );
|
||||
vm_vec_scale_add2( &vecs[2], &orient->vec.rvec, radius );
|
||||
vm_vec_scale_add2( &vecs[2], &orient->vec.fvec, Grid_depth );
|
||||
|
||||
vm_vec_scale_add( &vecs[3], ¢er, &orient->vec.uvec, -radius );
|
||||
vm_vec_scale_add2( &vecs[3], &orient->vec.rvec, -radius );
|
||||
vm_vec_scale_add2( &vecs[3], &orient->vec.fvec, Grid_depth );
|
||||
|
||||
// vm_vec_scale_add( &vecs[4], ¢er, &orient->vec.fvec, -Grid_depth );
|
||||
vecs[4] = center;
|
||||
|
||||
verts[0].texture_position.u = 0.01f;
|
||||
verts[0].texture_position.v = 0.01f;
|
||||
|
||||
verts[1].texture_position.u = 0.99f;
|
||||
verts[1].texture_position.v = 0.01f;
|
||||
|
||||
verts[2].texture_position.u = 0.99f;
|
||||
verts[2].texture_position.v = 0.99f;
|
||||
|
||||
verts[3].texture_position.u = 0.01f;
|
||||
verts[3].texture_position.v = 0.99f;
|
||||
|
||||
verts[4].texture_position.u = 0.5f;
|
||||
verts[4].texture_position.v = 0.5f;
|
||||
|
||||
g3_transfer_vertex( &verts[0], &vecs[0] );
|
||||
g3_transfer_vertex( &verts[1], &vecs[1] );
|
||||
g3_transfer_vertex( &verts[2], &vecs[2] );
|
||||
g3_transfer_vertex( &verts[3], &vecs[3] );
|
||||
g3_transfer_vertex( &verts[4], &vecs[4] );
|
||||
|
||||
warpin_batch_draw_face( texture_bitmap_num, &verts[0], &verts[4], &verts[1] );
|
||||
warpin_batch_draw_face( texture_bitmap_num, &verts[1], &verts[4], &verts[2] );
|
||||
warpin_batch_draw_face( texture_bitmap_num, &verts[4], &verts[3], &verts[2] );
|
||||
warpin_batch_draw_face( texture_bitmap_num, &verts[0], &verts[3], &verts[4] );
|
||||
}
|
||||
|
||||
if (Warp_ball_bitmap > -1 && Cmdline_warp_flash == 1) {
|
||||
//flash_ball warp_ball(20, .1f,.25f, &vmd_z_vector, &vmd_zero_vector, 4.0f, 0.5f);
|
||||
flash_ball warp_ball(20, .1f,.25f, &orient->vec.fvec, pos, 4.0f, 0.5f);
|
||||
|
||||
float adg = (2.0f * life_percent) - 1.0f;
|
||||
float pct = (powf(adg, 4.0f) - powf(adg, 128.0f)) * 4.0f;
|
||||
|
||||
if (pct > 0.00001f) {
|
||||
warp_ball.render(Warp_ball_bitmap, max_radius * pct * 0.5f, adg * adg, adg * adg * 6.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,14 +124,14 @@ BOOL AltShipClassDlg::OnInitDialog()
|
||||
m_set_from_ship_class.AddString("Set From Variable");
|
||||
}
|
||||
count = 0;
|
||||
for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it)
|
||||
for (i=0; i<Num_ship_classes; i++)
|
||||
{
|
||||
if (player_ships_only && !(it->flags & SIF_PLAYER_SHIP)) {
|
||||
if (player_ships_only && !(Ship_info[i].flags & SIF_PLAYER_SHIP)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ship_class_indices[count++] = std::distance(Ship_info.cbegin(), it);
|
||||
m_set_from_ship_class.AddString(it->name);
|
||||
ship_class_indices[count++] = i;
|
||||
m_set_from_ship_class.AddString(Ship_info[i].name);
|
||||
}
|
||||
m_set_from_ship_class.SetCurSel(num_string_variables?1:0); // Set to the first ship class
|
||||
|
||||
@@ -176,7 +176,7 @@ void AltShipClassDlg::alt_class_list_rebuild()
|
||||
m_alt_class_list.AddString(Ship_info[alt_class_pool[i].ship_class].name);
|
||||
}
|
||||
else {
|
||||
m_alt_class_list.AddString("Invalid Ship Class");
|
||||
m_alt_class_list.AddString("Invalid Ship Class");
|
||||
Int3();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ FictionViewerDlg::FictionViewerDlg(CWnd* pParent /*=NULL*/)
|
||||
//{{AFX_DATA_INIT(FictionViewerDlg)
|
||||
m_story_file = _T("");
|
||||
m_font_file = _T("");
|
||||
m_voice_file = _T("");
|
||||
m_fiction_music = 0;
|
||||
//}}AFX_DATA_INIT
|
||||
}
|
||||
@@ -34,7 +33,6 @@ void FictionViewerDlg::DoDataExchange(CDataExchange* pDX)
|
||||
//{{AFX_DATA_MAP(FictionViewerDlg)
|
||||
DDX_Text(pDX, IDC_STORY_FILE, m_story_file);
|
||||
DDX_Text(pDX, IDC_FONT_FILE, m_font_file);
|
||||
DDX_Text(pDX, IDC_VOICE_FILE, m_voice_file);
|
||||
DDX_CBIndex(pDX, IDC_FICTION_MUSIC, m_fiction_music);
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
@@ -59,27 +57,9 @@ BOOL FictionViewerDlg::OnInitDialog()
|
||||
box->AddString(Spooled_music[i].name);
|
||||
}
|
||||
|
||||
// make sure we have at least one stage
|
||||
if (Fiction_viewer_stages.empty())
|
||||
{
|
||||
fiction_viewer_stage stage;
|
||||
memset(&stage, 0, sizeof(fiction_viewer_stage));
|
||||
stage.formula = Locked_sexp_true;
|
||||
|
||||
Fiction_viewer_stages.push_back(stage);
|
||||
}
|
||||
else if (Fiction_viewer_stages.size() > 1)
|
||||
{
|
||||
MessageBox("You have multiple fiction viewer stages defined for this mission. At present, FRED will only allow you to edit the first stage.");
|
||||
}
|
||||
|
||||
// init fields based on first fiction viewer stage
|
||||
fiction_viewer_stage *stagep = &Fiction_viewer_stages.at(0);
|
||||
m_story_file = _T(stagep->story_filename);
|
||||
m_font_file = _T(stagep->font_filename);
|
||||
m_voice_file = _T(stagep->voice_filename);
|
||||
|
||||
// music is managed through the mission
|
||||
// init variables
|
||||
m_story_file = _T(fiction_file());
|
||||
m_font_file = _T(fiction_font());
|
||||
m_fiction_music = Mission_music[SCORE_FICTION_VIEWER] + 1;
|
||||
|
||||
CDialog::OnInitDialog();
|
||||
@@ -91,15 +71,9 @@ void FictionViewerDlg::OnOK()
|
||||
{
|
||||
UpdateData(TRUE);
|
||||
|
||||
// store the fields in the data structure
|
||||
fiction_viewer_stage *stagep = &Fiction_viewer_stages.at(0);
|
||||
strcpy_s(stagep->story_filename, (LPCSTR)m_story_file);
|
||||
strcpy_s(stagep->font_filename, (LPCSTR)m_font_file);
|
||||
strcpy_s(stagep->voice_filename, (LPCSTR)m_voice_file);
|
||||
|
||||
// if we don't have a story file, remove this stage (stage 0)
|
||||
if (strlen(stagep->story_filename) == 0)
|
||||
Fiction_viewer_stages.erase(Fiction_viewer_stages.begin());
|
||||
// load it up
|
||||
fiction_viewer_reset();
|
||||
fiction_viewer_load((char *)(LPCSTR) m_story_file, (char *)(LPCSTR) m_font_file);
|
||||
|
||||
// set music
|
||||
Mission_music[SCORE_FICTION_VIEWER] = m_fiction_music - 1;
|
||||
@@ -137,8 +111,5 @@ void FictionViewerDlg::OnClose()
|
||||
|
||||
int FictionViewerDlg::query_modified()
|
||||
{
|
||||
fiction_viewer_stage *stagep = &Fiction_viewer_stages.at(0);
|
||||
|
||||
return strcmp(m_story_file, stagep->story_filename) || strcmp(m_font_file, stagep->font_filename) ||
|
||||
strcmp(m_voice_file, stagep->voice_filename) || m_fiction_music != (Mission_music[SCORE_FICTION_VIEWER] + 1);
|
||||
return strcmp(m_story_file, fiction_file()) || strcmp(m_font_file, fiction_font()) || m_fiction_music != (Mission_music[SCORE_FICTION_VIEWER] + 1);
|
||||
}
|
||||
@@ -22,12 +22,8 @@ public:
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(FictionViewerDlg)
|
||||
enum { IDD = IDD_FICTION_VIEWER };
|
||||
CString m_fiction_background_640;
|
||||
CString m_fiction_background_1024;
|
||||
int m_fiction_ui;
|
||||
CString m_story_file;
|
||||
CString m_font_file;
|
||||
CString m_voice_file;
|
||||
int m_fiction_music;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
@@ -440,7 +440,7 @@ void asteroid_editor::update_init()
|
||||
for (k = 0; k < MAX_ACTIVE_DEBRIS_TYPES; k++)
|
||||
{
|
||||
box_index = ((CComboBox*)GetDlgItem(Dlg_id[k]))->AddString("None");
|
||||
((CComboBox*)GetDlgItem(Dlg_id[k]))->SetItemData(box_index, static_cast<DWORD_PTR>(-1));
|
||||
((CComboBox*)GetDlgItem(Dlg_id[k]))->SetItemData(box_index, -1);
|
||||
}
|
||||
|
||||
// now add each kind of debris to each box
|
||||
|
||||
+60
-155
@@ -37,6 +37,7 @@ bg_bitmap_dlg::bg_bitmap_dlg(CWnd* pParent) : CDialog(bg_bitmap_dlg::IDD, pParen
|
||||
{
|
||||
//{{AFX_DATA_INIT(bg_bitmap_dlg)
|
||||
m_neb_intensity = _T("");
|
||||
m_skybox_model = _T("");
|
||||
m_envmap = _T("");
|
||||
m_nebula_color = -1;
|
||||
m_nebula_index = -1;
|
||||
@@ -64,11 +65,6 @@ bg_bitmap_dlg::bg_bitmap_dlg(CWnd* pParent) : CDialog(bg_bitmap_dlg::IDD, pParen
|
||||
b_scale_x = 1.0f; b_scale_y = 1.0f;
|
||||
b_div_x = 1; b_div_y = 1;
|
||||
b_index = -1;
|
||||
|
||||
m_skybox_model = _T("");
|
||||
m_skybox_pitch = 0;
|
||||
m_skybox_bank = 0;
|
||||
m_skybox_heading = 0;
|
||||
m_sky_flag_1 = The_mission.skybox_flags & MR_NO_LIGHTING ? 1 : 0;
|
||||
m_sky_flag_2 = The_mission.skybox_flags & MR_ALL_XPARENT ? 1 : 0;
|
||||
m_sky_flag_3 = The_mission.skybox_flags & MR_NO_ZBUFFER ? 1 : 0;
|
||||
@@ -126,12 +122,6 @@ void bg_bitmap_dlg::DoDataExchange(CDataExchange* pDX)
|
||||
DDX_Text(pDX, IDC_SBITMAP_DIV_Y, b_div_y);
|
||||
DDV_MinMaxInt(pDX, b_div_y, 1, 5);
|
||||
DDX_Text(pDX, IDC_SKYBOX_FNAME, m_skybox_model);
|
||||
DDX_Text(pDX, IDC_SKYBOX_P, m_skybox_pitch);
|
||||
DDV_MinMaxInt(pDX, m_skybox_pitch, 0, 359);
|
||||
DDX_Text(pDX, IDC_SKYBOX_B, m_skybox_bank);
|
||||
DDV_MinMaxInt(pDX, m_skybox_bank, 0, 359);
|
||||
DDX_Text(pDX, IDC_SKYBOX_H, m_skybox_heading);
|
||||
DDV_MinMaxInt(pDX, m_skybox_heading, 0, 359);
|
||||
DDX_Text(pDX, IDC_ENVMAP, m_envmap);
|
||||
DDX_Check(pDX, IDC_SKY_FLAG_NO_LIGHTING, m_sky_flag_1);
|
||||
DDX_Check(pDX, IDC_SKY_FLAG_XPARENT, m_sky_flag_2);
|
||||
@@ -180,12 +170,6 @@ BEGIN_MESSAGE_MAP(bg_bitmap_dlg, CDialog)
|
||||
ON_BN_CLICKED(IDC_SWAP_BACKGROUND, OnSwapBackground)
|
||||
ON_CBN_SELCHANGE(IDC_BACKGROUND_NUM, OnBackgroundDropdownChange)
|
||||
ON_BN_CLICKED(IDC_SKYBOX_MODEL, OnSkyboxBrowse)
|
||||
ON_NOTIFY(UDN_DELTAPOS, IDC_SKYBOX_P_SPIN, OnDeltaposSkyboxPSpin)
|
||||
ON_NOTIFY(UDN_DELTAPOS, IDC_SKYBOX_B_SPIN, OnDeltaposSkyboxBSpin)
|
||||
ON_NOTIFY(UDN_DELTAPOS, IDC_SKYBOX_H_SPIN, OnDeltaposSkyboxHSpin)
|
||||
ON_EN_KILLFOCUS(IDC_SKYBOX_P, OnKillfocusSkyboxP)
|
||||
ON_EN_KILLFOCUS(IDC_SKYBOX_B, OnKillfocusSkyboxB)
|
||||
ON_EN_KILLFOCUS(IDC_SKYBOX_H, OnKillfocusSkyboxH)
|
||||
ON_BN_CLICKED(IDC_ENVMAP_BROWSE, OnEnvmapBrowse)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
@@ -227,21 +211,6 @@ void bg_bitmap_dlg::create()
|
||||
m_skybox_model = _T(The_mission.skybox_model);
|
||||
m_envmap = _T(The_mission.envmap_name);
|
||||
|
||||
angles skybox_angles;
|
||||
vm_extract_angles_matrix(&skybox_angles, &The_mission.skybox_orientation);
|
||||
m_skybox_pitch = fl2ir(fl_degrees(skybox_angles.p));
|
||||
m_skybox_bank = fl2ir(fl_degrees(skybox_angles.b));
|
||||
m_skybox_heading = fl2ir(fl_degrees(skybox_angles.h));
|
||||
|
||||
//make sure angle values are in the 0-359 degree range
|
||||
if (m_skybox_pitch < 0)
|
||||
m_skybox_pitch = m_skybox_pitch + 360;
|
||||
if (m_skybox_bank < 0)
|
||||
m_skybox_bank = m_skybox_bank + 360;
|
||||
if (m_skybox_heading < 0)
|
||||
m_skybox_heading = m_skybox_heading + 360;
|
||||
|
||||
|
||||
for(i=0; i<MAX_NEB2_BITMAPS; i++){
|
||||
if(strlen(Neb2_bitmap_filenames[i]) > 0){ //-V805
|
||||
((CComboBox*)GetDlgItem(IDC_NEB2_TEXTURE))->AddString(Neb2_bitmap_filenames[i]);
|
||||
@@ -270,7 +239,7 @@ void bg_bitmap_dlg::create()
|
||||
if(Neb2_awacs < 0.0f){
|
||||
m_neb_intensity = CString("3000");
|
||||
} else {
|
||||
char whee[25] = "";
|
||||
char whee[255] = "";
|
||||
m_neb_intensity = CString(itoa((int)Neb2_awacs, whee, 10));
|
||||
}
|
||||
|
||||
@@ -433,14 +402,9 @@ void bg_bitmap_dlg::OnClose()
|
||||
string_copy(The_mission.skybox_model, m_skybox_model, NAME_LENGTH, 1);
|
||||
string_copy(The_mission.envmap_name, m_envmap, NAME_LENGTH, 1);
|
||||
|
||||
angles skybox_angles;
|
||||
skybox_angles.p = fl_radians(m_skybox_pitch);
|
||||
skybox_angles.b = fl_radians(m_skybox_bank);
|
||||
skybox_angles.h = fl_radians(m_skybox_heading);
|
||||
vm_angles_2_matrix(&The_mission.skybox_orientation, &skybox_angles);
|
||||
|
||||
//store the skybox flags
|
||||
The_mission.skybox_flags = 0;
|
||||
|
||||
if(m_sky_flag_1) {
|
||||
The_mission.skybox_flags |= MR_NO_LIGHTING;
|
||||
}
|
||||
@@ -730,9 +694,9 @@ void bg_bitmap_dlg::OnSunChange()
|
||||
starfield_list_entry *sle = &background->suns[s_index];
|
||||
|
||||
s_name = CString(sle->filename);
|
||||
s_pitch = fl2ir(fl_degrees(sle->ang.p) + delta);
|
||||
s_bank = fl2ir(fl_degrees(sle->ang.b) + delta);
|
||||
s_heading = fl2ir(fl_degrees(sle->ang.h) + delta);
|
||||
s_pitch = (int) (fl_degrees(sle->ang.p) + delta);
|
||||
s_bank = (int) (fl_degrees(sle->ang.b) + delta);
|
||||
s_heading = (int) (fl_degrees(sle->ang.h) + delta);
|
||||
s_scale = sle->scale_x;
|
||||
|
||||
// stuff back into the controls
|
||||
@@ -894,9 +858,9 @@ void bg_bitmap_dlg::OnBitmapChange()
|
||||
starfield_list_entry *sle = &background->bitmaps[b_index];
|
||||
|
||||
b_name = CString(sle->filename);
|
||||
b_pitch = fl2ir(fl_degrees(sle->ang.p) + delta);
|
||||
b_bank = fl2ir(fl_degrees(sle->ang.b) + delta);
|
||||
b_heading = fl2ir(fl_degrees(sle->ang.h) + delta);
|
||||
b_pitch = (int) (fl_degrees(sle->ang.p) + delta);
|
||||
b_bank = (int) (fl_degrees(sle->ang.b) + delta);
|
||||
b_heading = (int) (fl_degrees(sle->ang.h) + delta);
|
||||
b_scale_x = sle->scale_x;
|
||||
b_scale_y = sle->scale_y;
|
||||
b_div_x = sle->div_x;
|
||||
@@ -1215,51 +1179,6 @@ void bg_bitmap_dlg::OnKillfocusSun1Scale()
|
||||
OnSunChange();
|
||||
}
|
||||
|
||||
void bg_bitmap_dlg::OnDeltaposSkyboxPSpin(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
{
|
||||
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
|
||||
|
||||
get_data_spinner(pNMUpDown, IDC_SKYBOX_P, &m_skybox_pitch, 0, 359);
|
||||
OnOrientationChange();
|
||||
*pResult = 0;
|
||||
}
|
||||
|
||||
void bg_bitmap_dlg::OnDeltaposSkyboxBSpin(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
{
|
||||
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
|
||||
|
||||
get_data_spinner(pNMUpDown, IDC_SKYBOX_B, &m_skybox_bank, 0, 359);
|
||||
OnOrientationChange();
|
||||
*pResult = 0;
|
||||
}
|
||||
|
||||
void bg_bitmap_dlg::OnDeltaposSkyboxHSpin(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
{
|
||||
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
|
||||
|
||||
get_data_spinner(pNMUpDown, IDC_SKYBOX_H, &m_skybox_heading, 0, 359);
|
||||
OnOrientationChange();
|
||||
*pResult = 0;
|
||||
}
|
||||
|
||||
void bg_bitmap_dlg::OnKillfocusSkyboxP()
|
||||
{
|
||||
get_data_int(IDC_SKYBOX_P, &m_skybox_pitch, 0, 359);
|
||||
OnOrientationChange();
|
||||
}
|
||||
|
||||
void bg_bitmap_dlg::OnKillfocusSkyboxB()
|
||||
{
|
||||
get_data_int(IDC_SKYBOX_B, &m_skybox_bank, 0, 359);
|
||||
OnOrientationChange();
|
||||
}
|
||||
|
||||
void bg_bitmap_dlg::OnKillfocusSkyboxH()
|
||||
{
|
||||
get_data_int(IDC_SKYBOX_H, &m_skybox_heading, 0, 359);
|
||||
OnOrientationChange();
|
||||
}
|
||||
|
||||
|
||||
extern void parse_one_background(background_t *background);
|
||||
|
||||
@@ -1267,7 +1186,7 @@ void bg_bitmap_dlg::OnImportBackground()
|
||||
{
|
||||
CFileDialog cfd(TRUE, ".fs2", NULL, 0, "FreeSpace2 Missions (*.fs2)|*.fs2||\0");
|
||||
char filename[256], error_str[1024];
|
||||
int temp, count;
|
||||
int rval, temp, count;
|
||||
char *saved_mp;
|
||||
|
||||
//warn on pressing the button
|
||||
@@ -1280,62 +1199,59 @@ void bg_bitmap_dlg::OnImportBackground()
|
||||
|
||||
strcpy_s(filename, cfd.GetPathName());
|
||||
|
||||
try
|
||||
{
|
||||
// parse in the new file
|
||||
read_file_text(filename);
|
||||
reset_parse();
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("BGBITMAPDLG: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
sprintf(error_str, "Could not parse file: %s", filename);
|
||||
|
||||
if (!skip_to_start_of_string("#Background bitmaps"))
|
||||
return;
|
||||
|
||||
// skip beginning stuff
|
||||
required_string("#Background bitmaps");
|
||||
required_string("$Num stars:");
|
||||
stuff_int(&temp);
|
||||
required_string("$Ambient light level:");
|
||||
stuff_int(&temp);
|
||||
|
||||
saved_mp = Mp;
|
||||
|
||||
// see if we have more than one background in this mission
|
||||
count = 0;
|
||||
while (skip_to_string("$Bitmap List:"))
|
||||
count++;
|
||||
|
||||
Mp = saved_mp;
|
||||
|
||||
// pick one (if count is 0, it's retail with just one background)
|
||||
if (count > 0)
|
||||
{
|
||||
int i, which = 0;
|
||||
|
||||
if (count > 1)
|
||||
{
|
||||
BackgroundChooser dlg(count);
|
||||
if (dlg.DoModal() == IDCANCEL)
|
||||
return;
|
||||
|
||||
which = dlg.GetChosenBackground();
|
||||
}
|
||||
|
||||
for (i = 0; i < which + 1; i++)
|
||||
skip_to_string("$Bitmap List:");
|
||||
}
|
||||
|
||||
// now parse the background we've selected
|
||||
parse_one_background(&Backgrounds[get_active_background()]);
|
||||
|
||||
reinitialize_lists();
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("BGBITMAPDLG: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
sprintf(error_str, "Could not parse file: %s\n\nError message: %s", filename, e.what());
|
||||
|
||||
MessageBox((LPCTSTR)error_str, (LPCTSTR) "Unable to import mission background!", MB_ICONERROR | MB_OK);
|
||||
MessageBox((LPCTSTR) error_str, (LPCTSTR) "Unable to import mission background!", MB_ICONERROR | MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
// parse in the new file
|
||||
read_file_text(filename);
|
||||
reset_parse();
|
||||
|
||||
if (!skip_to_start_of_string("#Background bitmaps"))
|
||||
return;
|
||||
|
||||
// skip beginning stuff
|
||||
required_string("#Background bitmaps");
|
||||
required_string("$Num stars:");
|
||||
stuff_int(&temp);
|
||||
required_string("$Ambient light level:");
|
||||
stuff_int(&temp);
|
||||
|
||||
saved_mp = Mp;
|
||||
|
||||
// see if we have more than one background in this mission
|
||||
count = 0;
|
||||
while(skip_to_string("$Bitmap List:"))
|
||||
count++;
|
||||
|
||||
Mp = saved_mp;
|
||||
|
||||
// pick one (if count is 0, it's retail with just one background)
|
||||
if (count > 0)
|
||||
{
|
||||
int i, which = 0;
|
||||
|
||||
if (count > 1)
|
||||
{
|
||||
BackgroundChooser dlg(count);
|
||||
if (dlg.DoModal() == IDCANCEL)
|
||||
return;
|
||||
|
||||
which = dlg.GetChosenBackground();
|
||||
}
|
||||
|
||||
for (i = 0; i < which + 1; i++)
|
||||
skip_to_string("$Bitmap List:");
|
||||
}
|
||||
|
||||
// now parse the background we've selected
|
||||
parse_one_background(&Backgrounds[get_active_background()]);
|
||||
|
||||
reinitialize_lists();
|
||||
}
|
||||
|
||||
void bg_bitmap_dlg::reinitialize_lists()
|
||||
@@ -1430,17 +1346,6 @@ void bg_bitmap_dlg::OnSkyboxBrowse()
|
||||
stars_set_background_model( (char*)(LPCTSTR)m_skybox_model, NULL );
|
||||
}
|
||||
|
||||
void bg_bitmap_dlg::OnOrientationChange()
|
||||
{
|
||||
angles temp_angles;
|
||||
matrix temp_orient;
|
||||
temp_angles.p = fl_radians(m_skybox_pitch);
|
||||
temp_angles.b = fl_radians(m_skybox_bank);
|
||||
temp_angles.h = fl_radians(m_skybox_heading);
|
||||
vm_angles_2_matrix(&temp_orient, &temp_angles);
|
||||
stars_set_background_orientation( &temp_orient );
|
||||
}
|
||||
|
||||
void bg_bitmap_dlg::OnEnvmapBrowse()
|
||||
{
|
||||
CString filename;
|
||||
|
||||
@@ -35,9 +35,7 @@ public:
|
||||
void get_data_spinner(NM_UPDOWN* pUD, int id, int *var, int min, int max);
|
||||
void get_data_int(int id, int *var, int min, int max);
|
||||
void get_data_float(int id, float *var, float max, float min);
|
||||
|
||||
afx_msg void OnClose();
|
||||
|
||||
|
||||
bg_bitmap_dlg(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
@@ -87,9 +85,6 @@ public:
|
||||
int m_sky_flag_6;
|
||||
CString m_skybox_model;
|
||||
CString m_envmap;
|
||||
int m_skybox_pitch;
|
||||
int m_skybox_bank;
|
||||
int m_skybox_heading;
|
||||
float m_neb_near_multi;
|
||||
float m_neb_far_multi;
|
||||
//}}AFX_DATA
|
||||
@@ -110,10 +105,9 @@ protected:
|
||||
int get_swap_background();
|
||||
void reinitialize_lists();
|
||||
|
||||
void OnOrientationChange();
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(bg_bitmap_dlg)
|
||||
afx_msg void OnClose();
|
||||
afx_msg void OnCancel();
|
||||
afx_msg void OnOK();
|
||||
afx_msg void OnSelchangeNebcolor();
|
||||
@@ -149,12 +143,6 @@ protected:
|
||||
afx_msg void OnSwapBackground();
|
||||
afx_msg void OnBackgroundDropdownChange();
|
||||
afx_msg void OnSkyboxBrowse();
|
||||
afx_msg void OnDeltaposSkyboxPSpin(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnDeltaposSkyboxBSpin(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnDeltaposSkyboxHSpin(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnKillfocusSkyboxP();
|
||||
afx_msg void OnKillfocusSkyboxB();
|
||||
afx_msg void OnKillfocusSkyboxH();
|
||||
afx_msg void OnEnvmapBrowse();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
@@ -76,8 +76,6 @@ briefing_editor_dlg::briefing_editor_dlg(CWnd* pParent /*=NULL*/)
|
||||
m_cut_prev = FALSE;
|
||||
m_current_briefing = -1;
|
||||
m_flipicon = FALSE;
|
||||
m_use_wing = FALSE;
|
||||
m_use_cargo = FALSE;
|
||||
//}}AFX_DATA_INIT
|
||||
m_voice_id = -1;
|
||||
m_cur_stage = 0;
|
||||
@@ -111,10 +109,9 @@ void briefing_editor_dlg::DoDataExchange(CDataExchange* pDX)
|
||||
DDX_Check(pDX, IDC_CUT_NEXT, m_cut_next);
|
||||
DDX_Check(pDX, IDC_CUT_PREV, m_cut_prev);
|
||||
DDX_Check(pDX, IDC_FLIP_ICON, m_flipicon);
|
||||
DDX_Check(pDX, IDC_USE_WING_ICON, m_use_wing);
|
||||
DDX_Check(pDX, IDC_USE_CARGO_ICON, m_use_cargo);
|
||||
//}}AFX_DATA_MAP
|
||||
|
||||
DDV_MaxChars(pDX, m_text, MAX_BRIEF_LEN - 1);
|
||||
DDV_MaxChars(pDX, m_voice, MAX_FILENAME_LEN - 1);
|
||||
DDV_MaxChars(pDX, m_icon_label, MAX_LABEL_LEN - 1);
|
||||
DDV_MaxChars(pDX, m_icon_text, MAX_ICON_TEXT_LEN - 1);
|
||||
@@ -135,7 +132,6 @@ BEGIN_MESSAGE_MAP(briefing_editor_dlg, CDialog)
|
||||
ON_BN_CLICKED(IDC_SAVE_VIEW, OnSaveView)
|
||||
ON_CBN_SELCHANGE(IDC_ICON_IMAGE, OnSelchangeIconImage)
|
||||
ON_CBN_SELCHANGE(IDC_TEAM, OnSelchangeTeam)
|
||||
ON_CBN_SELCHANGE(IDC_SHIP_TYPE, OnSelchangeShipType)
|
||||
ON_BN_CLICKED(IDC_PROPAGATE_ICONS, OnPropagateIcons)
|
||||
ON_WM_INITMENU()
|
||||
ON_BN_CLICKED(IDC_LINES, OnLines)
|
||||
@@ -146,8 +142,6 @@ BEGIN_MESSAGE_MAP(briefing_editor_dlg, CDialog)
|
||||
ON_BN_CLICKED(IDC_COPY_VIEW, OnCopyView)
|
||||
ON_BN_CLICKED(IDC_PASTE_VIEW, OnPasteView)
|
||||
ON_BN_CLICKED(IDC_FLIP_ICON, OnFlipIcon)
|
||||
ON_BN_CLICKED(IDC_USE_WING_ICON, OnWingIcon)
|
||||
ON_BN_CLICKED(IDC_USE_CARGO_ICON, OnCargoIcon)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
@@ -188,7 +182,7 @@ void briefing_editor_dlg::create()
|
||||
CDialog::Create(IDD);
|
||||
theApp.init_window(&Briefing_wnd_data, this);
|
||||
box = (CComboBox *) GetDlgItem(IDC_ICON_IMAGE);
|
||||
for (i=0; i<MIN_BRIEF_ICONS; i++)
|
||||
for (i=0; i<MAX_BRIEF_ICONS; i++)
|
||||
box->AddString(Icon_names[i]);
|
||||
|
||||
box = (CComboBox *) GetDlgItem(IDC_TEAM);
|
||||
@@ -196,8 +190,8 @@ void briefing_editor_dlg::create()
|
||||
box->AddString(Iff_info[i].iff_name);
|
||||
|
||||
box = (CComboBox *) GetDlgItem(IDC_SHIP_TYPE);
|
||||
for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it)
|
||||
box->AddString(it->name);
|
||||
for (i=0; i<Num_ship_classes; i++)
|
||||
box->AddString(Ship_info[i].name);
|
||||
|
||||
box = (CComboBox *) GetDlgItem(IDC_BRIEFING_MUSIC);
|
||||
box->AddString("None");
|
||||
@@ -308,8 +302,7 @@ void briefing_editor_dlg::restore_editor_state()
|
||||
|
||||
void briefing_editor_dlg::update_data(int update)
|
||||
{
|
||||
char buf[MAX_LABEL_LEN], buf2[MAX_ICON_TEXT_LEN];
|
||||
SCP_string buf3;
|
||||
char buf[MAX_LABEL_LEN], buf2[MAX_ICON_TEXT_LEN], buf3[MAX_BRIEF_LEN];
|
||||
int i, j, l, lines, count, enable = TRUE, valid = 0, invalid = 0;
|
||||
object *objp;
|
||||
brief_stage *ptr = NULL;
|
||||
@@ -324,12 +317,12 @@ void briefing_editor_dlg::update_data(int update)
|
||||
strcpy_s(The_mission.substitute_briefing_music_name, m_substitute_briefing_music);
|
||||
if (m_last_stage >= 0) {
|
||||
ptr = &Briefing->stages[m_last_stage];
|
||||
deconvert_multiline_string(buf3, m_text);
|
||||
lcl_fred_replace_stuff(buf3);
|
||||
if (ptr->text != buf3)
|
||||
deconvert_multiline_string(buf3, m_text, MAX_BRIEF_LEN);
|
||||
lcl_fred_replace_stuff(buf3, MAX_BRIEF_LEN);
|
||||
if (stricmp(ptr->new_text, buf3))
|
||||
set_modified();
|
||||
|
||||
ptr->text = buf3;
|
||||
strcpy(ptr->new_text, buf3);
|
||||
MODIFY(ptr->camera_time, atoi(m_time));
|
||||
string_copy(ptr->voice, m_voice, MAX_FILENAME_LEN, 1);
|
||||
i = ptr->flags;
|
||||
@@ -439,7 +432,6 @@ void briefing_editor_dlg::update_data(int update)
|
||||
}
|
||||
|
||||
strcpy_s(ptr->icons[m_last_icon].label, buf);
|
||||
|
||||
if ( m_hilight )
|
||||
ptr->icons[m_last_icon].flags |= BI_HIGHLIGHT;
|
||||
else
|
||||
@@ -450,40 +442,30 @@ void briefing_editor_dlg::update_data(int update)
|
||||
else
|
||||
ptr->icons[m_last_icon].flags &= ~BI_MIRROR_ICON;
|
||||
|
||||
if (m_use_wing)
|
||||
ptr->icons[m_last_icon].flags |= BI_USE_WING_ICON;
|
||||
else
|
||||
ptr->icons[m_last_icon].flags &= ~BI_USE_WING_ICON;
|
||||
|
||||
if (m_use_cargo)
|
||||
ptr->icons[m_last_icon].flags |= BI_USE_CARGO_ICON;
|
||||
else
|
||||
ptr->icons[m_last_icon].flags &= ~BI_USE_CARGO_ICON;
|
||||
|
||||
if ((ptr->icons[m_last_icon].type != m_icon_image) && !m_change_local) {
|
||||
set_modified();
|
||||
reset_icon_loop(m_last_stage);
|
||||
while (get_next_icon(m_id))
|
||||
iconp->type = m_icon_image;
|
||||
}
|
||||
ptr->icons[m_last_icon].type = m_icon_image;
|
||||
|
||||
ptr->icons[m_last_icon].type = m_icon_image;
|
||||
if ((ptr->icons[m_last_icon].team != m_icon_team) && !m_change_local) {
|
||||
set_modified();
|
||||
reset_icon_loop(m_last_stage);
|
||||
while (get_next_icon(m_id))
|
||||
iconp->team = m_icon_team;
|
||||
}
|
||||
ptr->icons[m_last_icon].team = m_icon_team;
|
||||
|
||||
ptr->icons[m_last_icon].team = m_icon_team;
|
||||
if ((ptr->icons[m_last_icon].ship_class != m_ship_type) && !m_change_local) {
|
||||
set_modified();
|
||||
reset_icon_loop(m_last_stage);
|
||||
while (get_next_icon(m_id))
|
||||
iconp->ship_class = m_ship_type;
|
||||
}
|
||||
MODIFY(ptr->icons[m_last_icon].ship_class, m_ship_type);
|
||||
|
||||
MODIFY(ptr->icons[m_last_icon].ship_class, m_ship_type);
|
||||
deconvert_multiline_string(buf2, m_icon_text, MAX_ICON_TEXT_LEN);
|
||||
/*
|
||||
if (stricmp(ptr->icons[m_last_icon].text, buf2) && !m_change_local) {
|
||||
@@ -507,7 +489,7 @@ void briefing_editor_dlg::update_data(int update)
|
||||
if ((m_cur_stage >= 0) && (m_cur_stage < Briefing->num_stages)) {
|
||||
ptr = &Briefing->stages[m_cur_stage];
|
||||
m_stage_title.Format("Stage %d of %d", m_cur_stage + 1, Briefing->num_stages);
|
||||
convert_multiline_string(m_text, ptr->text);
|
||||
m_text = convert_multiline_string(ptr->new_text);
|
||||
m_time.Format("%d", ptr->camera_time);
|
||||
m_voice = ptr->voice;
|
||||
m_cut_prev = (ptr->flags & BS_BACKWARD_CUT) ? 1 : 0;
|
||||
@@ -562,8 +544,6 @@ void briefing_editor_dlg::update_data(int update)
|
||||
if ((m_cur_stage >= 0) && (m_cur_icon >= 0) && (m_cur_icon < ptr->num_icons)) {
|
||||
m_hilight = (ptr->icons[m_cur_icon].flags & BI_HIGHLIGHT)?1:0;
|
||||
m_flipicon = (ptr->icons[m_cur_icon].flags & BI_MIRROR_ICON)?1:0;
|
||||
m_use_wing = (ptr->icons[m_cur_icon].flags & BI_USE_WING_ICON)?1:0;
|
||||
m_use_cargo = (ptr->icons[m_cur_icon].flags & BI_USE_CARGO_ICON)?1:0;
|
||||
m_icon_image = ptr->icons[m_cur_icon].type;
|
||||
m_icon_team = ptr->icons[m_cur_icon].team;
|
||||
m_icon_label = ptr->icons[m_cur_icon].label;
|
||||
@@ -575,8 +555,6 @@ void briefing_editor_dlg::update_data(int update)
|
||||
} else {
|
||||
m_flipicon = FALSE;
|
||||
m_hilight = FALSE;
|
||||
m_use_wing = FALSE;
|
||||
m_use_cargo = FALSE;
|
||||
m_icon_image = -1;
|
||||
m_icon_team = -1;
|
||||
m_ship_type = -1;
|
||||
@@ -586,23 +564,12 @@ void briefing_editor_dlg::update_data(int update)
|
||||
enable = FALSE;
|
||||
}
|
||||
|
||||
// see if icon is overridden by ships.tbl
|
||||
// if so, disable the icon type box
|
||||
int sip_bii_ship = (m_ship_type >= 0) ? Ship_info[m_ship_type].bii_index_ship : -1;
|
||||
int sip_bii_wing = (sip_bii_ship >= 0) ? Ship_info[m_ship_type].bii_index_wing : -1;
|
||||
int sip_bii_cargo = (sip_bii_ship >= 0) ? Ship_info[m_ship_type].bii_index_ship_with_cargo : -1;
|
||||
|
||||
GetDlgItem(IDC_USE_WING_ICON) -> ShowWindow(sip_bii_wing >= 0);
|
||||
GetDlgItem(IDC_USE_CARGO_ICON) -> ShowWindow(sip_bii_cargo >= 0);
|
||||
|
||||
GetDlgItem(IDC_ICON_TEXT) -> EnableWindow(enable);
|
||||
GetDlgItem(IDC_ICON_LABEL) -> EnableWindow(enable);
|
||||
GetDlgItem(IDC_ICON_IMAGE) -> EnableWindow(enable && (sip_bii_ship < 0));
|
||||
GetDlgItem(IDC_ICON_IMAGE) -> EnableWindow(enable);
|
||||
GetDlgItem(IDC_SHIP_TYPE) -> EnableWindow(enable);
|
||||
GetDlgItem(IDC_HILIGHT) -> EnableWindow(enable);
|
||||
GetDlgItem(IDC_FLIP_ICON) -> EnableWindow(enable);
|
||||
GetDlgItem(IDC_USE_WING_ICON) -> EnableWindow(enable);
|
||||
GetDlgItem(IDC_USE_CARGO_ICON) -> EnableWindow(enable);
|
||||
GetDlgItem(IDC_LOCAL) -> EnableWindow(enable);
|
||||
GetDlgItem(IDC_TEAM) -> EnableWindow(enable);
|
||||
GetDlgItem(IDC_ID) -> EnableWindow(enable);
|
||||
@@ -885,7 +852,7 @@ void briefing_editor_dlg::OnInsertStage()
|
||||
void briefing_editor_dlg::copy_stage(int from, int to)
|
||||
{
|
||||
if ((from < 0) || (from >= Briefing->num_stages)) {
|
||||
Briefing->stages[to].text = "<Text here>";
|
||||
strcpy(Briefing->stages[to].new_text, "<Text here>");
|
||||
strcpy_s(Briefing->stages[to].voice, "none.wav");
|
||||
Briefing->stages[to].camera_pos = view_pos;
|
||||
Briefing->stages[to].camera_orient = view_orient;
|
||||
@@ -896,7 +863,7 @@ void briefing_editor_dlg::copy_stage(int from, int to)
|
||||
}
|
||||
|
||||
// Copy all the data in the stage structure.
|
||||
Briefing->stages[to].text = Briefing->stages[from].text;
|
||||
strcpy( Briefing->stages[to].new_text, Briefing->stages[from].new_text );
|
||||
strcpy_s( Briefing->stages[to].voice, Briefing->stages[from].voice );
|
||||
Briefing->stages[to].camera_pos = Briefing->stages[from].camera_pos;
|
||||
Briefing->stages[to].camera_orient = Briefing->stages[from].camera_orient;
|
||||
@@ -949,7 +916,7 @@ void briefing_editor_dlg::OnMakeIcon()
|
||||
iconp = &Briefing->stages[m_cur_stage].icons[m_cur_icon];
|
||||
ship = waypoint = -1;
|
||||
team = 0;
|
||||
SCP_list<CJumpNode>::iterator jnp;
|
||||
SCP_list<jump_node>::iterator jnp;
|
||||
|
||||
vm_vec_make(&min, 9e19f, 9e19f, 9e19f);
|
||||
vm_vec_make(&max, -9e19f, -9e19f, -9e19f);
|
||||
@@ -981,7 +948,7 @@ void briefing_editor_dlg::OnMakeIcon()
|
||||
|
||||
case OBJ_JUMP_NODE:
|
||||
for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
|
||||
if(jnp->GetSCPObject() == ptr)
|
||||
if(jnp->get_obj() == ptr)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1030,7 +997,7 @@ void briefing_editor_dlg::OnMakeIcon()
|
||||
name = wp_list->get_name();
|
||||
}
|
||||
else if (jnp != Jump_nodes.end())
|
||||
name = jnp->GetName();
|
||||
name = jnp->get_name_ptr();
|
||||
else
|
||||
return;
|
||||
|
||||
@@ -1127,11 +1094,11 @@ void briefing_editor_dlg::OnMakeIcon()
|
||||
else if(jnp != Jump_nodes.end()){
|
||||
// find the first navbuoy
|
||||
iconp->ship_class = -1;
|
||||
for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it)
|
||||
for (int i = 0; i < Num_ship_classes; i++)
|
||||
{
|
||||
if (it->flags & SIF_NAVBUOY)
|
||||
if (Ship_info[i].flags & SIF_NAVBUOY)
|
||||
{
|
||||
iconp->ship_class = std::distance(Ship_info.cbegin(), it);
|
||||
iconp->ship_class = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1141,11 +1108,11 @@ void briefing_editor_dlg::OnMakeIcon()
|
||||
else {
|
||||
// find the first navbuoy
|
||||
iconp->ship_class = -1;
|
||||
for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it)
|
||||
for (int i = 0; i < Num_ship_classes; i++)
|
||||
{
|
||||
if (it->flags & SIF_NAVBUOY)
|
||||
if (Ship_info[i].flags & SIF_NAVBUOY)
|
||||
{
|
||||
iconp->ship_class = std::distance(Ship_info.cbegin(), it);
|
||||
iconp->ship_class = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1234,11 +1201,6 @@ void briefing_editor_dlg::OnSelchangeTeam()
|
||||
update_data(1);
|
||||
}
|
||||
|
||||
void briefing_editor_dlg::OnSelchangeShipType()
|
||||
{
|
||||
update_data(1);
|
||||
}
|
||||
|
||||
int briefing_editor_dlg::check_mouse_hit(int x, int y)
|
||||
{
|
||||
int i;
|
||||
@@ -1437,15 +1399,10 @@ void briefing_editor_dlg::OnPasteView()
|
||||
|
||||
void briefing_editor_dlg::OnFlipIcon()
|
||||
{
|
||||
update_data(1);
|
||||
}
|
||||
|
||||
void briefing_editor_dlg::OnWingIcon()
|
||||
{
|
||||
update_data(1);
|
||||
}
|
||||
|
||||
void briefing_editor_dlg::OnCargoIcon()
|
||||
{
|
||||
// if (m_flipicon)
|
||||
// Briefing->stages[m_cur_stage].icons[m_cur_icon].flags |= BI_MIRROR_ICON;
|
||||
// else
|
||||
// Briefing->stages[m_cur_stage].icons[m_cur_icon].flags &= ~BI_MIRROR_ICON;
|
||||
update_data(1);
|
||||
|
||||
}
|
||||
@@ -66,8 +66,6 @@ public:
|
||||
BOOL m_cut_prev;
|
||||
int m_current_briefing;
|
||||
BOOL m_flipicon;
|
||||
BOOL m_use_wing;
|
||||
BOOL m_use_cargo;
|
||||
//}}AFX_DATA
|
||||
|
||||
CBitmap m_play_bm;
|
||||
@@ -122,7 +120,6 @@ protected:
|
||||
afx_msg void OnSaveView();
|
||||
afx_msg void OnSelchangeIconImage();
|
||||
afx_msg void OnSelchangeTeam();
|
||||
afx_msg void OnSelchangeShipType();
|
||||
afx_msg void OnPropagateIcons();
|
||||
afx_msg void OnInitMenu(CMenu* pMenu);
|
||||
afx_msg void OnLines();
|
||||
@@ -133,8 +130,6 @@ protected:
|
||||
afx_msg void OnCopyView();
|
||||
afx_msg void OnPasteView();
|
||||
afx_msg void OnFlipIcon();
|
||||
afx_msg void OnWingIcon();
|
||||
afx_msg void OnCargoIcon();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
private:
|
||||
|
||||
@@ -180,7 +180,7 @@ void campaign_editor::load_campaign()
|
||||
load_tree(0);
|
||||
|
||||
if (!strlen(Campaign.filename))
|
||||
strcpy_s(Campaign.filename, Default_campaign_file_name);
|
||||
strcpy_s(Campaign.filename, BUILTIN_CAMPAIGN);
|
||||
|
||||
if (mission_campaign_load(Campaign.filename, NULL, 0)) {
|
||||
MessageBox("Couldn't open Campaign file!", "Error");
|
||||
@@ -218,7 +218,7 @@ void campaign_editor::initialize( int init_files )
|
||||
m_num_players.Format("%d", Campaign.num_players);
|
||||
|
||||
if (Campaign.desc) {
|
||||
convert_multiline_string(m_desc, Campaign.desc);
|
||||
m_desc = convert_multiline_string(Campaign.desc);
|
||||
} else {
|
||||
m_desc = _T("");
|
||||
}
|
||||
@@ -246,6 +246,7 @@ void campaign_editor::initialize( int init_files )
|
||||
void campaign_editor::mission_selected(int num)
|
||||
{
|
||||
CEdit *bc_dialog, *bc_hall, *bc_persona;
|
||||
char mainhalltext[10];
|
||||
char personatext[10];
|
||||
|
||||
bc_dialog = (CEdit *) GetDlgItem(IDC_BRIEFING_CUTSCENE);
|
||||
@@ -258,7 +259,8 @@ void campaign_editor::mission_selected(int num)
|
||||
bc_dialog->SetWindowText(Campaign.missions[num].briefing_cutscene);
|
||||
|
||||
// new main hall stuff
|
||||
bc_hall->SetWindowText(Campaign.missions[num].main_hall.c_str());
|
||||
sprintf(mainhalltext, "%d", Campaign.missions[num].main_hall);
|
||||
bc_hall->SetWindowText(CString(mainhalltext));
|
||||
|
||||
// new debriefing persona stuff
|
||||
sprintf(personatext, "%d", Campaign.missions[num].debrief_persona_index);
|
||||
@@ -332,13 +334,11 @@ void campaign_editor::load_tree(int save_first)
|
||||
if (Cur_campaign_mission < 0) {
|
||||
GetDlgItem(IDC_SEXP_TREE)->EnableWindow(FALSE);
|
||||
GetDlgItem(IDC_BRIEFING_CUTSCENE)->EnableWindow(FALSE);
|
||||
GetDlgItem(IDC_MAIN_HALL)->EnableWindow(FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
GetDlgItem(IDC_SEXP_TREE)->EnableWindow(TRUE);
|
||||
GetDlgItem(IDC_BRIEFING_CUTSCENE)->EnableWindow(TRUE);
|
||||
GetDlgItem(IDC_MAIN_HALL)->EnableWindow(TRUE);
|
||||
|
||||
GetDlgItem(IDC_MISSISON_LOOP_DESC)->EnableWindow(FALSE);
|
||||
GetDlgItem(IDC_LOOP_BRIEF_ANIM)->EnableWindow(FALSE);
|
||||
@@ -707,21 +707,21 @@ void campaign_editor::update_loop_desc_window()
|
||||
|
||||
// set new text
|
||||
if ((Cur_campaign_link >= 0) && Links[Cur_campaign_link].mission_branch_txt && enable_branch_desc_window) {
|
||||
convert_multiline_string(m_branch_desc, Links[Cur_campaign_link].mission_branch_txt);
|
||||
m_branch_desc = convert_multiline_string(Links[Cur_campaign_link].mission_branch_txt);
|
||||
} else {
|
||||
m_branch_desc = _T("");
|
||||
}
|
||||
|
||||
// set new text
|
||||
if ((Cur_campaign_link >= 0) && Links[Cur_campaign_link].mission_branch_brief_anim && enable_branch_desc_window) {
|
||||
convert_multiline_string(m_branch_brief_anim, Links[Cur_campaign_link].mission_branch_brief_anim);
|
||||
m_branch_brief_anim = convert_multiline_string(Links[Cur_campaign_link].mission_branch_brief_anim);
|
||||
} else {
|
||||
m_branch_brief_anim = _T("");
|
||||
}
|
||||
|
||||
// set new text
|
||||
if ((Cur_campaign_link >= 0) && Links[Cur_campaign_link].mission_branch_brief_sound && enable_branch_desc_window) {
|
||||
convert_multiline_string(m_branch_brief_sound, Links[Cur_campaign_link].mission_branch_brief_sound);
|
||||
m_branch_brief_sound = convert_multiline_string(Links[Cur_campaign_link].mission_branch_brief_sound);
|
||||
} else {
|
||||
m_branch_brief_sound = _T("");
|
||||
}
|
||||
@@ -817,8 +817,7 @@ void campaign_editor::OnBrowseLoopAni()
|
||||
|
||||
// switch directories
|
||||
pushed_dir = cfile_push_chdir(CF_TYPE_INTERFACE);
|
||||
CFileDialog dlg(TRUE, "ani", NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
|
||||
"Ani Files (*.ani)|*.ani|Eff File (*.eff)|*.eff|APNG Files (*.png)|*.png|All Anims (*.ani, *.eff, *.png)|*.ani;*.eff;*.png");
|
||||
CFileDialog dlg(TRUE, "ani", NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR, "Ani Files (*.ani)|*.ani");
|
||||
|
||||
if (dlg.DoModal() == IDOK) {
|
||||
m_branch_brief_anim = dlg.GetFileName();
|
||||
@@ -856,12 +855,19 @@ void campaign_editor::OnBrowseLoopSound()
|
||||
void campaign_editor::OnChangeMainHall()
|
||||
{
|
||||
CString str;
|
||||
int hall;
|
||||
|
||||
UpdateData(TRUE);
|
||||
|
||||
if (Cur_campaign_mission >= 0)
|
||||
{
|
||||
GetDlgItem(IDC_MAIN_HALL)->GetWindowText(str);
|
||||
Campaign.missions[Cur_campaign_mission].main_hall = SCP_string((LPCTSTR)(str));
|
||||
hall = atoi(str);
|
||||
|
||||
if (hall > 255) hall = 255;
|
||||
if (hall < 0) hall = 0;
|
||||
|
||||
Campaign.missions[Cur_campaign_mission].main_hall = (ubyte) hall;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ protected:
|
||||
afx_msg void OnEndEdit();
|
||||
afx_msg void OnChangeBriefingCutscene();
|
||||
afx_msg void OnSelchangeType();
|
||||
afx_msg void MainHallChange();
|
||||
afx_msg void OnToggleLoop();
|
||||
afx_msg void OnBrowseLoopAni();
|
||||
afx_msg void OnBrowseLoopSound();
|
||||
|
||||
@@ -571,7 +571,7 @@ void campaign_tree_view::OnLButtonDown(UINT nFlags, CPoint point)
|
||||
read_mission_goal_list(Cur_campaign_mission);
|
||||
|
||||
if (Campaign.missions[Cur_campaign_mission].notes) {
|
||||
convert_multiline_string(str, Campaign.missions[Cur_campaign_mission].notes);
|
||||
str = convert_multiline_string(Campaign.missions[Cur_campaign_mission].notes);
|
||||
box = (CEdit *) Campaign_tree_formp->GetDlgItem(IDC_HELP_BOX);
|
||||
if (box)
|
||||
box->SetWindowText(str);
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "MissionSave.h"
|
||||
#include "InitialShips.h"
|
||||
#include "mission/missionparse.h"
|
||||
#include "parse/parselo.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
@@ -374,9 +373,9 @@ int campaign_tree_wnd::error_checker()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int campaign_tree_wnd::error(const char *msg, ...)
|
||||
int campaign_tree_wnd::error(char *msg, ...)
|
||||
{
|
||||
SCP_string buf;
|
||||
char buf[2048];
|
||||
va_list args;
|
||||
|
||||
g_err++;
|
||||
@@ -384,16 +383,15 @@ int campaign_tree_wnd::error(const char *msg, ...)
|
||||
vsprintf(buf, msg, args);
|
||||
va_end(args);
|
||||
|
||||
nprintf(("Error", buf.c_str()));
|
||||
if (MessageBox(buf.c_str(), "Error", MB_OKCANCEL | MB_ICONEXCLAMATION) == IDOK)
|
||||
if (MessageBox(buf, "Error", MB_OKCANCEL | MB_ICONEXCLAMATION) == IDOK)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int campaign_tree_wnd::internal_error(const char *msg, ...)
|
||||
int campaign_tree_wnd::internal_error(char *msg, ...)
|
||||
{
|
||||
SCP_string buf, buf2;
|
||||
char buf[2048], buf2[2048];
|
||||
va_list args;
|
||||
|
||||
g_err++;
|
||||
@@ -402,10 +400,9 @@ int campaign_tree_wnd::internal_error(const char *msg, ...)
|
||||
va_end(args);
|
||||
|
||||
sprintf(buf2, "%s\n\nThis is an internal error. Please let Hoffoss\n"
|
||||
"know about this so he can fix it. Click cancel to debug.", buf.c_str());
|
||||
"know about this so he can fix it. Click cancel to debug.", buf);
|
||||
|
||||
nprintf(("Error", buf.c_str()));
|
||||
if (MessageBox(buf2.c_str(), "Internal Error", MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
|
||||
if (MessageBox(buf2, "Internal Error", MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
|
||||
Int3(); // drop to debugger so the problem can be analyzed.
|
||||
|
||||
return -1;
|
||||
@@ -413,7 +410,7 @@ int campaign_tree_wnd::internal_error(const char *msg, ...)
|
||||
|
||||
int campaign_tree_wnd::fred_check_sexp(int sexp, int type, char *msg, ...)
|
||||
{
|
||||
SCP_string buf, sexp_buf, error_buf;
|
||||
char buf[512], buf2[2048], buf3[MAX_EVENT_SIZE];
|
||||
int err = 0, z, faulty_node;
|
||||
va_list args;
|
||||
|
||||
@@ -428,17 +425,17 @@ int campaign_tree_wnd::fred_check_sexp(int sexp, int type, char *msg, ...)
|
||||
if (!z)
|
||||
return 0;
|
||||
|
||||
convert_sexp_to_string(sexp_buf, sexp, SEXP_ERROR_CHECK_MODE);
|
||||
truncate_message_lines(sexp_buf, 30);
|
||||
sprintf(error_buf, "Error in %s: %s\n\nIn sexpression: %s\n\n(Error appears to be: %s)", buf.c_str(), sexp_error_message(z), sexp_buf.c_str(), Sexp_nodes[faulty_node].text);
|
||||
convert_sexp_to_string(sexp, buf2, SEXP_ERROR_CHECK_MODE, MAX_EVENT_SIZE);
|
||||
sprintf(buf3, "Error in %s: %s\n\nIn sexpression: %s\n\n(Error appears to be: %s)",
|
||||
buf, sexp_error_message(z), buf2, Sexp_nodes[faulty_node].text);
|
||||
|
||||
if (z < 0 && z > -100)
|
||||
err = 1;
|
||||
|
||||
if (err)
|
||||
return internal_error(error_buf.c_str());
|
||||
return internal_error(buf3);
|
||||
|
||||
if (error(error_buf.c_str()))
|
||||
if (error(buf3))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -27,8 +27,8 @@ public:
|
||||
public:
|
||||
int error_checker();
|
||||
int fred_check_sexp(int sexp, int type, char *msg, ...);
|
||||
int error(const char *msg, ...);
|
||||
int internal_error(const char *msg, ...);
|
||||
int error(char *msg, ...);
|
||||
int internal_error(char *msg, ...);
|
||||
int save_modified();
|
||||
|
||||
// Overrides
|
||||
|
||||
+15
-10
@@ -47,6 +47,7 @@ void cmd_brief_dlg::DoDataExchange(CDataExchange* pDX)
|
||||
DDX_Text(pDX, IDC_WAVE_FILENAME, m_wave_filename);
|
||||
//}}AFX_DATA_MAP
|
||||
|
||||
DDV_MaxChars(pDX, m_text, CMD_BRIEF_TEXT_MAX - 1);
|
||||
DDV_MaxChars(pDX, m_ani_filename, MAX_FILENAME_LEN - 1);
|
||||
DDV_MaxChars(pDX, m_wave_filename, MAX_FILENAME_LEN - 1);
|
||||
}
|
||||
@@ -90,13 +91,16 @@ void cmd_brief_dlg::update_data(int update)
|
||||
|
||||
// save previously editing data before we load over it.
|
||||
if (last_cmd_brief && m_last_stage >= 0 && m_last_stage < last_cmd_brief->num_stages) {
|
||||
cmd_brief_stage *last_stage = &last_cmd_brief->stage[m_last_stage];
|
||||
char buf[CMD_BRIEF_TEXT_MAX];
|
||||
|
||||
deconvert_multiline_string(last_stage->text, m_text);
|
||||
lcl_fred_replace_stuff(last_stage->text);
|
||||
if (last_cmd_brief->stage[m_last_stage].text)
|
||||
free(last_cmd_brief->stage[m_last_stage].text);
|
||||
|
||||
string_copy(last_stage->ani_filename, m_ani_filename, MAX_FILENAME_LEN);
|
||||
string_copy(last_stage->wave_filename, m_wave_filename, MAX_FILENAME_LEN);
|
||||
deconvert_multiline_string(buf, m_text, CMD_BRIEF_TEXT_MAX);
|
||||
lcl_fred_replace_stuff(buf, CMD_BRIEF_TEXT_MAX);
|
||||
last_cmd_brief->stage[m_last_stage].text = strdup(buf);
|
||||
string_copy(last_cmd_brief->stage[m_last_stage].ani_filename, m_ani_filename, MAX_FILENAME_LEN);
|
||||
string_copy(last_cmd_brief->stage[m_last_stage].wave_filename, m_wave_filename, MAX_FILENAME_LEN);
|
||||
}
|
||||
|
||||
// load data of new stage into dialog
|
||||
@@ -105,7 +109,7 @@ void cmd_brief_dlg::update_data(int update)
|
||||
m_cur_stage = 0;
|
||||
|
||||
m_stage_title.Format("Stage %d of %d", m_cur_stage + 1, Cur_cmd_brief->num_stages);
|
||||
convert_multiline_string(m_text, Cur_cmd_brief->stage[m_cur_stage].text);
|
||||
m_text = convert_multiline_string(Cur_cmd_brief->stage[m_cur_stage].text);
|
||||
m_ani_filename = Cur_cmd_brief->stage[m_cur_stage].ani_filename;
|
||||
m_wave_filename = Cur_cmd_brief->stage[m_cur_stage].wave_filename;
|
||||
enable = TRUE;
|
||||
@@ -239,7 +243,8 @@ void cmd_brief_dlg::OnDeleteStage()
|
||||
z = m_cur_stage;
|
||||
m_cur_stage = -1;
|
||||
update_data(1);
|
||||
Cur_cmd_brief->stage[z].text = "";
|
||||
if (Cur_cmd_brief->stage[z].text)
|
||||
free(Cur_cmd_brief->stage[z].text);
|
||||
|
||||
for (i=z+1; i<Cur_cmd_brief->num_stages; i++)
|
||||
Cur_cmd_brief->stage[i-1] = Cur_cmd_brief->stage[i];
|
||||
@@ -257,14 +262,14 @@ void cmd_brief_dlg::OnDeleteStage()
|
||||
void cmd_brief_dlg::copy_stage(int from, int to)
|
||||
{
|
||||
if ((from < 0) || (from >= Cur_cmd_brief->num_stages)) {
|
||||
Cur_cmd_brief->stage[to].text = "<Text here>";
|
||||
Cur_cmd_brief->stage[to].text = strdup("<Text here>");
|
||||
strcpy_s(Cur_cmd_brief->stage[to].ani_filename, "<default>");
|
||||
strcpy_s(Cur_cmd_brief->stage[to].wave_filename, "none");
|
||||
return;
|
||||
}
|
||||
|
||||
Cur_cmd_brief->stage[to] = Cur_cmd_brief->stage[from];
|
||||
Cur_cmd_brief->stage[to].text = Cur_cmd_brief->stage[from].text;
|
||||
Cur_cmd_brief->stage[to].text = strdup(Cur_cmd_brief->stage[from].text);
|
||||
}
|
||||
|
||||
void cmd_brief_dlg::OnBrowseAni()
|
||||
@@ -275,7 +280,7 @@ void cmd_brief_dlg::OnBrowseAni()
|
||||
UpdateData(TRUE);
|
||||
z = cfile_push_chdir(CF_TYPE_INTERFACE);
|
||||
CFileDialog dlg(TRUE, "ani", NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
|
||||
"Ani Files (*.ani)|*.ani|Eff Files (*.eff)|*.eff|APNG Files (*.png)|*.png|All Anims (*.ani, ,*.eff, *.png)|*.ani;*.eff;*.png|");
|
||||
"Ani Files (*.ani)|*.ani|Avi Files (*.avi)|*.avi|Both (*.ani, *.avi)|*.ani;*.avi||");
|
||||
|
||||
if (dlg.DoModal() == IDOK) {
|
||||
m_ani_filename = dlg.GetFileName();
|
||||
|
||||
@@ -119,7 +119,7 @@ void create_wing_dlg::OnOK()
|
||||
}
|
||||
}
|
||||
|
||||
if (find_matching_waypoint_list((LPCSTR) m_name) != NULL)
|
||||
if (find_matching_waypoint_list(const_cast<char *>((const char *) m_name)) != NULL)
|
||||
{
|
||||
MessageBox("This wing name is already being used by a waypoint path");
|
||||
return;
|
||||
|
||||
@@ -67,7 +67,9 @@ void debriefing_editor_dlg::DoDataExchange(CDataExchange* pDX)
|
||||
DDX_CBIndex(pDX, IDC_FAILED_MISSION_TRACK, m_debriefFail_music);
|
||||
//}}AFX_DATA_MAP
|
||||
|
||||
DDV_MaxChars(pDX, m_text, MAX_BRIEF_LEN - 1);
|
||||
DDV_MaxChars(pDX, m_voice, MAX_FILENAME_LEN - 1);
|
||||
DDV_MaxChars(pDX, m_rec_text, MAX_RECOMMENDATION_LEN - 1);
|
||||
}
|
||||
|
||||
BEGIN_MESSAGE_MAP(debriefing_editor_dlg, CDialog)
|
||||
@@ -202,10 +204,10 @@ void debriefing_editor_dlg::update_data(int update)
|
||||
free_sexp2(ptr->formula);
|
||||
|
||||
ptr->formula = m_tree.save_tree();
|
||||
deconvert_multiline_string(ptr->text, m_text);
|
||||
lcl_fred_replace_stuff(ptr->text);
|
||||
deconvert_multiline_string(ptr->recommendation_text, m_rec_text);
|
||||
lcl_fred_replace_stuff(ptr->recommendation_text);
|
||||
deconvert_multiline_string(ptr->new_text, m_text, MAX_DEBRIEF_LEN);
|
||||
lcl_fred_replace_stuff(ptr->new_text, MAX_DEBRIEF_LEN);
|
||||
deconvert_multiline_string(ptr->new_recommendation_text, m_rec_text, MAX_RECOMMENDATION_LEN);
|
||||
lcl_fred_replace_stuff(ptr->new_recommendation_text,MAX_RECOMMENDATION_LEN);
|
||||
string_copy(ptr->voice, m_voice, MAX_FILENAME_LEN);
|
||||
}
|
||||
|
||||
@@ -214,8 +216,8 @@ void debriefing_editor_dlg::update_data(int update)
|
||||
ptr = &Debriefing->stages[m_cur_stage];
|
||||
m_stage_title.Format("Stage %d of %d", m_cur_stage + 1, Debriefing->num_stages);
|
||||
m_tree.load_tree(ptr->formula);
|
||||
convert_multiline_string(m_text, ptr->text);
|
||||
convert_multiline_string(m_rec_text, ptr->recommendation_text);
|
||||
m_text = convert_multiline_string(ptr->new_text);
|
||||
m_rec_text = convert_multiline_string(ptr->new_recommendation_text);
|
||||
m_voice = ptr->voice;
|
||||
enable = TRUE;
|
||||
|
||||
@@ -385,20 +387,21 @@ void debriefing_editor_dlg::OnInsertStage()
|
||||
void debriefing_editor_dlg::copy_stage(int from, int to, int clear_formula)
|
||||
{
|
||||
if ((from < 0) || (from >= Debriefing->num_stages)) {
|
||||
Debriefing->stages[to].text = "<Text here>";
|
||||
strcpy(Debriefing->stages[to].new_text, "<Text here>");
|
||||
strcpy_s(Debriefing->stages[to].voice, "none.wav");
|
||||
Debriefing->stages[to].formula = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (clear_formula)
|
||||
Debriefing->stages[to].formula = -1;
|
||||
else
|
||||
Debriefing->stages[to].formula = Debriefing->stages[from].formula;
|
||||
|
||||
Debriefing->stages[to].text = Debriefing->stages[from].text;
|
||||
strcpy( Debriefing->stages[to].new_text, Debriefing->stages[from].new_text );
|
||||
strcpy_s( Debriefing->stages[to].voice, Debriefing->stages[from].voice );
|
||||
Debriefing->stages[to].recommendation_text = Debriefing->stages[from].recommendation_text;
|
||||
strcpy( Debriefing->stages[to].new_recommendation_text, Debriefing->stages[from].new_recommendation_text );
|
||||
}
|
||||
|
||||
void debriefing_editor_dlg::OnRclickTree(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
|
||||
@@ -401,9 +401,9 @@ void DumpStats::get_object_stats(CString &buffer)
|
||||
// Jumpnodes
|
||||
buffer += "\r\nJUMPNODES\r\n";
|
||||
|
||||
SCP_list<CJumpNode>::iterator jnp;
|
||||
SCP_list<jump_node>::iterator jnp;
|
||||
for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
|
||||
temp.Format("\tJumpnode: %s\r\n", jnp->GetName());
|
||||
temp.Format("\tJumpnode: %s\r\n", jnp->get_name_ptr());
|
||||
buffer += temp;
|
||||
}
|
||||
|
||||
|
||||
+18
-114
@@ -20,7 +20,6 @@
|
||||
#include "cfile/cfile.h"
|
||||
#include "sound/audiostr.h"
|
||||
#include "localization/localize.h"
|
||||
#include "mod_table/mod_table.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
@@ -60,14 +59,6 @@ event_editor::event_editor(CWnd* pParent /*=NULL*/)
|
||||
modified = 0;
|
||||
select_sexp_node = -1;
|
||||
m_wave_id = -1;
|
||||
m_log_true = 0;
|
||||
m_log_false = 0;
|
||||
m_log_always_false = 0;
|
||||
m_log_1st_repeat = 0;
|
||||
m_log_last_repeat = 0;
|
||||
m_log_1st_trigger = 0;
|
||||
m_log_last_trigger = 0;
|
||||
m_log_state_change = 0;
|
||||
}
|
||||
|
||||
void event_editor::DoDataExchange(CDataExchange* pDX)
|
||||
@@ -89,14 +80,6 @@ void event_editor::DoDataExchange(CDataExchange* pDX)
|
||||
DDX_CBIndex(pDX, IDC_PERSONA_NAME, m_persona);
|
||||
DDX_CBString(pDX, IDC_WAVE_FILENAME, m_wave_filename);
|
||||
DDX_LBIndex(pDX, IDC_MESSAGE_LIST, m_cur_msg);
|
||||
DDX_Check(pDX, IDC_MISSION_LOG_TRUE, m_log_true);
|
||||
DDX_Check(pDX, IDC_MISSION_LOG_FALSE, m_log_false);
|
||||
DDX_Check(pDX, IDC_MISSION_LOG_ALWAYS_FALSE, m_log_always_false);
|
||||
DDX_Check(pDX, IDC_MISSION_LOG_1ST_REPEAT, m_log_1st_repeat);
|
||||
DDX_Check(pDX, IDC_MISSION_LOG_LAST_REPEAT, m_log_last_repeat);
|
||||
DDX_Check(pDX, IDC_MISSION_LOG_1ST_TRIGGER, m_log_1st_trigger);
|
||||
DDX_Check(pDX, IDC_MISSION_LOG_LAST_TRIGGER, m_log_last_trigger);
|
||||
DDX_Check(pDX, IDC_MISSION_LOG_STATE_CHANGE, m_log_state_change);
|
||||
|
||||
|
||||
// m_team == -1 maps to 2
|
||||
@@ -223,23 +206,21 @@ BOOL event_editor::OnInitDialog()
|
||||
}
|
||||
}
|
||||
|
||||
if (!Disable_hc_message_ani) {
|
||||
maybe_add_head(box, "Head-TP2");
|
||||
maybe_add_head(box, "Head-VC2");
|
||||
maybe_add_head(box, "Head-TP4");
|
||||
maybe_add_head(box, "Head-TP5");
|
||||
maybe_add_head(box, "Head-TP6");
|
||||
maybe_add_head(box, "Head-TP7");
|
||||
maybe_add_head(box, "Head-TP8");
|
||||
maybe_add_head(box, "Head-VP2");
|
||||
maybe_add_head(box, "Head-VP2");
|
||||
maybe_add_head(box, "Head-CM2");
|
||||
maybe_add_head(box, "Head-CM3");
|
||||
maybe_add_head(box, "Head-CM4");
|
||||
maybe_add_head(box, "Head-CM5");
|
||||
maybe_add_head(box, "Head-BSH");
|
||||
|
||||
}
|
||||
// add new heads, if not already in
|
||||
maybe_add_head(box, "Head-TP2");
|
||||
maybe_add_head(box, "Head-VC2");
|
||||
maybe_add_head(box, "Head-TP4");
|
||||
maybe_add_head(box, "Head-TP5");
|
||||
maybe_add_head(box, "Head-TP6");
|
||||
maybe_add_head(box, "Head-TP7");
|
||||
maybe_add_head(box, "Head-TP8");
|
||||
maybe_add_head(box, "Head-VP2");
|
||||
maybe_add_head(box, "Head-VP2");
|
||||
maybe_add_head(box, "Head-CM2");
|
||||
maybe_add_head(box, "Head-CM3");
|
||||
maybe_add_head(box, "Head-CM4");
|
||||
maybe_add_head(box, "Head-CM5");
|
||||
maybe_add_head(box, "Head-BSH");
|
||||
|
||||
/*
|
||||
box->AddString("Head-VC"); // force it in, since Sandeep wants it and it's not used in built-in messages
|
||||
@@ -438,8 +419,6 @@ int event_editor::query_modified()
|
||||
return 1;
|
||||
if (advanced_stricmp(m_events[i].objective_key_text, Mission_events[i].objective_key_text))
|
||||
return 1;
|
||||
if (m_events[i].mission_log_flags != Mission_events[i].mission_log_flags)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (m_cur_msg < 0)
|
||||
@@ -531,7 +510,6 @@ void event_editor::OnOk()
|
||||
Mission_events[i].formula = m_event_tree.save_tree(m_events[i].formula);
|
||||
Mission_events[i].objective_text = m_events[i].objective_text;
|
||||
Mission_events[i].objective_key_text = m_events[i].objective_key_text;
|
||||
Mission_events[i].mission_log_flags = m_events[i].mission_log_flags;
|
||||
}
|
||||
|
||||
// now update all sexp references
|
||||
@@ -672,10 +650,6 @@ void event_editor::OnButtonNewEvent()
|
||||
return;
|
||||
}
|
||||
|
||||
// before we do anything, we must check and save off any data from the current event (e.g
|
||||
// the repeat count and interval count)
|
||||
save();
|
||||
|
||||
reset_event(m_num_events++, TVI_LAST);
|
||||
}
|
||||
|
||||
@@ -689,11 +663,6 @@ void event_editor::OnInsert()
|
||||
return;
|
||||
}
|
||||
|
||||
// before we do anything, we must check and save off any data from the current event (e.g
|
||||
// the repeat count and interval count)
|
||||
save();
|
||||
|
||||
|
||||
if(cur_event < 0 || m_num_events == 0)
|
||||
{
|
||||
//There are no events yet, so just create one
|
||||
@@ -748,7 +717,6 @@ void event_editor::reset_event(int num, HTREEITEM after)
|
||||
m_events[num].objective_text = NULL;
|
||||
m_events[num].objective_key_text = NULL;
|
||||
m_events[num].team = -1;
|
||||
m_events[num].mission_log_flags = 0;
|
||||
m_sig[num] = -1;
|
||||
|
||||
m_event_tree.item_index = -1;
|
||||
@@ -759,8 +727,6 @@ void event_editor::reset_event(int num, HTREEITEM after)
|
||||
m_event_tree.item_index = index;
|
||||
m_event_tree.add_operator("do-nothing");
|
||||
|
||||
update_cur_event();
|
||||
|
||||
m_event_tree.SelectItem(h);
|
||||
// GetDlgItem(IDC_CHAIN_DELAY) -> EnableWindow(FALSE);
|
||||
if (num >= MAX_MISSION_EVENTS){
|
||||
@@ -908,26 +874,6 @@ void event_editor::save_event(int e)
|
||||
}
|
||||
}
|
||||
|
||||
// handle event log flags
|
||||
m_events[e].mission_log_flags = 0;
|
||||
if (m_log_true)
|
||||
m_events[e].mission_log_flags |= MLF_SEXP_TRUE;
|
||||
if (m_log_false)
|
||||
m_events[e].mission_log_flags |= MLF_SEXP_FALSE;
|
||||
if (m_log_always_false)
|
||||
m_events[e].mission_log_flags |= MLF_SEXP_KNOWN_FALSE;
|
||||
if (m_log_1st_repeat)
|
||||
m_events[e].mission_log_flags |= MLF_FIRST_REPEAT_ONLY;
|
||||
if (m_log_last_repeat)
|
||||
m_events[e].mission_log_flags |= MLF_LAST_REPEAT_ONLY;
|
||||
if (m_log_1st_trigger)
|
||||
m_events[e].mission_log_flags |= MLF_FIRST_TRIGGER_ONLY;
|
||||
if (m_log_last_trigger)
|
||||
m_events[e].mission_log_flags |= MLF_LAST_TRIGGER_ONLY;
|
||||
if (m_log_state_change)
|
||||
m_events[e].mission_log_flags |= MLF_STATE_CHANGE;
|
||||
|
||||
|
||||
// Search for item to update
|
||||
HTREEITEM h = m_event_tree.GetRootItem();
|
||||
while (h) {
|
||||
@@ -1049,48 +995,6 @@ void event_editor::update_cur_event()
|
||||
GetDlgItem(IDC_EVENT_TEAM)->EnableWindow(TRUE);
|
||||
}
|
||||
|
||||
// handle event log flags
|
||||
if (m_events[cur_event].mission_log_flags & MLF_SEXP_TRUE) {
|
||||
m_log_true = TRUE;
|
||||
}else {
|
||||
m_log_true = FALSE;
|
||||
}
|
||||
if (m_events[cur_event].mission_log_flags & MLF_SEXP_FALSE) {
|
||||
m_log_false = TRUE;
|
||||
}else {
|
||||
m_log_false = FALSE;
|
||||
}
|
||||
if (m_events[cur_event].mission_log_flags & MLF_SEXP_KNOWN_FALSE) {
|
||||
m_log_always_false = TRUE;
|
||||
}else {
|
||||
m_log_always_false = FALSE;
|
||||
}
|
||||
if (m_events[cur_event].mission_log_flags & MLF_FIRST_REPEAT_ONLY) {
|
||||
m_log_1st_repeat = TRUE;
|
||||
}else {
|
||||
m_log_1st_repeat = FALSE;
|
||||
}
|
||||
if (m_events[cur_event].mission_log_flags & MLF_LAST_REPEAT_ONLY) {
|
||||
m_log_last_repeat = TRUE;
|
||||
}else {
|
||||
m_log_last_repeat = FALSE;
|
||||
}
|
||||
if (m_events[cur_event].mission_log_flags & MLF_FIRST_TRIGGER_ONLY) {
|
||||
m_log_1st_trigger = TRUE;
|
||||
}else {
|
||||
m_log_1st_trigger = FALSE;
|
||||
}
|
||||
if (m_events[cur_event].mission_log_flags & MLF_LAST_TRIGGER_ONLY) {
|
||||
m_log_last_trigger = TRUE;
|
||||
}else {
|
||||
m_log_last_trigger = FALSE;
|
||||
}
|
||||
if (m_events[cur_event].mission_log_flags & MLF_STATE_CHANGE) {
|
||||
m_log_state_change = TRUE;
|
||||
}else {
|
||||
m_log_state_change = FALSE;
|
||||
}
|
||||
|
||||
UpdateData(FALSE);
|
||||
}
|
||||
|
||||
@@ -1245,7 +1149,7 @@ int event_editor::save_message(int num)
|
||||
}
|
||||
|
||||
string_copy(m_messages[num].message, m_message_text, MESSAGE_LENGTH - 1);
|
||||
lcl_fred_replace_stuff(m_messages[num].message, MESSAGE_LENGTH - 1);
|
||||
lcl_fred_replace_stuff(m_messages[num].message, MESSAGE_LENGTH);
|
||||
if (m_messages[num].avi_info.name){
|
||||
free(m_messages[num].avi_info.name);
|
||||
}
|
||||
@@ -1310,7 +1214,7 @@ void event_editor::OnDeleteMsg()
|
||||
char buf[256];
|
||||
|
||||
// handle this case somewhat gracefully
|
||||
Assertion((m_cur_msg >= -1) && (m_cur_msg < m_num_messages), "Unexpected m_cur_msg value (%d); expected either -1, or between 0-%d. Get a coder!\n", m_cur_msg, m_num_messages - 1);
|
||||
Assert((m_cur_msg >= 0) && (m_cur_msg < m_num_messages));
|
||||
if((m_cur_msg < 0) || (m_cur_msg >= m_num_messages)){
|
||||
return;
|
||||
}
|
||||
@@ -1350,7 +1254,7 @@ void event_editor::OnBrowseAvi()
|
||||
|
||||
z = cfile_push_chdir(CF_TYPE_INTERFACE);
|
||||
CFileDialog dlg(TRUE, "ani", m_avi_filename, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
|
||||
"Ani Files (*.ani)|*.ani|Eff Files (*.eff)|*.eff|APNG Files (*.png)|*.png|All Anims (*.ani, *.eff, *.png)|*.ani;*.eff;*.png|");
|
||||
"Ani Files (*.ani)|*.ani|Avi Files (*.avi)|*.avi|Both (*.ani, *.avi)|*.ani;*.avi||");
|
||||
|
||||
if (dlg.DoModal() == IDOK) {
|
||||
m_avi_filename = dlg.GetFileName();
|
||||
|
||||
@@ -71,14 +71,6 @@ public:
|
||||
int m_team;
|
||||
int m_message_team;
|
||||
int m_last_message_node;
|
||||
int m_log_true;
|
||||
int m_log_false;
|
||||
int m_log_always_false;
|
||||
int m_log_1st_repeat;
|
||||
int m_log_last_repeat;
|
||||
int m_log_1st_trigger;
|
||||
int m_log_last_trigger;
|
||||
int m_log_state_change;
|
||||
//}}AFX_DATA
|
||||
|
||||
CBitmap m_play_bm;
|
||||
|
||||
+1
-9
@@ -29,14 +29,6 @@
|
||||
|
||||
#include "AFXADV.H"
|
||||
|
||||
#ifdef WIN32
|
||||
// According to AMD and NV, these _should_ force their drivers into high-performance mode
|
||||
extern "C" {
|
||||
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
#ifndef FRED
|
||||
#error macro FRED is not defined when trying to build release Fred. Please define FRED macro in build settings in all Fred projects
|
||||
@@ -684,7 +676,7 @@ void CFREDApp::record_window_data(window_data *wndd, CWnd *wnd)
|
||||
|
||||
void CAboutDlg::OnBug()
|
||||
{
|
||||
char *path = "http://scp.indiegames.us/mantis/";
|
||||
char *path = "http://mgo.maxgaming.net/mantis/login_page.php";
|
||||
|
||||
char buffer[MAX_PATH];
|
||||
sprintf(buffer,"explorer.exe \"%s\"", path);
|
||||
|
||||
+287
-315
File diff suppressed because it is too large.
Load diff
Loaded 100 of 984 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user